Skip to content

Commit 9189a0a

Browse files
blinko-spaceclaude
andcommitted
✨feat: add desktop window theme and color setting support
- Implement set_desktop_theme command for Windows/macOS/Linux - Add set_desktop_colors command for custom background colors - Update setTauriTheme to support desktop platforms - Set window background colors based on light/dark theme - Support hex color format parsing (#FF0000) - Apply theme changes to main window only - Integrate with existing Android status bar theming 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent c989b75 commit 9189a0a

File tree

11 files changed

+97
-87
lines changed

11 files changed

+97
-87
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
<img align='right' height='40px' src="./public/logo.svg" alt="Blinko" />
2+
<img align='right' height='40px' src="./public/logo.png" alt="Blinko" />
33

44
# Blinko - Open Source, Self-hosted
55

README.zh-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<img align='right' height='40px' src="./public/logo.svg" alt="Blinko" />
1+
<img align='right' height='40px' src="./public/logo.png" alt="Blinko" />
22

33
# Blinko - 开源、自托管的笔记应用
44

app/public/logo.png

98.2 KB
Loading

app/public/logo.svg

Lines changed: 0 additions & 77 deletions
This file was deleted.

app/src-tauri/src/desktop/window.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,81 @@ pub fn hide_quicktool_window<R: tauri::Runtime>(app: AppHandle<R>) -> Result<(),
234234
} else {
235235
Err("Quicktool window not found".to_string())
236236
}
237+
}
238+
239+
#[tauri::command]
240+
pub fn set_desktop_theme<R: tauri::Runtime>(app: AppHandle<R>, theme: String) -> Result<(), String> {
241+
use tauri::{Theme, window::Color};
242+
243+
let tauri_theme = match theme.as_str() {
244+
"light" => Theme::Light,
245+
"dark" => Theme::Dark,
246+
_ => return Err(format!("Invalid theme: {}", theme))
247+
};
248+
249+
// Define background colors based on theme
250+
let background_color = match theme.as_str() {
251+
"light" => Color(248, 248, 248, 255), // #F8F8F8
252+
"dark" => Color(28, 28, 30, 255), // #1C1C1E
253+
_ => Color(248, 248, 248, 255),
254+
};
255+
256+
// Set theme for main window only
257+
if let Some(window) = app.get_webview_window("main") {
258+
// Set system theme
259+
if let Err(e) = window.set_theme(Some(tauri_theme)) {
260+
eprintln!("Failed to set theme for main window: {}", e);
261+
} else {
262+
println!("Set main window theme to: {}", theme);
263+
}
264+
265+
// Set window background color
266+
if let Err(e) = window.set_background_color(Some(background_color)) {
267+
eprintln!("Failed to set background color for main window: {}", e);
268+
} else {
269+
println!("Set main window background color to: {:?}", background_color);
270+
}
271+
}
272+
273+
Ok(())
274+
}
275+
276+
#[tauri::command]
277+
pub fn set_desktop_colors<R: tauri::Runtime>(
278+
app: AppHandle<R>,
279+
background_color: Option<String>
280+
) -> Result<(), String> {
281+
use tauri::window::Color;
282+
283+
// Helper function to parse hex color to RGBA
284+
fn hex_to_rgba(hex: &str) -> Result<(u8, u8, u8, u8), String> {
285+
let hex = hex.trim_start_matches('#');
286+
if hex.len() != 6 {
287+
return Err("Invalid hex color format".to_string());
288+
}
289+
290+
let r = u8::from_str_radix(&hex[0..2], 16).map_err(|_| "Invalid red component")?;
291+
let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| "Invalid green component")?;
292+
let b = u8::from_str_radix(&hex[4..6], 16).map_err(|_| "Invalid blue component")?;
293+
294+
Ok((r, g, b, 255))
295+
}
296+
297+
// Set background color for main window only
298+
if let Some(color_str) = background_color {
299+
if let Ok((r, g, b, a)) = hex_to_rgba(&color_str) {
300+
if let Some(window) = app.get_webview_window("main") {
301+
let color = Color(r, g, b, a);
302+
if let Err(e) = window.set_background_color(Some(color)) {
303+
eprintln!("Failed to set custom background color for main window: {}", e);
304+
} else {
305+
println!("Set main window custom background color to: {}", color_str);
306+
}
307+
}
308+
} else {
309+
return Err("Invalid color format. Use hex format like #FF0000".to_string());
310+
}
311+
}
312+
313+
Ok(())
237314
}

