diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6a374c8..84dc19e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -159,6 +159,14 @@ fn send_markdown_path(state: State<'_, AppState>) -> Vec { files } +#[tauri::command] +fn save_theme(app: AppHandle, theme: String) -> Result<(), String> { + let config_dir = app.path().app_config_dir().map_err(|e| e.to_string())?; + fs::create_dir_all(&config_dir).map_err(|e| e.to_string())?; + let theme_path = config_dir.join("theme.txt"); + fs::write(theme_path, theme).map_err(|e| e.to_string()) +} + #[tauri::command] async fn get_app_mode() -> String { @@ -415,7 +423,7 @@ pub fn run() { let _window = tauri::WebviewWindowBuilder::new(app, label, tauri::WebviewUrl::App("index.html".into())) .title("Markpad") - .inner_size(850.0, 650.0) + .inner_size(900.0, 650.0) .min_inner_size(400.0, 300.0) .visible(false) .resizable(true) @@ -425,11 +433,28 @@ pub fn run() { .visible(false) .build()?; - #[cfg(target_os = "windows")] - { - use tauri::window::Color; - let _ = _window.set_background_color(Some(Color(18, 18, 18, 255))); - } + let config_dir = app.path().app_config_dir()?; + let theme_path = config_dir.join("theme.txt"); + let theme_pref = fs::read_to_string(theme_path).unwrap_or_else(|_| "system".to_string()); + + let window = app.get_webview_window(label).unwrap(); + + let bg_color = match theme_pref.as_str() { + "dark" => Some(tauri::window::Color(24, 24, 24, 255)), + "light" => Some(tauri::window::Color(253, 253, 253, 255)), + _ => { + if let Ok(t) = window.theme() { + match t { + tauri::Theme::Dark => Some(tauri::window::Color(24, 24, 24, 255)), + _ => Some(tauri::window::Color(253, 253, 253, 255)), + } + } else { + Some(tauri::window::Color(253, 253, 253, 255)) + } + } + }; + + let _ = window.set_background_color(bg_color); let _ = _window.set_shadow(true); @@ -469,7 +494,8 @@ pub fn run() { unwatch_file, show_context_menu, - show_window + show_window, + save_theme ]) .build(tauri::generate_context!()) .expect("error while building tauri application") diff --git a/src/app.html b/src/app.html index ddbc242..c03d688 100644 --- a/src/app.html +++ b/src/app.html @@ -2,6 +2,26 @@ + diff --git a/src/lib/Installer.svelte b/src/lib/Installer.svelte index 333f4c9..0d85412 100644 --- a/src/lib/Installer.svelte +++ b/src/lib/Installer.svelte @@ -1,5 +1,6 @@ @@ -98,11 +105,15 @@
App Icon +

Markdown Viewer

{#if isInstalled} -

Markdown Viewer

+
+ Current: v{installedVersion} + + Target: v{installerVersion} +
{:else} -

Markdown Viewer

-

A simple markdown viewer

+

A simple markdown viewer v{installerVersion}

{/if}
@@ -252,12 +263,12 @@ width: 70px; height: 70px; margin-bottom: 12px; - filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.1)); + filter: invert(0.8) drop-shadow(0 4px 12px rgba(0, 0, 0, 0.1)); } @media (prefers-color-scheme: dark) { .app-icon { - filter: invert(1) drop-shadow(0 4px 12px rgba(0, 0, 0, 0.1)); + filter: invert(0) drop-shadow(0 4px 12px rgba(0, 0, 0, 0.1)); } } @@ -489,4 +500,31 @@ transform: translateY(0); } } + + .version-comparison { + font-size: 11px; + margin-top: 8px; + opacity: 0.6; + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + font-weight: 500; + } + + .v-label { + opacity: 0.6; + font-weight: 400; + } + + .v-arrow { + color: var(--color-accent-fg); + font-weight: bold; + } + + .v-lite { + margin-left: 4px; + opacity: 0.4; + font-size: 11px; + } diff --git a/src/lib/MarkdownViewer.svelte b/src/lib/MarkdownViewer.svelte index 34fad02..bc65cb2 100644 --- a/src/lib/MarkdownViewer.svelte +++ b/src/lib/MarkdownViewer.svelte @@ -62,10 +62,13 @@ onMount(() => { const storedTheme = localStorage.getItem('theme') as 'system' | 'dark' | 'light' | null; if (storedTheme) theme = storedTheme; + // Clear the forced background color from app.html + document.documentElement.style.removeProperty('background-color'); }); $effect(() => { localStorage.setItem('theme', theme); + invoke('save_theme', { theme }).catch(console.error); if (theme === 'system') { delete document.documentElement.dataset.theme; @@ -188,7 +191,7 @@ if (img.hasAttribute('title')) media.setAttribute('title', img.getAttribute('title')!); img.replaceWith(media); - continue; + continue; } if (isYoutubeLink(src)) { diff --git a/src/lib/components/Editor.svelte b/src/lib/components/Editor.svelte index b8cbf49..bf1a97d 100644 --- a/src/lib/components/Editor.svelte +++ b/src/lib/components/Editor.svelte @@ -117,6 +117,7 @@ wordWrap: settings.wordWrap as 'on' | 'off' | 'wordWrapColumn' | 'bounded', lineNumbers: settings.lineNumbers as 'on' | 'off' | 'relative' | 'interval', renderLineHighlight: settings.renderLineHighlight ? 'line' : 'none', + occurrencesHighlight: settings.occurrencesHighlight ? 'singleFile' : 'off', }); if (tabManager.activeTab?.editorViewState) { @@ -196,6 +197,14 @@ }, }); + editor.addAction({ + id: 'toggle-occurrences-highlight', + label: 'Toggle Occurrences Highlight', + run: () => { + settings.toggleOccurrencesHighlight(); + }, + }); + editor.addAction({ id: 'toggle-tabs', label: 'Toggle Tabs', @@ -526,6 +535,7 @@ wordWrap: settings.wordWrap as 'on' | 'off' | 'wordWrapColumn' | 'bounded', lineNumbers: settings.lineNumbers as 'on' | 'off' | 'relative' | 'interval', renderLineHighlight: settings.renderLineHighlight as 'line' | 'none', + occurrencesHighlight: settings.occurrencesHighlight ? 'singleFile' : 'off', fontSize: 14 * (zoomLevel / 100), }); } diff --git a/src/lib/components/HomePage.svelte b/src/lib/components/HomePage.svelte index 667e1cc..7d53494 100644 --- a/src/lib/components/HomePage.svelte +++ b/src/lib/components/HomePage.svelte @@ -1,4 +1,7 @@