Unify animations (#3729)

Unify the animation in a single code and add the CTRL + . in the
onboarding
This commit is contained in:
jif-oai
2025-09-18 16:27:15 +01:00
committed by GitHub
parent d4aba772cb
commit 1b3c8b8e94
5 changed files with 220 additions and 81 deletions

View File

@@ -1,5 +1,4 @@
use crate::frames::ALL_VARIANTS as FRAME_VARIANTS;
use crate::frames::FRAME_TICK_DEFAULT;
use crate::ascii_animation::AsciiAnimation;
use crate::tui::FrameRequester;
use crate::tui::Tui;
use crate::tui::TuiEvent;
@@ -7,7 +6,6 @@ use color_eyre::eyre::Result;
use crossterm::event::KeyCode;
use crossterm::event::KeyEvent;
use crossterm::event::KeyModifiers;
use rand::Rng as _;
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::prelude::Widget;
@@ -17,10 +15,8 @@ use ratatui::widgets::Clear;
use ratatui::widgets::Paragraph;
use ratatui::widgets::WidgetRef;
use ratatui::widgets::Wrap;
use std::time::Duration;
use tokio_stream::StreamExt;
const FRAME_TICK: Duration = FRAME_TICK_DEFAULT;
const MIN_ANIMATION_HEIGHT: u16 = 24;
const MIN_ANIMATION_WIDTH: u16 = 60;
@@ -39,9 +35,7 @@ enum ModelUpgradeOption {
struct ModelUpgradePopup {
highlighted: ModelUpgradeOption,
decision: Option<ModelUpgradeDecision>,
request_frame: FrameRequester,
frame_idx: usize,
variant_idx: usize,
animation: AsciiAnimation,
}
impl ModelUpgradePopup {
@@ -49,9 +43,7 @@ impl ModelUpgradePopup {
Self {
highlighted: ModelUpgradeOption::TryNewModel,
decision: None,
request_frame,
frame_idx: 0,
variant_idx: 0,
animation: AsciiAnimation::new(request_frame),
}
}
@@ -65,7 +57,7 @@ impl ModelUpgradePopup {
KeyCode::Esc => self.select(ModelUpgradeOption::KeepCurrent),
KeyCode::Char('.') => {
if key_event.modifiers.contains(KeyModifiers::CONTROL) {
self.pick_random_variant();
let _ = self.animation.pick_random_variant();
}
}
_ => {}
@@ -75,37 +67,13 @@ impl ModelUpgradePopup {
fn highlight(&mut self, option: ModelUpgradeOption) {
if self.highlighted != option {
self.highlighted = option;
self.request_frame.schedule_frame();
self.animation.request_frame();
}
}
fn select(&mut self, option: ModelUpgradeOption) {
self.decision = Some(option.into());
self.request_frame.schedule_frame();
}
fn advance_animation(&mut self) {
let len = self.frames().len();
self.frame_idx = (self.frame_idx + 1) % len;
self.request_frame.schedule_frame_in(FRAME_TICK);
}
fn frames(&self) -> &'static [&'static str] {
FRAME_VARIANTS[self.variant_idx]
}
fn pick_random_variant(&mut self) {
let total = FRAME_VARIANTS.len();
if total <= 1 {
return;
}
let mut rng = rand::rng();
let mut next = self.variant_idx;
while next == self.variant_idx {
next = rng.random_range(0..total);
}
self.variant_idx = next;
self.request_frame.schedule_frame();
self.animation.request_frame();
}
}
@@ -121,6 +89,7 @@ impl From<ModelUpgradeOption> for ModelUpgradeDecision {
impl WidgetRef for &ModelUpgradePopup {
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
Clear.render(area, buf);
self.animation.schedule_next_frame();
// Skip the animation entirely when the viewport is too small so we don't clip frames.
let show_animation =
@@ -128,7 +97,7 @@ impl WidgetRef for &ModelUpgradePopup {
let mut lines: Vec<Line> = Vec::new();
if show_animation {
let frame = self.frames()[self.frame_idx];
let frame = self.animation.current_frame();
lines.extend(frame.lines().map(|l| l.into()));
// Spacer between animation and text content.
lines.push("".into());
@@ -188,8 +157,6 @@ pub(crate) async fn run_model_upgrade_popup(tui: &mut Tui) -> Result<ModelUpgrad
frame.render_widget_ref(&popup, frame.area());
})?;
popup.advance_animation();
let events = tui.event_stream();
tokio::pin!(events);
while popup.decision.is_none() {
@@ -197,7 +164,6 @@ pub(crate) async fn run_model_upgrade_popup(tui: &mut Tui) -> Result<ModelUpgrad
match event {
TuiEvent::Key(key_event) => popup.handle_key_event(key_event),
TuiEvent::Draw => {
popup.advance_animation();
let _ = tui.draw(u16::MAX, |frame| {
frame.render_widget_ref(&popup, frame.area());
});