app/src-tauri/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ pub fn run() {
7070
copy_to_clipboard,
7171
test_text_selection,
7272
check_accessibility_permissions,
73-
show_quicktool
73+
show_quicktool,
74+
set_desktop_theme,
75+
set_desktop_colors
7476
])
7577
.setup(|app| {
7678
#[cfg(not(any(target_os = "android", target_os = "ios")))]

app/src/components/BlinkoSettings/AboutSetting.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export const AboutSetting = observer(() => {
8989
title={t('about')}
9090
>
9191
<div className="flex items-start space-x-4 mb-6">
92-
<Image src="/logo.svg" alt="Blinko" className="w-16 h-16 rounded-xl" />
92+
<Image src="/logo.png" alt="Blinko" className="w-16 h-16 rounded-xl" />
9393
<div>
9494
<h2 className="text-xl font-semibold">Blinko</h2>
9595
<div className="flex flex-col gap-2 mt-1">

app/src/components/Common/FallbackImage/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export const FallbackImage = ({ src, alt, className, ...props }: ImageProps) =>
88
};
99

1010
if (error) {
11-
return <Image src={'/logo.svg'} alt={alt} className={className} {...props} onError={handleError} />;
11+
return <Image src={'/logo.png'} alt={alt} className={className} {...props} onError={handleError} />;
1212
}
1313

14-
return <Image src={src} alt={alt} className={className} {...props} onError={handleError} fallbackSrc="/logo.svg" />;
14+
return <Image src={src} alt={alt} className={className} {...props} onError={handleError} fallbackSrc="/logo.png" />;
1515
}

app/src/lib/tauriHelper.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { download } from '@tauri-apps/plugin-upload'
1010
import { downloadDir, publicDir } from '@tauri-apps/api/path'
1111
import { setStatusBarColor } from 'tauri-plugin-blinko-api'
1212
import { useEffect, useState } from 'react';
13+
import { invoke } from '@tauri-apps/api/core';
1314

1415
export interface PermissionStatus {
1516
audio: boolean;
@@ -114,11 +115,17 @@ export async function downloadFromLink(uri: string, filename?: string) {
114115
}
115116
}
116117

117-
export function setTauriTheme(theme: any) {
118+
export async function setTauriTheme(theme: any) {
118119
if (isAndroid()) {
119120
const lightColor = '#f8f8f8';
120121
const darkColor = '#1C1C1E';
121122
setStatusBarColor(theme === 'light' ? lightColor : darkColor);
123+
} else if (isDesktop()) {
124+
try {
125+
await invoke('set_desktop_theme', { theme });
126+
} catch (error) {
127+
console.error('Failed to set desktop theme:', error);
128+
}
122129
}
123130
}
124131

app/src/store/user.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ export class UserStore implements Store {
244244
const themeToSet = savedTheme === 'system' ? systemTheme : savedTheme;
245245
setTheme(themeToSet);
246246
this.updatePWAColor(themeToSet);
247-
setTauriTheme(themeToSet);
247+
setTauriTheme(themeToSet).catch(console.error);
248248
this.themeInitialized = true;
249249
}
250250

@@ -294,6 +294,7 @@ export class UserStore implements Store {
294294
const newTheme = config.theme === 'system' ? systemTheme : config.theme;
295295
setTheme(newTheme);
296296
this.updatePWAColor(newTheme);
297+
setTauriTheme(newTheme).catch(console.error);
297298
}
298299
}
299300
} catch (error) {
@@ -372,7 +373,7 @@ export class UserStore implements Store {
372373
}, []);
373374

374375
useEffect(() => {
375-
setTauriTheme(theme);
376+
setTauriTheme(theme).catch(console.error);
376377
}, [theme]);
377378

378379
useEffect(() => {

0 commit comments

Comments
 (0)