diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 51fa5d9..293570b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,38 +15,22 @@ jobs: args: '--target aarch64-apple-darwin' arch: 'silicon' type: 'aarch64' - assetPattern: '[name]_[arch][ext]' - platform: 'macos-latest' args: '--target x86_64-apple-darwin' arch: 'silicon' type: 'x86_64' - assetPattern: '[name]_[arch][ext]' - platform: 'ubuntu-22.04' args: '' - assetPattern: '[name]_[arch][ext]' - variant: 'default' - - platform: 'ubuntu-22.04' - args: "--config '{\"bundle\":{\"createUpdaterArtifacts\":false}}'" - assetPattern: '[name]_[arch]_legacy[ext]' - variant: 'legacy' - - platform: 'ubuntu-24.04' - args: "--config '{\"bundle\":{\"createUpdaterArtifacts\":false}}'" - assetPattern: '[name]_[arch]_alternate[ext]' - variant: 'alternate' - platform: 'ubuntu-22.04-arm' args: '' - assetPattern: '[name]_[arch][ext]' - variant: 'default' - platform: 'windows-11-arm' args: '--target x86_64-pc-windows-msvc' arch: 'arm64' type: 'x86_64' - assetPattern: '[name]_[arch][ext]' - platform: "windows-11-arm" args: "--target aarch64-pc-windows-msvc" arch: 'arm64' type: 'aarch64' - assetPattern: '[name]_[arch][ext]' runs-on: ${{ matrix.platform }} env: @@ -61,14 +45,9 @@ jobs: node-version: lts/* cache: 'npm' - - name: Purge cargo - if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm' || matrix.platform == 'ubuntu-24.04' - run: | - rm -rf ~/.cargo/registry ~/.cargo/git ./target || true - - name: install Rust stable (linux only) uses: dtolnay/rust-toolchain@stable - if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm' || matrix.platform == 'ubuntu-24.04' + if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm' - name: install Rust stable (macos only) uses: dtolnay/rust-toolchain@stable @@ -86,49 +65,16 @@ jobs: uses: swatinem/rust-cache@v2 with: workspaces: './src-tauri -> target' - key: ${{ runner.os }}-${{ runner.arch }}${{ matrix.variant && format('-{0}', matrix.variant) || '' }} + key: ${{ runner.os }}-${{ runner.arch }} - name: install dependencies (linux only) - if: matrix.variant == 'default' || matrix.variant == 'alternate' + if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm' # This must match the platform value defined above. run: | sudo apt-get update sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf - - - name: install dependencies (linux legacy only) - if: matrix.variant == 'legacy' - run: | - sudo apt-get update - - sudo apt-get install -y \ - build-essential \ - curl \ - wget \ - file \ - libgtk-3-dev \ - libxdo-dev \ - libssl-dev \ - libappindicator3-dev \ - librsvg2-dev \ - patchelf - - mkdir -p /tmp/ubuntu-packages - cd /tmp/ubuntu-packages - wget https://launchpadlibrarian.net/723972773/libwebkit2gtk-4.1-0_2.44.0-0ubuntu0.22.04.1_amd64.deb - wget https://launchpadlibrarian.net/723972761/libwebkit2gtk-4.1-dev_2.44.0-0ubuntu0.22.04.1_amd64.deb - wget https://launchpadlibrarian.net/723972770/libjavascriptcoregtk-4.1-0_2.44.0-0ubuntu0.22.04.1_amd64.deb - wget https://launchpadlibrarian.net/723972746/libjavascriptcoregtk-4.1-dev_2.44.0-0ubuntu0.22.04.1_amd64.deb - wget https://launchpadlibrarian.net/723972735/gir1.2-javascriptcoregtk-4.1_2.44.0-0ubuntu0.22.04.1_amd64.deb - wget https://launchpadlibrarian.net/723972739/gir1.2-webkit2-4.1_2.44.0-0ubuntu0.22.04.1_amd64.deb - wget https://launchpadlibrarian.net/606433947/libicu70_70.1-2ubuntu1_amd64.deb - wget https://launchpadlibrarian.net/606433941/libicu-dev_70.1-2ubuntu1_amd64.deb - wget https://launchpadlibrarian.net/606433945/icu-devtools_70.1-2ubuntu1_amd64.deb - wget https://launchpadlibrarian.net/595623693/libjpeg8_8c-2ubuntu10_amd64.deb - wget https://launchpadlibrarian.net/587202140/libjpeg-turbo8_2.1.2-0ubuntu1_amd64.deb - wget https://launchpadlibrarian.net/592959859/xdg-desktop-portal-gtk_1.14.0-1build1_amd64.deb - sudo apt-get install -y /tmp/ubuntu-packages/*.deb - + - name: install dependencies (linux arm only) - if: matrix.platform == 'ubuntu-22.04-arm' + if: matrix.platform == 'ubuntu-22.04-arm' # This must match the platform value defined above. run: | sudo apt-get install -y xdg-utils libayatana-appindicator3-dev @@ -137,14 +83,6 @@ jobs: run: | cargo install trusted-signing-cli - - name: Override linuxdeploy (linux legacy only) - if: matrix.variant == 'legacy' - run: | - TAURI_TOOLKIT_PATH="${XDG_CACHE_HOME:-$HOME/.cache}/tauri" - mkdir -p "$TAURI_TOOLKIT_PATH" - wget https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20250213-2/linuxdeploy-x86_64.AppImage -O "$TAURI_TOOLKIT_PATH/linuxdeploy-x86_64.AppImage" - chmod +x "$TAURI_TOOLKIT_PATH/linuxdeploy-x86_64.AppImage" - - name: install frontend dependencies run: npm install @@ -172,7 +110,7 @@ jobs: echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV echo "Certificate imported." - - uses: tauri-apps/tauri-action@v0.5.23 + - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -198,7 +136,7 @@ jobs: tagName: v__VERSION__ releaseName: 'v__VERSION__' releaseBody: "\"Rclone\n\n# Rclone UI v__VERSION__\n- Bug squashing & improvements.\n\n**See the assets to download this version and install.**" - assetNamePattern: ${{ matrix.assetPattern }} + assetNamePattern: '[name]_[arch][ext]' releaseDraft: true prerelease: false args: ${{ matrix.args }} diff --git a/lib/store.ts b/lib/store.ts index d92a9db..1654632 100644 --- a/lib/store.ts +++ b/lib/store.ts @@ -111,10 +111,6 @@ interface PersistedState { lastSkippedVersion: string | undefined hideStartup: boolean - - themeV2: { - tray: 'light' | 'dark' | undefined - } } const getStorage = (store: LazyStore): StateStorage => ({ @@ -257,10 +253,6 @@ export const usePersistedStore = create()( lastSkippedVersion: undefined, hideStartup: false, - - themeV2: { - tray: undefined, - }, }), { name: 'store', diff --git a/lib/tray.ts b/lib/tray.ts index 2b68368..f2776ee 100644 --- a/lib/tray.ts +++ b/lib/tray.ts @@ -9,7 +9,6 @@ import { getAllWindows, getCurrentWindow } from '@tauri-apps/api/window' import { ask } from '@tauri-apps/plugin-dialog' import { platform } from '@tauri-apps/plugin-os' import { buildMenu } from './menu' -import { usePersistedStore } from './store' import { resetMainWindow } from './window' export async function triggerTrayRebuild() { @@ -25,76 +24,20 @@ async function getTray() { } async function resolveTrayIconForTheme() { - const existingTheme = usePersistedStore.getState().themeV2 - - if ('tray' in existingTheme && existingTheme.tray) { - return existingTheme.tray === 'dark' - ? 'icons/favicon/icon.png' - : 'icons/favicon/icon-light.png' - } - let theme: 'light' | 'dark' = 'dark' - - if (['macos', 'windows'].includes(platform())) { - try { - const detectedTheme = (await invoke('get_system_theme')) as - | 'light' - | 'dark' - | 'unknown' - - const currentWindow = getCurrentWindow() - const windowTheme = await currentWindow.theme() - - if (windowTheme !== detectedTheme) { - Sentry.captureException(new Error('Window theme mismatch'), { - extra: { - detectedTheme, - windowTheme, - os: platform(), - }, - }) - } - - if (detectedTheme === 'unknown') { - const answer = await ask( - 'Could not determine your system theme, please select the correct one below', - { - title: 'Hmm...', - okLabel: 'Dark', - cancelLabel: 'Light', - } - ) - - if (answer) { - theme = 'dark' - } else { - theme = 'light' - } - } else { - theme = detectedTheme - } - } catch {} - } else { - const answer = await ask( - 'Based on your tray/menubar, how do you want the icon to look?\n\nIf your menubar has a dark background select light, otherwise select dark.', - { - title: 'Greetings, Linux User', - okLabel: 'Dark', - cancelLabel: 'Light', - } - ) - - if (answer) { - theme = 'dark' + try { + if (platform() === 'macos') { + const t = (await invoke('get_system_theme')) || 'dark' + theme = t === 'dark' ? 'dark' : 'light' } else { - theme = 'light' + const currentWindow = getCurrentWindow() + const t = await currentWindow.theme() + theme = t === 'dark' ? 'dark' : 'light' } - } + } catch {} console.log('[resolveTrayIconForTheme] theme', theme) - usePersistedStore.setState({ themeV2: { tray: theme } }) - const pickedPath = theme === 'dark' ? 'icons/favicon/icon.png' : 'icons/favicon/icon-light.png' console.log('[resolveTrayIconForTheme] pickedPath', pickedPath) @@ -179,10 +122,10 @@ export async function initTray() { try { console.log('[initTray]') - // const initialIcon = await resolveResource('icons/favicon/frame_00_delay-0.1s.png') + const initialIcon = await resolveTrayIconForTheme() await TrayIcon.new({ id: 'main-tray', - icon: (await resolveResource('icons/favicon/icon.png'))!, + icon: initialIcon!, tooltip: 'Rclone', menuOnLeftClick: true, action: async (event: TrayIconEvent) => { diff --git a/package-lock.json b/package-lock.json index b101192..54a8855 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rclone-ui", - "version": "2.7.19", + "version": "2.7.20", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rclone-ui", - "version": "2.7.19", + "version": "2.7.20", "dependencies": { "@formkit/auto-animate": "^0.9.0", "@heroui/react": "^2.7.11", diff --git a/package.json b/package.json index 726beef..16f4699 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "rclone-ui", "private": true, - "version": "2.7.19", + "version": "2.7.20", "type": "module", "scripts": { "dev": "node scripts/buildExternal.js && vite", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e8513c1..adb9b4e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -255,10 +255,9 @@ checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "app" -version = "2.7.19" +version = "2.7.20" dependencies = [ "cocoa", - "dark-light", "fix-path-env", "log", "machine-uid", @@ -286,7 +285,7 @@ dependencies = [ "tauri-plugin-store", "tauri-plugin-updater", "x11rb", - "zbus 5.9.0", + "zbus", "zip 0.6.6", ] @@ -344,7 +343,7 @@ dependencies = [ "wayland-backend", "wayland-client", "wayland-protocols", - "zbus 5.9.0", + "zbus", ] [[package]] @@ -385,17 +384,6 @@ dependencies = [ "slab", ] -[[package]] -name = "async-fs" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" -dependencies = [ - "async-lock", - "blocking", - "futures-lite", -] - [[package]] name = "async-io" version = "2.5.0" @@ -1178,22 +1166,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "dark-light" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a76fa97167fa740dcdbfe18e8895601e1bc36525f09b044e00916e717c03a3c" -dependencies = [ - "dconf_rs", - "detect-desktop-environment", - "dirs 4.0.0", - "objc", - "rust-ini", - "web-sys", - "winreg 0.10.1", - "zbus 4.4.0", -] - [[package]] name = "darling" version = "0.20.11" @@ -1235,12 +1207,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" -[[package]] -name = "dconf_rs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7046468a81e6a002061c01e6a7c83139daf91b11c30e66795b13217c2d885c8b" - [[package]] name = "debugid" version = "0.8.0" @@ -1316,12 +1282,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "detect-desktop-environment" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21d8ad60dd5b13a4ee6bd8fa2d5d88965c597c67bce32b5fc49c94f55cb50810" - [[package]] name = "digest" version = "0.10.7" @@ -1435,12 +1395,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "dlv-list" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" - [[package]] name = "document-features" version = "0.2.11" @@ -3338,19 +3292,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "cfg_aliases 0.2.1", - "libc", - "memoffset", -] - [[package]] name = "nix" version = "0.30.1" @@ -3391,7 +3332,7 @@ dependencies = [ "mac-notification-sys", "serde", "tauri-winrt-notification", - "zbus 5.9.0", + "zbus", ] [[package]] @@ -3805,16 +3746,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "ordered-multimap" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" -dependencies = [ - "dlv-list", - "hashbrown 0.12.3", -] - [[package]] name = "ordered-stream" version = "0.2.0" @@ -4837,16 +4768,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "rust-ini" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" -dependencies = [ - "cfg-if", - "ordered-multimap", -] - [[package]] name = "rust_decimal" version = "1.37.2" @@ -6185,7 +6106,7 @@ dependencies = [ "thiserror 2.0.14", "url", "windows", - "zbus 5.9.0", + "zbus", ] [[package]] @@ -6279,7 +6200,7 @@ dependencies = [ "thiserror 2.0.14", "tracing", "windows-sys 0.60.2", - "zbus 5.9.0", + "zbus", ] [[package]] @@ -8107,16 +8028,6 @@ dependencies = [ "rustix 1.0.8", ] -[[package]] -name = "xdg-home" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "yoke" version = "0.8.0" @@ -8141,44 +8052,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zbus" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" -dependencies = [ - "async-broadcast", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "enumflags2", - "event-listener", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix 0.29.0", - "ordered-stream", - "rand 0.8.5", - "serde", - "serde_repr", - "sha1", - "static_assertions", - "tracing", - "uds_windows", - "windows-sys 0.52.0", - "xdg-home", - "zbus_macros 4.4.0", - "zbus_names 3.0.0", - "zvariant 4.2.0", -] - [[package]] name = "zbus" version = "5.9.0" @@ -8208,22 +8081,9 @@ dependencies = [ "uds_windows", "windows-sys 0.59.0", "winnow 0.7.12", - "zbus_macros 5.9.0", - "zbus_names 4.2.0", - "zvariant 5.6.0", -] - -[[package]] -name = "zbus_macros" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" -dependencies = [ - "proc-macro-crate 3.3.0", - "proc-macro2", - "quote", - "syn 2.0.104", - "zvariant_utils 2.1.0", + "zbus_macros", + "zbus_names", + "zvariant", ] [[package]] @@ -8236,20 +8096,9 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.104", - "zbus_names 4.2.0", - "zvariant 5.6.0", - "zvariant_utils 3.2.0", -] - -[[package]] -name = "zbus_names" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" -dependencies = [ - "serde", - "static_assertions", - "zvariant 4.2.0", + "zbus_names", + "zvariant", + "zvariant_utils", ] [[package]] @@ -8261,7 +8110,7 @@ dependencies = [ "serde", "static_assertions", "winnow 0.7.12", - "zvariant 5.6.0", + "zvariant", ] [[package]] @@ -8405,19 +8254,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "zvariant" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" -dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "zvariant_derive 4.2.0", -] - [[package]] name = "zvariant" version = "5.6.0" @@ -8429,21 +8265,8 @@ dependencies = [ "serde", "url", "winnow 0.7.12", - "zvariant_derive 5.6.0", - "zvariant_utils 3.2.0", -] - -[[package]] -name = "zvariant_derive" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" -dependencies = [ - "proc-macro-crate 3.3.0", - "proc-macro2", - "quote", - "syn 2.0.104", - "zvariant_utils 2.1.0", + "zvariant_derive", + "zvariant_utils", ] [[package]] @@ -8456,18 +8279,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.104", - "zvariant_utils 3.2.0", -] - -[[package]] -name = "zvariant_utils" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", + "zvariant_utils", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 10c556f..59ebcc4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "app" -version = "2.7.19" +version = "2.7.20" description = "A Tauri App" authors = ["you"] license = "" @@ -52,6 +52,3 @@ cocoa = "0.26" [target.'cfg(target_os = "linux")'.dependencies] zbus = { version = "5" } x11rb = "0.13" - -[target.'cfg(not(target_os = "linux"))'.dependencies] -dark-light = "1.1.1" diff --git a/src-tauri/flatpak.metainfo.xml b/src-tauri/flatpak.metainfo.xml index 91d2a40..8bb98b7 100644 --- a/src-tauri/flatpak.metainfo.xml +++ b/src-tauri/flatpak.metainfo.xml @@ -94,10 +94,10 @@ - - https://github.com/rclone-ui/rclone-ui/releases/tag/v2.7.19 + + https://github.com/rclone-ui/rclone-ui/releases/tag/v2.7.20 -

2.7.19 Release

+

2.7.20 Release

  • Improved Linux stability and overall performance.
diff --git a/src-tauri/icons/favicon/icon-light.png b/src-tauri/icons/favicon/icon-light.png index 538315b..ad31977 100644 Binary files a/src-tauri/icons/favicon/icon-light.png and b/src-tauri/icons/favicon/icon-light.png differ diff --git a/src-tauri/icons/favicon/icon.png b/src-tauri/icons/favicon/icon.png index 171298e..5bed538 100644 Binary files a/src-tauri/icons/favicon/icon.png and b/src-tauri/icons/favicon/icon.png differ diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6568cdb..0c8c703 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -250,21 +250,96 @@ fn get_uid() -> String { #[tauri::command] fn get_system_theme() -> String { - #[cfg(not(target_os = "linux"))] + #[cfg(target_os = "macos")] { - match dark_light::detect() { - dark_light::Mode::Dark => "dark".to_string(), - dark_light::Mode::Light => "light".to_string(), - dark_light::Mode::Default => "unknown".to_string(), + use std::process::Command; + if let Ok(output) = Command::new("defaults") + .args(&["read", "-g", "AppleInterfaceStyle"]) + .output() + { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("dark") { + return "dark".to_string(); + } + } } + return "light".to_string(); + } + + #[cfg(target_os = "windows")] + { + use std::process::Command; + if let Ok(output) = Command::new("reg").args(&[ + "query", + r"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", + "/v", + "AppsUseLightTheme", + ]).output() { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("0x0") || out.contains("0x00000000") { + return "dark".to_string(); + } + if out.contains("0x1") || out.contains("0x00000001") { + return "light".to_string(); + } + } + } + return "light".to_string(); } #[cfg(target_os = "linux")] { - "unknown".to_string() + use std::process::Command; + + // GNOME color-scheme (prefer-dark) + if let Ok(output) = Command::new("gsettings") + .args(&["get", "org.gnome.desktop.interface", "color-scheme"]) + .output() + { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("dark") { + return "dark".to_string(); + } + } + } + + // GNOME gtk-theme name contains "dark" + if let Ok(output) = Command::new("gsettings") + .args(&["get", "org.gnome.desktop.interface", "gtk-theme"]) + .output() + { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("dark") { + return "dark".to_string(); + } + } + } + + // KDE color scheme via kreadconfig5 + if let Ok(output) = Command::new("kreadconfig5") + .args(&["--group", "General", "--key", "ColorScheme"]) + .output() + { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("dark") { + return "dark".to_string(); + } + } + } + + return "light".to_string(); + } + + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] + { + "dark".to_string() } } - #[tauri::command] fn is_rclone_running(port: Option) -> bool { @@ -469,103 +544,52 @@ async fn prompt_text( if is_sensitive { // Try zenity password dialog first - match std::process::Command::new("zenity") + if let Ok(output) = std::process::Command::new("zenity") .args(&["--password", "--title", &title, "--text", &message]) .output() { - Ok(output) => { - if output.status.success() { - let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if output.status.success() { + let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if !result.is_empty() { return Ok(Some(result)); - } else { - // Check if user cancelled (exit code 1) or other error - let exit_code = output.status.code().unwrap_or(-1); - if exit_code == 1 { - // User clicked Cancel - return Ok(None); - } - // For other errors, fall through to try kdialog - let stderr = String::from_utf8_lossy(&output.stderr); - eprintln!("zenity password dialog failed (exit {}): {}", exit_code, stderr); } } - Err(e) => { - // Command not found or couldn't execute, try kdialog - eprintln!("zenity not available: {}", e); - } } // Fallback to kdialog password - match std::process::Command::new("kdialog") + if let Ok(output) = std::process::Command::new("kdialog") .args(&["--password", &message, "--title", &title]) .output() { - Ok(output) => { - if output.status.success() { - let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if output.status.success() { + let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if !result.is_empty() { return Ok(Some(result)); - } else { - let exit_code = output.status.code().unwrap_or(-1); - if exit_code == 1 { - // User clicked Cancel - return Ok(None); - } - let stderr = String::from_utf8_lossy(&output.stderr); - eprintln!("kdialog password dialog failed (exit {}): {}", exit_code, stderr); } } - Err(e) => { - eprintln!("kdialog not available: {}", e); - } } return Err("No suitable password dialog found. Please install zenity or kdialog.".to_string()); } else { // Try zenity text entry first - match std::process::Command::new("zenity") + if let Ok(output) = std::process::Command::new("zenity") .args(&["--entry", "--title", &title, "--text", &message, "--entry-text", &default_value]) .output() { - Ok(output) => { - if output.status.success() { - let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); - return Ok(Some(result)); - } else { - let exit_code = output.status.code().unwrap_or(-1); - if exit_code == 1 { - // User clicked Cancel - return Ok(None); - } - let stderr = String::from_utf8_lossy(&output.stderr); - eprintln!("zenity entry dialog failed (exit {}): {}", exit_code, stderr); - } - } - Err(e) => { - eprintln!("zenity not available: {}", e); + if output.status.success() { + let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); + return Ok(Some(result)); } } // Fallback to kdialog input box - match std::process::Command::new("kdialog") + if let Ok(output) = std::process::Command::new("kdialog") .args(&["--inputbox", &message, &default_value, "--title", &title]) .output() { - Ok(output) => { - if output.status.success() { - let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); - return Ok(Some(result)); - } else { - let exit_code = output.status.code().unwrap_or(-1); - if exit_code == 1 { - // User clicked Cancel - return Ok(None); - } - let stderr = String::from_utf8_lossy(&output.stderr); - eprintln!("kdialog inputbox failed (exit {}): {}", exit_code, stderr); - } - } - Err(e) => { - eprintln!("kdialog not available: {}", e); + if output.status.success() { + let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); + return Ok(Some(result)); } } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3ee9f88..7084891 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "https://schema.tauri.app/config/2", "productName": "Rclone UI", "mainBinaryName": "Rclone UI", - "version": "2.7.19", + "version": "2.7.20", "identifier": "com.rclone.ui", "build": { "frontendDist": "../dist", diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 365bdc2..d0f03e0 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -49,7 +49,7 @@ import { MedalIcon, PencilIcon, PlusIcon, - SatelliteDishIcon, + SatelliteDish, ServerIcon, Trash2Icon, } from 'lucide-react' @@ -213,7 +213,7 @@ function Settings() { key="proxy" title={
- + Proxy
} @@ -292,7 +292,11 @@ function GeneralSection() { const [isWorkingUpdate, setIsWorkingUpdate] = useState(false) const [update, setUpdate] = useState(null) - const [showServe, setShowServe] = useState(false) + const [rcloneVersion, setRcloneVersion] = useState<{ yours: string; latest: string } | null>( + null + ) + + const showServe = rcloneVersion?.yours && compareVersions(rcloneVersion.yours, '1.70.0') === 1 async function updateCallback() { if (!update) { @@ -393,28 +397,19 @@ function GeneralSection() { await getCurrentWindow().emit('relaunch-app') } - function updateDisabledActions({ - name, - value, - }: { name: (typeof disabledActions)[number]; value: boolean }) { - if (value) { - setDisabledActions(disabledActions?.filter((action) => action !== name) || []) - } else { - setDisabledActions([...(disabledActions || []), name]) - } - triggerTrayRebuild() - } - useEffect(() => { // needed since the first value from the persisted store is undefined setPasswordInput(settingsPass || '') }, [settingsPass]) + // biome-ignore lint/correctness/useExhaustiveDependencies: + useEffect(() => { + triggerTrayRebuild() + }, [disabledActions]) + useEffect(() => { getRcloneVersion().then((version) => { - if (version?.yours && compareVersions(version.yours, '1.70.0') === 1) { - setShowServe(true) - } + setRcloneVersion(version) }) }, []) @@ -530,66 +525,123 @@ function GeneralSection() { - updateDisabledActions({ name: 'tray-mount', value }) - } + onValueChange={(value) => { + if (value) { + setDisabledActions( + disabledActions?.filter((action) => action !== 'tray-mount') || + [] + ) + } else { + setDisabledActions([...(disabledActions || []), 'tray-mount']) + } + }} > Show Mount option - updateDisabledActions({ name: 'tray-sync', value }) - } + onValueChange={(value) => { + if (value) { + setDisabledActions( + disabledActions?.filter((action) => action !== 'tray-sync') || + [] + ) + } else { + setDisabledActions([...(disabledActions || []), 'tray-sync']) + } + }} > Show Sync option - updateDisabledActions({ name: 'tray-copy', value }) - } + onValueChange={(value) => { + if (value) { + setDisabledActions( + disabledActions?.filter((action) => action !== 'tray-copy') || + [] + ) + } else { + setDisabledActions([...(disabledActions || []), 'tray-copy']) + } + }} > Show Copy option - updateDisabledActions({ name: 'tray-move', value }) - } + onValueChange={(value) => { + if (value) { + setDisabledActions( + disabledActions?.filter((action) => action !== 'tray-move') || + [] + ) + } else { + setDisabledActions([...(disabledActions || []), 'tray-move']) + } + }} > Show Move option - updateDisabledActions({ name: 'tray-download', value }) - } + onValueChange={(value) => { + if (value) { + setDisabledActions( + disabledActions?.filter( + (action) => action !== 'tray-download' + ) || [] + ) + } else { + setDisabledActions([...(disabledActions || []), 'tray-download']) + } + }} > Show Download option - updateDisabledActions({ name: 'tray-serve', value }) - } + onValueChange={(value) => { + if (value) { + setDisabledActions( + disabledActions?.filter((action) => action !== 'tray-serve') || + [] + ) + } else { + setDisabledActions([...(disabledActions || []), 'tray-serve']) + } + }} isDisabled={!showServe} > Show Serve option - updateDisabledActions({ name: 'tray-purge', value }) - } + onValueChange={(value) => { + if (value) { + setDisabledActions( + disabledActions?.filter((action) => action !== 'tray-purge') || + [] + ) + } else { + setDisabledActions([...(disabledActions || []), 'tray-purge']) + } + }} > Show Purge option - updateDisabledActions({ name: 'tray-delete', value }) - } + onValueChange={(value) => { + if (value) { + setDisabledActions( + disabledActions?.filter((action) => action !== 'tray-delete') || + [] + ) + } else { + setDisabledActions([...(disabledActions || []), 'tray-delete']) + } + }} > Show Delete option