From 360bbb44a4addd4571b48d45c5e311faf11d8af4 Mon Sep 17 00:00:00 2001 From: jooaf Date: Fri, 30 May 2025 18:11:56 -0500 Subject: [PATCH] Fix: Fixing text color in light and dark mode --- Cargo.lock | 2 +- src/markdown_renderer.rs | 46 ++++++++++++++++++++++----------- src/scrollable_textarea.rs | 52 ++++++++++++++++++++++++++++++-------- src/ui_handler.rs | 4 +-- 4 files changed, 76 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee0c9fe..bef5071 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1436,7 +1436,7 @@ dependencies = [ [[package]] name = "thoth-cli" -version = "0.1.81" +version = "0.1.83" dependencies = [ "anyhow", "arboard", diff --git a/src/markdown_renderer.rs b/src/markdown_renderer.rs index 16ce02d..29ef683 100644 --- a/src/markdown_renderer.rs +++ b/src/markdown_renderer.rs @@ -11,6 +11,8 @@ use syntect::{ parsing::{SyntaxReference, SyntaxSet}, }; +use crate::ThemeMode; + pub struct MarkdownRenderer { syntax_set: SyntaxSet, theme_set: ThemeSet, @@ -28,20 +30,34 @@ const HEADER_COLORS: [Color; 6] = [ impl Default for MarkdownRenderer { fn default() -> Self { - Self::new() + Self::new(&ThemeMode::Dark) } } impl MarkdownRenderer { - pub fn new() -> Self { + pub fn new(theme_mode: &ThemeMode) -> Self { + let theme_name = match theme_mode { + ThemeMode::Light => "base16-ocean.light", + ThemeMode::Dark => "base16-mocha.dark", + }; + MarkdownRenderer { syntax_set: SyntaxSet::load_defaults_newlines(), theme_set: ThemeSet::load_defaults(), - theme: "base16-mocha.dark".to_string(), + theme: theme_name.to_string(), cache: HashMap::new(), } } + pub fn set_theme(&mut self, theme_mode: &ThemeMode) { + let theme_name = match theme_mode { + ThemeMode::Light => "base16-ocean.light", + ThemeMode::Dark => "base16-mocha.dark", + }; + self.theme = theme_name.to_string(); + self.cache.clear(); + } + pub fn render_markdown( &mut self, markdown: String, @@ -697,7 +713,7 @@ mod tests { #[test] fn test_render_markdown() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "# Header\n\nThis is **bold** and *italic* text."; let rendered = renderer .render_markdown(markdown.to_string(), "".to_string(), 40) @@ -716,7 +732,7 @@ mod tests { #[test] fn test_render_markdown_with_code_block() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "# Header\n\n```rust\nfn main() {\n println!(\"Hello, world!\");\n}\n```"; let rendered = renderer @@ -735,11 +751,11 @@ mod tests { #[test] fn test_render_json() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let json = r#"{ "name": "John Doe", "age": 30, - "city": "New York" + "city": "New &ThemeMode::DarkYork" }"#; let rendered = renderer @@ -759,7 +775,7 @@ mod tests { #[test] fn test_render_markdown_with_lists() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "# List Test\n\n- Item 1\n- Item 2\n - Nested item\n\n1. First item\n2. Second item"; let rendered = renderer @@ -778,7 +794,7 @@ mod tests { #[test] fn test_render_markdown_with_links() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "Visit [Google](https://google.com) for search"; let rendered = renderer .render_markdown(markdown.to_string(), "".to_string(), 40) @@ -792,7 +808,7 @@ mod tests { #[test] fn test_render_markdown_with_blockquotes() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "> This is a blockquote\n> Another line"; let rendered = renderer .render_markdown(markdown.to_string(), "".to_string(), 40) @@ -806,7 +822,7 @@ mod tests { #[test] fn test_render_markdown_with_task_lists() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "- [ ] Unchecked task\n- [x] Checked task\n- [ x ] Also checked task\n- [ ] Another unchecked task"; let rendered = renderer .render_markdown(markdown.to_string(), "".to_string(), 40) @@ -824,7 +840,7 @@ mod tests { #[test] fn test_render_markdown_with_inline_code() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "Some `inline code` here"; let rendered = renderer .render_markdown(markdown.to_string(), "".to_string(), 40) @@ -838,7 +854,7 @@ mod tests { #[test] fn test_render_markdown_with_strikethrough() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "This is ~~strikethrough~~ text"; let rendered = renderer .render_markdown(markdown.to_string(), "".to_string(), 40) @@ -856,7 +872,7 @@ mod tests { #[test] fn test_render_markdown_with_one_line_code_block() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "# Header\n\n```rust\n```\n\nText after.".to_string(); let rendered = renderer .render_markdown(markdown, "".to_string(), 40) @@ -882,7 +898,7 @@ mod tests { #[test] fn test_indentation_preservation() { - let mut renderer = MarkdownRenderer::new(); + let mut renderer = MarkdownRenderer::new(&ThemeMode::Dark); let markdown = "Regular text\n Indented text\n Double indented text"; let rendered = renderer .render_markdown(markdown.to_string(), "".to_string(), 50) diff --git a/src/scrollable_textarea.rs b/src/scrollable_textarea.rs index ca36915..1905243 100644 --- a/src/scrollable_textarea.rs +++ b/src/scrollable_textarea.rs @@ -5,8 +5,8 @@ use std::{ rc::Rc, }; -use crate::MarkdownRenderer; use crate::{EditorClipboard, ThemeColors, BORDER_PADDING_SIZE, MIN_TEXTAREA_HEIGHT}; +use crate::{MarkdownRenderer, ThemeMode}; use anyhow; use anyhow::Result; use rand::Rng; @@ -25,18 +25,36 @@ const RENDER_CACHE_SIZE: usize = 100; struct MarkdownCache { cache: HashMap>, renderer: MarkdownRenderer, + current_theme: ThemeMode, } impl MarkdownCache { - fn new() -> Self { + fn new(theme_mode: &ThemeMode) -> Self { MarkdownCache { cache: HashMap::with_capacity(RENDER_CACHE_SIZE), - renderer: MarkdownRenderer::new(), + renderer: MarkdownRenderer::new(theme_mode), + current_theme: theme_mode.clone(), } } - fn get_or_render(&mut self, content: &str, title: &str, width: usize) -> Result> { - let cache_key = format!("{}:{}", title, content); + fn update_theme(&mut self, theme_mode: &ThemeMode) { + if self.current_theme != *theme_mode { + self.renderer.set_theme(theme_mode); + self.current_theme = theme_mode.clone(); + self.cache.clear(); + } + } + + fn get_or_render( + &mut self, + content: &str, + title: &str, + width: usize, + theme_mode: &ThemeMode, + ) -> Result> { + self.update_theme(theme_mode); + + let cache_key = format!("{}:{}:{:?}", title, content, theme_mode); if let Some(cached) = self.cache.get(&cache_key) { return Ok(cached.clone()); } @@ -87,7 +105,7 @@ impl ScrollableTextArea { full_screen_mode: false, viewport_height: 0, start_sel: 0, - markdown_cache: Rc::new(RefCell::new(MarkdownCache::new())), + markdown_cache: Rc::new(RefCell::new(MarkdownCache::new(&ThemeMode::Dark))), } } @@ -316,14 +334,20 @@ impl ScrollableTextArea { f.render_widget(textarea.widget(), area); } - pub fn render(&mut self, f: &mut Frame, area: Rect, theme: &ThemeColors) -> Result<()> { + pub fn render( + &mut self, + f: &mut Frame, + area: Rect, + theme: &ThemeColors, + theme_mode: &ThemeMode, + ) -> Result<()> { self.viewport_height = area.height; if self.full_screen_mode { if self.edit_mode { self.render_full_screen_edit(f, area, theme); } else { - self.render_full_screen(f, area, theme)?; + self.render_full_screen(f, area, theme, theme_mode)?; } } else { let mut remaining_height = area.height; @@ -397,6 +421,7 @@ impl ScrollableTextArea { &content, title, f.size().width as usize - BORDER_PADDING_SIZE, + theme_mode, )?; let paragraph = Paragraph::new(rendered_markdown) .block(block) @@ -446,7 +471,13 @@ impl ScrollableTextArea { } } - fn render_full_screen(&mut self, f: &mut Frame, area: Rect, theme: &ThemeColors) -> Result<()> { + fn render_full_screen( + &mut self, + f: &mut Frame, + area: Rect, + theme: &ThemeColors, + theme_mode: &ThemeMode, + ) -> Result<()> { let textarea = &mut self.textareas[self.focused_index]; textarea.set_selection_style(Style::default().bg(theme.selection)); let title = &self.titles[self.focused_index]; @@ -461,6 +492,7 @@ impl ScrollableTextArea { &content, title, f.size().width as usize - BORDER_PADDING_SIZE, + theme_mode, )?; let paragraph = Paragraph::new(rendered_markdown) @@ -490,7 +522,7 @@ mod tests { full_screen_mode: false, viewport_height: 0, start_sel: 0, - markdown_cache: Rc::new(RefCell::new(MarkdownCache::new())), + markdown_cache: Rc::new(RefCell::new(MarkdownCache::new(&ThemeMode::Dark))), } } diff --git a/src/ui_handler.rs b/src/ui_handler.rs index 1c7a0bd..fd5e786 100644 --- a/src/ui_handler.rs +++ b/src/ui_handler.rs @@ -97,12 +97,12 @@ pub fn draw_ui( if state.scrollable_textarea.full_screen_mode { state .scrollable_textarea - .render(f, f.size(), theme) + .render(f, f.size(), theme, &state.config.theme) .unwrap(); } else { state .scrollable_textarea - .render(f, chunks[1], theme) + .render(f, chunks[1], theme, &state.config.theme) .unwrap(); }