Skip to content

Commit 81eaedf

Browse files
committed
Add retry button that can be used to restart block
After a block fails, the user can click the retry button to restart the block. This is nicer than having to restart the whole status bar, or sending a signal.
1 parent e7b4ee8 commit 81eaedf

File tree

10 files changed

+63
-18
lines changed

10 files changed

+63
-18
lines changed

files/icons/awesome4.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pomodoro_break = "\uf0f4" # fa-coffee
5858
pomodoro_paused = "\uf04c" # fa-pause
5959
pomodoro_started = "\uf04b" # fa-play
6060
pomodoro_stopped = "\uf04d" # fa-stop
61+
refresh = "\uf021" # fa-refresh
6162
resolution = "\uf096" # fa-square-o
6263
scratchpad = "\uf2d2" # fa-window-restore
6364
tasks = "\uf0ae" # fa-tasks

files/icons/awesome5.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pomodoro_break = "\uf0f4" # fa-coffee
5858
pomodoro_paused = "\uf04c" # fa-pause
5959
pomodoro_started = "\uf04b" # fa-play
6060
pomodoro_stopped = "\uf04d" # fa-stop
61+
refresh = "\uf021" # fa-sync
6162
resolution = "\uf096" # fa-square-o
6263
scratchpad = "\uf2d2" # fa-window-restore
6364
tasks = "\uf0ae"

files/icons/awesome6.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pomodoro_break = "\uf0f4" # fa-coffee
6262
pomodoro_paused = "\uf04c" # fa-pause
6363
pomodoro_started = "\uf04b" # fa-play
6464
pomodoro_stopped = "\uf04d" # fa-stop
65+
refresh = "\uf021" # fa-arrows-rotate
6566
resolution = "\uf096" # fa-square-o
6667
scratchpad = "\uf2d2" # fa-window-restore
6768
tasks = "\uf0ae"

files/icons/emoji.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pomodoro_break = "☕"
5454
pomodoro_paused = "⏸️"
5555
pomodoro_started = "▶️"
5656
pomodoro_stopped = "⏹️"
57+
refresh = "🔄"
5758
resolution = "🔳"
5859
scratchpad = "🗔"
5960
tasks = ""

files/icons/material-nf.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ pomodoro_break = "\U000f0176" # nf-md-coffee
9191
pomodoro_paused = "\U000f03e4" # nf-md-pause
9292
pomodoro_started = "\U000f040a" # nf-md-play
9393
pomodoro_stopped = "\U000f04db" # nf-md-stop
94+
refresh = "\U000f0450" # nf-md-refresh
9495
resolution = "\U000f0293" # nf-md-fullscreen
9596
scratchpad = "\U000f05b2" # nf-md-window_restore
9697
tasks = "\U000f05c7" # nf-md-playlist_check

files/icons/material.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ pomodoro_break = "\uefef" # coffee | TODO: broken?
7575
pomodoro_paused = "\ue034" # pause
7676
pomodoro_started = "\ue037" # play_arrow
7777
pomodoro_stopped = "\uef6a" # play_disabled ef6a | TODO: broken?
78+
refresh = "\ue5d5" # refresh
7879
resolution = "\uf152" # crop-square-rounded
7980
scratchpad = "\ue883" # flip_to_front
8081
tasks = "\ue8f9" # work

src/blocks.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ use crate::geolocator::{Geolocator, IPAddressInfo};
4545
use crate::widget::Widget;
4646
use crate::{BoxedFuture, Request, RequestCmd};
4747

