-

+
DBX
diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue
index 01b25a08b..0f1a7f633 100644
--- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue
+++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue
@@ -36,6 +36,7 @@ import {
type AiProvider,
type AiApiStyle,
type EditorTheme,
+ type DesktopIconTheme,
} from "@/stores/settingsStore";
import { loadEditorTheme, editorFontTheme } from "@/lib/editorThemes";
import { isTauriRuntime } from "@/lib/tauriRuntime";
@@ -66,6 +67,7 @@ import type { SqlSnippet } from "@/types/database";
import { uuid } from "@/lib/utils";
import { DEFAULT_SQL_SNIPPETS } from "@/lib/sqlCompletion";
import AiProviderLogo from "@/components/icons/AiProviderLogo.vue";
+import AppLogo from "@/components/icons/AppLogo.vue";
import type { AppThemeAppearance } from "@/lib/appTheme";
import { useConnectionStore } from "@/stores/connectionStore";
@@ -93,6 +95,7 @@ const editExecuteMode = ref(settingsStore.editorSettings.executeMode);
const editWordWrap = ref(settingsStore.editorSettings.wordWrap);
const editAppLayout = ref(settingsStore.editorSettings.appLayout);
const editShowTrayIcon = ref(settingsStore.desktopSettings.show_tray_icon);
+const editIconTheme = ref(settingsStore.desktopSettings.icon_theme);
const editShowColumnCommentsInHeader = ref(settingsStore.editorSettings.showColumnCommentsInHeader);
const editCompactColumnHeaderActions = ref(settingsStore.editorSettings.compactColumnHeaderActions);
const editRedisScanPageSize = ref(settingsStore.editorSettings.redisScanPageSize);
@@ -228,6 +231,7 @@ watch(
editWordWrap.value = settingsStore.editorSettings.wordWrap;
editAppLayout.value = settingsStore.editorSettings.appLayout;
editShowTrayIcon.value = settingsStore.desktopSettings.show_tray_icon;
+ editIconTheme.value = settingsStore.desktopSettings.icon_theme;
editShowColumnCommentsInHeader.value = settingsStore.editorSettings.showColumnCommentsInHeader;
editCompactColumnHeaderActions.value = settingsStore.editorSettings.compactColumnHeaderActions;
editRedisScanPageSize.value = settingsStore.editorSettings.redisScanPageSize;
@@ -266,6 +270,7 @@ function hasChanges(): boolean {
editWordWrap.value !== settingsStore.editorSettings.wordWrap ||
editAppLayout.value !== settingsStore.editorSettings.appLayout ||
editShowTrayIcon.value !== settingsStore.desktopSettings.show_tray_icon ||
+ editIconTheme.value !== settingsStore.desktopSettings.icon_theme ||
editShowColumnCommentsInHeader.value !== settingsStore.editorSettings.showColumnCommentsInHeader ||
editCompactColumnHeaderActions.value !== settingsStore.editorSettings.compactColumnHeaderActions ||
editRedisScanPageSize.value !== settingsStore.editorSettings.redisScanPageSize ||
@@ -305,6 +310,7 @@ async function persistSettings() {
});
await settingsStore.updateDesktopSettings({
show_tray_icon: editShowTrayIcon.value,
+ icon_theme: editIconTheme.value,
});
if (sidebarObjectDisplayChanged) {
await connectionStore.refreshAllTree();
@@ -329,6 +335,7 @@ function resetDefaults() {
editWordWrap.value = DEFAULT_EDITOR_SETTINGS.wordWrap;
editAppLayout.value = DEFAULT_EDITOR_SETTINGS.appLayout;
editShowTrayIcon.value = DEFAULT_DESKTOP_SETTINGS.show_tray_icon;
+ editIconTheme.value = DEFAULT_DESKTOP_SETTINGS.icon_theme;
editShowColumnCommentsInHeader.value = DEFAULT_EDITOR_SETTINGS.showColumnCommentsInHeader;
editCompactColumnHeaderActions.value = DEFAULT_EDITOR_SETTINGS.compactColumnHeaderActions;
editRedisScanPageSize.value = DEFAULT_EDITOR_SETTINGS.redisScanPageSize;
@@ -362,6 +369,10 @@ function setSidebarObjectDisplay(value: "grouped" | "simple") {
editSidebarObjectDisplay.value = value;
}
+function setIconTheme(value: DesktopIconTheme) {
+ editIconTheme.value = value;
+}
+
function onShortcutChange(actionId: ShortcutActionId, value: any) {
if (typeof value !== "string") return;
const definition = SHORTCUT_DEFINITIONS.find((item) => item.id === actionId);
@@ -591,6 +602,7 @@ watch(
await settingsStore.initAiConfig();
await settingsStore.initDesktopSettings();
editShowTrayIcon.value = settingsStore.desktopSettings.show_tray_icon;
+ editIconTheme.value = settingsStore.desktopSettings.icon_theme;
webdavPassword.value = "";
await refreshWebDavPasswordStatus();
syncAiEditState();
@@ -1164,6 +1176,43 @@ watch(
-

+
{{ t("settings.officialDocs") }}
diff --git a/apps/desktop/src/components/icons/AppLogo.vue b/apps/desktop/src/components/icons/AppLogo.vue
new file mode 100644
index 000000000..d25684c0a
--- /dev/null
+++ b/apps/desktop/src/components/icons/AppLogo.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts
index 629d77686..8f4f1c864 100644
--- a/apps/desktop/src/i18n/locales/en.ts
+++ b/apps/desktop/src/i18n/locales/en.ts
@@ -1456,6 +1456,11 @@ export default {
appLayoutSeparatedDescription: "Clear panel separation with block-style tabs.",
appLayoutClassic: "Classic compact",
appLayoutClassicDescription: "Continuous tab bar with compact panel headers.",
+ iconTheme: "Icon and logo style",
+ iconThemeDefault: "Default",
+ iconThemeDefaultDescription: "Use the color DBX app icon.",
+ iconThemeBlack: "Black",
+ iconThemeBlackDescription: "Use the black DBX mark for the window, tray, and logo.",
showTrayIcon: "Show tray/menu bar icon",
showTrayIconDescription:
"When disabled, no icon is shown, but closing the window still hides DBX in the background as before.",
diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts
index e525cf1ea..9aba0e583 100644
--- a/apps/desktop/src/i18n/locales/es.ts
+++ b/apps/desktop/src/i18n/locales/es.ts
@@ -1349,6 +1349,11 @@ export default {
appLayoutSeparatedDescription: "Separación clara de paneles con pestañas en bloque.",
appLayoutClassic: "Clásico compacto",
appLayoutClassicDescription: "Barra de pestañas continua con encabezados de panel compactos.",
+ iconTheme: "Estilo de icono y logo",
+ iconThemeDefault: "Predeterminado",
+ iconThemeDefaultDescription: "Usar el icono de color de DBX.",
+ iconThemeBlack: "Negro",
+ iconThemeBlackDescription: "Usar la marca negra de DBX en ventana, bandeja y logo.",
showTrayIcon: "Mostrar icono en bandeja/barra de menú",
showTrayIconDescription:
"Si está desactivado, no se muestra el icono, pero cerrar la ventana sigue ocultando DBX en segundo plano como antes.",
diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts
index 0b887adf0..20825570c 100644
--- a/apps/desktop/src/i18n/locales/zh-CN.ts
+++ b/apps/desktop/src/i18n/locales/zh-CN.ts
@@ -1430,6 +1430,11 @@ export default {
appLayoutSeparatedDescription: "面板分隔更清晰,标签页为块状样式。",
appLayoutClassic: "经典紧凑",
appLayoutClassicDescription: "使用连续标签栏和更紧凑的面板标题。",
+ iconTheme: "图标与 Logo 样式",
+ iconThemeDefault: "默认",
+ iconThemeDefaultDescription: "使用彩色 DBX 应用图标。",
+ iconThemeBlack: "黑色",
+ iconThemeBlackDescription: "窗口、托盘和 Logo 都使用黑色 DBX 标识。",
showTrayIcon: "显示系统托盘/菜单栏图标",
showTrayIconDescription: "关闭后不显示图标,但关闭窗口仍会像之前一样隐藏到后台。",
dataGridDisplay: "数据表格显示",
diff --git a/apps/desktop/src/lib/http.ts b/apps/desktop/src/lib/http.ts
index c03d83f73..5a36f0543 100644
--- a/apps/desktop/src/lib/http.ts
+++ b/apps/desktop/src/lib/http.ts
@@ -789,7 +789,7 @@ export async function loadAiConfig(): Promise
{
}
export async function loadDesktopSettings(): Promise {
- return { show_tray_icon: true };
+ return { show_tray_icon: true, icon_theme: "default" };
}
export async function saveDesktopSettings(_settings: DesktopSettings): Promise {
diff --git a/apps/desktop/src/lib/tauri.ts b/apps/desktop/src/lib/tauri.ts
index 01a2604fa..a6dfa05ac 100644
--- a/apps/desktop/src/lib/tauri.ts
+++ b/apps/desktop/src/lib/tauri.ts
@@ -97,6 +97,7 @@ export interface DriverStoreUsage {
export interface DesktopSettings {
show_tray_icon: boolean;
+ icon_theme: "default" | "black";
}
export interface WebDavConfig {
diff --git a/apps/desktop/src/stores/settingsStore.ts b/apps/desktop/src/stores/settingsStore.ts
index 51c7b8302..8152cd884 100644
--- a/apps/desktop/src/stores/settingsStore.ts
+++ b/apps/desktop/src/stores/settingsStore.ts
@@ -38,12 +38,24 @@ export interface AiConfig {
export interface DesktopSettings {
show_tray_icon: boolean;
+ icon_theme: DesktopIconTheme;
}
+export type DesktopIconTheme = "default" | "black";
+
export const DEFAULT_DESKTOP_SETTINGS: DesktopSettings = {
show_tray_icon: true,
+ icon_theme: "default",
};
+function normalizeDesktopSettings(settings: Partial | null | undefined): DesktopSettings {
+ const iconTheme = settings?.icon_theme === "black" ? "black" : DEFAULT_DESKTOP_SETTINGS.icon_theme;
+ return {
+ show_tray_icon: settings?.show_tray_icon ?? DEFAULT_DESKTOP_SETTINGS.show_tray_icon,
+ icon_theme: iconTheme,
+ };
+}
+
export interface AiProviderPreset extends Omit {
label: string;
iconSlug?: string;
@@ -415,7 +427,7 @@ export const useSettingsStore = defineStore("settings", () => {
async function initDesktopSettings() {
if (isDesktopSettingsLoaded.value) return;
- desktopSettings.value = await api.loadDesktopSettings().catch(() => ({ ...DEFAULT_DESKTOP_SETTINGS }));
+ desktopSettings.value = normalizeDesktopSettings(await api.loadDesktopSettings().catch(() => null));
isDesktopSettingsLoaded.value = true;
}
@@ -425,9 +437,9 @@ export const useSettingsStore = defineStore("settings", () => {
...desktopSettings.value,
...partial,
};
- desktopSettings.value = next;
+ desktopSettings.value = normalizeDesktopSettings(next);
try {
- await api.saveDesktopSettings(next);
+ await api.saveDesktopSettings(desktopSettings.value);
} catch (error) {
desktopSettings.value = previous;
throw error;
diff --git a/crates/dbx-core/src/storage.rs b/crates/dbx-core/src/storage.rs
index 8bf30874e..a0d040a0b 100644
--- a/crates/dbx-core/src/storage.rs
+++ b/crates/dbx-core/src/storage.rs
@@ -18,11 +18,28 @@ pub struct Storage {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DesktopSettings {
pub show_tray_icon: bool,
+ pub icon_theme: DesktopIconTheme,
}
impl Default for DesktopSettings {
fn default() -> Self {
- Self { show_tray_icon: true }
+ Self { show_tray_icon: true, icon_theme: DesktopIconTheme::Default }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum DesktopIconTheme {
+ Default,
+ Black,
+}
+
+impl DesktopIconTheme {
+ fn from_settings_value(value: Option<&serde_json::Value>) -> Self {
+ match value.and_then(|value| value.as_str()) {
+ Some("black") => Self::Black,
+ _ => Self::Default,
+ }
}
}
@@ -326,6 +343,10 @@ impl Storage {
let mut settings = self.load_app_settings_json().await?;
settings.remove("run_in_background");
settings.insert("show_tray_icon".to_string(), serde_json::Value::Bool(desktop_settings.show_tray_icon));
+ settings.insert(
+ "icon_theme".to_string(),
+ serde_json::to_value(desktop_settings.icon_theme).map_err(|e| e.to_string())?,
+ );
self.save_app_settings_json(&settings).await
}
@@ -337,6 +358,7 @@ impl Storage {
.and_then(|value| value.as_bool())
.or_else(|| settings.get("run_in_background").and_then(|value| value.as_bool()))
.unwrap_or_else(|| DesktopSettings::default().show_tray_icon),
+ icon_theme: DesktopIconTheme::from_settings_value(settings.get("icon_theme")),
})
}
@@ -1063,7 +1085,7 @@ fn map_from_sql_err(err: serde_json::Error) -> rusqlite::Error {
#[cfg(test)]
mod tests {
- use super::{DesktopSettings, Storage};
+ use super::{DesktopIconTheme, DesktopSettings, Storage};
use std::time::{SystemTime, UNIX_EPOCH};
fn temp_db_path(name: &str) -> std::path::PathBuf {
@@ -1076,7 +1098,7 @@ mod tests {
let path = temp_db_path("desktop-settings-default");
let storage = Storage::open(&path).await.unwrap();
- assert_eq!(storage.load_desktop_settings().await.unwrap(), DesktopSettings { show_tray_icon: true });
+ assert_eq!(storage.load_desktop_settings().await.unwrap(), DesktopSettings::default());
}
#[tokio::test]
@@ -1087,7 +1109,10 @@ mod tests {
settings.insert("run_in_background".to_string(), serde_json::Value::Bool(false));
storage.save_app_settings_json(&settings).await.unwrap();
- assert_eq!(storage.load_desktop_settings().await.unwrap(), DesktopSettings { show_tray_icon: false });
+ assert_eq!(
+ storage.load_desktop_settings().await.unwrap(),
+ DesktopSettings { show_tray_icon: false, ..DesktopSettings::default() }
+ );
}
#[tokio::test]
@@ -1096,10 +1121,16 @@ mod tests {
let storage = Storage::open(&path).await.unwrap();
storage.save_password_hash("hash-1").await.unwrap();
- storage.save_desktop_settings(&DesktopSettings { show_tray_icon: false }).await.unwrap();
+ storage
+ .save_desktop_settings(&DesktopSettings { show_tray_icon: false, icon_theme: DesktopIconTheme::Black })
+ .await
+ .unwrap();
assert_eq!(storage.load_password_hash().await.unwrap(), Some("hash-1".to_string()));
- assert_eq!(storage.load_desktop_settings().await.unwrap(), DesktopSettings { show_tray_icon: false });
+ assert_eq!(
+ storage.load_desktop_settings().await.unwrap(),
+ DesktopSettings { show_tray_icon: false, icon_theme: DesktopIconTheme::Black }
+ );
}
#[tokio::test]
@@ -1110,11 +1141,18 @@ mod tests {
settings.insert("run_in_background".to_string(), serde_json::Value::Bool(false));
storage.save_app_settings_json(&settings).await.unwrap();
- storage.save_desktop_settings(&DesktopSettings { show_tray_icon: true }).await.unwrap();
+ storage
+ .save_desktop_settings(&DesktopSettings {
+ icon_theme: DesktopIconTheme::Black,
+ ..DesktopSettings::default()
+ })
+ .await
+ .unwrap();
let settings = storage.load_app_settings_json().await.unwrap();
assert_eq!(settings.get("run_in_background"), None);
assert_eq!(settings.get("show_tray_icon").and_then(|value| value.as_bool()), Some(true));
+ assert_eq!(settings.get("icon_theme").and_then(|value| value.as_str()), Some("black"));
}
#[tokio::test]
@@ -1122,11 +1160,17 @@ mod tests {
let path = temp_db_path("password-preserve-desktop-settings");
let storage = Storage::open(&path).await.unwrap();
- storage.save_desktop_settings(&DesktopSettings { show_tray_icon: false }).await.unwrap();
+ storage
+ .save_desktop_settings(&DesktopSettings { show_tray_icon: false, icon_theme: DesktopIconTheme::Black })
+ .await
+ .unwrap();
storage.save_password_hash("hash-2").await.unwrap();
assert_eq!(storage.load_password_hash().await.unwrap(), Some("hash-2".to_string()));
- assert_eq!(storage.load_desktop_settings().await.unwrap(), DesktopSettings { show_tray_icon: false });
+ assert_eq!(
+ storage.load_desktop_settings().await.unwrap(),
+ DesktopSettings { show_tray_icon: false, icon_theme: DesktopIconTheme::Black }
+ );
}
#[tokio::test]
diff --git a/src-tauri/icons/icon-black.png b/src-tauri/icons/icon-black.png
new file mode 100644
index 000000000..c016b386b
Binary files /dev/null and b/src-tauri/icons/icon-black.png differ
diff --git a/src-tauri/src/commands/app_settings.rs b/src-tauri/src/commands/app_settings.rs
index 28a003167..3a4144009 100644
--- a/src-tauri/src/commands/app_settings.rs
+++ b/src-tauri/src/commands/app_settings.rs
@@ -4,7 +4,7 @@ use dbx_core::storage::DesktopSettings;
use tauri::{AppHandle, State};
use super::connection::AppState;
-use crate::apply_desktop_tray_preference;
+use crate::apply_desktop_settings;
#[tauri::command]
pub async fn load_desktop_settings(state: State<'_, Arc>) -> Result {
@@ -18,8 +18,8 @@ pub async fn save_desktop_settings(
settings: DesktopSettings,
) -> Result<(), String> {
state.storage.save_desktop_settings(&settings).await?;
- if let Err(err) = apply_desktop_tray_preference(&app, settings.show_tray_icon) {
- eprintln!("Failed to apply desktop tray preference: {err}");
+ if let Err(err) = apply_desktop_settings(&app, &settings) {
+ eprintln!("Failed to apply desktop settings: {err}");
}
Ok(())
}
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index f04cb46b5..2d2e481b5 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -5,7 +5,7 @@ mod models;
mod window_state_guard;
use commands::connection::AppState;
-use dbx_core::storage::Storage;
+use dbx_core::storage::{DesktopIconTheme, DesktopSettings, Storage};
use std::sync::Arc;
use std::time::Instant;
#[cfg(target_os = "macos")]
@@ -21,6 +21,7 @@ use tauri_plugin_deep_link::DeepLinkExt;
const DESKTOP_TRAY_ID: &str = "main-tray";
#[cfg(target_os = "macos")]
const MACOS_TRAY_ICON: tauri::image::Image<'_> = tauri::include_image!("icons/tray-macos-template.png");
+const BLACK_APP_ICON: tauri::image::Image<'_> = tauri::include_image!("icons/icon-black.png");
fn should_hide_window_on_close(target_os: &str) -> bool {
matches!(target_os, "macos" | "windows")
@@ -54,15 +55,35 @@ fn open_connection_deep_links(app: &tauri::AppHandle, links: Vec) {
}
#[cfg_attr(not(any(target_os = "macos", target_os = "windows")), allow(dead_code))]
-fn setup_desktop_tray>(manager: &M) -> tauri::Result<()> {
+fn setup_desktop_tray>(
+ manager: &M,
+ icon_theme: DesktopIconTheme,
+) -> tauri::Result<()> {
let menu = MenuBuilder::new(manager).text("show", "Show DBX").separator().text("quit", "Quit DBX").build()?;
let mut tray =
TrayIconBuilder::::with_id(DESKTOP_TRAY_ID).tooltip("DBX").menu(&menu).show_menu_on_left_click(false);
#[cfg(target_os = "macos")]
{
- tray = tray.icon(MACOS_TRAY_ICON).icon_as_template(true);
+ match icon_theme {
+ DesktopIconTheme::Default => {
+ tray = tray.icon(MACOS_TRAY_ICON).icon_as_template(true);
+ }
+ DesktopIconTheme::Black => {
+ tray = tray.icon(BLACK_APP_ICON).icon_as_template(false);
+ }
+ }
}
- #[cfg(not(target_os = "macos"))]
+ #[cfg(target_os = "windows")]
+ {
+ let icon = match icon_theme {
+ DesktopIconTheme::Default => manager.app_handle().default_window_icon().cloned(),
+ DesktopIconTheme::Black => Some(BLACK_APP_ICON),
+ };
+ if let Some(icon) = icon {
+ tray = tray.icon(icon);
+ }
+ }
+ #[cfg(not(any(target_os = "macos", target_os = "windows")))]
{
if let Some(icon) = manager.app_handle().default_window_icon().cloned() {
tray = tray.icon(icon);
@@ -86,12 +107,59 @@ fn setup_desktop_tray>(manager: &M) -> tauri::R
Ok(())
}
-pub(crate) fn apply_desktop_tray_preference(app: &tauri::AppHandle, show_tray_icon: bool) -> tauri::Result<()> {
+fn apply_desktop_icon_theme(app: &tauri::AppHandle, icon_theme: DesktopIconTheme) -> tauri::Result<()> {
+ if let Some(window) = app.get_webview_window("main") {
+ match icon_theme {
+ DesktopIconTheme::Default => {
+ if let Some(icon) = app.default_window_icon().cloned() {
+ window.set_icon(icon)?;
+ }
+ }
+ DesktopIconTheme::Black => window.set_icon(BLACK_APP_ICON)?,
+ }
+ }
+ Ok(())
+}
+
+fn apply_desktop_tray_icon_theme(app: &tauri::AppHandle, icon_theme: DesktopIconTheme) -> tauri::Result<()> {
+ if let Some(tray) = app.tray_by_id(DESKTOP_TRAY_ID) {
+ #[cfg(target_os = "macos")]
+ {
+ match icon_theme {
+ DesktopIconTheme::Default => {
+ tray.set_icon(Some(MACOS_TRAY_ICON))?;
+ tray.set_icon_as_template(true)?;
+ }
+ DesktopIconTheme::Black => {
+ tray.set_icon(Some(BLACK_APP_ICON))?;
+ tray.set_icon_as_template(false)?;
+ }
+ }
+ }
+ #[cfg(target_os = "windows")]
+ {
+ let icon = match icon_theme {
+ DesktopIconTheme::Default => app.default_window_icon().cloned(),
+ DesktopIconTheme::Black => Some(BLACK_APP_ICON),
+ };
+ tray.set_icon(icon)?;
+ }
+ #[cfg(not(any(target_os = "macos", target_os = "windows")))]
+ {
+ let _ = (tray, icon_theme);
+ }
+ }
+ Ok(())
+}
+
+pub(crate) fn apply_desktop_settings(app: &tauri::AppHandle, desktop_settings: &DesktopSettings) -> tauri::Result<()> {
+ apply_desktop_icon_theme(app, desktop_settings.icon_theme)?;
if matches!(std::env::consts::OS, "macos" | "windows") {
if let Some(tray) = app.tray_by_id(DESKTOP_TRAY_ID) {
- tray.set_visible(show_tray_icon)?;
- } else if show_tray_icon {
- setup_desktop_tray(app)?;
+ tray.set_visible(desktop_settings.show_tray_icon)?;
+ apply_desktop_tray_icon_theme(app, desktop_settings.icon_theme)?;
+ } else if desktop_settings.show_tray_icon {
+ setup_desktop_tray(app, desktop_settings.icon_theme)?;
}
}
Ok(())
@@ -121,7 +189,7 @@ mod tests {
assert!(!should_setup_desktop_tray("linux", true));
let source = include_str!("lib.rs");
assert!(source.contains(
- "if should_setup_desktop_tray(std::env::consts::OS, desktop_settings.show_tray_icon) {\n setup_desktop_tray(app)?;"
+ "if should_setup_desktop_tray(std::env::consts::OS, desktop_settings.show_tray_icon) {\n setup_desktop_tray(app, desktop_settings.icon_theme)?;"
));
}
@@ -133,10 +201,18 @@ mod tests {
assert!(!source.contains(remove_call));
}
+ #[test]
+ fn can_apply_black_logo_icon_theme() {
+ let source = include_str!("lib.rs");
+ assert!(source.contains("const BLACK_APP_ICON"));
+ assert!(source.contains("DesktopIconTheme::Black => window.set_icon(BLACK_APP_ICON)?"));
+ assert!(source.contains("DesktopIconTheme::Black => Some(BLACK_APP_ICON)"));
+ }
+
#[test]
fn desktop_settings_save_treats_runtime_tray_update_as_best_effort() {
let source = include_str!("commands/app_settings.rs");
- assert!(source.contains("if let Err(err) = apply_desktop_tray_preference"));
+ assert!(source.contains("if let Err(err) = apply_desktop_settings"));
assert!(!source.contains("map_err(|err| err.to_string())"));
}
@@ -233,8 +309,9 @@ pub fn run() {
}
}
if should_setup_desktop_tray(std::env::consts::OS, desktop_settings.show_tray_icon) {
- setup_desktop_tray(app)?;
+ setup_desktop_tray(app, desktop_settings.icon_theme)?;
}
+ apply_desktop_icon_theme(app.handle(), desktop_settings.icon_theme)?;
window_state_guard::enforce_main_window_bounds(app.handle());
if should_show_main_window_after_setup() {
show_main_window(app.handle());