intelli_shell/widgets/
loading.rs1use std::borrow::Cow;
2
3use ratatui::{
4 Frame,
5 layout::Rect,
6 style::Style,
7 widgets::{Clear, Paragraph},
8};
9
10use crate::config::Theme;
11
12pub const SPINNER_CHARS: [&str; 10] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
14
15pub struct LoadingSpinner<'a> {
17 spinner_state: usize,
19 style: Style,
21 message: Option<Cow<'a, str>>,
23}
24
25impl<'a> LoadingSpinner<'a> {
26 pub fn new(theme: &Theme) -> Self {
28 Self {
29 spinner_state: 0,
30 style: theme.primary.into(),
31 message: None,
32 }
33 }
34
35 pub fn with_message(mut self, message: impl Into<Cow<'a, str>>) -> Self {
37 self.set_message(message);
38 self
39 }
40
41 pub fn set_message(&mut self, message: impl Into<Cow<'a, str>>) {
43 self.message = Some(message.into());
44 }
45
46 pub fn tick(&mut self) {
48 self.spinner_state = (self.spinner_state + 1) % SPINNER_CHARS.len();
49 }
50
51 pub fn render_in(&self, frame: &mut Frame, area: Rect) {
53 let spinner_char = SPINNER_CHARS[self.spinner_state];
54 let loading_text = if let Some(ref msg) = self.message {
55 format!(" {spinner_char} {msg} ")
56 } else {
57 format!(" {spinner_char} ")
58 };
59
60 let loading_paragraph = Paragraph::new(loading_text).style(self.style);
62
63 frame.render_widget(Clear, area);
65 frame.render_widget(loading_paragraph, area);
66 }
67}