diff --git a/README.md b/README.md
index 14c72e9..0e255ff 100644
--- a/README.md
+++ b/README.md
@@ -129,10 +129,12 @@ Extra option (if `--features sound` is enabled by local build only):
| Key | Description |
| --- | --- |
-| Enter | apply changes |
+| s | save changes |
+| ^s | save initial value |
| Esc | skip changes |
| ← or → | change selection |
-| ↑ or ↓ | change values to go up or down |
+| ↑ | edit to go up |
+| ↓ | edit to go down |
**In `Pomodoro` screen only**
diff --git a/src/app.rs b/src/app.rs
index 4d4a416..ee6472a 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -414,7 +414,7 @@ impl StatefulWidget for AppWidget {
let [v0, v1, v2] = Layout::vertical([
Constraint::Length(1),
Constraint::Percentage(100),
- Constraint::Length(if state.footer.get_show_menu() { 4 } else { 1 }),
+ Constraint::Length(if state.footer.get_show_menu() { 5 } else { 1 }),
])
.areas(area);
diff --git a/src/widgets/clock.rs b/src/widgets/clock.rs
index d1449e6..07d4dbf 100644
--- a/src/widgets/clock.rs
+++ b/src/widgets/clock.rs
@@ -143,6 +143,10 @@ impl ClockState {
&self.initial_value
}
+ pub fn set_initial_value(&mut self, duration: DurationEx) {
+ self.initial_value = duration;
+ }
+
pub fn get_current_value(&self) -> &DurationEx {
&self.current_value
}
diff --git a/src/widgets/countdown.rs b/src/widgets/countdown.rs
index 83ac8d9..181dca7 100644
--- a/src/widgets/countdown.rs
+++ b/src/widgets/countdown.rs
@@ -162,6 +162,96 @@ impl TuiEventHandler for CountdownState {
edit_time.set_max_time(max_time);
}
}
+ // EDIT CLOCK mode
+ TuiEvent::Key(key) if self.is_clock_edit_mode() => match key.code {
+ // skip editing
+ KeyCode::Esc => {
+ // Important: set current value first
+ self.clock.set_current_value(*self.clock.get_prev_value());
+ // before toggling back to non-edit mode
+ self.clock.toggle_edit();
+ }
+ // Apply changes and set new initial value
+ KeyCode::Char('s') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ // toggle edit mode
+ self.clock.toggle_edit();
+ // set initial value
+ self.clock
+ .set_initial_value(*self.clock.get_current_value());
+ // always reset `elapsed_clock`
+ self.elapsed_clock.reset();
+ }
+ // Apply changes
+ KeyCode::Char('s') => {
+ // toggle edit mode
+ self.clock.toggle_edit();
+ // always reset `elapsed_clock`
+ self.elapsed_clock.reset();
+ }
+ KeyCode::Right => {
+ self.clock.edit_prev();
+ }
+ KeyCode::Left => {
+ self.clock.edit_next();
+ }
+ KeyCode::Up => {
+ self.clock.edit_up();
+ }
+ KeyCode::Down => {
+ self.clock.edit_down();
+ }
+ _ => return Some(event),
+ },
+ // EDIT LOCAL TIME mode
+ TuiEvent::Key(key) if self.is_time_edit_mode() => match key.code {
+ // skip editing
+ KeyCode::Esc => {
+ self.edit_time = None;
+ }
+ // Apply changes and set new initial value
+ KeyCode::Char('s') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ if let Some(edit_time) = &mut self.edit_time.clone() {
+ // Order matters:
+ // 1. update current value
+ self.edit_time_done(edit_time);
+ // 2. set initial value
+ self.clock
+ .set_initial_value(*self.clock.get_current_value());
+ }
+ // always reset `elapsed_clock`
+ self.elapsed_clock.reset();
+ }
+ // Apply changes of editing by local time
+ KeyCode::Char('s') => {
+ if let Some(edit_time) = &mut self.edit_time.clone() {
+ self.edit_time_done(edit_time)
+ }
+ // always reset `elapsed_clock`
+ self.elapsed_clock.reset();
+ }
+ // move edit position to the left
+ KeyCode::Left => {
+ // safe unwrap because we are in `is_time_edit_mode`
+ self.edit_time.as_mut().unwrap().next();
+ }
+ // move edit position to the right
+ KeyCode::Right => {
+ // safe unwrap because we are in `is_time_edit_mode`
+ self.edit_time.as_mut().unwrap().prev();
+ }
+ // Value up
+ KeyCode::Up => {
+ // safe unwrap because of previous check in `is_time_edit_mode`
+ self.edit_time.as_mut().unwrap().up();
+ }
+ // Value down
+ KeyCode::Down => {
+ // safe unwrap because of previous check in `is_time_edit_mode`
+ self.edit_time.as_mut().unwrap().down();
+ }
+ _ => return Some(event),
+ },
+ // default mode
TuiEvent::Key(key) => match key.code {
KeyCode::Char('r') => {
// reset both clocks to use intial values
@@ -187,23 +277,8 @@ impl TuiEventHandler for CountdownState {
self.edit_time_done(edit_time);
}
}
- // skip editing clock
- KeyCode::Esc if self.is_clock_edit_mode() => {
- // Important: set current value first
- self.clock.set_current_value(*self.clock.get_prev_value());
- // before toggling back to non-edit mode
- self.clock.toggle_edit();
- }
- // skip editing by local time
- KeyCode::Esc if self.is_time_edit_mode() => {
- self.edit_time = None;
- }
-
// Enter edit by local time mode
- KeyCode::Char('e')
- if key.modifiers.contains(KeyModifiers::CONTROL)
- && !self.is_time_edit_mode() =>
- {
+ KeyCode::Char('e') if key.modifiers.contains(KeyModifiers::CONTROL) => {
// set `edit_time`
self.edit_time = Some(EditTimeState::new(EditTimeStateArgs {
time: self.time_to_edit(),
@@ -216,9 +291,8 @@ impl TuiEventHandler for CountdownState {
self.elapsed_clock.toggle_pause();
}
}
-
- // Enter edit clock
- KeyCode::Char('e') if !self.is_clock_edit_mode() => {
+ // Enter edit clock mode
+ KeyCode::Char('e') => {
// toggle edit mode
self.clock.toggle_edit();
@@ -227,53 +301,6 @@ impl TuiEventHandler for CountdownState {
self.elapsed_clock.toggle_pause();
}
}
-
- // Apply changes of editing by local time
- KeyCode::Enter if self.is_time_edit_mode() => {
- if let Some(edit_time) = &mut self.edit_time.clone() {
- self.edit_time_done(edit_time)
- }
- // always reset `elapsed_clock`
- self.elapsed_clock.reset();
- }
-
- // Apply changes of editing clock
- // Note: Using Ctrl+e is deprecated, use Enter instead
- KeyCode::Enter if self.is_clock_edit_mode() => {
- // toggle edit mode
- self.clock.toggle_edit();
- // always reset `elapsed_clock`
- self.elapsed_clock.reset();
- }
-
- KeyCode::Left if self.is_clock_edit_mode() => {
- self.clock.edit_next();
- }
- KeyCode::Left if self.is_time_edit_mode() => {
- // safe unwrap because of previous check in `is_time_edit_mode`
- self.edit_time.as_mut().unwrap().next();
- }
- KeyCode::Right if self.is_clock_edit_mode() => {
- self.clock.edit_prev();
- }
- KeyCode::Right if self.is_time_edit_mode() => {
- // safe unwrap because of previous check in `is_time_edit_mode`
- self.edit_time.as_mut().unwrap().prev();
- }
- KeyCode::Up if self.is_clock_edit_mode() => {
- self.clock.edit_up();
- }
- KeyCode::Up if self.is_time_edit_mode() => {
- // safe unwrap because of previous check in `is_time_edit_mode`
- self.edit_time.as_mut().unwrap().up();
- }
- KeyCode::Down if self.is_clock_edit_mode() => {
- self.clock.edit_down();
- }
- KeyCode::Down if self.is_time_edit_mode() => {
- // safe unwrap because of previous check in `is_time_edit_mode`
- self.edit_time.as_mut().unwrap().down();
- }
_ => return Some(event),
},
_ => return Some(event),
diff --git a/src/widgets/footer.rs b/src/widgets/footer.rs
index b67ef12..de97cc8 100644
--- a/src/widgets/footer.rs
+++ b/src/widgets/footer.rs
@@ -112,62 +112,6 @@ impl StatefulWidget for Footer {
)),
Cell::from(Line::from(content_labels)),
]),
- // controls
- Row::new(vec![
- Cell::from(Span::styled(
- "controls",
- Style::default().add_modifier(Modifier::BOLD),
- )),
- Cell::from(Line::from({
- match self.app_edit_mode {
- AppEditMode::None => {
- let mut spans = vec![
- Span::from(if self.running_clock {
- "[s]top"
- } else {
- "[s]tart"
- }),
- 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"),
- ]);
- }
- spans
- }
- _ => vec![
- Span::from("[enter]apply changes"),
- Span::from(SPACE),
- Span::from("[esc]skip changes"),
- Span::from(SPACE),
- Span::from(format!(
- "[{} {}]edit selection",
- scrollbar::HORIZONTAL.begin,
- scrollbar::HORIZONTAL.end
- )), // ← →,
- Span::from(SPACE),
- Span::from(format!("[{}]edit up", scrollbar::VERTICAL.begin)), // ↑
- Span::from(SPACE),
- Span::from(format!("[{}]edit up", scrollbar::VERTICAL.end)), // ↓,
- ],
- }
- })),
- ]),
// appearance
Row::new(vec![
Cell::from(Span::styled(
@@ -188,6 +132,89 @@ impl StatefulWidget for Footer {
)),
])),
]),
+ // controls - 1. row
+ Row::new(vec![
+ Cell::from(Span::styled(
+ "controls",
+ Style::default().add_modifier(Modifier::BOLD),
+ )),
+ Cell::from(Line::from({
+ match self.app_edit_mode {
+ AppEditMode::None => {
+ let mut spans = vec![Span::from(if self.running_clock {
+ "[s]top"
+ } else {
+ "[s]tart"
+ })];
+ 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"),
+ ]);
+ }
+ spans.extend_from_slice(&[
+ 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"),
+ ]);
+ }
+ spans
+ }
+ _ => vec![
+ Span::from("[s]ave changes"),
+ Span::from(SPACE),
+ Span::from("[^s]ave initial value"),
+ Span::from(SPACE),
+ Span::from("[esc]skip changes"),
+ ],
+ }
+ })),
+ ]),
+ // controls - 2. row
+ Row::new(vec![
+ Cell::from(Line::from("")),
+ Cell::from(Line::from({
+ match self.app_edit_mode {
+ AppEditMode::None => {
+ let mut spans = vec![];
+ if self.selected_content == Content::Pomodoro {
+ spans.extend_from_slice(&[Span::from(
+ "[← →]switch work/pause",
+ )]);
+ }
+ spans
+ }
+ _ => vec![
+ Span::from(format!(
+ // ← →,
+ "[{} {}]change selection",
+ scrollbar::HORIZONTAL.begin,
+ scrollbar::HORIZONTAL.end
+ )),
+ Span::from(SPACE),
+ Span::from(format!(
+ // ↑
+ "[{}]edit up",
+ scrollbar::VERTICAL.begin
+ )),
+ Span::from(SPACE),
+ Span::from(format!(
+ // ↓
+ "[{}]edit up",
+ scrollbar::VERTICAL.end
+ )),
+ ],
+ }
+ })),
+ ]),
],
widths,
)
diff --git a/src/widgets/pomodoro.rs b/src/widgets/pomodoro.rs
index d5b0e8a..cc4fcc4 100644
--- a/src/widgets/pomodoro.rs
+++ b/src/widgets/pomodoro.rs
@@ -5,10 +5,9 @@ use crate::{
utils::center,
widgets::clock::{ClockState, ClockStateArgs, ClockWidget, Countdown},
};
-use crossterm::event::KeyModifiers;
+use crossterm::event::{KeyCode, KeyModifiers};
use ratatui::{
buffer::Buffer,
- crossterm::event::KeyCode,
layout::{Constraint, Layout, Rect},
text::Line,
widgets::{StatefulWidget, Widget},
@@ -141,46 +140,69 @@ impl TuiEventHandler for PomodoroState {
self.get_clock_mut().tick();
self.get_clock_mut().update_done_count();
}
+ // EDIT mode
+ TuiEvent::Key(key) if edit_mode => match key.code {
+ // Skip changes
+ KeyCode::Esc => {
+ let clock = self.get_clock_mut();
+ // Important: set current value first
+ clock.set_current_value(*clock.get_prev_value());
+ // before toggling back to non-edit mode
+ clock.toggle_edit();
+ }
+ // Apply changes and update initial value
+ KeyCode::Char('s') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ self.get_clock_mut().toggle_edit();
+ // update initial value
+ let c = *self.get_clock().get_current_value();
+ self.get_clock_mut().set_initial_value(c);
+ }
+ // Apply changes
+ KeyCode::Char('s') => {
+ self.get_clock_mut().toggle_edit();
+ }
+ // Value up
+ KeyCode::Up => {
+ self.get_clock_mut().edit_up();
+ }
+ // Value down
+ KeyCode::Down => {
+ self.get_clock_mut().edit_down();
+ }
+ // move edit position to the left
+ KeyCode::Left => {
+ self.get_clock_mut().edit_next();
+ }
+ // move edit position to the right
+ KeyCode::Right => {
+ self.get_clock_mut().edit_prev();
+ }
+ _ => return Some(event),
+ },
+ // default mode
TuiEvent::Key(key) => match key.code {
+ // Toggle run/pause
KeyCode::Char('s') => {
self.get_clock_mut().toggle_pause();
}
- // Skip changes
- KeyCode::Esc if edit_mode => {
- let clock = self.get_clock_mut();
- clock.toggle_edit();
- clock.set_current_value(*clock.get_prev_value());
- }
- // Apply changes
- KeyCode::Enter if edit_mode => {
- self.get_clock_mut().toggle_edit();
- }
// Enter edit mode
- KeyCode::Char('e') if !edit_mode => {
+ KeyCode::Char('e') => {
self.get_clock_mut().toggle_edit();
}
- KeyCode::Left if edit_mode => {
- self.get_clock_mut().edit_next();
- }
+ // toggle WORK/PAUSE
KeyCode::Left => {
- // `next` is acting as same as a `prev` function, we don't have
+ // `next` is acting as same as a "prev" function we don't have
self.next();
}
- KeyCode::Right if edit_mode => {
- self.get_clock_mut().edit_prev();
- }
+ // toggle WORK/PAUSE
KeyCode::Right => {
self.next();
}
- KeyCode::Up if edit_mode => {
- self.get_clock_mut().edit_up();
- }
- KeyCode::Down if edit_mode => {
- self.get_clock_mut().edit_down();
- }
+ // reset round
KeyCode::Char('r') if key.modifiers.contains(KeyModifiers::CONTROL) => {
self.round = 1;
}
+ // reset values
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() {
diff --git a/src/widgets/timer.rs b/src/widgets/timer.rs
index ac46bde..3d1ccdf 100644
--- a/src/widgets/timer.rs
+++ b/src/widgets/timer.rs
@@ -39,39 +39,53 @@ impl TuiEventHandler for TimerState {
self.clock.tick();
self.clock.update_done_count();
}
- TuiEvent::Key(key) => match key.code {
- KeyCode::Char('s') => {
- self.clock.toggle_pause();
- }
- KeyCode::Char('r') => {
- self.clock.reset();
- }
- KeyCode::Esc if edit_mode => {
+ // EDIT mode
+ TuiEvent::Key(key) if edit_mode => match key.code {
+ // Skip changes
+ KeyCode::Esc => {
// Important: set current value first
self.clock.set_current_value(*self.clock.get_prev_value());
// before toggling back to non-edit mode
self.clock.toggle_edit();
}
- KeyCode::Enter if edit_mode => {
+ // Apply changes
+ KeyCode::Char('s') => {
self.clock.toggle_edit();
}
- KeyCode::Char('e') if !edit_mode => {
- self.clock.toggle_edit();
- }
- KeyCode::Left if edit_mode => {
+ // move change position to the left
+ KeyCode::Left => {
self.clock.edit_next();
}
- KeyCode::Right if edit_mode => {
+ // move change position to the right
+ KeyCode::Right => {
self.clock.edit_prev();
}
- KeyCode::Up if edit_mode => {
+ // change value up
+ KeyCode::Up => {
self.clock.edit_up();
}
- KeyCode::Down if edit_mode => {
+ // change value down
+ KeyCode::Down => {
self.clock.edit_down();
}
_ => return Some(event),
},
+ // default mode
+ TuiEvent::Key(key) => match key.code {
+ // Toggle run/pause
+ KeyCode::Char('s') => {
+ self.clock.toggle_pause();
+ }
+ // reset clock
+ KeyCode::Char('r') => {
+ self.clock.reset();
+ }
+ // enter edit mode
+ KeyCode::Char('e') => {
+ self.clock.toggle_edit();
+ }
+ _ => return Some(event),
+ },
_ => return Some(event),
}
None