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();
}