replace string settings with typed enums

- preserve local wall-time handling and import completion timestamps
- validate invalid properties without overwriting items
This commit is contained in:
Chili Palmer
2026-08-19 21:44:10 +02:00
parent 1f9f00ae7a
commit a6b38af396
7 changed files with 494 additions and 239 deletions

View File

@@ -12,7 +12,7 @@ use ratatui::{
use crate::{
app::{App, FormKind, InputKind, Mode, form_choices},
filter,
model::{Item, ViewColumn},
model::{Aggregate, Item, ViewColumn, ViewKind},
parser::format_when,
};
@@ -232,7 +232,7 @@ fn draw_items(frame: &mut Frame<'_>, app: &mut App, area: Rect) {
);
return;
}
if app.current_view().kind == "datebook" {
if app.current_view().kind == ViewKind::Datebook {
draw_datebook(frame, app, area);
return;
}
@@ -261,7 +261,7 @@ fn draw_items(frame: &mut Frame<'_>, app: &mut App, area: Rect) {
for index in 0..app.items.len() {
display.push(DisplayLine::Item(index));
}
if columns.iter().any(|c| c.aggregate != "none") {
if columns.iter().any(|c| c.aggregate != Aggregate::None) {
display.push(DisplayLine::Aggregate((0..app.items.len()).collect()));
}
} else {
@@ -285,7 +285,7 @@ fn draw_items(frame: &mut Frame<'_>, app: &mut App, area: Rect) {
for index in &indices {
display.push(DisplayLine::Item(*index));
}
if columns.iter().any(|c| c.aggregate != "none") {
if columns.iter().any(|c| c.aggregate != Aggregate::None) {
display.push(DisplayLine::Aggregate(indices));
}
}
@@ -448,10 +448,10 @@ fn column_value(column: &ViewColumn, item: &Item, app: &App) -> String {
}
}
fn aggregate_value(column: &ViewColumn, indices: &[usize], items: &[Item], app: &App) -> String {
if column.aggregate == "none" {
if column.aggregate == Aggregate::None {
return String::new();
}
if column.aggregate == "count" {
if column.aggregate == Aggregate::Count {
return format!("count {}", indices.len());
}
let values = indices
@@ -465,12 +465,12 @@ fn aggregate_value(column: &ViewColumn, indices: &[usize], items: &[Item], app:
if values.is_empty() {
return String::new();
}
let value = match column.aggregate.as_str() {
"sum" => values.iter().sum(),
"avg" => values.iter().sum::<f64>() / values.len() as f64,
"min" => values.iter().copied().fold(f64::INFINITY, f64::min),
"max" => values.iter().copied().fold(f64::NEG_INFINITY, f64::max),
_ => return String::new(),
let value = match column.aggregate {
Aggregate::Sum => values.iter().sum(),
Aggregate::Average => values.iter().sum::<f64>() / values.len() as f64,
Aggregate::Minimum => values.iter().copied().fold(f64::INFINITY, f64::min),
Aggregate::Maximum => values.iter().copied().fold(f64::NEG_INFINITY, f64::max),
Aggregate::None | Aggregate::Count => return String::new(),
};
format!("{} {}", column.aggregate, format_number(value, app))
}
@@ -1787,7 +1787,7 @@ mod tests {
let mut db = Database::open(&path).unwrap();
let mut settings = db.document_settings().unwrap();
settings.note_tab_width = 3;
settings.trash_policy = "immediate".into();
settings.trash_policy = crate::model::TrashPolicy::Immediate;
db.save_document_settings(&settings).unwrap();
db.add_item("Disposable item").unwrap();
let mut app = App::new_with_preferences(