feat(countdown): rocket countdown (#45)
This commit is contained in:
@@ -207,10 +207,18 @@ impl<T> ClockState<T> {
|
||||
&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 {
|
||||
matches!(self.mode, Mode::Editable(_, _))
|
||||
}
|
||||
@@ -294,6 +302,10 @@ impl<T> ClockState<T> {
|
||||
self.update_format();
|
||||
}
|
||||
|
||||
pub fn is_done(&self) -> bool {
|
||||
self.mode == Mode::Done
|
||||
}
|
||||
|
||||
fn update_format(&mut self) {
|
||||
self.format = self.get_format();
|
||||
}
|
||||
|
||||
@@ -5,32 +5,50 @@ use ratatui::{
|
||||
text::Line,
|
||||
widgets::{StatefulWidget, Widget},
|
||||
};
|
||||
use std::cmp::max;
|
||||
use std::{cmp::max, time::Duration};
|
||||
|
||||
use crate::{
|
||||
common::Style,
|
||||
constants::TICK_VALUE_MS,
|
||||
events::{Event, EventHandler},
|
||||
utils::center,
|
||||
widgets::clock::{self, ClockState, ClockWidget},
|
||||
widgets::clock::{self, ClockState, ClockStateArgs, ClockWidget},
|
||||
};
|
||||
|
||||
/// State for Countdown Widget
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CountdownState {
|
||||
/// clock to count down
|
||||
clock: ClockState<clock::Countdown>,
|
||||
/// clock to count up afterwards
|
||||
timer: ClockState<clock::Timer>,
|
||||
}
|
||||
|
||||
impl CountdownState {
|
||||
pub const fn new(clock: ClockState<clock::Countdown>) -> Self {
|
||||
Self { clock }
|
||||
pub fn new(clock: ClockState<clock::Countdown>) -> Self {
|
||||
Self {
|
||||
clock,
|
||||
timer: ClockState::<clock::Timer>::new(ClockStateArgs {
|
||||
initial_value: Duration::ZERO,
|
||||
current_value: Duration::ZERO,
|
||||
tick_value: Duration::from_millis(TICK_VALUE_MS),
|
||||
with_decis: false,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_with_decis(&mut self, with_decis: bool) {
|
||||
self.clock.with_decis = with_decis;
|
||||
self.timer.with_decis = with_decis;
|
||||
}
|
||||
|
||||
pub fn get_clock(&self) -> &ClockState<clock::Countdown> {
|
||||
&self.clock
|
||||
}
|
||||
|
||||
pub fn is_running(&self) -> bool {
|
||||
self.clock.is_running() || self.timer.is_running()
|
||||
}
|
||||
}
|
||||
|
||||
impl EventHandler for CountdownState {
|
||||
@@ -38,20 +56,35 @@ impl EventHandler for CountdownState {
|
||||
let edit_mode = self.clock.is_edit_mode();
|
||||
match event {
|
||||
Event::Tick => {
|
||||
self.clock.tick();
|
||||
}
|
||||
Event::Key(key) if key.code == KeyCode::Char('r') => {
|
||||
self.clock.reset();
|
||||
if !self.clock.is_done() {
|
||||
self.clock.tick();
|
||||
} else {
|
||||
self.timer.tick();
|
||||
if self.timer.is_initial() {
|
||||
self.timer.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::Key(key) => match key.code {
|
||||
KeyCode::Char('r') => {
|
||||
// reset both clocks
|
||||
self.clock.reset();
|
||||
self.timer.reset();
|
||||
}
|
||||
KeyCode::Char('s') => {
|
||||
self.clock.toggle_pause();
|
||||
// toggle pause status depending on who is running
|
||||
if !self.clock.is_done() {
|
||||
self.clock.toggle_pause();
|
||||
} else {
|
||||
self.timer.toggle_pause();
|
||||
}
|
||||
}
|
||||
KeyCode::Char('e') => {
|
||||
self.clock.toggle_edit();
|
||||
// stop + reset timer entering `edit` mode
|
||||
if self.timer.is_running() {
|
||||
self.timer.toggle_pause();
|
||||
}
|
||||
}
|
||||
KeyCode::Left if edit_mode => {
|
||||
self.clock.edit_next();
|
||||
@@ -61,9 +94,13 @@ impl EventHandler for CountdownState {
|
||||
}
|
||||
KeyCode::Up if edit_mode => {
|
||||
self.clock.edit_up();
|
||||
// whenever clock value is changed, reset timer
|
||||
self.timer.reset();
|
||||
}
|
||||
KeyCode::Down if edit_mode => {
|
||||
self.clock.edit_down();
|
||||
// whenever clock value is changed, reset timer
|
||||
self.timer.reset();
|
||||
}
|
||||
_ => return Some(event),
|
||||
},
|
||||
@@ -81,7 +118,27 @@ impl StatefulWidget for Countdown {
|
||||
type State = CountdownState;
|
||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||
let clock = ClockWidget::new(self.style);
|
||||
let label = Line::raw((format!("Countdown {}", state.clock.get_mode())).to_uppercase());
|
||||
|
||||
let label = Line::raw(
|
||||
if state.clock.is_done() {
|
||||
if state.clock.with_decis {
|
||||
format!(
|
||||
"Countdown {} +{}",
|
||||
state.clock.get_mode(),
|
||||
state.timer.get_current_value().to_string_with_decis()
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"Countdown {} +{}",
|
||||
state.clock.get_mode(),
|
||||
state.timer.get_current_value()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
format!("Countdown {}", state.clock.get_mode())
|
||||
}
|
||||
.to_uppercase(),
|
||||
);
|
||||
|
||||
let area = center(
|
||||
area,
|
||||
|
||||
Reference in New Issue
Block a user