diff --git a/demo/pomodoro.gif b/demo/pomodoro.gif index b49bf2c..2bb0bdb 100644 Binary files a/demo/pomodoro.gif and b/demo/pomodoro.gif differ diff --git a/demo/pomodoro.tape b/demo/pomodoro.tape index ef61760..4fec186 100644 --- a/demo/pomodoro.tape +++ b/demo/pomodoro.tape @@ -10,9 +10,8 @@ Set Padding 0 Set Margin 1 # --- START --- -Set LoopOffset 4 Hide -Type "cargo run -- -r -d -m p" +Type "cargo run -- -d -m p --blink on" Enter Sleep 0.2 Show @@ -25,7 +24,7 @@ Sleep 0.2 Down@30ms 80 Sleep 100ms Type "e" -Sleep 3 +Sleep 4 # --- POMODORO PAUSE --- Right Sleep 0.5 @@ -36,4 +35,4 @@ Sleep 0.2 Down@30ms 60 Sleep 100ms Type "e" -Sleep 3 +Sleep 4 diff --git a/src/app.rs b/src/app.rs index b1f9141..6ab323e 100644 --- a/src/app.rs +++ b/src/app.rs @@ -61,6 +61,7 @@ pub struct AppArgs { pub app_time_format: AppTimeFormat, pub content: Content, pub pomodoro_mode: PomodoroMode, + pub pomodoro_round: u64, pub initial_value_work: Duration, pub current_value_work: Duration, pub initial_value_pause: Duration, @@ -94,6 +95,7 @@ impl From for App { content: args.mode.unwrap_or(stg.content), style: args.style.unwrap_or(stg.style), pomodoro_mode: stg.pomodoro_mode, + pomodoro_round: stg.pomodoro_count, initial_value_work: args.work.unwrap_or(stg.inital_value_work), // invalidate `current_value_work` if an initial value is set via args current_value_work: args.work.unwrap_or(stg.current_value_work), @@ -142,6 +144,7 @@ impl App { content, with_decis, pomodoro_mode, + pomodoro_round, notification, blink, sound_path, @@ -183,6 +186,7 @@ impl App { initial_value_pause, current_value_pause, with_decis, + round: pomodoro_round, app_tx: app_tx.clone(), }), footer: FooterState::new(show_menu, app_time_format), @@ -359,6 +363,7 @@ impl App { style: self.style, with_decis: self.with_decis, pomodoro_mode: self.pomodoro.get_mode().clone(), + pomodoro_count: self.pomodoro.get_round(), inital_value_work: Duration::from(*self.pomodoro.get_clock_work().get_initial_value()), current_value_work: Duration::from(*self.pomodoro.get_clock_work().get_current_value()), inital_value_pause: Duration::from( diff --git a/src/storage.rs b/src/storage.rs index c2c0f3e..ff8796f 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -18,6 +18,7 @@ pub struct AppStorage { pub style: Style, pub with_decis: bool, pub pomodoro_mode: PomodoroMode, + pub pomodoro_count: u64, // pomodoro -> work pub inital_value_work: Duration, pub current_value_work: Duration, @@ -46,6 +47,7 @@ impl Default for AppStorage { style: Style::default(), with_decis: false, pomodoro_mode: PomodoroMode::Work, + pomodoro_count: 1, // pomodoro -> work inital_value_work: DEFAULT_WORK, current_value_work: DEFAULT_WORK, diff --git a/src/widgets/footer.rs b/src/widgets/footer.rs index b2a6e41..d9078b0 100644 --- a/src/widgets/footer.rs +++ b/src/widgets/footer.rs @@ -149,21 +149,25 @@ impl StatefulWidget for Footer { }), Span::from(SPACE), Span::from("[r]eset"), + ]; + if self.selected_content == Content::Pomodoro { + spans.extend_from_slice(&[ + Span::from(SPACE), + Span::from("[^r]eset round"), + Span::from(SPACE), + Span::from("[← →]switch work/pause"), + ]); + } + spans.extend_from_slice(&[ Span::from(SPACE), Span::from("[e]dit"), - ]; + ]); if self.selected_content == Content::Countdown { spans.extend_from_slice(&[ Span::from(SPACE), Span::from("[^e]dit by local time"), ]); } - if self.selected_content == Content::Pomodoro { - spans.extend_from_slice(&[ - Span::from(SPACE), - Span::from("[← →]switch work/pause"), - ]); - } spans } others => vec![ diff --git a/src/widgets/pomodoro.rs b/src/widgets/pomodoro.rs index 0ca0b3c..d32c6bf 100644 --- a/src/widgets/pomodoro.rs +++ b/src/widgets/pomodoro.rs @@ -5,6 +5,7 @@ use crate::{ utils::center, widgets::clock::{ClockState, ClockStateArgs, ClockWidget, Countdown}, }; +use crossterm::event::KeyModifiers; use ratatui::{ buffer::Buffer, crossterm::event::KeyCode, @@ -45,6 +46,7 @@ impl ClockMap { pub struct PomodoroState { mode: Mode, clock_map: ClockMap, + round: u64, } pub struct PomodoroStateArgs { @@ -55,6 +57,7 @@ pub struct PomodoroStateArgs { pub current_value_pause: Duration, pub with_decis: bool, pub app_tx: AppEventTx, + pub round: u64, } impl PomodoroState { @@ -67,6 +70,7 @@ impl PomodoroState { current_value_pause, with_decis, app_tx, + round, } = args; Self { mode, @@ -88,6 +92,7 @@ impl PomodoroState { }) .with_name("Pause".to_owned()), }, + round, } } @@ -111,6 +116,10 @@ impl PomodoroState { &self.mode } + pub fn get_round(&self) -> u64 { + self.round + } + pub fn set_with_decis(&mut self, with_decis: bool) { self.clock_map.work.with_decis = with_decis; self.clock_map.pause.with_decis = with_decis; @@ -158,7 +167,14 @@ impl TuiEventHandler for PomodoroState { KeyCode::Down if edit_mode => { self.get_clock_mut().edit_down(); } + KeyCode::Char('r') if key.modifiers.contains(KeyModifiers::CONTROL) => { + self.round = 1; + } KeyCode::Char('r') => { + // count number of finished rounds of WORK before resetting the clock + if self.get_mode() == &Mode::Work && self.get_clock().is_done() { + self.round += 1; + } self.get_clock_mut().reset(); } _ => return Some(event), @@ -186,6 +202,7 @@ impl StatefulWidget for PomodoroWidget { )) .to_uppercase(), ); + let label_round = Line::raw((format!("round {}", state.get_round(),)).to_uppercase()); let area = center( area, @@ -196,13 +213,18 @@ impl StatefulWidget for PomodoroWidget { ), label.width() as u16, )), - Constraint::Length(clock_widget.get_height() + 1 /* height of mode_str */), + Constraint::Length( + // height of `label` + `label_round` + clock_widget.get_height() + 2, + ), ); - let [v1, v2] = - Layout::vertical(Constraint::from_lengths([clock_widget.get_height(), 1])).areas(area); + let [v1, v2, v3] = + Layout::vertical(Constraint::from_lengths([clock_widget.get_height(), 1, 1])) + .areas(area); clock_widget.render(v1, buf, state.get_clock_mut()); label.centered().render(v2, buf); + label_round.centered().render(v3, buf); } }