feat: switch app icon with theme

This commit is contained in:
lucaronin
2026-05-24 12:10:54 +02:00
parent 9ca05c1665
commit 7d6ba934c6
11 changed files with 270 additions and 6 deletions

60
src-tauri/Cargo.lock generated
View File

@@ -470,6 +470,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "byteorder-lite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "bytes"
version = "1.11.1"
@@ -1934,7 +1940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371"
dependencies = [
"byteorder",
"png",
"png 0.17.16",
]
[[package]]
@@ -2051,6 +2057,19 @@ dependencies = [
"icu_properties",
]
[[package]]
name = "image"
version = "0.25.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104"
dependencies = [
"bytemuck",
"byteorder-lite",
"moxcms",
"num-traits",
"png 0.18.1",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -2469,6 +2488,16 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "moxcms"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
dependencies = [
"num-traits",
"pxfm",
]
[[package]]
name = "muda"
version = "0.17.1"
@@ -2484,7 +2513,7 @@ dependencies = [
"objc2-core-foundation",
"objc2-foundation",
"once_cell",
"png",
"png 0.17.16",
"serde",
"thiserror 2.0.18",
"windows-sys 0.60.2",
@@ -3250,6 +3279,19 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "png"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
dependencies = [
"bitflags 2.11.0",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]]
name = "polling"
version = "3.11.0"
@@ -3392,6 +3434,12 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "pxfm"
version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f"
[[package]]
name = "quick-xml"
version = "0.38.4"
@@ -4742,6 +4790,7 @@ dependencies = [
"heck 0.5.0",
"http",
"http-range",
"image",
"jni",
"libc",
"log",
@@ -4809,7 +4858,7 @@ dependencies = [
"ico",
"json-patch",
"plist",
"png",
"png 0.17.16",
"proc-macro2",
"quote",
"semver",
@@ -5290,6 +5339,9 @@ dependencies = [
"gray_matter",
"log",
"notify",
"objc2",
"objc2-app-kit",
"objc2-foundation",
"regex",
"reqwest 0.12.28",
"sentry",
@@ -5517,7 +5569,7 @@ dependencies = [
"objc2-core-graphics",
"objc2-foundation",
"once_cell",
"png",
"png 0.17.16",
"serde",
"thiserror 2.0.18",
"windows-sys 0.60.2",

View File

@@ -21,7 +21,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
log = "0.4"
notify = "6.1"
tauri = { version = "2.10.0", features = ["protocol-asset", "devtools"] }
tauri = { version = "2.10.0", features = ["protocol-asset", "devtools", "image-png"] }
tauri-plugin-log = "2"
gray_matter = "0.2"
walkdir = "2"
@@ -41,4 +41,9 @@ uuid = { version = "1", features = ["v4"] }
tempfile = "3"
reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls"] }
[target.'cfg(target_os = "macos")'.dependencies]
objc2 = "0.6"
objc2-app-kit = { version = "0.3", default-features = false, features = ["std", "NSApplication", "NSImage"] }
objc2-foundation = { version = "0.3", default-features = false, features = ["std", "NSData", "NSThread"] }
[dev-dependencies]

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@@ -0,0 +1,41 @@
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_110_75)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M924 356.627C924 346.845 924.004 337.062 923.944 327.279C923.895 319.038 923.8 310.799 923.576 302.562C923.092 284.609 922.033 266.502 918.84 248.749C915.602 230.741 910.314 213.98 901.981 197.617C893.789 181.534 883.088 166.817 870.32 154.058C857.555 141.299 842.834 130.605 826.746 122.418C810.366 114.083 793.587 108.797 775.558 105.56C757.803 102.372 739.691 101.315 721.738 100.83C713.495 100.607 705.253 100.513 697.008 100.462C687.22 100.402 677.432 100.407 667.644 100.407L553.997 100H468.997L357.361 100.407C347.554 100.407 337.747 100.402 327.94 100.462C319.678 100.513 311.42 100.607 303.161 100.83C285.167 101.315 267.014 102.373 249.217 105.565C231.164 108.801 214.36 114.085 197.958 122.414C181.835 130.602 167.083 141.297 154.291 154.058C141.501 166.816 130.78 181.53 122.573 197.61C114.217 213.981 108.919 230.752 105.673 248.77C102.477 266.516 101.418 284.617 100.931 302.562C100.709 310.8 100.613 319.039 100.563 327.279C100.503 337.063 100 349.216 100 358.999L100.003 469.089L100 554.998L100.508 667.427C100.508 677.223 100.504 687.019 100.563 696.815C100.613 705.067 100.709 713.317 100.932 721.566C101.418 739.542 102.479 757.675 105.678 775.452C108.923 793.484 114.22 810.269 122.569 826.653C130.777 842.759 141.5 857.495 154.291 870.272C167.082 883.049 181.83 893.757 197.95 901.956C214.362 910.302 231.174 915.595 249.238 918.836C267.027 922.029 285.174 923.088 303.161 923.573C311.42 923.796 319.679 923.891 327.941 923.941C337.748 924.001 347.554 923.997 357.361 923.997L470.006 924H555.217L667.644 923.996C677.432 923.996 687.22 924.001 697.008 923.941C705.253 923.891 713.495 923.796 721.738 923.573C739.698 923.087 757.816 922.027 775.579 918.832C793.597 915.591 810.368 910.3 826.739 901.959C842.831 893.761 857.554 883.051 870.32 870.272C883.086 857.497 893.786 842.763 901.978 826.66C910.316 810.268 915.604 793.475 918.844 775.431C922.034 757.661 923.092 739.535 923.577 721.566C923.8 713.316 923.895 705.066 923.944 696.815C924.005 687.019 924 677.223 924 667.427C924 667.427 923.994 556.983 923.994 554.998V468.999C923.994 467.533 924 356.627 924 356.627Z" fill="#151923"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M924 356.627C924 346.845 924.004 337.062 923.944 327.279C923.895 319.038 923.8 310.799 923.576 302.562C923.092 284.609 922.033 266.502 918.84 248.749C915.602 230.741 910.314 213.98 901.981 197.617C893.789 181.534 883.088 166.817 870.32 154.058C857.555 141.299 842.834 130.605 826.746 122.418C810.366 114.083 793.587 108.797 775.558 105.56C757.803 102.372 739.691 101.315 721.738 100.83C713.495 100.607 705.253 100.513 697.008 100.462C687.22 100.402 677.432 100.407 667.644 100.407L553.997 100H468.997L357.361 100.407C347.554 100.407 337.747 100.402 327.94 100.462C319.678 100.513 311.42 100.607 303.161 100.83C285.167 101.315 267.014 102.373 249.217 105.565C231.164 108.801 214.36 114.085 197.958 122.414C181.835 130.602 167.083 141.297 154.291 154.058C141.501 166.816 130.78 181.53 122.573 197.61C114.217 213.981 108.919 230.752 105.673 248.77C102.477 266.516 101.418 284.617 100.931 302.562C100.709 310.8 100.613 319.039 100.563 327.279C100.503 337.063 100 349.216 100 358.999L100.003 469.089L100 554.998L100.508 667.427C100.508 677.223 100.504 687.019 100.563 696.815C100.613 705.067 100.709 713.317 100.932 721.566C101.418 739.542 102.479 757.675 105.678 775.452C108.923 793.484 114.22 810.269 122.569 826.653C130.777 842.759 141.5 857.495 154.291 870.272C167.082 883.049 181.83 893.757 197.95 901.956C214.362 910.302 231.174 915.595 249.238 918.836C267.027 922.029 285.174 923.088 303.161 923.573C311.42 923.796 319.679 923.891 327.941 923.941C337.748 924.001 347.554 923.997 357.361 923.997L470.006 924H555.217L667.644 923.996C677.432 923.996 687.22 924.001 697.008 923.941C705.253 923.891 713.495 923.796 721.738 923.573C739.698 923.087 757.816 922.027 775.579 918.832C793.597 915.591 810.368 910.3 826.739 901.959C842.831 893.761 857.554 883.051 870.32 870.272C883.086 857.497 893.786 842.763 901.978 826.66C910.316 810.268 915.604 793.475 918.844 775.431C922.034 757.661 923.092 739.535 923.577 721.566C923.8 713.316 923.895 705.066 923.944 696.815C924.005 687.019 924 677.223 924 667.427C924 667.427 923.994 556.983 923.994 554.998V468.999C923.994 467.533 924 356.627 924 356.627Z" fill="url(#paint0_linear_110_75)" fill-opacity="0.42"/>
</g>
<mask id="mask0_110_75" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="100" y="100" width="824" height="824">
<path fill-rule="evenodd" clip-rule="evenodd" d="M924 356.627C924 346.845 924.004 337.062 923.944 327.279C923.895 319.038 923.8 310.799 923.576 302.562C923.092 284.609 922.033 266.502 918.84 248.749C915.602 230.741 910.314 213.98 901.981 197.617C893.789 181.534 883.088 166.817 870.32 154.058C857.555 141.299 842.834 130.605 826.746 122.418C810.366 114.083 793.587 108.797 775.558 105.56C757.803 102.372 739.691 101.315 721.738 100.83C713.495 100.607 705.253 100.513 697.008 100.462C687.22 100.402 677.432 100.407 667.644 100.407L553.997 100H468.997L357.361 100.407C347.554 100.407 337.747 100.402 327.94 100.462C319.678 100.513 311.42 100.607 303.161 100.83C285.167 101.315 267.014 102.373 249.217 105.565C231.164 108.801 214.36 114.085 197.958 122.414C181.835 130.602 167.083 141.297 154.291 154.058C141.501 166.816 130.78 181.53 122.573 197.61C114.217 213.981 108.919 230.752 105.673 248.77C102.477 266.516 101.418 284.617 100.931 302.562C100.709 310.8 100.613 319.039 100.563 327.279C100.503 337.063 100 349.216 100 358.999L100.003 469.089L100 554.998L100.508 667.427C100.508 677.223 100.504 687.019 100.563 696.815C100.613 705.067 100.709 713.317 100.932 721.566C101.418 739.542 102.479 757.675 105.678 775.452C108.923 793.484 114.22 810.269 122.569 826.653C130.777 842.759 141.5 857.495 154.291 870.272C167.082 883.049 181.83 893.757 197.95 901.956C214.362 910.302 231.174 915.595 249.238 918.836C267.027 922.029 285.174 923.088 303.161 923.573C311.42 923.796 319.679 923.891 327.941 923.941C337.748 924.001 347.554 923.997 357.361 923.997L470.006 924H555.217L667.644 923.996C677.432 923.996 687.22 924.001 697.008 923.941C705.253 923.891 713.495 923.796 721.738 923.573C739.698 923.087 757.816 922.027 775.579 918.832C793.597 915.591 810.368 910.3 826.739 901.959C842.831 893.761 857.554 883.051 870.32 870.272C883.086 857.497 893.786 842.763 901.978 826.66C910.316 810.268 915.604 793.475 918.844 775.431C922.034 757.661 923.092 739.535 923.577 721.566C923.8 713.316 923.895 705.066 923.944 696.815C924.005 687.019 924 677.223 924 667.427C924 667.427 923.994 556.983 923.994 554.998V468.999C923.994 467.533 924 356.627 924 356.627Z" fill="white"/>
</mask>
<g mask="url(#mask0_110_75)">
</g>
<g opacity="0.4" filter="url(#filter1_f_110_75)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M491.45 246.005C502.143 235.332 519.52 235.332 530.213 246.005C581.007 299.371 712 460.802 712 584.878C712 695.612 622.443 785 511.5 785C400.557 785 311 695.612 311 584.878C311 460.802 441.993 299.371 491.45 246.005ZM400.972 603.993C398.809 591.733 387.083 583.189 374.74 584.878C362.397 586.568 354.168 597.843 356.331 610.103C367.894 675.638 420.114 728.676 486.27 742.031C488.878 742.56 491.491 742.603 493.947 742.267C503.142 741.008 510.721 734.157 512.354 724.625C514.445 712.509 506.134 700.696 493.807 698.205C446.539 688.645 409.226 650.772 400.972 603.993Z" fill="#155DFF"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M400.972 603.993C398.809 591.733 387.083 583.189 374.74 584.878C362.397 586.568 354.168 597.843 356.331 610.103C367.894 675.638 420.114 728.676 486.27 742.031C488.878 742.56 491.491 742.603 493.947 742.267C503.142 741.008 510.721 734.157 512.354 724.625C514.445 712.509 506.134 700.696 493.807 698.205C446.539 688.645 409.226 650.772 400.972 603.993Z" fill="#C4E4FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M491.45 246.005C502.143 235.332 519.52 235.332 530.213 246.005C581.007 299.371 712 460.802 712 584.878C712 695.612 622.443 785 511.5 785C400.557 785 311 695.612 311 584.878C311 460.802 441.993 299.371 491.45 246.005ZM400.972 603.993C398.809 591.733 387.083 583.189 374.74 584.878C362.397 586.568 354.168 597.843 356.331 610.103C367.894 675.638 420.114 728.676 486.27 742.031C488.878 742.56 491.491 742.603 493.947 742.267C503.142 741.008 510.721 734.157 512.354 724.625C514.445 712.509 506.134 700.696 493.807 698.205C446.539 688.645 409.226 650.772 400.972 603.993Z" fill="#155DFF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M491.45 246.005C502.143 235.332 519.52 235.332 530.213 246.005C581.007 299.371 712 460.802 712 584.878C712 695.612 622.443 785 511.5 785C400.557 785 311 695.612 311 584.878C311 460.802 441.993 299.371 491.45 246.005ZM400.972 603.993C398.809 591.733 387.083 583.189 374.74 584.878C362.397 586.568 354.168 597.843 356.331 610.103C367.894 675.638 420.114 728.676 486.27 742.031C488.878 742.56 491.491 742.603 493.947 742.267C503.142 741.008 510.721 734.157 512.354 724.625C514.445 712.509 506.134 700.696 493.807 698.205C446.539 688.645 409.226 650.772 400.972 603.993Z" fill="url(#paint1_linear_110_75)"/>
<defs>
<filter id="filter0_d_110_75" x="75" y="80" width="884" height="884" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="5" dy="10"/>
<feGaussianBlur stdDeviation="15"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_110_75"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_110_75" result="shape"/>
</filter>
<filter id="filter1_f_110_75" x="281" y="208" width="461" height="607" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="15" result="effect1_foregroundBlur_110_75"/>
</filter>
<linearGradient id="paint0_linear_110_75" x1="233" y1="138.5" x2="784.5" y2="1320.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#2D3546"/>
<stop offset="1" stop-color="#070A10"/>
</linearGradient>
<linearGradient id="paint1_linear_110_75" x1="126" y1="-35.5" x2="723" y2="744" gradientUnits="userSpaceOnUse">
<stop stop-color="#00AEFF"/>
<stop offset="1" stop-color="#155DFF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

97
src-tauri/src/app_icon.rs Normal file
View File

@@ -0,0 +1,97 @@
use tauri::Manager;
const LIGHT_ICON_BYTES: &[u8] = include_bytes!("../icons/512x512.png");
const DARK_ICON_BYTES: &[u8] = include_bytes!("../icons/512x512-dark.png");
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum AppIconMode {
Light,
Dark,
}
impl AppIconMode {
fn parse(value: &str) -> Result<Self, String> {
match value {
"light" => Ok(Self::Light),
"dark" => Ok(Self::Dark),
_ => Err(format!("Unsupported app icon theme mode: {value}")),
}
}
fn png_bytes(self) -> &'static [u8] {
match self {
Self::Light => LIGHT_ICON_BYTES,
Self::Dark => DARK_ICON_BYTES,
}
}
}
pub fn update_app_icon_for_theme(
app_handle: &tauri::AppHandle,
theme_mode: &str,
) -> Result<(), String> {
let icon_bytes = AppIconMode::parse(theme_mode)?.png_bytes();
let image = tauri::image::Image::from_bytes(icon_bytes)
.map_err(|err| format!("Failed to decode app icon: {err}"))?;
for window in app_handle.webview_windows().into_values() {
window
.set_icon(image.clone())
.map_err(|err| format!("Failed to update window icon: {err}"))?;
}
apply_platform_app_icon(app_handle, icon_bytes)
}
#[cfg(target_os = "macos")]
fn apply_platform_app_icon(
app_handle: &tauri::AppHandle,
icon_bytes: &'static [u8],
) -> Result<(), String> {
app_handle
.run_on_main_thread(move || {
if let Err(err) = set_macos_application_icon(icon_bytes) {
log::warn!("Failed to update macOS application icon: {err}");
}
})
.map_err(|err| format!("Failed to schedule macOS app icon update: {err}"))
}
#[cfg(target_os = "macos")]
fn set_macos_application_icon(icon_bytes: &[u8]) -> Result<(), String> {
use objc2::AllocAnyThread;
use objc2_app_kit::{NSApplication, NSImage};
use objc2_foundation::{MainThreadMarker, NSData};
let marker = unsafe { MainThreadMarker::new_unchecked() };
let app = NSApplication::sharedApplication(marker);
let data = NSData::with_bytes(icon_bytes);
let app_icon = NSImage::initWithData(NSImage::alloc(), &data)
.ok_or_else(|| "Failed to create macOS app icon image".to_string())?;
unsafe { app.setApplicationIconImage(Some(&app_icon)) };
Ok(())
}
#[cfg(not(target_os = "macos"))]
fn apply_platform_app_icon(
_app_handle: &tauri::AppHandle,
_icon_bytes: &'static [u8],
) -> Result<(), String> {
Ok(())
}
#[cfg(test)]
mod tests {
use super::AppIconMode;
#[test]
fn parses_supported_icon_modes() {
assert_eq!(AppIconMode::parse("light"), Ok(AppIconMode::Light));
assert_eq!(AppIconMode::parse("dark"), Ok(AppIconMode::Dark));
}
#[test]
fn rejects_unknown_icon_modes() {
assert!(AppIconMode::parse("system").is_err());
}
}

View File

@@ -0,0 +1,11 @@
#[cfg(desktop)]
#[tauri::command]
pub fn update_app_icon(app_handle: tauri::AppHandle, theme_mode: String) -> Result<(), String> {
crate::app_icon::update_app_icon_for_theme(&app_handle, &theme_mode)
}
#[cfg(mobile)]
#[tauri::command]
pub fn update_app_icon(_theme_mode: String) -> Result<(), String> {
Ok(())
}

View File

@@ -1,4 +1,5 @@
mod ai;
mod app_icon;
mod clipboard;
mod delete;
mod folders;
@@ -14,6 +15,7 @@ mod version;
use std::borrow::Cow;
pub use ai::*;
pub use app_icon::*;
pub use clipboard::*;
pub use delete::*;
pub use folders::*;

View File

@@ -1,5 +1,6 @@
pub mod ai_agents;
pub mod ai_models;
mod app_icon;
pub mod app_updater;
pub mod claude_cli;
mod claude_invocation;
@@ -501,6 +502,7 @@ macro_rules! app_invoke_handler {
commands::get_settings,
commands::check_for_app_update,
commands::update_menu_state,
commands::update_app_icon,
commands::trigger_menu_command,
commands::update_current_window_min_size,
commands::perform_current_window_titlebar_double_click,

View File

@@ -7,6 +7,7 @@ import {
writeStoredThemeMode,
type ThemeMode,
} from '../lib/themeMode'
import { syncAppIconThemeMode } from '../lib/appIconTheme'
function resolveRuntimeThemeMode(themeMode: ThemeMode | null | undefined): ThemeMode {
if (themeMode) return themeMode
@@ -26,8 +27,9 @@ function writeThemeModeMirror(themeMode: ThemeMode): void {
}
function applySelectedThemeMode(themeMode: ThemeMode): void {
applyThemeSelectionToDocument(document, themeMode, currentMatchMedia())
const resolvedMode = applyThemeSelectionToDocument(document, themeMode, currentMatchMedia())
writeThemeModeMirror(themeMode)
void syncAppIconThemeMode(resolvedMode)
}
function getSystemThemeMediaQueryList(): MediaQueryList | null {

View File

@@ -0,0 +1,39 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { syncAppIconThemeMode } from './appIconTheme'
const mocks = vi.hoisted(() => ({
invoke: vi.fn(),
isTauri: vi.fn(),
}))
vi.mock('@tauri-apps/api/core', () => ({
invoke: mocks.invoke,
}))
vi.mock('../mock-tauri', () => ({
isTauri: mocks.isTauri,
}))
describe('syncAppIconThemeMode', () => {
beforeEach(() => {
mocks.invoke.mockReset()
mocks.isTauri.mockReset()
})
it('skips browser runs', async () => {
mocks.isTauri.mockReturnValue(false)
await syncAppIconThemeMode('dark')
expect(mocks.invoke).not.toHaveBeenCalled()
})
it('sends the resolved theme mode to Tauri', async () => {
mocks.isTauri.mockReturnValue(true)
mocks.invoke.mockResolvedValue(undefined)
await syncAppIconThemeMode('dark')
expect(mocks.invoke).toHaveBeenCalledWith('update_app_icon', { themeMode: 'dark' })
})
})

13
src/lib/appIconTheme.ts Normal file
View File

@@ -0,0 +1,13 @@
import { invoke } from '@tauri-apps/api/core'
import { isTauri } from '../mock-tauri'
import type { ResolvedThemeMode } from './themeMode'
export async function syncAppIconThemeMode(themeMode: ResolvedThemeMode): Promise<void> {
if (!isTauri()) return
try {
await invoke('update_app_icon', { themeMode })
} catch (error) {
console.warn('Failed to update app icon for theme mode', error)
}
}