timr-tui/src/common.rs
Jens Krause 3d9b235f12
Rust 1.85.0 + Rust 2024 Edition (#68)
- Add `rust-toolchain.toml`
- Refactor `flake` to consider `rust-toolchain.toml`, especially Rust version
- `just`: Add run-sound command
- Ignore sound files
- Format
2025-02-25 20:30:20 +01:00

208 lines
5.2 KiB
Rust

use clap::ValueEnum;
use ratatui::symbols::shade;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use time::format_description;
#[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(Clone, Debug)]
pub enum ClockTypeId {
Countdown,
Timer,
}
#[derive(Debug, Copy, Clone, ValueEnum, Default, Serialize, Deserialize)]
pub enum Style {
#[default]
#[value(name = "full", alias = "f")]
Full,
#[value(name = "light", alias = "l")]
Light,
#[value(name = "medium", alias = "m")]
Medium,
#[value(name = "dark", alias = "d")]
Dark,
#[value(name = "thick", alias = "t")]
Thick,
#[value(name = "cross", alias = "c")]
Cross,
// https://en.wikipedia.org/wiki/Braille_Patterns
// Note: Might not be supported in all terminals
// see https://docs.rs/ratatui/latest/src/ratatui/symbols.rs.html#150
#[value(name = "braille", alias = "b")]
Braille,
}
impl Style {
pub fn next(&self) -> Self {
match self {
Style::Full => Style::Dark,
Style::Dark => Style::Medium,
Style::Medium => Style::Light,
Style::Light => Style::Braille,
Style::Braille => Style::Thick,
Style::Thick => Style::Cross,
Style::Cross => Style::Full,
}
}
pub fn get_digit_symbol(&self) -> &str {
match &self {
Style::Full => shade::FULL,
Style::Light => shade::LIGHT,
Style::Medium => shade::MEDIUM,
Style::Dark => shade::DARK,
Style::Cross => "",
Style::Thick => "",
Style::Braille => "",
}
}
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub enum AppTimeFormat {
/// `hh:mm:ss`
#[default]
HhMmSs,
/// `hh:mm`
HhMm,
/// `hh:mm AM` (or PM)
Hh12Mm,
/// `` (empty)
Hidden,
}
impl AppTimeFormat {
pub fn next(&self) -> Self {
match self {
AppTimeFormat::HhMmSs => AppTimeFormat::HhMm,
AppTimeFormat::HhMm => AppTimeFormat::Hh12Mm,
AppTimeFormat::Hh12Mm => AppTimeFormat::Hidden,
AppTimeFormat::Hidden => AppTimeFormat::HhMmSs,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum AppTime {
Local(OffsetDateTime),
Utc(OffsetDateTime),
}
impl From<AppTime> for OffsetDateTime {
fn from(app_time: AppTime) -> Self {
match app_time {
AppTime::Local(t) => t,
AppTime::Utc(t) => t,
}
}
}
impl AppTime {
pub fn format(&self, app_format: &AppTimeFormat) -> String {
let parse_str = match app_format {
AppTimeFormat::HhMmSs => Some("[hour]:[minute]:[second]"),
AppTimeFormat::HhMm => Some("[hour]:[minute]"),
AppTimeFormat::Hh12Mm => Some("[hour repr:12 padding:none]:[minute] [period]"),
AppTimeFormat::Hidden => None,
};
if let Some(str) = parse_str {
format_description::parse(str)
.map_err(|_| "parse error")
.and_then(|fd| {
OffsetDateTime::from(*self)
.format(&fd)
.map_err(|_| "format error")
})
.unwrap_or_else(|e| e.to_string())
} else {
"".to_owned()
}
}
}
#[derive(Debug)]
pub enum AppEditMode {
None,
Clock,
Time,
}
#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Eq, Default, Serialize, Deserialize)]
pub enum Toggle {
#[value(name = "on")]
On,
#[default]
#[value(name = "off")]
Off,
}
#[cfg(test)]
mod tests {
use super::*;
use time::{Date, Month, PrimitiveDateTime, Time};
#[test]
fn test_format_app_time() {
let dt = PrimitiveDateTime::new(
Date::from_calendar_date(2025, Month::January, 6).unwrap(),
Time::from_hms(18, 6, 10).unwrap(),
)
.assume_utc();
// hh:mm:ss
assert_eq!(
AppTime::Utc(dt).format(&AppTimeFormat::HhMmSs),
"18:06:10",
"utc"
);
assert_eq!(
AppTime::Local(dt).format(&AppTimeFormat::HhMmSs),
"18:06:10",
"local"
);
// hh:mm
assert_eq!(
AppTime::Utc(dt).format(&AppTimeFormat::HhMm),
"18:06",
"utc"
);
assert_eq!(
AppTime::Local(dt).format(&AppTimeFormat::HhMm),
"18:06",
"local"
);
// hh:mm period
assert_eq!(
AppTime::Utc(dt).format(&AppTimeFormat::Hh12Mm),
"6:06 PM",
"utc"
);
assert_eq!(
AppTime::Local(dt).format(&AppTimeFormat::Hh12Mm),
"6:06 PM",
"local"
);
// hidden
assert_eq!(AppTime::Utc(dt).format(&AppTimeFormat::Hidden), "", "utc");
assert_eq!(
AppTime::Local(dt).format(&AppTimeFormat::Hidden),
"",
"local"
);
}
}