From fa03a30a313cfcba30b844930cb713383ac17ffa Mon Sep 17 00:00:00 2001 From: Ruben Rosario Date: Sun, 21 Jun 2026 17:05:01 +0100 Subject: [PATCH] Add vertical scroll to Notes field in EditTask popup - Added notes_scroll to App and AppView - Up/Down in Notes field scrolls (Tab cycles fields instead) - Reset scroll on opening EditTask popup - Notes Paragraph uses .scroll((notes_scroll, 0)) --- src/app.rs | 25 +++++++++++++++++++++---- src/main.rs | 1 + src/ui/components.rs | 4 +++- src/ui/mod.rs | 4 +++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/app.rs b/src/app.rs index d548efd..7d1232d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -37,6 +37,7 @@ pub struct App { pub should_quit: bool, pub task_list_scroll: u16, pub detail_scroll: u16, + pub notes_scroll: u16, pub db: Arc, #[allow(dead_code)] pub api_client: Arc, @@ -104,6 +105,7 @@ impl App { should_quit: false, task_list_scroll: 0, detail_scroll: 0, + notes_scroll: 0, db, api_client, needs_auth: !has_token, @@ -347,6 +349,7 @@ impl App { self.popup_secondary.clear(); self.popup_secondary_cursor = 0; self.edit_field = 0; + self.notes_scroll = 0; self.show_popup = Some(Popup::EditTask { field: 0 }); } } @@ -365,6 +368,7 @@ impl App { self.popup_secondary = task.notes.clone().unwrap_or_default(); self.popup_secondary_cursor = self.popup_secondary.len(); self.edit_field = 0; + self.notes_scroll = 0; self.show_popup = Some(Popup::EditTask { field: 0 }); } } @@ -500,15 +504,28 @@ impl App { self.editing_task_id = None; self.show_popup = None; } - KeyCode::Tab | KeyCode::Down => { + KeyCode::Tab => { let new_field = (field + 1) % 5; self.edit_field = new_field; self.show_popup = Some(Popup::EditTask { field: new_field }); } + KeyCode::Down => { + if *field == 1 { + self.notes_scroll = self.notes_scroll.saturating_add(1); + } else { + let new_field = (field + 1) % 5; + self.edit_field = new_field; + self.show_popup = Some(Popup::EditTask { field: new_field }); + } + } KeyCode::Up => { - let new_field = (field + 4) % 5; - self.edit_field = new_field; - self.show_popup = Some(Popup::EditTask { field: new_field }); + if *field == 1 { + self.notes_scroll = self.notes_scroll.saturating_sub(1); + } else { + let new_field = (field + 4) % 5; + self.edit_field = new_field; + self.show_popup = Some(Popup::EditTask { field: new_field }); + } } KeyCode::Enter => { let title = self.popup_input.trim().to_string(); diff --git a/src/main.rs b/src/main.rs index b35893c..d28e6d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,6 +141,7 @@ fn main() -> io::Result<()> { network_status: &app.network_status, task_list_scroll: app.task_list_scroll, detail_scroll: app.detail_scroll, + notes_scroll: app.notes_scroll, auth_error: app.auth_error.as_deref(), sync_stats: &app.sync_stats, }; diff --git a/src/ui/components.rs b/src/ui/components.rs index 038efb0..925efac 100644 --- a/src/ui/components.rs +++ b/src/ui/components.rs @@ -326,6 +326,7 @@ pub fn render_edit_task_popup( title_cursor: usize, notes: &str, notes_cursor: usize, + notes_scroll: u16, active_field: usize, ) { let popup_area = centered_rect(75, 14, area); @@ -382,7 +383,8 @@ pub fn render_edit_task_popup( let notes_lines: Vec = notes.lines().map(|l| Line::from(Span::raw(l.to_string()))).collect(); let notes_para = Paragraph::new(Text::from(notes_lines)) .block(notes_block) - .wrap(Wrap { trim: false }); + .wrap(Wrap { trim: false }) + .scroll((notes_scroll, 0)); frame.render_widget(notes_para, rows[2]); // ── Date buttons row ── diff --git a/src/ui/mod.rs b/src/ui/mod.rs index b48d7e5..e87673c 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -45,6 +45,7 @@ pub struct AppView<'a> { pub network_status: &'a NetworkStatus, pub task_list_scroll: u16, pub detail_scroll: u16, + pub notes_scroll: u16, pub auth_error: Option<&'a str>, pub sync_stats: &'a SyncStats, } @@ -99,7 +100,8 @@ pub fn draw(frame: &mut Frame, view: AppView) { Popup::Input => render_input_popup(frame, area, view.popup_input, view.popup_cursor), Popup::EditTask { field } => render_edit_task_popup( frame, area, view.popup_input, view.popup_cursor, - view.popup_secondary, view.popup_secondary_cursor, *field, + view.popup_secondary, view.popup_secondary_cursor, + view.notes_scroll, *field, ), Popup::DatePicker => render_date_picker(frame, area, view.draft_date), Popup::ConfirmDelete => render_confirm_popup(frame, area),