codeberg_cli/render/
spinner.rs1use std::future::Future;
2use std::time::Duration;
3
4use indicatif::{ProgressBar, ProgressStyle};
5
6pub async fn spin_until_ready<F, FO>(future: F) -> FO
7where
8 F: Future<Output = FO>,
9{
10 let spinner = ProgressBar::new_spinner();
18 spinner.set_style(ProgressStyle::default_spinner());
19 let result = tokio::select! {
20 _ = spin_endless(&spinner) => { unreachable!("future running indefinitely"); }
21 output = future => { output }
22 };
23 spinner.finish_and_clear();
24 result
25}
26
27async fn spin_endless(spinner: &ProgressBar) -> ! {
28 loop {
29 spinner.tick();
30 tokio::time::sleep(Duration::from_millis(100)).await;
31 }
32}
33
34pub async fn spin_and_try_every_second_for<F, FG, FO>(
35 future: FG,
36 num_tries: usize,
37) -> anyhow::Result<FO>
38where
39 FG: Fn() -> F,
40 F: Future<Output = anyhow::Result<FO>>,
41{
42 let spinner = ProgressBar::new_spinner();
43 spinner.set_style(ProgressStyle::default_spinner());
44 let result = tokio::select! {
45 _ = spin_endless(&spinner) => { unreachable!("future running indefinitely"); }
46 output = try_future_x_times(future, num_tries) => { output }
47 };
48 spinner.finish_and_clear();
49 result
50}
51
52async fn try_future_x_times<F, FG, FO>(future: FG, num_tries: usize) -> anyhow::Result<FO>
53where
54 FG: Fn() -> F,
55 F: Future<Output = anyhow::Result<FO>>,
56{
57 let mut tries = num_tries;
58 loop {
59 tries -= 1;
60 tokio::time::sleep(Duration::from_secs(1)).await;
61 let res = future().await;
62 if res.is_ok() || tries == 0 {
63 return res;
64 }
65 }
66}