48+
pub(super) const RESTART_BLOCK_BTN: &str = "restart_block_btn";
49+
4850
macro_rules! define_blocks {
4951
{
5052
$(
@@ -90,20 +92,32 @@ macro_rules! define_blocks {
9092
Self::$block(config) => futures.push(async move {
9193
let mut error_count: u8 = 0;
9294
while let Err(mut err) = $block::run(&config, &api).await {
95+
let Ok(mut actions) = api.get_actions() else { return };
96+
if api.set_default_actions(&[
97+
(MouseButton::Left, Some(RESTART_BLOCK_BTN), "error_count_reset"),
98+
]).is_err() {
99+
return;
100+
}
93101
let should_retry = api
94102
.max_retries
95103
.map_or(true, |max_retries| error_count < max_retries);
96104
if !should_retry {
97105
err = Error {
98-
message: Some("Block failed too many times, giving up".into()),
106+
message: Some("Block stopped, left click refresh icon to restart block".into()),
99107
cause: Some(Arc::new(err)),
100108
};
101109
}
102-
if api.set_error(err).is_err() {
110+
if api.set_error_with_restartable(err, !should_retry).is_err() {
103111
return;
104112
}
105113
tokio::select! {
106114
_ = tokio::time::sleep(api.error_interval), if should_retry => (),
115+
Some(action) = actions.recv(), if !should_retry => match action.as_ref(){
116+
"error_count_reset" => {
117+
error_count = 0;
118+
},
119+
_ => (),
120+
},
107121
_ = api.wait_for_update_request() => (),
108122
}
109123
error_count = error_count.saturating_add(1);
@@ -246,12 +260,17 @@ impl CommonApi {
246260
.error("Failed to send Request")
247261
}
248262

249-
/// Sends the error to be displayed.
263+
/// Sends the error to be displayed, no restart button will be shown.
250264
pub fn set_error(&self, error: Error) -> Result<()> {
265+
self.set_error_with_restartable(error, false)
266+
}
267+
268+
/// Sends the error to be displayed.
269+
pub fn set_error_with_restartable(&self, error: Error, restartable: bool) -> Result<()> {
251270
self.request_sender
252271
.send(Request {
253272
block_id: self.id,
254-
cmd: RequestCmd::SetError(error),
273+
cmd: RequestCmd::SetError { error, restartable },
255274
})
256275
.error("Failed to send Request")
257276
}

src/config.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,15 @@ impl Default for SharedConfig {
6060
}
6161

6262
fn default_error_format() -> FormatConfig {
63-
" {$short_error_message|X} ".parse().unwrap()
63+
" {$restart_block_icon |}{$short_error_message|X} "
64+
.parse()
65+
.unwrap()
6466
}
6567

6668
fn default_error_fullscreen() -> FormatConfig {
67-
" $full_error_message ".parse().unwrap()
69+
" {$restart_block_icon |}$full_error_message "
70+
.parse()
71+
.unwrap()
6872
}
6973

7074
fn default_icons_format() -> Arc<String> {

src/icons.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ impl Default for Icons {
8484
"pomodoro_paused" => "PAUSED",
8585
"pomodoro_started" => "STARTED",
8686
"pomodoro_stopped" => "STOPPED",
87+
"refresh" => "REFRESH",
8788
"resolution" => "RES",
8889
"scratchpad" => "[]",
8990
"tasks" => "TSK",

src/lib.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use futures::stream::{FuturesUnordered, StreamExt as _};
3737
use tokio::process::Command;
3838
use tokio::sync::{Notify, mpsc};
3939

40-
use crate::blocks::{BlockAction, BlockError, CommonApi};
40+
use crate::blocks::{BlockAction, BlockError, CommonApi, RESTART_BLOCK_BTN};
4141
use crate::click::{ClickHandler, MouseButton};
4242
use crate::config::{BlockConfigEntry, Config, SharedConfig};
4343
use crate::errors::*;
@@ -131,7 +131,7 @@ struct Request {
131131
enum RequestCmd {
132132
SetWidget(Widget),
133133
UnsetWidget,
134-
SetError(Error),
134+
SetError { error: Error, restartable: bool },
135135
SetDefaultActions(&'static [(MouseButton, Option<&'static str>, &'static str)]),
136136
SubscribeToActions(mpsc::UnboundedSender<BlockAction>),
137137
}
@@ -186,6 +186,10 @@ impl Block {
186186
}
187187

188188
fn set_error(&mut self, fullscreen: bool, error: Error) {
189+
self.set_error_with_restartable(fullscreen, false, error);
190+
}
191+
192+
fn set_error_with_restartable(&mut self, fullscreen: bool, restartable: bool, error: Error) {
189193
let error = BlockError {
190194
block_id: self.id,
191195
block_name: self.name,
@@ -202,6 +206,7 @@ impl Block {
202206
widget.set_values(map! {
203207
"full_error_message" => Value::text(error.to_string()),
204208
[if let Some(v) = &error.error.message] "short_error_message" => Value::text(v.to_string()),
209+
[if restartable] "restart_block_icon" => Value::icon("refresh").with_instance(RESTART_BLOCK_BTN),
205210
});
206211
self.state = BlockState::Error { widget };
207212
}
@@ -326,8 +331,12 @@ impl BarState {
326331
self.fullscreen_block = None;
327332
}
328333
}
329-
RequestCmd::SetError(error) => {
330-
block.set_error(self.fullscreen_block == Some(request.block_id), error);
334+
RequestCmd::SetError { error, restartable } => {
335+
block.set_error_with_restartable(
336+
self.fullscreen_block == Some(request.block_id),
337+
restartable,
338+
error,
339+
);
331340
}
332341
RequestCmd::SetDefaultActions(actions) => {
333342
block.default_actions = actions;
@@ -415,16 +424,22 @@ impl BarState {
415424
}
416425
}
417426
BlockState::Error { widget } => {
418-
if self.fullscreen_block == Some(event.id) {
419-
self.fullscreen_block = None;
420-
widget.set_format(block.error_format.clone());
427+
if let Some((_, _, action)) = block.default_actions
428+
.iter()
429+
.find(|(btn, widget, _)| *btn == event.button && *widget == event.instance.as_deref()) {
430+
block.send_action(Cow::Borrowed(action));
421431
} else {
422-
self.fullscreen_block = Some(event.id);
423-
widget.set_format(block.error_fullscreen_format.clone());
432+
if self.fullscreen_block == Some(event.id) {
433+
self.fullscreen_block = None;
434+
widget.set_format(block.error_format.clone());
435+
} else {
436+
self.fullscreen_block = Some(event.id);
437+
widget.set_format(block.error_fullscreen_format.clone());
438+
}
439+
block.notify_intervals(&self.widget_updates_sender);
440+
self.render_block(event.id)?;
441+
self.render();
424442
}
425-
block.notify_intervals(&self.widget_updates_sender);
426-
self.render_block(event.id)?;
427-
self.render();
428443
}
429444
}
430445
}

0 commit comments

Comments
 (0)