ui: add tui-skeleton for a fun loading animation

This commit is contained in:
2026-06-05 13:39:16 +02:00
parent 17903f1ac9
commit af61b3bd8a
3 changed files with 32 additions and 9 deletions
Generated
+11
View File
@@ -1010,6 +1010,7 @@ dependencies = [
"throbber-widgets-tui", "throbber-widgets-tui",
"tokio", "tokio",
"tui-input", "tui-input",
"tui-skeleton",
] ]
[[package]] [[package]]
@@ -4619,6 +4620,16 @@ dependencies = [
"unicode-width", "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]] [[package]]
name = "tungstenite" name = "tungstenite"
version = "0.28.0" version = "0.28.0"
+1
View File
@@ -33,3 +33,4 @@ tempfile = "3.27.0"
throbber-widgets-tui = "0.11.0" throbber-widgets-tui = "0.11.0"
tokio = { version = "1.52.3", features = ["full"] } tokio = { version = "1.52.3", features = ["full"] }
tui-input = "0.15.3" tui-input = "0.15.3"
tui-skeleton = "0.3.0"
+20 -9
View File
@@ -13,6 +13,7 @@ use tui_input::{Input, backend::crossterm::EventHandler};
use futures::{StreamExt, future::FutureExt}; use futures::{StreamExt, future::FutureExt};
use ratatui::prelude::*; 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}; 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) { fn draw_options(&mut self, frame: &mut Frame, area: Rect) {
frame.render_stateful_widget( let borders = Block::bordered().border_style(style::Color::LightGreen).title("Reply Options (Press 'Ctrl+R' to regenerate, Ctrl+Enter to use)");
List::new(self.scene.reply_options().clone()) if self.scene.reply_options().len() == 0 && self.is_requesting {
.block(Block::bordered().border_style(style::Color::LightGreen).title("Reply Options (Press 'Ctrl+R' to regenerate, Ctrl+Enter to use)")) let list = SkeletonText::new(std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as u64)
.style(ratatui::style::Color::White) .braille(true)
.highlight_symbol("> ") .line_widths(&[0.25, 0.5, 0.4, 0.6])
.highlight_style(style::Style::new().bold().fg(style::Color::Cyan)), .mode(AnimationMode::Noise)
area, .block(borders);
&mut self.reply_state 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) { fn draw_user_input(&mut self, frame: &mut Frame, area: Rect) {