Persist app state (#21)
This commit is contained in:
120
src/app.rs
120
src/app.rs
@@ -1,17 +1,19 @@
|
||||
use crate::{
|
||||
args::{Args, ClockStyle, Content},
|
||||
args::Args,
|
||||
constants::TICK_VALUE_MS,
|
||||
events::{Event, EventHandler, Events},
|
||||
storage::AppStorage,
|
||||
terminal::Terminal,
|
||||
widgets::{
|
||||
clock::{self, Clock, ClockArgs},
|
||||
clock::{self, Clock, ClockArgs, Style},
|
||||
countdown::{Countdown, CountdownWidget},
|
||||
footer::Footer,
|
||||
header::Header,
|
||||
pomodoro::{Pomodoro, PomodoroArgs, PomodoroWidget},
|
||||
pomodoro::{Mode as PomodoroMode, Pomodoro, PomodoroArgs, PomodoroWidget},
|
||||
timer::{Timer, TimerWidget},
|
||||
},
|
||||
};
|
||||
use clap::ValueEnum;
|
||||
use color_eyre::Result;
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
@@ -19,9 +21,23 @@ use ratatui::{
|
||||
layout::{Constraint, Layout, Rect},
|
||||
widgets::{StatefulWidget, Widget},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use tracing::debug;
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Default, Serialize, Deserialize,
|
||||
)]
|
||||
pub enum Content {
|
||||
#[default]
|
||||
#[value(name = "countdown", alias = "c")]
|
||||
Countdown,
|
||||
#[value(name = "timer", alias = "t")]
|
||||
Timer,
|
||||
#[value(name = "pomodoro", alias = "p")]
|
||||
Pomodoro,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum Mode {
|
||||
Running,
|
||||
@@ -36,49 +52,92 @@ pub struct App {
|
||||
countdown: Countdown,
|
||||
timer: Timer,
|
||||
pomodoro: Pomodoro,
|
||||
clock_style: ClockStyle,
|
||||
style: Style,
|
||||
with_decis: bool,
|
||||
}
|
||||
|
||||
pub struct AppArgs {
|
||||
pub style: Style,
|
||||
pub with_decis: bool,
|
||||
pub content: Content,
|
||||
pub pomodoro_mode: PomodoroMode,
|
||||
pub initial_value_work: Duration,
|
||||
pub current_value_work: Duration,
|
||||
pub initial_value_pause: Duration,
|
||||
pub current_value_pause: Duration,
|
||||
pub initial_value_countdown: Duration,
|
||||
pub current_value_countdown: Duration,
|
||||
pub current_value_timer: Duration,
|
||||
}
|
||||
|
||||
/// Getting `AppArgs` by merging `Args` and `AppStorage`.
|
||||
/// `Args` wins btw.
|
||||
impl From<(Args, AppStorage)> for AppArgs {
|
||||
fn from((args, stg): (Args, AppStorage)) -> Self {
|
||||
AppArgs {
|
||||
with_decis: args.decis || stg.with_decis,
|
||||
content: args.mode.unwrap_or(stg.content),
|
||||
style: args.style.unwrap_or(stg.style),
|
||||
pomodoro_mode: stg.pomodoro_mode,
|
||||
initial_value_work: args.work.unwrap_or(stg.inital_value_work),
|
||||
current_value_work: stg.current_value_work,
|
||||
initial_value_pause: args.pause,
|
||||
current_value_pause: stg.current_value_pause,
|
||||
initial_value_countdown: args.countdown,
|
||||
current_value_countdown: stg.current_value_countdown,
|
||||
current_value_timer: stg.current_value_timer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(args: Args) -> Self {
|
||||
let Args {
|
||||
pub fn new(args: AppArgs) -> Self {
|
||||
let AppArgs {
|
||||
style,
|
||||
work: work_initial_value,
|
||||
pause: pause_initial_value,
|
||||
mode: content,
|
||||
countdown: countdown_initial_value,
|
||||
decis: with_decis,
|
||||
..
|
||||
initial_value_work,
|
||||
initial_value_pause,
|
||||
initial_value_countdown,
|
||||
current_value_work,
|
||||
current_value_pause,
|
||||
current_value_countdown,
|
||||
current_value_timer,
|
||||
content,
|
||||
with_decis,
|
||||
pomodoro_mode,
|
||||
} = args;
|
||||
Self {
|
||||
mode: Mode::Running,
|
||||
content,
|
||||
show_menu: false,
|
||||
clock_style: style,
|
||||
style,
|
||||
with_decis,
|
||||
countdown: Countdown::new(Clock::<clock::Countdown>::new(ClockArgs {
|
||||
initial_value: countdown_initial_value,
|
||||
initial_value: initial_value_countdown,
|
||||
current_value: current_value_countdown,
|
||||
tick_value: Duration::from_millis(TICK_VALUE_MS),
|
||||
style,
|
||||
with_decis,
|
||||
})),
|
||||
timer: Timer::new(Clock::<clock::Timer>::new(ClockArgs {
|
||||
initial_value: Duration::ZERO,
|
||||
current_value: current_value_timer,
|
||||
tick_value: Duration::from_millis(TICK_VALUE_MS),
|
||||
style,
|
||||
with_decis,
|
||||
})),
|
||||
pomodoro: Pomodoro::new(PomodoroArgs {
|
||||
work: work_initial_value,
|
||||
pause: pause_initial_value,
|
||||
mode: pomodoro_mode,
|
||||
initial_value_work,
|
||||
current_value_work,
|
||||
initial_value_pause,
|
||||
current_value_pause,
|
||||
style,
|
||||
with_decis,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&mut self, mut terminal: Terminal, mut events: Events) -> Result<()> {
|
||||
pub async fn run(mut self, mut terminal: Terminal, mut events: Events) -> Result<Self> {
|
||||
while self.is_running() {
|
||||
if let Some(event) = events.next().await {
|
||||
// Pipe events into subviews and handle only 'unhandled' events afterwards
|
||||
@@ -97,7 +156,7 @@ impl App {
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn is_running(&self) -> bool {
|
||||
@@ -113,11 +172,11 @@ impl App {
|
||||
KeyCode::Char('p') => self.content = Content::Pomodoro,
|
||||
KeyCode::Char('m') => self.show_menu = !self.show_menu,
|
||||
KeyCode::Char(',') => {
|
||||
self.clock_style = self.clock_style.next();
|
||||
self.style = self.style.next();
|
||||
// update clocks
|
||||
self.timer.set_style(self.clock_style);
|
||||
self.countdown.set_style(self.clock_style);
|
||||
self.pomodoro.set_style(self.clock_style);
|
||||
self.timer.set_style(self.style);
|
||||
self.countdown.set_style(self.style);
|
||||
self.pomodoro.set_style(self.style);
|
||||
}
|
||||
KeyCode::Char('.') => {
|
||||
self.with_decis = !self.with_decis;
|
||||
@@ -138,6 +197,23 @@ impl App {
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn to_storage(&self) -> AppStorage {
|
||||
AppStorage {
|
||||
content: self.content,
|
||||
show_menu: self.show_menu,
|
||||
style: self.style,
|
||||
with_decis: self.with_decis,
|
||||
pomodoro_mode: self.pomodoro.get_mode().clone(),
|
||||
inital_value_work: self.pomodoro.get_clock_work().initial_value,
|
||||
current_value_work: self.pomodoro.get_clock_work().current_value,
|
||||
inital_value_pause: self.pomodoro.get_clock_pause().initial_value,
|
||||
current_value_pause: self.pomodoro.get_clock_pause().current_value,
|
||||
inital_value_countdown: self.countdown.get_clock().initial_value,
|
||||
current_value_countdown: self.countdown.get_clock().current_value,
|
||||
current_value_timer: self.timer.get_clock().current_value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AppWidget;
|
||||
|
||||
Reference in New Issue
Block a user