diff --git a/Cargo.lock b/Cargo.lock index 379a64c..7f1ca5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1010,6 +1010,7 @@ dependencies = [ "throbber-widgets-tui", "tokio", "tui-input", + "tui-skeleton", ] [[package]] @@ -4619,6 +4620,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "tui-skeleton" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3eb5b0d4f9fc43565038283e53913bfd961a63f914d3352a71348c695e508e" +dependencies = [ + "ratatui-core", + "ratatui-widgets", +] + [[package]] name = "tungstenite" version = "0.28.0" diff --git a/Cargo.toml b/Cargo.toml index 7ef3005..8204c09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,3 +33,4 @@ tempfile = "3.27.0" throbber-widgets-tui = "0.11.0" tokio = { version = "1.52.3", features = ["full"] } tui-input = "0.15.3" +tui-skeleton = "0.3.0" diff --git a/src/main.rs b/src/main.rs index 9ba8037..10a204b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use tui_input::{Input, backend::crossterm::EventHandler}; use futures::{StreamExt, future::FutureExt}; use ratatui::prelude::*; +use tui_skeleton::{AnimationMode, SkeletonList, SkeletonText}; use crate::{events::AudioRecordRequest, prediction::{BandcampResult, PossibleResponse}, scene::{ConversationEntry, PlaylistEntry, Scene, StageActions, StageDirection}, tts::start_tts}; @@ -138,15 +139,25 @@ impl App { } fn draw_options(&mut self, frame: &mut Frame, area: Rect) { - frame.render_stateful_widget( - List::new(self.scene.reply_options().clone()) - .block(Block::bordered().border_style(style::Color::LightGreen).title("Reply Options (Press 'Ctrl+R' to regenerate, Ctrl+Enter to use)")) - .style(ratatui::style::Color::White) - .highlight_symbol("> ") - .highlight_style(style::Style::new().bold().fg(style::Color::Cyan)), - area, - &mut self.reply_state - ); + let borders = Block::bordered().border_style(style::Color::LightGreen).title("Reply Options (Press 'Ctrl+R' to regenerate, Ctrl+Enter to use)"); + if self.scene.reply_options().len() == 0 && self.is_requesting { + let list = SkeletonText::new(std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as u64) + .braille(true) + .line_widths(&[0.25, 0.5, 0.4, 0.6]) + .mode(AnimationMode::Noise) + .block(borders); + frame.render_widget(list, area); + } else { + frame.render_stateful_widget( + List::new(self.scene.reply_options().clone()) + .block(borders) + .style(ratatui::style::Color::White) + .highlight_symbol("> ") + .highlight_style(style::Style::new().bold().fg(style::Color::Cyan)), + area, + &mut self.reply_state + ); + } } fn draw_user_input(&mut self, frame: &mut Frame, area: Rect) {