From d0a5b3026965db8796f8416675d2b4ac099e23a3 Mon Sep 17 00:00:00 2001 From: jooaf Date: Tue, 7 Jan 2025 00:05:26 -0600 Subject: [PATCH] adding fix for full screen mode scrolling --- Cargo.lock | 2 +- src/lib.rs | 1 + src/markdown_renderer.rs | 6 +++-- src/scrollable_textarea.rs | 49 ++++++++++++++++++++++++++++++++++---- src/ui_handler.rs | 20 ++++++++++++++-- 5 files changed, 69 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b735a1..0b6b5ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1412,7 +1412,7 @@ dependencies = [ [[package]] name = "thoth-cli" -version = "0.1.70" +version = "0.1.71" dependencies = [ "anyhow", "arboard", diff --git a/src/lib.rs b/src/lib.rs index 72334ca..ceabe65 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,3 +28,4 @@ pub fn get_save_backup_file_path() -> PathBuf { pub const ORANGE: ratatui::style::Color = ratatui::style::Color::Rgb(255, 165, 0); pub const DAEMONIZE_ARG: &str = "__thoth_copy_daemonize"; +pub const MIN_TEXTAREA_HEIGHT: usize = 3; diff --git a/src/markdown_renderer.rs b/src/markdown_renderer.rs index ec01a7a..1a89157 100644 --- a/src/markdown_renderer.rs +++ b/src/markdown_renderer.rs @@ -257,6 +257,8 @@ fn into_span((style, text): (SyntectStyle, &str)) -> Span<'static> { #[cfg(test)] mod tests { + use crate::MIN_TEXTAREA_HEIGHT; + use super::*; #[test] @@ -267,7 +269,7 @@ mod tests { .render_markdown(markdown.to_string(), "".to_string(), 40) .unwrap(); - assert!(rendered.lines.len() >= 3); + assert!(rendered.lines.len() >= MIN_TEXTAREA_HEIGHT); assert!(rendered.lines[0] .spans .iter() @@ -337,7 +339,7 @@ mod tests { .render_markdown(markdown, "".to_string(), 40) .unwrap(); - assert!(rendered.lines.len() > 3); + assert!(rendered.lines.len() > MIN_TEXTAREA_HEIGHT); assert!(rendered.lines[0] .spans .iter() diff --git a/src/scrollable_textarea.rs b/src/scrollable_textarea.rs index 0b336b4..ac76c5d 100644 --- a/src/scrollable_textarea.rs +++ b/src/scrollable_textarea.rs @@ -5,7 +5,7 @@ use std::{ rc::Rc, }; -use crate::EditorClipboard; +use crate::{EditorClipboard, MIN_TEXTAREA_HEIGHT}; use crate::{MarkdownRenderer, ORANGE}; use anyhow; use anyhow::Result; @@ -95,6 +95,7 @@ impl ScrollableTextArea { self.full_screen_mode = !self.full_screen_mode; if self.full_screen_mode { self.edit_mode = false; + self.scroll = 0 } } @@ -184,7 +185,8 @@ impl ScrollableTextArea { } else { let mut height_sum = 0; for i in self.scroll..=self.focused_index { - let textarea_height = self.textareas[i].lines().len().max(3) as u16 + 2; + let textarea_height = + self.textareas[i].lines().len().max(MIN_TEXTAREA_HEIGHT) as u16 + 2; height_sum += textarea_height; if height_sum > self.viewport_height { @@ -204,7 +206,7 @@ impl ScrollableTextArea { pub fn calculate_height_to_focused(&self) -> u16 { self.textareas[self.scroll..=self.focused_index] .iter() - .map(|ta| ta.lines().len().max(3) as u16 + 2) + .map(|ta| ta.lines().len().max(MIN_TEXTAREA_HEIGHT) as u16 + 2) .sum() } @@ -284,7 +286,9 @@ impl ScrollableTextArea { let height = if is_editing { remaining_height } else { - content_height.min(remaining_height).max(3) + content_height + .min(remaining_height) + .max(MIN_TEXTAREA_HEIGHT as u16) }; visible_textareas.push((i, textarea, height)); @@ -349,6 +353,43 @@ impl ScrollableTextArea { Ok(()) } + pub fn handle_scroll(&mut self, direction: isize) { + if !self.full_screen_mode { + return; + } + + let current_height = self.textareas[self.focused_index].lines().len(); + let is_scrolling_down = direction > 0; + let is_at_last_textarea = self.focused_index == self.textareas.len() - 1; + let is_at_first_textarea = self.focused_index == 0; + + // Scrolling down + if is_scrolling_down { + let can_scroll_further = self.scroll < current_height.saturating_sub(1); + let can_move_to_next = !is_at_last_textarea; + + if can_scroll_further { + self.scroll += 1; + } else if can_move_to_next { + self.focused_index += 1; + self.scroll = 0; + } + return; + } + + // Scrolling up + let can_scroll_up = self.scroll > 0; + let can_move_to_previous = !is_at_first_textarea; + + if can_scroll_up { + self.scroll -= 1; + } else if can_move_to_previous { + self.focused_index -= 1; + let prev_height = self.textareas[self.focused_index].lines().len(); + self.scroll = prev_height.saturating_sub(1); + } + } + fn render_full_screen(&mut self, f: &mut Frame, area: Rect) -> Result<()> { let textarea = &mut self.textareas[self.focused_index]; textarea.set_selection_style(Style::default().bg(Color::Red)); diff --git a/src/ui_handler.rs b/src/ui_handler.rs index 899a0d6..57898b9 100644 --- a/src/ui_handler.rs +++ b/src/ui_handler.rs @@ -132,6 +132,10 @@ fn handle_full_screen_input(state: &mut UIState, key: event::KeyEvent) -> Result } else { state.scrollable_textarea.toggle_full_screen(); } + + state + .scrollable_textarea + .jump_to_textarea(state.scrollable_textarea.focused_index); } KeyCode::Enter => { if !state.scrollable_textarea.edit_mode { @@ -141,8 +145,20 @@ fn handle_full_screen_input(state: &mut UIState, key: event::KeyEvent) -> Result .insert_newline(); } } - KeyCode::Up => handle_up_key(state, key), - KeyCode::Down => handle_down_key(state, key), + KeyCode::Up => { + if state.scrollable_textarea.edit_mode { + handle_up_key(state, key); + } else { + state.scrollable_textarea.handle_scroll(-1); + } + } + KeyCode::Down => { + if state.scrollable_textarea.edit_mode { + handle_down_key(state, key); + } else { + state.scrollable_textarea.handle_scroll(1); + } + } KeyCode::Char('y') if key.modifiers.contains(KeyModifiers::CONTROL) => { match state.scrollable_textarea.copy_focused_textarea_contents() { Ok(_) => {