feat(countdown): persist elapsed time (#46)
This commit is contained in:
parent
c8af76c9e5
commit
9ea9f88266
11
src/app.rs
11
src/app.rs
@ -57,6 +57,7 @@ pub struct AppArgs {
|
|||||||
pub current_value_pause: Duration,
|
pub current_value_pause: Duration,
|
||||||
pub initial_value_countdown: Duration,
|
pub initial_value_countdown: Duration,
|
||||||
pub current_value_countdown: Duration,
|
pub current_value_countdown: Duration,
|
||||||
|
pub elapsed_value_countdown: Duration,
|
||||||
pub current_value_timer: Duration,
|
pub current_value_timer: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +81,7 @@ impl From<(Args, AppStorage)> for AppArgs {
|
|||||||
initial_value_countdown: args.countdown.unwrap_or(stg.inital_value_countdown),
|
initial_value_countdown: args.countdown.unwrap_or(stg.inital_value_countdown),
|
||||||
// invalidate `current_value_countdown` if an initial value is set via args
|
// invalidate `current_value_countdown` if an initial value is set via args
|
||||||
current_value_countdown: args.countdown.unwrap_or(stg.current_value_countdown),
|
current_value_countdown: args.countdown.unwrap_or(stg.current_value_countdown),
|
||||||
|
elapsed_value_countdown: stg.elapsed_value_countdown,
|
||||||
current_value_timer: stg.current_value_timer,
|
current_value_timer: stg.current_value_timer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,6 +106,7 @@ impl App {
|
|||||||
current_value_work,
|
current_value_work,
|
||||||
current_value_pause,
|
current_value_pause,
|
||||||
current_value_countdown,
|
current_value_countdown,
|
||||||
|
elapsed_value_countdown,
|
||||||
current_value_timer,
|
current_value_timer,
|
||||||
content,
|
content,
|
||||||
with_decis,
|
with_decis,
|
||||||
@ -115,12 +118,15 @@ impl App {
|
|||||||
app_time: get_app_time(),
|
app_time: get_app_time(),
|
||||||
style,
|
style,
|
||||||
with_decis,
|
with_decis,
|
||||||
countdown: CountdownState::new(ClockState::<clock::Countdown>::new(ClockStateArgs {
|
countdown: CountdownState::new(
|
||||||
|
ClockState::<clock::Countdown>::new(ClockStateArgs {
|
||||||
initial_value: initial_value_countdown,
|
initial_value: initial_value_countdown,
|
||||||
current_value: current_value_countdown,
|
current_value: current_value_countdown,
|
||||||
tick_value: Duration::from_millis(TICK_VALUE_MS),
|
tick_value: Duration::from_millis(TICK_VALUE_MS),
|
||||||
with_decis,
|
with_decis,
|
||||||
})),
|
}),
|
||||||
|
elapsed_value_countdown,
|
||||||
|
),
|
||||||
timer: TimerState::new(ClockState::<clock::Timer>::new(ClockStateArgs {
|
timer: TimerState::new(ClockState::<clock::Timer>::new(ClockStateArgs {
|
||||||
initial_value: Duration::ZERO,
|
initial_value: Duration::ZERO,
|
||||||
current_value: current_value_timer,
|
current_value: current_value_timer,
|
||||||
@ -247,6 +253,7 @@ impl App {
|
|||||||
current_value_countdown: Duration::from(
|
current_value_countdown: Duration::from(
|
||||||
*self.countdown.get_clock().get_current_value(),
|
*self.countdown.get_clock().get_current_value(),
|
||||||
),
|
),
|
||||||
|
elapsed_value_countdown: Duration::from(*self.countdown.get_elapsed_value()),
|
||||||
current_value_timer: Duration::from(*self.timer.get_clock().get_current_value()),
|
current_value_timer: Duration::from(*self.timer.get_clock().get_current_value()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ pub struct AppStorage {
|
|||||||
// countdown
|
// countdown
|
||||||
pub inital_value_countdown: Duration,
|
pub inital_value_countdown: Duration,
|
||||||
pub current_value_countdown: Duration,
|
pub current_value_countdown: Duration,
|
||||||
|
pub elapsed_value_countdown: Duration,
|
||||||
// timer
|
// timer
|
||||||
pub current_value_timer: Duration,
|
pub current_value_timer: Duration,
|
||||||
}
|
}
|
||||||
@ -50,6 +51,7 @@ impl Default for AppStorage {
|
|||||||
// countdown
|
// countdown
|
||||||
inital_value_countdown: DEFAULT_COUNTDOWN,
|
inital_value_countdown: DEFAULT_COUNTDOWN,
|
||||||
current_value_countdown: DEFAULT_COUNTDOWN,
|
current_value_countdown: DEFAULT_COUNTDOWN,
|
||||||
|
elapsed_value_countdown: Duration::ZERO,
|
||||||
// timer
|
// timer
|
||||||
current_value_timer: Duration::ZERO,
|
current_value_timer: Duration::ZERO,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,6 +91,27 @@ pub struct ClockStateArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ClockState<T> {
|
impl<T> ClockState<T> {
|
||||||
|
pub fn with_mode(mut self, mode: Mode) -> Self {
|
||||||
|
self.mode = mode;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mode(&self) -> &Mode {
|
||||||
|
&self.mode
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_initial(&self) -> bool {
|
||||||
|
self.mode == Mode::Initial
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self) {
|
||||||
|
self.mode = Mode::Tick
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_running(&self) -> bool {
|
||||||
|
self.mode == Mode::Tick
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toggle_pause(&mut self) {
|
pub fn toggle_pause(&mut self) {
|
||||||
self.mode = if self.mode == Mode::Tick {
|
self.mode = if self.mode == Mode::Tick {
|
||||||
Mode::Pause
|
Mode::Pause
|
||||||
@ -185,6 +206,7 @@ impl<T> ClockState<T> {
|
|||||||
};
|
};
|
||||||
self.update_format();
|
self.update_format();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit_current_down(&mut self) {
|
pub fn edit_current_down(&mut self) {
|
||||||
self.current_value = match self.mode {
|
self.current_value = match self.mode {
|
||||||
Mode::Editable(Time::Decis, _) => {
|
Mode::Editable(Time::Decis, _) => {
|
||||||
@ -203,22 +225,6 @@ impl<T> ClockState<T> {
|
|||||||
self.update_mode();
|
self.update_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mode(&self) -> &Mode {
|
|
||||||
&self.mode
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
|
||||||
self.mode = Mode::Tick
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_running(&self) -> bool {
|
|
||||||
self.mode == Mode::Tick
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_initial(&self) -> bool {
|
|
||||||
self.mode == Mode::Initial
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_edit_mode(&self) -> bool {
|
pub fn is_edit_mode(&self) -> bool {
|
||||||
matches!(self.mode, Mode::Editable(_, _))
|
matches!(self.mode, Mode::Editable(_, _))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,9 +10,10 @@ use std::{cmp::max, time::Duration};
|
|||||||
use crate::{
|
use crate::{
|
||||||
common::Style,
|
common::Style,
|
||||||
constants::TICK_VALUE_MS,
|
constants::TICK_VALUE_MS,
|
||||||
|
duration::DurationEx,
|
||||||
events::{Event, EventHandler},
|
events::{Event, EventHandler},
|
||||||
utils::center,
|
utils::center,
|
||||||
widgets::clock::{self, ClockState, ClockStateArgs, ClockWidget},
|
widgets::clock::{self, ClockState, ClockStateArgs, ClockWidget, Mode as ClockMode},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// State for Countdown Widget
|
/// State for Countdown Widget
|
||||||
@ -20,26 +21,34 @@ use crate::{
|
|||||||
pub struct CountdownState {
|
pub struct CountdownState {
|
||||||
/// clock to count down
|
/// clock to count down
|
||||||
clock: ClockState<clock::Countdown>,
|
clock: ClockState<clock::Countdown>,
|
||||||
/// clock to count up afterwards
|
/// clock to count time after `DONE` - similar to Mission Elapsed Time (MET)
|
||||||
timer: ClockState<clock::Timer>,
|
elapsed_clock: ClockState<clock::Timer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CountdownState {
|
impl CountdownState {
|
||||||
pub fn new(clock: ClockState<clock::Countdown>) -> Self {
|
pub fn new(clock: ClockState<clock::Countdown>, elapsed_value: Duration) -> Self {
|
||||||
Self {
|
Self {
|
||||||
clock,
|
clock,
|
||||||
timer: ClockState::<clock::Timer>::new(ClockStateArgs {
|
elapsed_clock: ClockState::<clock::Timer>::new(ClockStateArgs {
|
||||||
initial_value: Duration::ZERO,
|
initial_value: Duration::ZERO,
|
||||||
current_value: Duration::ZERO,
|
current_value: elapsed_value,
|
||||||
tick_value: Duration::from_millis(TICK_VALUE_MS),
|
tick_value: Duration::from_millis(TICK_VALUE_MS),
|
||||||
with_decis: false,
|
with_decis: false,
|
||||||
|
})
|
||||||
|
// A previous `elapsed_value > 0` means the `Clock` was running before,
|
||||||
|
// but not in `Initial` state anymore. Updating `Mode` here
|
||||||
|
// is needed to handle `Event::Tick` in `EventHandler::update` properly
|
||||||
|
.with_mode(if elapsed_value.gt(&Duration::ZERO) {
|
||||||
|
ClockMode::Pause
|
||||||
|
} else {
|
||||||
|
ClockMode::Initial
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_with_decis(&mut self, with_decis: bool) {
|
pub fn set_with_decis(&mut self, with_decis: bool) {
|
||||||
self.clock.with_decis = with_decis;
|
self.clock.with_decis = with_decis;
|
||||||
self.timer.with_decis = with_decis;
|
self.elapsed_clock.with_decis = with_decis;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_clock(&self) -> &ClockState<clock::Countdown> {
|
pub fn get_clock(&self) -> &ClockState<clock::Countdown> {
|
||||||
@ -47,7 +56,11 @@ impl CountdownState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_running(&self) -> bool {
|
pub fn is_running(&self) -> bool {
|
||||||
self.clock.is_running() || self.timer.is_running()
|
self.clock.is_running() || self.elapsed_clock.is_running()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_elapsed_value(&self) -> &DurationEx {
|
||||||
|
self.elapsed_clock.get_current_value()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,9 +72,9 @@ impl EventHandler for CountdownState {
|
|||||||
if !self.clock.is_done() {
|
if !self.clock.is_done() {
|
||||||
self.clock.tick();
|
self.clock.tick();
|
||||||
} else {
|
} else {
|
||||||
self.timer.tick();
|
self.elapsed_clock.tick();
|
||||||
if self.timer.is_initial() {
|
if self.elapsed_clock.is_initial() {
|
||||||
self.timer.run();
|
self.elapsed_clock.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,21 +82,21 @@ impl EventHandler for CountdownState {
|
|||||||
KeyCode::Char('r') => {
|
KeyCode::Char('r') => {
|
||||||
// reset both clocks
|
// reset both clocks
|
||||||
self.clock.reset();
|
self.clock.reset();
|
||||||
self.timer.reset();
|
self.elapsed_clock.reset();
|
||||||
}
|
}
|
||||||
KeyCode::Char('s') => {
|
KeyCode::Char('s') => {
|
||||||
// toggle pause status depending on who is running
|
// toggle pause status depending on which clock is running
|
||||||
if !self.clock.is_done() {
|
if !self.clock.is_done() {
|
||||||
self.clock.toggle_pause();
|
self.clock.toggle_pause();
|
||||||
} else {
|
} else {
|
||||||
self.timer.toggle_pause();
|
self.elapsed_clock.toggle_pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Char('e') => {
|
KeyCode::Char('e') => {
|
||||||
self.clock.toggle_edit();
|
self.clock.toggle_edit();
|
||||||
// stop + reset timer entering `edit` mode
|
// stop + reset timer entering `edit` mode
|
||||||
if self.timer.is_running() {
|
if self.elapsed_clock.is_running() {
|
||||||
self.timer.toggle_pause();
|
self.elapsed_clock.toggle_pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Left if edit_mode => {
|
KeyCode::Left if edit_mode => {
|
||||||
@ -94,13 +107,13 @@ impl EventHandler for CountdownState {
|
|||||||
}
|
}
|
||||||
KeyCode::Up if edit_mode => {
|
KeyCode::Up if edit_mode => {
|
||||||
self.clock.edit_up();
|
self.clock.edit_up();
|
||||||
// whenever clock value is changed, reset timer
|
// whenever `clock`'s value is changed, reset `elapsed_clock`
|
||||||
self.timer.reset();
|
self.elapsed_clock.reset();
|
||||||
}
|
}
|
||||||
KeyCode::Down if edit_mode => {
|
KeyCode::Down if edit_mode => {
|
||||||
self.clock.edit_down();
|
self.clock.edit_down();
|
||||||
// whenever clock value is changed, reset timer
|
// whenever clock value is changed, reset timer
|
||||||
self.timer.reset();
|
self.elapsed_clock.reset();
|
||||||
}
|
}
|
||||||
_ => return Some(event),
|
_ => return Some(event),
|
||||||
},
|
},
|
||||||
@ -125,13 +138,16 @@ impl StatefulWidget for Countdown {
|
|||||||
format!(
|
format!(
|
||||||
"Countdown {} +{}",
|
"Countdown {} +{}",
|
||||||
state.clock.get_mode(),
|
state.clock.get_mode(),
|
||||||
state.timer.get_current_value().to_string_with_decis()
|
state
|
||||||
|
.elapsed_clock
|
||||||
|
.get_current_value()
|
||||||
|
.to_string_with_decis()
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"Countdown {} +{}",
|
"Countdown {} +{}",
|
||||||
state.clock.get_mode(),
|
state.clock.get_mode(),
|
||||||
state.timer.get_current_value()
|
state.elapsed_clock.get_current_value()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user