Skip to content

Commit fb9a1c0

Browse files
committed
Add spin indicator component
1 parent 2feadd3 commit fb9a1c0

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

src/core/src/components/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ pub(crate) mod edit;
44
pub(crate) mod help;
55
pub(crate) mod search_bar;
66
mod shared;
7+
#[allow(dead_code)]
8+
pub(crate) mod spin_indicator;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use std::time::{Duration, Instant};
2+
3+
const INDICATOR_CHARACTERS: [&str; 4] = ["-", "\\", "|", "/"];
4+
const ANIMATE_SPEED: Duration = Duration::from_millis(100);
5+
6+
pub(crate) struct SpinIndicator {
7+
index: u8,
8+
last_refreshed_at: Instant,
9+
}
10+
11+
impl SpinIndicator {
12+
pub(crate) fn new() -> Self {
13+
Self {
14+
index: 0,
15+
last_refreshed_at: Instant::now(),
16+
}
17+
}
18+
19+
pub(crate) fn refresh(&mut self) {
20+
if self.last_refreshed_at.elapsed() >= ANIMATE_SPEED {
21+
self.last_refreshed_at = Instant::now();
22+
self.index = if self.index == 3 { 0 } else { self.index + 1 }
23+
}
24+
}
25+
26+
pub(crate) fn indicator(&self) -> String {
27+
format!("({})", INDICATOR_CHARACTERS[self.index as usize])
28+
}
29+
}
30+
#[cfg(test)]
31+
mod tests {
32+
use std::ops::{Add, Sub};
33+
34+
const SAFE_TEST_DURATION: Duration = Duration::from_secs(60);
35+
36+
use super::*;
37+
38+
#[test]
39+
fn does_not_advance_if_duration_has_not_elapsed() {
40+
let mut indicator = SpinIndicator::new();
41+
// this test is unlikely to finish before this elapsed time
42+
indicator.last_refreshed_at = Instant::now().add(SAFE_TEST_DURATION);
43+
assert_eq!(indicator.indicator(), "(-)");
44+
indicator.refresh();
45+
assert_eq!(indicator.indicator(), "(-)");
46+
}
47+
48+
#[test]
49+
fn does_not_advance_if_duration_has_elapsed() {
50+
let mut indicator = SpinIndicator::new();
51+
indicator.last_refreshed_at = Instant::now().sub(SAFE_TEST_DURATION);
52+
assert_eq!(indicator.indicator(), "(-)");
53+
indicator.refresh();
54+
assert_eq!(indicator.indicator(), "(\\)");
55+
}
56+
57+
const INDICATOR_CHARACTERS: [&str; 4] = ["-", "\\", "|", "/"];
58+
#[test]
59+
fn full_animation() {
60+
let mut indicator = SpinIndicator::new();
61+
indicator.last_refreshed_at = Instant::now().sub(SAFE_TEST_DURATION);
62+
assert_eq!(indicator.indicator(), "(-)");
63+
indicator.refresh();
64+
indicator.last_refreshed_at = indicator.last_refreshed_at.sub(SAFE_TEST_DURATION);
65+
assert_eq!(indicator.indicator(), "(\\)");
66+
indicator.refresh();
67+
indicator.last_refreshed_at = indicator.last_refreshed_at.sub(SAFE_TEST_DURATION);
68+
assert_eq!(indicator.indicator(), "(|)");
69+
indicator.refresh();
70+
indicator.last_refreshed_at = indicator.last_refreshed_at.sub(SAFE_TEST_DURATION);
71+
assert_eq!(indicator.indicator(), "(/)");
72+
indicator.refresh();
73+
indicator.last_refreshed_at = indicator.last_refreshed_at.sub(SAFE_TEST_DURATION);
74+
assert_eq!(indicator.indicator(), "(-)");
75+
}
76+
}

0 commit comments

Comments
 (0)