diff --git a/src/app.rs b/src/app.rs index 579b00b..f53a058 100644 --- a/src/app.rs +++ b/src/app.rs @@ -224,6 +224,10 @@ impl App { } let task = &mut self.tasks[self.selected_task]; task.due = Some(due); + crate::log_msg(&format!( + "[task_app] TASK UPDATE: title=\"{}\" id={} due={}", + task.title, task.id, due + )); self.db.update_task(task).ok(); self.db.push_sync( SyncAction::Update, @@ -441,7 +445,25 @@ impl App { } KeyCode::Char('d') | KeyCode::Char('D') => { if !self.needs_auth { - self.show_popup = Some(Popup::ConfirmDelete); + let context = match self.focus { + Focus::Tabs => { + if self.selected_list < self.lists.len() { + format!("Delete list: \"{}\"?", self.lists[self.selected_list].title) + } else { + "Delete this list?".to_string() + } + } + _ => { + if !self.tasks.is_empty() && self.selected_task < self.tasks.len() { + let title = &self.tasks[self.selected_task].title; + let preview: String = title.chars().take(40).collect(); + format!("Delete task: \"{}\"?", preview) + } else { + "Delete this task?".to_string() + } + } + }; + self.show_popup = Some(Popup::ConfirmDelete { context }); } } KeyCode::Char('e') | KeyCode::Char('E') => { @@ -470,10 +492,15 @@ impl App { self.show_popup = Some(Popup::BulkAction); } else { let task = &mut self.tasks[self.selected_task]; + let old_status = task.status.clone(); task.status = match task.status { TaskStatus::Completed => TaskStatus::NeedsAction, TaskStatus::NeedsAction => TaskStatus::Completed, }; + crate::log_msg(&format!( + "[task_app] TASK UPDATE: title=\"{}\" id={} status={:?}->{:?}", + task.title, task.id, old_status, task.status + )); self.db.update_task(task).ok(); self.db.push_sync( SyncAction::Update, @@ -538,11 +565,15 @@ impl App { self.pending_bulk_move = false; self.bulk_move_to_new_list(&input); self.show_popup = None; - } else if !input.is_empty() { + } else if !input.is_empty() { let list = TaskList { id: uuid_v4(), title: input, }; + crate::log_msg(&format!( + "[task_app] LIST CREATE: title=\"{}\" id={}", + list.title, list.id + )); self.db.insert_list(&list).ok(); self.db.push_sync( SyncAction::CreateList, @@ -655,6 +686,10 @@ impl App { if let Some(d) = due { task.due = Some(d); } + crate::log_msg(&format!( + "[task_app] TASK UPDATE: title=\"{}\" id={} has_notes={} has_due={}", + task.title, task.id, task.notes.is_some(), task.due.is_some() + )); self.db.update_task(task).ok(); self.db.push_sync( SyncAction::Update, @@ -678,6 +713,10 @@ impl App { created_at: None, updated_at: None, }; + crate::log_msg(&format!( + "[task_app] TASK CREATE: title=\"{}\" id={} list={}", + task.title, task.id, list_id + )); self.db.insert_task(&task).ok(); self.db.push_sync( SyncAction::Create, @@ -783,6 +822,10 @@ impl App { if !self.tasks.is_empty() { let task = &mut self.tasks[self.selected_task]; task.due = Some(self.draft_date); + crate::log_msg(&format!( + "[task_app] TASK UPDATE: title=\"{}\" id={} due={}", + task.title, task.id, self.draft_date + )); self.db.update_task(task).ok(); self.db.push_sync( SyncAction::Update, @@ -803,7 +846,7 @@ impl App { } _ => {} }, - Popup::ConfirmDelete => match key.code { + Popup::ConfirmDelete { context: _ } => match key.code { KeyCode::Esc => { self.show_popup = None; } @@ -812,13 +855,18 @@ impl App { Focus::Tabs => { if self.selected_list < self.lists.len() { let list_id = self.lists[self.selected_list].id.clone(); + let title = self.lists[self.selected_list].title.clone(); self.db.delete_list(&list_id).ok(); - self.db.push_sync( - SyncAction::DeleteList, - &list_id, - &list_id, - "", - ).ok(); + self.db.push_sync( + SyncAction::DeleteList, + &list_id, + &list_id, + "", + ).ok(); + crate::log_msg(&format!( + "[task_app] LIST DELETE: title=\"{}\" id={}", + title, list_id + )); self.trigger_sync(); self.load_lists(); if self.selected_list >= self.lists.len() { @@ -832,6 +880,7 @@ impl App { let task = &self.tasks[self.selected_task]; let task_id = task.id.clone(); let list_id = task.list_id.clone(); + let title = task.title.clone(); self.db.delete_task(&task_id).ok(); if !list_id.contains('-') { self.db.push_sync( @@ -841,6 +890,10 @@ impl App { "", ).ok(); } + crate::log_msg(&format!( + "[task_app] TASK DELETE: title=\"{}\" id={} list={}", + title, task_id, list_id + )); self.trigger_sync(); self.load_tasks(); if self.selected_task >= self.tasks.len() { @@ -923,6 +976,10 @@ impl App { &serde_json::to_string(task).unwrap_or_default(), ).ok(); } + crate::log_msg(&format!( + "[task_app] BULK COMPLETED: {} tasks", + indices.len() + )); self.clear_selection(); self.trigger_sync(); self.load_tasks(); @@ -943,6 +1000,10 @@ impl App { &serde_json::to_string(task).unwrap_or_default(), ).ok(); } + crate::log_msg(&format!( + "[task_app] BULK DUE: {} tasks -> today", + indices.len() + )); self.clear_selection(); self.trigger_sync(); self.load_tasks(); @@ -1021,6 +1082,10 @@ impl App { &serde_json::to_string(task).unwrap_or_default(), ).ok(); } + crate::log_msg(&format!( + "[task_app] BULK UNCOMPLETE: {} tasks", + indices.len() + )); self.clear_selection(); self.trigger_sync(); self.load_tasks(); @@ -1043,6 +1108,10 @@ impl App { &serde_json::to_string(task).unwrap_or_default(), ).ok(); } + crate::log_msg(&format!( + "[task_app] BULK DUE: {} tasks -> tomorrow", + indices.len() + )); self.clear_selection(); self.trigger_sync(); self.load_tasks(); @@ -1065,6 +1134,10 @@ impl App { &serde_json::to_string(task).unwrap_or_default(), ).ok(); } + crate::log_msg(&format!( + "[task_app] BULK DUE: {} tasks -> next week", + indices.len() + )); self.clear_selection(); self.trigger_sync(); self.load_tasks(); @@ -1163,6 +1236,10 @@ impl App { let new_pos = self.tasks[new_index as usize].position; if self.db.reorder_task(&task_id, new_pos).is_ok() { + crate::log_msg(&format!( + "[task_app] TASK REORDER: id={} list={} new_pos={}", + task_id, list_id, new_pos + )); let payload = serde_json::json!({ "task_id": task_id, "new_position": new_pos diff --git a/src/main.rs b/src/main.rs index de3b00c..1427914 100644 --- a/src/main.rs +++ b/src/main.rs @@ -238,11 +238,21 @@ async fn run_initial_sync( Ok(lists) => { total_lists = lists.len(); for list in &lists { + log_msg(&format!( + "[task_app] LIST SYNC: title=\"{}\" id={}", + list.title, list.id + )); db.insert_list(list).ok(); } for list in &lists { if let Ok(tasks) = api.fetch_tasks(&list.id).await { total_tasks += tasks.len(); + log_msg(&format!( + "[task_app] TASK SYNC: {} tasks in list=\"{}\" id={}", + tasks.len(), + list.title, + list.id + )); db.replace_all_tasks(&list.id, &tasks).ok(); } } @@ -482,6 +492,10 @@ async fn pull_sync( Ok(lists) => { total_lists = lists.len(); for list in &lists { + log_msg(&format!( + "[task_app] LIST SYNC: title=\"{}\" id={}", + list.title, list.id + )); db.insert_list(list).ok(); } for list in &lists { @@ -493,10 +507,20 @@ async fn pull_sync( if let Ok(tasks) = result { total_tasks += tasks.len(); if use_incremental { + log_msg(&format!( + "[task_app] TASK SYNC (incremental): {} tasks in list=\"{}\"", + tasks.len(), + list.title + )); for task in &tasks { db.insert_task(task).ok(); } } else { + log_msg(&format!( + "[task_app] TASK SYNC (full): {} tasks in list=\"{}\"", + tasks.len(), + list.title + )); db.replace_all_tasks(&list.id, &tasks).ok(); } } diff --git a/src/ui/components.rs b/src/ui/components.rs index 6e4b7b1..e3a8315 100644 --- a/src/ui/components.rs +++ b/src/ui/components.rs @@ -477,8 +477,8 @@ pub fn render_date_picker( frame.render_widget(paragraph, popup_area); } -pub fn render_confirm_popup(frame: &mut Frame, area: Rect) { - let popup_area = centered_rect(50, 5, area); +pub fn render_confirm_popup(frame: &mut Frame, area: Rect, context: &str) { + let popup_area = centered_rect(60, 6, area); frame.render_widget(Clear, popup_area); let block = Block::default() .borders(Borders::ALL) @@ -490,7 +490,7 @@ pub fn render_confirm_popup(frame: &mut Frame, area: Rect) { let text = Text::from(vec![ Line::from(""), Line::from(Span::styled( - " Delete this item? ", + format!(" {} ", context), Style::default().fg(Color::Red).add_modifier(Modifier::BOLD), )), Line::from(""), diff --git a/src/ui/mod.rs b/src/ui/mod.rs index c0970f4..009e30e 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -22,7 +22,7 @@ pub enum Popup { Input, EditTask { field: usize }, DatePicker, - ConfirmDelete, + ConfirmDelete { context: String }, BulkAction, PickList, DeviceAuth { url: String, code: String }, @@ -129,7 +129,7 @@ pub fn draw(frame: &mut Frame, view: AppView) { view.notes_scroll, *field, ), Popup::DatePicker => render_date_picker(frame, area, view.draft_date), - Popup::ConfirmDelete => render_confirm_popup(frame, area), + Popup::ConfirmDelete { context } => render_confirm_popup(frame, area, context), Popup::BulkAction => render_bulk_action_popup(frame, area, view.selected_tasks.len(), view.bulk_action_selected), Popup::PickList => render_pick_list_popup(frame, area, view.popup_list_indices, view.popup_list_selected), Popup::DeviceAuth { url, code } => render_device_auth_popup(frame, area, url, code, view.auth_error),