Skip to content

Commit fc0b837

Browse files
committed
chore: define Spinner to set spinner configs
1 parent 45d1c54 commit fc0b837

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

examples/byop/src/byop.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ struct BYOP {
169169
renderer: SharedRenderer<Index>,
170170
task_monitor: Arc<TaskMonitor>,
171171
readline: text_editor::State,
172+
spinner: Arc<spinner::Spinner>,
172173
}
173174

174175
#[async_trait::async_trait]
@@ -229,6 +230,12 @@ impl BYOP {
229230
task_monitor: Arc::new(TaskMonitor::new(renderer.clone())),
230231
renderer,
231232
readline,
233+
spinner: Arc::new(
234+
spinner::Spinner::default()
235+
.frames(spinner::frame::DOTS.clone())
236+
.suffix("Executing...")
237+
.duration(Duration::from_millis(100)),
238+
),
232239
})
233240
}
234241

@@ -422,14 +429,14 @@ impl BYOP {
422429
async fn spawn(&mut self) -> anyhow::Result<()> {
423430
let renderer = self.renderer.clone();
424431
let task_monitor = Arc::clone(&self.task_monitor);
432+
let spinner = Arc::clone(&self.spinner);
433+
425434
let spinner_task = tokio::spawn(async move {
426435
spinner::run(
427-
spinner::frame::DOTS.clone(),
428-
"Executing...",
429-
Duration::from_millis(100),
436+
spinner.as_ref(),
430437
task_monitor.as_ref(),
431438
Index::Spinner,
432-
renderer.clone(),
439+
renderer,
433440
)
434441
.await
435442
});

promkit-widgets/src/spinner.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,55 @@ use crate::core::{Pane, grapheme::StyledGraphemes, render::SharedRenderer};
55
pub mod frame;
66
use frame::Frame;
77

8+
/// Trait to define the state of the spinner.
89
pub trait State {
910
fn is_idle(&self) -> impl Future<Output = bool> + Send;
1011
}
1112

13+
/// A spinner that can be used to indicate loading or processing states.
14+
#[derive(Clone, Debug)]
15+
pub struct Spinner {
16+
/// The frames of the spinner, which are the characters that will be displayed in a rotating manner.
17+
pub frames: Frame,
18+
/// A suffix that will be displayed alongside the spinner.
19+
pub suffix: String,
20+
/// The duration between frame updates.
21+
pub duration: Duration,
22+
}
23+
24+
impl Default for Spinner {
25+
fn default() -> Self {
26+
Self {
27+
frames: frame::DOTS.clone(),
28+
suffix: String::new(),
29+
duration: Duration::from_millis(100),
30+
}
31+
}
32+
}
33+
34+
impl Spinner {
35+
/// Set frames for the spinner.
36+
pub fn frames(mut self, frames: Frame) -> Self {
37+
self.frames = frames;
38+
self
39+
}
40+
41+
/// Set a suffix for the spinner.
42+
pub fn suffix(mut self, suffix: impl Into<String>) -> Self {
43+
self.suffix = suffix.into();
44+
self
45+
}
46+
47+
/// Set the duration between frame updates.
48+
pub fn duration(mut self, duration: Duration) -> Self {
49+
self.duration = duration;
50+
self
51+
}
52+
}
53+
1254
/// Spawn a background task that shows a spinner while the state is active.
1355
pub async fn run<S, I>(
14-
spinner: Frame,
15-
suffix: &str,
16-
duration: Duration,
56+
spinner: &Spinner,
1757
state: S,
1858
index: I,
1959
renderer: SharedRenderer<I>,
@@ -23,21 +63,21 @@ where
2363
I: Clone + Ord + Send,
2464
{
2565
let mut frame_index = 0;
26-
let mut interval = tokio::time::interval(duration);
66+
let mut interval = tokio::time::interval(spinner.duration);
2767

2868
loop {
2969
interval.tick().await;
3070

3171
if !state.is_idle().await {
32-
frame_index = (frame_index + 1) % spinner.len();
72+
frame_index = (frame_index + 1) % spinner.frames.len();
3373

3474
renderer
3575
.update([(
3676
index.clone(),
3777
Pane::new(
3878
vec![StyledGraphemes::from(format!(
3979
"{} {}",
40-
spinner[frame_index], suffix
80+
spinner.frames[frame_index], spinner.suffix
4181
))],
4282
0,
4383
),

0 commit comments

Comments
 (0)