Repository: OpenSecretCloud/Maple
Pull request #42: Auto updater
Author: login: AnthonyRonning
Created: 2025-04-02T18:11:47Z | Merged: 2025-04-03T20:00:47Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Expanded the development environment to support a native desktop framework with automated background update checks.

- **Improvements**
  - Refined code quality checks by narrowing the analysis to specific source files and expanding ignored directories for better performance.
  - Upgraded key dependency versions and toolchain specifications to enhance stability and cross-platform support.
  - Introduced enhanced error handling and logging for the update process in desktop environments.

- **Version Updates**
  - Incremented application version to 0.2.0 in multiple configuration files.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/flake.lock b/flake.lock
index eb0f93ed..4ec6900f 100644
--- a/flake.lock
+++ b/flake.lock
@@ -34,10 +34,45 @@
         "type": "github"
       }
     },
+    "nixpkgs_2": {
+      "locked": {
+        "lastModified": 1743568003,
+        "narHash": "sha256-ZID5T65E8ruHqWRcdvZLsczWDOAWIE7om+vQOREwiX0=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "b7ba7f9f45c5cd0d8625e9e217c28f8eb6a19a76",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
     "root": {
       "inputs": {
         "flake-utils": "flake-utils",
-        "nixpkgs": "nixpkgs"
+        "nixpkgs": "nixpkgs",
+        "rust-overlay": "rust-overlay"
+      }
+    },
+    "rust-overlay": {
+      "inputs": {
+        "nixpkgs": "nixpkgs_2"
+      },
+      "locked": {
+        "lastModified": 1743561237,
+        "narHash": "sha256-dd97LXek202OWmUXvKYFdYWj0jHrn3p+L5Ojh1SEOqs=",
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "rev": "1de27ae43712a971c1da100dcd84386356f03ec7",
+        "type": "github"
+      },
+      "original": {
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "type": "github"
       }
     },
     "systems": {
diff --git a/flake.nix b/flake.nix
index 0932b4aa..1e5555c7 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,22 +1,56 @@
 {
-  description = "Cross-platform Bun development environment";
+  description = "Cross-platform Bun and Tauri development environment";
 
   inputs = {
     nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
     flake-utils.url = "github:numtide/flake-utils";
+    rust-overlay.url = "github:oxalica/rust-overlay";
   };
 
-  outputs = { self, nixpkgs, flake-utils }:
+  outputs = { self, nixpkgs, flake-utils, rust-overlay }:
     flake-utils.lib.eachDefaultSystem (system:
       let
-        pkgs = nixpkgs.legacyPackages.${system};
+        overlays = [ (import rust-overlay) ];
+        pkgs = import nixpkgs {
+          inherit system overlays;
+        };
+        
+        # Use specific rust version required by Tauri
+        rustToolchain = pkgs.rust-bin.stable."1.78.0".default.override {
+          extensions = [ "rust-src" ];
+        };
       in
       {
         devShells.default = pkgs.mkShell {
           packages = [
             pkgs.bun
             pkgs.just
-          ];
+            rustToolchain
+            
+            # Basic build dependencies
+            pkgs.pkg-config
+            pkgs.openssl
+            
+            # GTK dependencies for Tauri
+            pkgs.atk
+            pkgs.gtk3
+            pkgs.glib
+            pkgs.pango
+            pkgs.cairo
+            pkgs.gdk-pixbuf
+            pkgs.libsoup_3
+            pkgs.webkitgtk_4_1
+          ] ++ (if pkgs.stdenv.isDarwin then [
+            # macOS-specific dependencies
+            pkgs.darwin.apple_sdk.frameworks.WebKit
+            pkgs.darwin.apple_sdk.frameworks.AppKit
+          ] else []);
+          
+          # Set environment variables
+          shellHook = ''
+            echo "Using Rust version: $(rustc --version)"
+            echo "Tauri development environment ready"
+          '';
         };
       }
     );
diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js
index c4bc8f33..c4373ae9 100644
--- a/frontend/eslint.config.js
+++ b/frontend/eslint.config.js
@@ -6,8 +6,8 @@ import tseslint from 'typescript-eslint'
 
 export default tseslint.config({
   extends: [js.configs.recommended, ...tseslint.configs.recommended],
-  files: ['**/*.{ts,tsx}'],
-  ignores: ['dist'],
+  files: ['src/**/*.{ts,tsx}'],
+  ignores: ['dist', 'src-tauri', '**/target', '**/node_modules'],
   languageOptions: {
     ecmaVersion: 2020,
     globals: globals.browser,
diff --git a/frontend/package.json b/frontend/package.json
index ba3a4ffe..a2762418 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,12 +1,12 @@
 {
   "name": "maple",
   "private": true,
-  "version": "0.1.0",
+  "version": "0.2.0",
   "type": "module",
   "scripts": {
     "dev": "vite",
     "build": "tsc -b && vite build",
-    "lint": "eslint .",
+    "lint": "eslint './src/**/*.{ts,tsx}'",
     "preview": "vite preview",
     "add": "bunx shadcn-ui@latest add",
     "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
diff --git a/frontend/src-tauri/Cargo.lock b/frontend/src-tauri/Cargo.lock
index 359c5aa8..6e1415ee 100644
--- a/frontend/src-tauri/Cargo.lock
+++ b/frontend/src-tauri/Cargo.lock
@@ -105,6 +105,58 @@ version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
 
+[[package]]
+name = "ashpd"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df"
+dependencies = [
+ "enumflags2",
+ "futures-channel",
+ "futures-util",
+ "rand 0.9.0",
+ "raw-window-handle",
+ "serde",
+ "serde_repr",
+ "tokio",
+ "url",
+ "zbus",
+]
+
+[[package]]
+name = "async-broadcast"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
+dependencies = [
+ "event-listener",
+ "event-listener-strategy",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-recursion"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.88"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+]
+
 [[package]]
 name = "atk"
 version = "0.18.2"
@@ -188,12 +240,6 @@ dependencies = [
  "wyz",
 ]
 
-[[package]]
-name = "block"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
-
 [[package]]
 name = "block-buffer"
 version = "0.10.4"
@@ -384,12 +430,12 @@ dependencies = [
 
 [[package]]
 name = "cargo_toml"
-version = "0.21.0"
+version = "0.22.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472"
+checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257"
 dependencies = [
  "serde",
- "toml 0.8.20",
+ "toml",
 ]
 
 [[package]]
@@ -453,36 +499,6 @@ dependencies = [
  "windows-targets 0.52.6",
 ]
 
-[[package]]
-name = "cocoa"
-version = "0.26.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2"
-dependencies = [
- "bitflags 2.8.0",
- "block",
- "cocoa-foundation",
- "core-foundation",
- "core-graphics",
- "foreign-types",
- "libc",
- "objc",
-]
-
-[[package]]
-name = "cocoa-foundation"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d"
-dependencies = [
- "bitflags 2.8.0",
- "block",
- "core-foundation",
- "core-graphics-types",
- "libc",
- "objc",
-]
-
 [[package]]
 name = "combine"
 version = "4.6.7"
@@ -493,6 +509,15 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "concurrent-queue"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
+dependencies = [
+ "crossbeam-utils",
+]
+
 [[package]]
 name = "convert_case"
 version = "0.4.0"
@@ -708,34 +733,13 @@ dependencies = [
  "crypto-common",
 ]
 
-[[package]]
-name = "dirs"
-version = "5.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
-dependencies = [
- "dirs-sys 0.4.1",
-]
-
 [[package]]
 name = "dirs"
 version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
 dependencies = [
- "dirs-sys 0.5.0",
-]
-
-[[package]]
-name = "dirs-sys"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
-dependencies = [
- "libc",
- "option-ext",
- "redox_users 0.4.6",
- "windows-sys 0.48.0",
+ "dirs-sys",
 ]
 
 [[package]]
@@ -746,7 +750,7 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
 dependencies = [
  "libc",
  "option-ext",
- "redox_users 0.5.0",
+ "redox_users",
  "windows-sys 0.59.0",
 ]
 
@@ -756,6 +760,18 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
 
+[[package]]
+name = "dispatch2"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a0d569e003ff27784e0e14e4a594048698e0c0f0b66cabcb51511be55a7caa0"
+dependencies = [
+ "bitflags 2.8.0",
+ "block2 0.6.0",
+ "libc",
+ "objc2 0.6.0",
+]
+
 [[package]]
 name = "displaydoc"
 version = "0.2.5"
@@ -828,14 +844,14 @@ checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35"
 
 [[package]]
 name = "embed-resource"
-version = "2.5.1"
+version = "3.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b68b6f9f63a0b6a38bc447d4ce84e2b388f3ec95c99c641c8ff0dd3ef89a6379"
+checksum = "7fbc6e0d8e0c03a655b53ca813f0463d2c956bc4db8138dbc89f120b066551e3"
 dependencies = [
  "cc",
  "memchr",
  "rustc_version",
- "toml 0.8.20",
+ "toml",
  "vswhom",
  "winreg",
 ]
@@ -846,6 +862,33 @@ version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
 
+[[package]]
+name = "endi"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf"
+
+[[package]]
+name = "enumflags2"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147"
+dependencies = [
+ "enumflags2_derive",
+ "serde",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+]
+
 [[package]]
 name = "env_filter"
 version = "0.1.3"
@@ -882,6 +925,27 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
+[[package]]
+name = "event-listener"
+version = "5.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae"
+dependencies = [
+ "concurrent-queue",
+ "parking",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "event-listener-strategy"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
+dependencies = [
+ "event-listener",
+ "pin-project-lite",
+]
+
 [[package]]
 name = "fastrand"
 version = "2.3.0"
@@ -1028,6 +1092,19 @@ version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
 
+[[package]]
+name = "futures-lite"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "parking",
+ "pin-project-lite",
+]
+
 [[package]]
 name = "futures-macro"
 version = "0.3.31"
@@ -1544,9 +1621,9 @@ dependencies = [
 
 [[package]]
 name = "ico"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3804960be0bb5e4edb1e1ad67afd321a9ecfd875c3e65c099468fd2717d7cae"
+checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98"
 dependencies = [
  "byteorder",
  "png",
@@ -1719,15 +1796,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "infer"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847"
-dependencies = [
- "cfb",
-]
-
 [[package]]
 name = "infer"
 version = "0.19.0"
@@ -1950,15 +2018,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 
-[[package]]
-name = "malloc_buf"
-version = "0.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "maple"
 version = "0.1.0"
@@ -1968,8 +2027,11 @@ dependencies = [
  "serde_json",
  "tauri",
  "tauri-build",
+ "tauri-plugin",
+ "tauri-plugin-dialog",
  "tauri-plugin-log",
  "tauri-plugin-updater",
+ "tokio",
 ]
 
 [[package]]
@@ -2042,21 +2104,22 @@ dependencies = [
 
 [[package]]
 name = "muda"
-version = "0.15.3"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdae9c00e61cc0579bcac625e8ad22104c60548a025bfc972dc83868a28e1484"
+checksum = "4de14a9b5d569ca68d7c891d613b390cf5ab4f851c77aaa2f9e435555d3d9492"
 dependencies = [
  "crossbeam-channel",
  "dpi",
  "gtk",
  "keyboard-types",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-foundation 0.3.0",
  "once_cell",
  "png",
  "serde",
- "thiserror 1.0.69",
+ "thiserror 2.0.11",
  "windows-sys 0.59.0",
 ]
 
@@ -2096,6 +2159,19 @@ version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
 
+[[package]]
+name = "nix"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
+dependencies = [
+ "bitflags 2.8.0",
+ "cfg-if",
+ "cfg_aliases",
+ "libc",
+ "memoffset",
+]
+
 [[package]]
 name = "nodrop"
 version = "0.1.14"
@@ -2147,23 +2223,11 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "objc"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
-dependencies = [
- "malloc_buf",
-]
-
 [[package]]
 name = "objc-sys"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310"
-dependencies = [
- "cc",
-]
 
 [[package]]
 name = "objc2"
@@ -2182,69 +2246,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59"
 dependencies = [
  "objc2-encode",
+ "objc2-exception-helper",
 ]
 
 [[package]]
 name = "objc2-app-kit"
-version = "0.2.2"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
+checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb"
 dependencies = [
  "bitflags 2.8.0",
- "block2 0.5.1",
+ "block2 0.6.0",
  "libc",
- "objc2 0.5.2",
+ "objc2 0.6.0",
+ "objc2-cloud-kit",
  "objc2-core-data",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
  "objc2-core-image",
- "objc2-foundation 0.2.2",
- "objc2-quartz-core",
+ "objc2-foundation 0.3.0",
+ "objc2-quartz-core 0.3.0",
 ]
 
 [[package]]
-name = "objc2-app-kit"
+name = "objc2-cloud-kit"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb"
+checksum = "6c1948a9be5f469deadbd6bcb86ad7ff9e47b4f632380139722f7d9840c0d42c"
 dependencies = [
  "bitflags 2.8.0",
  "objc2 0.6.0",
  "objc2-foundation 0.3.0",
 ]
 
-[[package]]
-name = "objc2-cloud-kit"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
-dependencies = [
- "bitflags 2.8.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-core-location",
- "objc2-foundation 0.2.2",
-]
-
-[[package]]
-name = "objc2-contacts"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
-dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
-]
-
 [[package]]
 name = "objc2-core-data"
-version = "0.2.2"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
+checksum = "1f860f8e841f6d32f754836f51e6bc7777cd7e7053cf18528233f6811d3eceb4"
 dependencies = [
  "bitflags 2.8.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-foundation 0.3.0",
 ]
 
 [[package]]
@@ -2258,27 +2301,25 @@ dependencies = [
 ]
 
 [[package]]
-name = "objc2-core-image"
-version = "0.2.2"
+name = "objc2-core-graphics"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
+checksum = "f8dca602628b65356b6513290a21a6405b4d4027b8b250f0b98dddbb28b7de02"
 dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
- "objc2-metal",
+ "bitflags 2.8.0",
+ "objc2 0.6.0",
+ "objc2-core-foundation",
+ "objc2-io-surface",
 ]
 
 [[package]]
-name = "objc2-core-location"
-version = "0.2.2"
+name = "objc2-core-image"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
+checksum = "6ffa6bea72bf42c78b0b34e89c0bafac877d5f80bf91e159a5d96ea7f693ca56"
 dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-contacts",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-foundation 0.3.0",
 ]
 
 [[package]]
@@ -2287,6 +2328,15 @@ version = "4.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
 
+[[package]]
+name = "objc2-exception-helper"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 name = "objc2-foundation"
 version = "0.2.2"
@@ -2313,15 +2363,14 @@ dependencies = [
 ]
 
 [[package]]
-name = "objc2-link-presentation"
-version = "0.2.2"
+name = "objc2-io-surface"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
+checksum = "161a8b87e32610086e1a7a9e9ec39f84459db7b3a0881c1f16ca5a2605581c19"
 dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "bitflags 2.8.0",
+ "objc2 0.6.0",
+ "objc2-core-foundation",
 ]
 
 [[package]]
@@ -2344,7 +2393,7 @@ checksum = "a1ac59da3ceebc4a82179b35dc550431ad9458f9cc326e053f49ba371ce76c5a"
 dependencies = [
  "bitflags 2.8.0",
  "objc2 0.6.0",
- "objc2-app-kit 0.3.0",
+ "objc2-app-kit",
  "objc2-foundation 0.3.0",
 ]
 
@@ -2362,71 +2411,40 @@ dependencies = [
 ]
 
 [[package]]
-name = "objc2-symbols"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
-dependencies = [
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
-]
-
-[[package]]
-name = "objc2-ui-kit"
-version = "0.2.2"
+name = "objc2-quartz-core"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
+checksum = "6fb3794501bb1bee12f08dcad8c61f2a5875791ad1c6f47faa71a0f033f20071"
 dependencies = [
  "bitflags 2.8.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-cloud-kit",
- "objc2-core-data",
- "objc2-core-image",
- "objc2-core-location",
- "objc2-foundation 0.2.2",
- "objc2-link-presentation",
- "objc2-quartz-core",
- "objc2-symbols",
- "objc2-uniform-type-identifiers",
- "objc2-user-notifications",
-]
-
-[[package]]
-name = "objc2-uniform-type-identifiers"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
-dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-foundation 0.3.0",
 ]
 
 [[package]]
-name = "objc2-user-notifications"
-version = "0.2.2"
+name = "objc2-ui-kit"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
+checksum = "777a571be14a42a3990d4ebedaeb8b54cd17377ec21b92e8200ac03797b3bee1"
 dependencies = [
  "bitflags 2.8.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-core-location",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-core-foundation",
+ "objc2-foundation 0.3.0",
 ]
 
 [[package]]
 name = "objc2-web-kit"
-version = "0.2.2"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68bc69301064cebefc6c4c90ce9cba69225239e4b8ff99d445a2b5563797da65"
+checksum = "b717127e4014b0f9f3e8bba3d3f2acec81f1bde01f656823036e823ed2c94dce"
 dependencies = [
  "bitflags 2.8.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "block2 0.6.0",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-foundation 0.3.0",
 ]
 
 [[package]]
@@ -2450,6 +2468,16 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
 
+[[package]]
+name = "ordered-stream"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+]
+
 [[package]]
 name = "osakit"
 version = "0.3.1"
@@ -2489,6 +2517,12 @@ dependencies = [
  "system-deps",
 ]
 
+[[package]]
+name = "parking"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
+
 [[package]]
 name = "parking_lot"
 version = "0.12.3"
@@ -2708,7 +2742,7 @@ version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
 dependencies = [
- "zerocopy",
+ "zerocopy 0.7.35",
 ]
 
 [[package]]
@@ -2905,6 +2939,17 @@ dependencies = [
  "rand_core 0.6.4",
 ]
 
+[[package]]
+name = "rand"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+dependencies = [
+ "rand_chacha 0.9.0",
+ "rand_core 0.9.3",
+ "zerocopy 0.8.24",
+]
+
 [[package]]
 name = "rand_chacha"
 version = "0.2.2"
@@ -2925,6 +2970,16 @@ dependencies = [
  "rand_core 0.6.4",
 ]
 
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.3",
+]
+
 [[package]]
 name = "rand_core"
 version = "0.5.1"
@@ -2943,6 +2998,15 @@ dependencies = [
  "getrandom 0.2.15",
 ]
 
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom 0.3.1",
+]
+
 [[package]]
 name = "rand_hc"
 version = "0.2.0"
@@ -2976,17 +3040,6 @@ dependencies = [
  "bitflags 2.8.0",
 ]
 
-[[package]]
-name = "redox_users"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
-dependencies = [
- "getrandom 0.2.15",
- "libredox",
- "thiserror 1.0.69",
-]
-
 [[package]]
 name = "redox_users"
 version = "0.5.0"
@@ -3075,10 +3128,35 @@ dependencies = [
  "url",
  "wasm-bindgen",
  "wasm-bindgen-futures",
- "wasm-streams",
+ "wasm-streams",
+ "web-sys",
+ "webpki-roots",
+ "windows-registry",
+]
+
+[[package]]
+name = "rfd"
+version = "0.15.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80c844748fdc82aae252ee4594a89b6e7ebef1063de7951545564cbc4e57075d"
+dependencies = [
+ "ashpd",
+ "block2 0.6.0",
+ "dispatch2",
+ "glib-sys",
+ "gobject-sys",
+ "gtk-sys",
+ "js-sys",
+ "log",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-foundation 0.3.0",
+ "raw-window-handle",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
  "web-sys",
- "webpki-roots",
- "windows-registry",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -3471,6 +3549,15 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "simd-adler32"
 version = "0.3.7"
@@ -3534,7 +3621,7 @@ dependencies = [
  "log",
  "objc2 0.5.2",
  "objc2-foundation 0.2.2",
- "objc2-quartz-core",
+ "objc2-quartz-core 0.2.2",
  "raw-window-handle",
  "redox_syscall",
  "wasm-bindgen",
@@ -3574,6 +3661,12 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
 [[package]]
 name = "string_cache"
 version = "0.8.8"
@@ -3673,18 +3766,17 @@ dependencies = [
  "cfg-expr",
  "heck 0.5.0",
  "pkg-config",
- "toml 0.8.20",
+ "toml",
  "version-compare",
 ]
 
 [[package]]
 name = "tao"
-version = "0.31.1"
+version = "0.32.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3731d04d4ac210cd5f344087733943b9bfb1a32654387dad4d1c70de21aee2c9"
+checksum = "63c8b1020610b9138dd7b1e06cf259ae91aa05c30f3bd0d6b42a03997b92dec1"
 dependencies = [
  "bitflags 2.8.0",
- "cocoa",
  "core-foundation",
  "core-graphics",
  "crossbeam-channel",
@@ -3701,7 +3793,9 @@ dependencies = [
  "ndk",
  "ndk-context",
  "ndk-sys",
- "objc",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-foundation 0.3.0",
  "once_cell",
  "parking_lot",
  "raw-window-handle",
@@ -3710,7 +3804,7 @@ dependencies = [
  "unicode-segmentation",
  "url",
  "windows",
- "windows-core 0.58.0",
+ "windows-core 0.60.1",
  "windows-version",
  "x11-dl",
 ]
@@ -3751,13 +3845,13 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
 
 [[package]]
 name = "tauri"
-version = "2.2.5"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58a998b6be84104ca05c7e9a21f2180ddec020c8b84ea59a8fc8530a2a19588d"
+checksum = "4d08db1ff9e011e04014e737ec022610d756c0eae0b3b3a9037bccaf3003173a"
 dependencies = [
  "anyhow",
  "bytes",
- "dirs 6.0.0",
+ "dirs",
  "dunce",
  "embed_plist",
  "futures-util",
@@ -3771,9 +3865,9 @@ dependencies = [
  "log",
  "mime",
  "muda",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-foundation 0.3.0",
  "percent-encoding",
  "plist",
  "raw-window-handle",
@@ -3801,13 +3895,13 @@ dependencies = [
 
 [[package]]
 name = "tauri-build"
-version = "2.0.5"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e950124f6779c6cf98e3260c7a6c8488a74aa6350dd54c6950fdaa349bca2df"
+checksum = "0fd20e4661c2cce65343319e6e8da256958f5af958cafc47c0d0af66a55dcd17"
 dependencies = [
  "anyhow",
  "cargo_toml",
- "dirs 5.0.1",
+ "dirs",
  "glob",
  "heck 0.5.0",
  "json-patch",
@@ -3817,15 +3911,15 @@ dependencies = [
  "serde_json",
  "tauri-utils",
  "tauri-winres",
- "toml 0.8.20",
+ "toml",
  "walkdir",
 ]
 
 [[package]]
 name = "tauri-codegen"
-version = "2.0.4"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f77894f9ddb5cb6c04fcfe8c8869ebe0aded4dabf19917118d48be4a95599ab5"
+checksum = "458258b19032450ccf975840116ecf013e539eadbb74420bd890e8c56ab2b1a4"
 dependencies = [
  "base64 0.22.1",
  "brotli",
@@ -3850,9 +3944,9 @@ dependencies = [
 
 [[package]]
 name = "tauri-macros"
-version = "2.0.4"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3240a5caed760a532e8f687be6f05b2c7d11a1d791fb53ccc08cfeb3e5308736"
+checksum = "d402813d3b9c773a0fa58697c457c771f10e735498fdcb7b343264d18e5a601f"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
@@ -3864,9 +3958,9 @@ dependencies = [
 
 [[package]]
 name = "tauri-plugin"
-version = "2.0.4"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5841b9a0200e954ef7457f8d327091424328891e267a97b641dc246cc54d0dec"
+checksum = "a4190775d6ff73fe66d9af44c012739a2659720efd9c0e1e56a918678038699d"
 dependencies = [
  "anyhow",
  "glob",
@@ -3875,10 +3969,51 @@ dependencies = [
  "serde",
  "serde_json",
  "tauri-utils",
- "toml 0.8.20",
+ "toml",
  "walkdir",
 ]
 
+[[package]]
+name = "tauri-plugin-dialog"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcaf6e5d6062423a0f711a23c2a573ccba222b6a16a9322d8499928f27e41376"
+dependencies = [
+ "log",
+ "raw-window-handle",
+ "rfd",
+ "serde",
+ "serde_json",
+ "tauri",
+ "tauri-plugin",
+ "tauri-plugin-fs",
+ "thiserror 2.0.11",
+ "url",
+]
+
+[[package]]
+name = "tauri-plugin-fs"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88371e340ad2f07409a3b68294abe73f20bc9c1bc1b631a31dc37a3d0161f682"
+dependencies = [
+ "anyhow",
+ "dunce",
+ "glob",
+ "percent-encoding",
+ "schemars",
+ "serde",
+ "serde_json",
+ "serde_repr",
+ "tauri",
+ "tauri-plugin",
+ "tauri-utils",
+ "thiserror 2.0.11",
+ "toml",
+ "url",
+ "uuid",
+]
+
 [[package]]
 name = "tauri-plugin-log"
 version = "2.3.1"
@@ -3903,16 +4038,16 @@ dependencies = [
 
 [[package]]
 name = "tauri-plugin-updater"
-version = "2.6.1"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31bfcfb4a8318008d2108ccfba439d8263cf48867baabf372cb0e9f24771896"
+checksum = "d82da763248e635d60ee4aed56c862290e523acc838d83097171f9a544708387"
 dependencies = [
  "base64 0.22.1",
- "dirs 6.0.0",
+ "dirs",
  "flate2",
  "futures-util",
  "http",
- "infer 0.19.0",
+ "infer",
  "log",
  "minisign-verify",
  "osakit",
@@ -3935,10 +4070,11 @@ dependencies = [
 
 [[package]]
 name = "tauri-runtime"
-version = "2.3.0"
+version = "2.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2274ef891ccc0a8d318deffa9d70053f947664d12d58b9c0d1ae5e89237e01f7"
+checksum = "00ada7ac2f9276f09b8c3afffd3215fd5d9bff23c22df8a7c70e7ef67cacd532"
 dependencies = [
+ "cookie",
  "dpi",
  "gtk",
  "http",
@@ -3954,17 +4090,18 @@ dependencies = [
 
 [[package]]
 name = "tauri-runtime-wry"
-version = "2.3.0"
+version = "2.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3707b40711d3b9f6519150869e358ffbde7c57567fb9b5a8b51150606939b2a0"
+checksum = "cf2e5842c57e154af43a20a49c7efee0ce2578c20b4c2bdf266852b422d2e421"
 dependencies = [
  "gtk",
  "http",
  "jni",
  "log",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-foundation 0.3.0",
+ "once_cell",
  "percent-encoding",
  "raw-window-handle",
  "softbuffer",
@@ -3980,10 +4117,11 @@ dependencies = [
 
 [[package]]
 name = "tauri-utils"
-version = "2.1.1"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96fb10e7cc97456b2d5b9c03e335b5de5da982039a303a20d10006885e4523a0"
+checksum = "1f037e66c7638cc0a2213f61566932b9a06882b8346486579c90e4b019bac447"
 dependencies = [
+ "anyhow",
  "brotli",
  "cargo_metadata",
  "ctor",
@@ -3991,7 +4129,7 @@ dependencies = [
  "glob",
  "html5ever",
  "http",
- "infer 0.16.0",
+ "infer",
  "json-patch",
  "kuchikiki",
  "log",
@@ -4008,7 +4146,7 @@ dependencies = [
  "serde_with",
  "swift-rs",
  "thiserror 2.0.11",
- "toml 0.8.20",
+ "toml",
  "url",
  "urlpattern",
  "uuid",
@@ -4017,12 +4155,12 @@ dependencies = [
 
 [[package]]
 name = "tauri-winres"
-version = "0.1.1"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5993dc129e544393574288923d1ec447c857f3f644187f4fbf7d9a875fbfc4fb"
+checksum = "56eaa45f707bedf34d19312c26d350bc0f3c59a47e58e8adbeecdc850d2c13a0"
 dependencies = [
  "embed-resource",
- "toml 0.7.8",
+ "toml",
 ]
 
 [[package]]
@@ -4164,7 +4302,9 @@ dependencies = [
  "libc",
  "mio",
  "pin-project-lite",
+ "signal-hook-registry",
  "socket2",
+ "tracing",
  "windows-sys 0.52.0",
 ]
 
@@ -4191,18 +4331,6 @@ dependencies = [
  "tokio",
 ]
 
-[[package]]
-name = "toml"
-version = "0.7.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
-dependencies = [
- "serde",
- "serde_spanned",
- "toml_datetime",
- "toml_edit 0.19.15",
-]
-
 [[package]]
 name = "toml"
 version = "0.8.20"
@@ -4231,8 +4359,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 dependencies = [
  "indexmap 2.7.1",
- "serde",
- "serde_spanned",
  "toml_datetime",
  "winnow 0.5.40",
 ]
@@ -4295,9 +4421,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
 dependencies = [
  "pin-project-lite",
+ "tracing-attributes",
  "tracing-core",
 ]
 
+[[package]]
+name = "tracing-attributes"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+]
+
 [[package]]
 name = "tracing-core"
 version = "0.1.33"
@@ -4309,22 +4447,23 @@ dependencies = [
 
 [[package]]
 name = "tray-icon"
-version = "0.19.2"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d48a05076dd272615d03033bf04f480199f7d1b66a8ac64d75c625fc4a70c06b"
+checksum = "d433764348e7084bad2c5ea22c96c71b61b17afe3a11645710f533bd72b6a2b5"
 dependencies = [
- "core-graphics",
  "crossbeam-channel",
- "dirs 5.0.1",
+ "dirs",
  "libappindicator",
  "muda",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-foundation 0.3.0",
  "once_cell",
  "png",
  "serde",
- "thiserror 1.0.69",
+ "thiserror 2.0.11",
  "windows-sys 0.59.0",
 ]
 
@@ -4346,6 +4485,17 @@ version = "1.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
 
+[[package]]
+name = "uds_windows"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9"
+dependencies = [
+ "memoffset",
+ "tempfile",
+ "winapi",
+]
+
 [[package]]
 name = "unic-char-property"
 version = "0.9.0"
@@ -4700,14 +4850,14 @@ dependencies = [
 
 [[package]]
 name = "webview2-com"
-version = "0.34.0"
+version = "0.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "823e7ebcfaea51e78f72c87fc3b65a1e602c321f407a0b36dbb327d7bb7cd921"
+checksum = "b0d606f600e5272b514dbb66539dd068211cc20155be8d3958201b4b5bd79ed3"
 dependencies = [
  "webview2-com-macros",
  "webview2-com-sys",
  "windows",
- "windows-core 0.58.0",
+ "windows-core 0.60.1",
  "windows-implement",
  "windows-interface",
 ]
@@ -4725,13 +4875,13 @@ dependencies = [
 
 [[package]]
 name = "webview2-com-sys"
-version = "0.34.0"
+version = "0.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a82bce72db6e5ee83c68b5de1e2cd6ea195b9fbff91cb37df5884cbe3222df4"
+checksum = "bfb27fccd3c27f68e9a6af1bcf48c2d82534b8675b83608a4d81446d095a17ac"
 dependencies = [
- "thiserror 1.0.69",
+ "thiserror 2.0.11",
  "windows",
- "windows-core 0.58.0",
+ "windows-core 0.60.1",
 ]
 
 [[package]]
@@ -4767,13 +4917,14 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "window-vibrancy"
-version = "0.5.3"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "831ad7678290beae36be6f9fad9234139c7f00f3b536347de7745621716be82d"
+checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c"
 dependencies = [
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-foundation 0.3.0",
  "raw-window-handle",
  "windows-sys 0.59.0",
  "windows-version",
@@ -4781,12 +4932,24 @@ dependencies = [
 
 [[package]]
 name = "windows"
-version = "0.58.0"
+version = "0.60.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
+checksum = "ddf874e74c7a99773e62b1c671427abf01a425e77c3d3fb9fb1e4883ea934529"
 dependencies = [
- "windows-core 0.58.0",
- "windows-targets 0.52.6",
+ "windows-collections",
+ "windows-core 0.60.1",
+ "windows-future",
+ "windows-link",
+ "windows-numerics",
+]
+
+[[package]]
+name = "windows-collections"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5467f79cc1ba3f52ebb2ed41dbb459b8e7db636cc3429458d9a852e15bc24dec"
+dependencies = [
+ "windows-core 0.60.1",
 ]
 
 [[package]]
@@ -4800,22 +4963,32 @@ dependencies = [
 
 [[package]]
 name = "windows-core"
-version = "0.58.0"
+version = "0.60.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
+checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247"
 dependencies = [
  "windows-implement",
  "windows-interface",
- "windows-result",
- "windows-strings",
- "windows-targets 0.52.6",
+ "windows-link",
+ "windows-result 0.3.2",
+ "windows-strings 0.3.1",
+]
+
+[[package]]
+name = "windows-future"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a787db4595e7eb80239b74ce8babfb1363d8e343ab072f2ffe901400c03349f0"
+dependencies = [
+ "windows-core 0.60.1",
+ "windows-link",
 ]
 
 [[package]]
 name = "windows-implement"
-version = "0.58.0"
+version = "0.59.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
+checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4824,23 +4997,39 @@ dependencies = [
 
 [[package]]
 name = "windows-interface"
-version = "0.58.0"
+version = "0.59.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
 dependencies = [
  "proc-macro2",
  "quote",
  "syn 2.0.98",
 ]
 
+[[package]]
+name = "windows-link"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
+
+[[package]]
+name = "windows-numerics"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "005dea54e2f6499f2cee279b8f703b3cf3b5734a2d8d21867c8f44003182eeed"
+dependencies = [
+ "windows-core 0.60.1",
+ "windows-link",
+]
+
 [[package]]
 name = "windows-registry"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
 dependencies = [
- "windows-result",
- "windows-strings",
+ "windows-result 0.2.0",
+ "windows-strings 0.1.0",
  "windows-targets 0.52.6",
 ]
 
@@ -4853,16 +5042,34 @@ dependencies = [
  "windows-targets 0.52.6",
 ]
 
+[[package]]
+name = "windows-result"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
+dependencies = [
+ "windows-link",
+]
+
 [[package]]
 name = "windows-strings"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
 dependencies = [
- "windows-result",
+ "windows-result 0.2.0",
  "windows-targets 0.52.6",
 ]
 
+[[package]]
+name = "windows-strings"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
+dependencies = [
+ "windows-link",
+]
+
 [[package]]
 name = "windows-sys"
 version = "0.45.0"
@@ -5201,12 +5408,12 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
 
 [[package]]
 name = "wry"
-version = "0.48.1"
+version = "0.50.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2e33c08b174442ff80d5c791020696f9f8b4e4a87b8cfc7494aad6167ec44e1"
+checksum = "b19b78efae8b853c6c817e8752fc1dbf9cab8a8ffe9c30f399bd750ccf0f0730"
 dependencies = [
  "base64 0.22.1",
- "block2 0.5.1",
+ "block2 0.6.0",
  "cookie",
  "crossbeam-channel",
  "dpi",
@@ -5220,9 +5427,10 @@ dependencies = [
  "kuchikiki",
  "libc",
  "ndk",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "objc2 0.6.0",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-foundation 0.3.0",
  "objc2-ui-kit",
  "objc2-web-kit",
  "once_cell",
@@ -5237,7 +5445,7 @@ dependencies = [
  "webkit2gtk-sys",
  "webview2-com",
  "windows",
- "windows-core 0.58.0",
+ "windows-core 0.60.1",
  "windows-version",
  "x11-dl",
 ]
@@ -5282,6 +5490,16 @@ dependencies = [
  "rustix",
 ]
 
+[[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.7.5"
@@ -5306,6 +5524,63 @@ dependencies = [
  "synstructure",
 ]
 
+[[package]]
+name = "zbus"
+version = "5.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59c333f648ea1b647bc95dc1d34807c8e25ed7a6feff3394034dc4776054b236"
+dependencies = [
+ "async-broadcast",
+ "async-recursion",
+ "async-trait",
+ "enumflags2",
+ "event-listener",
+ "futures-core",
+ "futures-lite",
+ "hex",
+ "nix",
+ "ordered-stream",
+ "serde",
+ "serde_repr",
+ "static_assertions",
+ "tokio",
+ "tracing",
+ "uds_windows",
+ "windows-sys 0.59.0",
+ "winnow 0.7.2",
+ "xdg-home",
+ "zbus_macros",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus_macros"
+version = "5.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f325ad10eb0d0a3eb060203494c3b7ec3162a01a59db75d2deee100339709fc0"
+dependencies = [
+ "proc-macro-crate 3.2.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+ "zbus_names",
+ "zvariant",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zbus_names"
+version = "4.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97"
+dependencies = [
+ "serde",
+ "static_assertions",
+ "winnow 0.7.2",
+ "zvariant",
+]
+
 [[package]]
 name = "zerocopy"
 version = "0.7.35"
@@ -5313,7 +5588,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
 dependencies = [
  "byteorder",
- "zerocopy-derive",
+ "zerocopy-derive 0.7.35",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
+dependencies = [
+ "zerocopy-derive 0.8.24",
 ]
 
 [[package]]
@@ -5327,6 +5611,17 @@ dependencies = [
  "syn 2.0.98",
 ]
 
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+]
+
 [[package]]
 name = "zerofrom"
 version = "0.1.5"
@@ -5388,3 +5683,46 @@ dependencies = [
  "indexmap 2.7.1",
  "memchr",
 ]
+
+[[package]]
+name = "zvariant"
+version = "5.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2df9ee044893fcffbdc25de30546edef3e32341466811ca18421e3cd6c5a3ac"
+dependencies = [
+ "endi",
+ "enumflags2",
+ "serde",
+ "static_assertions",
+ "url",
+ "winnow 0.7.2",
+ "zvariant_derive",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zvariant_derive"
+version = "5.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74170caa85b8b84cc4935f2d56a57c7a15ea6185ccdd7eadb57e6edd90f94b2f"
+dependencies = [
+ "proc-macro-crate 3.2.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zvariant_utils"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde",
+ "static_assertions",
+ "syn 2.0.98",
+ "winnow 0.7.2",
+]
diff --git a/frontend/src-tauri/Cargo.toml b/frontend/src-tauri/Cargo.toml
index e43d83be..0a35b34d 100644
--- a/frontend/src-tauri/Cargo.toml
+++ b/frontend/src-tauri/Cargo.toml
@@ -21,6 +21,9 @@ tauri-build = { version = "2.0.4", features = [] }
 serde_json = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 log = "0.4"
-tauri = { version = "2.2.4", features = [] }
+tauri = { version = "2.4.1", features = [] }
 tauri-plugin-log = "2.3.1"
-tauri-plugin-updater = "2.0.0-rc"
+tauri-plugin-updater = "2.7.0"
+tauri-plugin-dialog = "2.2.1"
+tauri-plugin = "2.1.1"
+tokio = { version = "1.0", features = ["time"] }
diff --git a/frontend/src-tauri/build.rs b/frontend/src-tauri/build.rs
index 795b9b7c..d860e1e6 100644
--- a/frontend/src-tauri/build.rs
+++ b/frontend/src-tauri/build.rs
@@ -1,3 +1,3 @@
 fn main() {
-  tauri_build::build()
+    tauri_build::build()
 }
diff --git a/frontend/src-tauri/src/lib.rs b/frontend/src-tauri/src/lib.rs
index d53c634d..ca2cd29f 100644
--- a/frontend/src-tauri/src/lib.rs
+++ b/frontend/src-tauri/src/lib.rs
@@ -1,15 +1,224 @@
 #[cfg_attr(mobile, tauri::mobile_entry_point)]
 pub fn run() {
-  tauri::Builder::default()
-    .setup(|app| {
-      app.handle().plugin(
-        tauri_plugin_log::Builder::default()
-          .level(log::LevelFilter::Info)
-          .build(),
-      )?;
-      Ok(())
-    })
-    .plugin(tauri_plugin_updater::Builder::new().build())
-    .run(tauri::generate_context!())
-    .expect("error while running tauri application");
+    #[cfg(desktop)]
+    let app = tauri::Builder::default()
+        .plugin(tauri_plugin_log::Builder::default().level(log::LevelFilter::Info).build())
+        .plugin(tauri_plugin_dialog::init())
+        .setup(|app| {
+            // Create the application menu with update options
+            #[cfg(desktop)]
+            {
+                // Set up a simple updater handler
+                log::info!("Setting up automatic updater");
+
+                // Setup update check on startup with delay
+                let app_handle = app.handle().clone();
+                tauri::async_runtime::spawn(async move {
+                    // Wait for app to fully initialize (use async sleep to not block the thread)
+                    tokio::time::sleep(std::time::Duration::from_secs(5)).await;
+                    log::info!("Performing automatic update check on startup");
+
+                    // This will check for updates, download if available, and install them
+                    // The update will be applied silently in the background
+                    // It will take effect the next time the application is started
+                    let _ = check_for_updates(app_handle).await;
+                });
+
+                // Create a native menu with a "Check for Updates" option
+                {
+                    #[cfg(target_os = "macos")]
+                    use tauri::menu::{MenuBuilder, SubmenuBuilder};
+
+                    #[cfg(not(target_os = "macos"))]
+                    use tauri::menu::MenuBuilder;
+
+                    // Define menu item ID for "Check for Updates"
+                    let check_updates_id = "check-for-updates";
+
+                    // Get app handle for menu operations
+                    let handle = app.handle();
+
+                    // Build platform-specific menus
+                    #[cfg(target_os = "macos")]
+                    {
+                        // For macOS, we need to create a proper submenu structure
+                        // First create the app submenu (first submenu becomes the application menu)
+                        let app_submenu = SubmenuBuilder::new(handle, &app.package_info().name)
+                            // Add about menu item (standard macOS menu item)
+                            .about(None)
+                            // Add our update checker to the app menu
+                            .text(check_updates_id, "Check for Updates")
+                            .build()?;
+
+                        // Create the main menu and add our app submenu
+                        let menu = MenuBuilder::new(handle).items(&[&app_submenu]).build()?;
+
+                        // Set as the application menu
+                        app.set_menu(menu)?;
+
+                        // Log that we're setting up the menu
+                        log::info!(
+                            "Setting up macOS menu with app submenu containing About and Check for Updates options"
+                        );
+                    }
+
+                    #[cfg(not(target_os = "macos"))]
+                    {
+                        // For Windows/Linux, we can create a simpler menu
+                        let menu = MenuBuilder::new(handle)
+                            .about(None)
+                            .text(check_updates_id, "Check for Updates")
+                            .separator()
+                            .quit()
+                            .build()?;
+
+                        app.set_menu(menu)?;
+
+                        log::info!("Setting up Windows/Linux menu with About and Check for Updates options");
+                    }
+
+                    // Handle menu events
+                    let app_handle_for_menu = app.handle().clone();
+                    app.on_menu_event(move |_window, event| {
+                        // Menu event handler receives events for all menu items
+                        log::info!("Menu event received: {:?}", event.id());
+
+                        // Check for our menu ID - works the same on all platforms now
+                        if event.id().0 == check_updates_id {
+                            log::info!(
+                                "Check for updates menu item clicked - triggering update check..."
+                            );
+
+                            // Clone the app handle to use in the async task
+                            let app_handle_clone = app_handle_for_menu.clone();
+
+                            // Spawn a new async task to check for updates (non-blocking)
+                            tauri::async_runtime::spawn(async move {
+                                match check_for_updates(app_handle_clone).await {
+                                    Ok(_) => log::info!("Update check completed successfully"),
+                                    Err(e) => log::error!("Update check failed: {}", e),
+                                }
+                            });
+                        }
+                    });
+                }
+            }
+
+            Ok(())
+        })
+        .plugin(tauri_plugin_updater::Builder::new().build());
+
+    #[cfg(not(desktop))]
+    let app = tauri::Builder::default()
+        .plugin(
+            tauri_plugin_log::Builder::default()
+                .level(log::LevelFilter::Info)
+                .build(),
+        )
+        .plugin(tauri_plugin_updater::Builder::new().build());
+
+    app.run(tauri::generate_context!())
+        .expect("error while running tauri application");
+}
+
+/// Check for updates silently in the background
+#[cfg(desktop)]
+async fn check_for_updates(app_handle: tauri::AppHandle) -> Result<(), String> {
+    use tauri_plugin_updater::UpdaterExt;
+
+    log::info!("Checking for updates...");
+
+    // Get the updater
+    let updater = match app_handle.updater() {
+        Ok(u) => u,
+        Err(e) => {
+            log::error!("Failed to get updater: {}", e);
+            return Err(format!("Failed to get updater: {}", e));
+        }
+    };
+
+    // Check for updates
+    match updater.check().await {
+        Ok(Some(update)) => {
+            log::info!("Update available, attempting to download and install");
+
+            // Download the update
+            let progress_fn = |downloaded: usize, total: Option<u64>| {
+                if let Some(total) = total {
+                    log::info!("Download progress: {}/{} bytes", downloaded, total);
+                } else {
+                    log::info!("Download progress: {} bytes", downloaded);
+                }
+            };
+
+            let download_complete = || {
+                log::info!("Download complete!");
+            };
+
+            match update.download(progress_fn, download_complete).await {
+                Ok(bytes) => {
+                    log::info!("Update downloaded successfully");
+                    log::info!("Installing update to version {}", update.version);
+
+                    // Try to install the update immediately
+                    match update.install(bytes) {
+                        Ok(_) => {
+                            // Log that the update is ready
+                            log::info!("Update installed successfully. Will be applied on next application restart.");
+
+                            // Show a dialog prompting the user to restart
+                            let message = format!(
+                                "An update to version {} has been downloaded and is ready to install. \
+                                Would you like to restart the application now to apply the update?", 
+                                update.version
+                            );
+
+                            use tauri_plugin_dialog::{
+                                DialogExt, MessageDialogButtons, MessageDialogKind,
+                            };
+                            let dialog = app_handle.dialog();
+
+                            // Show a friendly info dialog with Yes/No buttons
+                            dialog
+                                .message(message)
+                                .title("Update Ready")
+                                .kind(MessageDialogKind::Info) // Use info icon for a friendlier look
+                                .buttons(MessageDialogButtons::OkCancelCustom(
+                                    "Yes".to_string(),
+                                    "No".to_string(),
+                                ))
+                                .show(move |should_restart| {
+                                    if should_restart {
+                                        log::info!("User chose to restart now for update");
+
+                                        // Restart the application instead of just exiting
+                                        // This will automatically apply the update
+                                        app_handle.restart();
+                                    } else {
+                                        log::info!("User chose to postpone update restart");
+                                    }
+                                });
+                        }
+                        Err(e) => {
+                            log::error!("Failed to install update: {}", e);
+                        }
+                    }
+
+                    Ok(())
+                }
+                Err(e) => {
+                    log::error!("Failed to download update: {}", e);
+                    Err(format!("Failed to download update: {}", e))
+                }
+            }
+        }
+        Ok(None) => {
+            log::info!("No updates available");
+            Ok(())
+        }
+        Err(e) => {
+            log::error!("Failed to check for updates: {}", e);
+            Err(format!("Failed to check for updates: {}", e))
+        }
+    }
 }
diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs
index ad5fe839..69c3a72e 100644
--- a/frontend/src-tauri/src/main.rs
+++ b/frontend/src-tauri/src/main.rs
@@ -2,5 +2,5 @@
 #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
 
 fn main() {
-  app_lib::run();
+    app_lib::run();
 }
diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json
index 5050e497..236e5a28 100644
--- a/frontend/src-tauri/tauri.conf.json
+++ b/frontend/src-tauri/tauri.conf.json
@@ -1,7 +1,7 @@
 {
   "$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
   "productName": "Maple",
-  "version": "0.1.0",
+  "version": "0.2.0",
   "identifier": "cloud.opensecret.maple",
   "build": {
     "frontendDist": "../dist",


Reviews:
user: login: greptile-apps[bot]
body: 
## PR Summary

This pull request refines linting and dependency configurations while adding an automatic updater feature for desktop builds in the Tauri application.

- Enhanced linting scope in frontend/package.json and frontend/eslint.config.js for targeted TypeScript files.
- Updated Tauri and plugin versions in frontend/src-tauri/Cargo.toml for improved functionality.
- Introduced an auto updater in frontend/src-tauri/src/lib.rs with asynchronous update checks and progress logging (note blocking sleep in async context).
- Adjusted dependencies in flake.nix to meet Tauri’s development requirements.
- Minor stylistic updates in frontend/src-tauri/build.rs and frontend/src-tauri/src/main.rs.

<sub>7 file(s) reviewed, 1 comment(s)</sub>
<sub>[Edit PR Review Bot Settings](https://app.greptile.com/review/github) | [Greptile](https://greptile.com?utm_source=greptile_expert&utm_medium=github&utm_campaign=code_reviews&utm_content=maple_42)</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T18:13:03Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 453c53b11f7d465a486fc8438e046075ce488f0b and 163a2f26a5751337044c06cad090f792ee631a11.

</details>

<details>
<summary>⛔ Files ignored due to path filters (2)</summary>

* `flake.lock` is excluded by `!**/*.lock`
* `frontend/src-tauri/Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `flake.nix` (1 hunks)
* `frontend/eslint.config.js` (1 hunks)
* `frontend/package.json` (1 hunks)
* `frontend/src-tauri/Cargo.toml` (1 hunks)
* `frontend/src-tauri/build.rs` (1 hunks)
* `frontend/src-tauri/src/lib.rs` (1 hunks)
* `frontend/src-tauri/src/main.rs` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>frontend/src-tauri/src/main.rs (1)</summary><blockquote>

<details>
<summary>frontend/src-tauri/src/lib.rs (1)</summary>

* `run` (2-53)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: build-macos (universal-apple-darwin)
* GitHub Check: build-linux
* GitHub Check: Cloudflare Pages

</details>

<details>
<summary>🔇 Additional comments (13)</summary><blockquote>

<details>
<summary>frontend/src-tauri/src/main.rs (1)</summary>

`4-5`: **LGTM - Proper indentation adjustment**

The indentation change properly aligns with Rust's conventional 4-space indentation standards and doesn't affect functionality. This main function appropriately delegates to the `app_lib::run()` function, which now includes the auto-update functionality.

</details>
<details>
<summary>frontend/src-tauri/build.rs (1)</summary>

`1-2`: **LGTM - Proper indentation adjustment**

The indentation change aligns with Rust's conventional 4-space indentation standards and doesn't affect functionality. This standard build script correctly calls `tauri_build::build()` for setting up the Tauri build environment.

</details>
<details>
<summary>frontend/package.json (1)</summary>

`9-9`: **LGTM - Better targeted linting scope**

The updated lint command appropriately narrows the scope to only TypeScript/TSX files in the source directory. This improves linting performance and focuses on relevant source files while avoiding potential issues with generated files or dependencies.

</details>
<details>
<summary>frontend/src-tauri/Cargo.toml (1)</summary>

`24-27`: **LGTM - Appropriate dependency updates for auto-updater functionality**

The dependency updates are aligned with the PR's auto-updater objective:
- `tauri` updated to v2.4.1
- `tauri-plugin-updater` upgraded from RC to stable v2.7.0
- Added `tauri-plugin` v2.1.1 base dependency

These specific versions should provide stable auto-update capabilities and proper plugin support.

</details>
<details>
<summary>frontend/eslint.config.js (1)</summary>

`9-10`: **LGTM - Improved ESLint targeting and exclusions**

The changes appropriately refine ESLint's scope:
1. Focusing only on TypeScript files in the source directory
2. Explicitly excluding Rust/Tauri code and build artifacts

This configuration properly accommodates the mixed JavaScript/Rust codebase and aligns with the package.json lint script changes, avoiding potential linting issues in non-source files.

</details>
<details>
<summary>frontend/src-tauri/src/lib.rs (4)</summary>

`3-11`: **Desktop builder plugin looks good.**

Your introduction of the Tauri log plugin for the desktop configuration is straightforward and well-structured.

---

`39-49`: **Non-desktop setup is consistent and sufficient.**

For non-desktop platforms, the logging setup is analogous to the desktop config. This keeps implementation consistent across targets.

---

`51-53`: **Launch flow is clear.**

Running the app with the generated Tauri context and handling the error at this entry point is suitable.

---

`55-122`: **Background updater function is robust.**

The error handling and progress logging in `check_for_updates` look thorough. If needed, you may capture or log its return value in the caller to confirm all errors are surfaced. Otherwise, this separation is acceptable.  


Would you like to confirm if ignoring the returned `Result` from `check_for_updates` is fully intentional?

</details>
<details>
<summary>flake.nix (4)</summary>

`2-2`: **Description accurately reflects Tauri addition.**

Renaming it to "Cross-platform Bun and Tauri development environment" is appropriate and clarifies the new scope.

---

`7-16`: **Overlay usage looks correct.**

Bringing in `rust-overlay` and merging it in the `pkgs` invocation is a standard approach for customizing Rust toolchains in Nix. Implementation is aligned with best practices.

---

`25-47`: **Comprehensive package set for Tauri on Linux and macOS.**

Including `pkg-config`, `openssl`, and GTK dependencies covers Tauri's typical build requirements on Linux; the macOS-specific frameworks are conditionally included. This is a well-rounded dev shell.

---

`50-53`: **Shell hook fosters clarity.**

Echoing the Rust version and environment readiness helps new contributors quickly confirm their setup.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-02T18:15:54Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>frontend/src-tauri/src/lib.rs (1)</summary><blockquote>

`55-122`: **Well-implemented update checker with thorough error handling.**

The `check_for_updates` function is comprehensive, with proper error handling and detailed logging at each step of the update process. The implementation correctly handles update checking, downloading with progress reporting, and installation.



Consider adding a notification system to inform the user about available updates and giving them options to install now, later, or skip. This would improve user experience by providing control over the update process.


```diff
match updater.check().await {
    Ok(Some(update)) => {
        log::info!("Update available, attempting to download and install");
+       
+       // Notify user about the update
+       app_handle.emit_all("update-available", update.version.clone()).unwrap_or_else(|e| {
+           log::error!("Failed to emit update-available event: {}", e);
+       });
+       
+       // Could add logic here to respect user preferences about automatic updates
```

</blockquote></details>
<details>
<summary>flake.nix (2)</summary><blockquote>

`25-47`: **Comprehensive dependency setup for cross-platform development.**

The package list now includes all necessary dependencies for Tauri development across platforms, with appropriate conditional handling for macOS-specific requirements. This ensures a complete and consistent development environment.



Consider organizing the dependencies into logical groups with clearer comments for better maintainability:


```diff
packages = [
  # JavaScript development
  pkgs.bun
  pkgs.just
  
  # Rust toolchain
  rustToolchain
  
  # Basic build dependencies
  pkgs.pkg-config
  pkgs.openssl
  
  # GTK dependencies for Tauri
  pkgs.atk
  pkgs.gtk3
  # ... other GTK dependencies
```

---

`50-53`: **Useful shell hook for developer feedback.**

The shell hook provides valuable feedback to developers by displaying the Rust version being used and confirming that the Tauri development environment is ready.



Consider adding version checks for other critical components like Bun:


```diff
shellHook = ''
  echo "Using Rust version: $(rustc --version)"
+ echo "Using Bun version: $(bun --version)"
  echo "Tauri development environment ready"
'';
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 163a2f26a5751337044c06cad090f792ee631a11 and 812925b59c7d3a39363a696156401fe2ca3546c0.

</details>

<details>
<summary>⛔ Files ignored due to path filters (2)</summary>

* `flake.lock` is excluded by `!**/*.lock`
* `frontend/src-tauri/Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `flake.nix` (1 hunks)
* `frontend/src-tauri/Cargo.toml` (1 hunks)
* `frontend/src-tauri/build.rs` (1 hunks)
* `frontend/src-tauri/src/lib.rs` (1 hunks)
* `frontend/src-tauri/src/main.rs` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary>

* frontend/src-tauri/build.rs
* frontend/src-tauri/src/main.rs
* frontend/src-tauri/Cargo.toml

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: Cloudflare Pages
* GitHub Check: build-macos (universal-apple-darwin)
* GitHub Check: build-linux

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>frontend/src-tauri/src/lib.rs (3)</summary>

`3-38`: **Good implementation of auto-updater for desktop environments.**

The separation of desktop and non-desktop configurations is well-designed, and I appreciate the detailed comments explaining the update process. The implementation correctly uses `tokio::time::sleep` for non-blocking sleep, which addresses a previous review comment about avoiding thread blocking.

---

`23-23`: **Consider using tauri's built-in async runtime.**

While `tokio::time::sleep` works correctly, for consistency with Tauri's API, you might want to use `tauri::async_runtime::sleep` as suggested in previous reviews.


```diff
- tokio::time::sleep(std::time::Duration::from_secs(5)).await;
+ tauri::async_runtime::sleep(std::time::Duration::from_secs(5)).await;
```

---

`39-49`: **Clean non-desktop configuration.**

The simplified setup for non-desktop environments is clean and focused, maintaining the same plugin structure as the desktop configuration for consistency.

</details>
<details>
<summary>flake.nix (2)</summary>

`2-8`: **Good update to description and inputs.**

The description now correctly reflects the expanded scope to include both Bun and Tauri development environments. The addition of the rust-overlay input is necessary for Rust toolchain management.

---

`19-21`: **Action Required: Update Rust Version Pinning for Tauri Compatibility**

The Tauri documentation and setup instructions indicate that Tauri expects developers to use the latest stable Rust toolchain rather than a fixed version such as 1.78.0.


```web
What is the minimum Rust version required by Tauri v2.4.1 for building desktop apps?
```

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-02T18:42:41Z
user: login: greptile-apps[bot]
body: 
## PR Summary
(updates since last review)


The PR introduces a native auto-updater feature for desktop builds while aligning dependency versions and configuration files to support the updated functionality.

- Enhanced auto-updater implementation in `/frontend/src-tauri/src/lib.rs` with asynchronous update checks and detailed logging.
- Upgraded Tauri and updater plugin versions in `/frontend/src-tauri/Cargo.toml` to support the new features.
- Updated auto-updater settings and version bump in `/frontend/src-tauri/tauri.conf.json`.
- Adjusted Rust toolchain settings in `/flake.nix`, but note the potential mismatch with Cargo.toml's declared version.
- Bumped project version in `/frontend/package.json` to properly indicate the new auto-updater functionality.

<sub>7 file(s) reviewed, no comment(s)</sub>
<sub>[Edit PR Review Bot Settings](https://app.greptile.com/review/github) | [Greptile](https://greptile.com?utm_source=greptile_expert&utm_medium=github&utm_campaign=code_reviews&utm_content=maple_42)</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T20:36:36Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>frontend/src-tauri/Cargo.toml (1)</summary><blockquote>

`29-29`: **Consider using a more specific tokio version constraint**

Using `1.0` as the version constraint is quite broad and may introduce compatibility issues in the future. Consider using a more specific version like `1.32` or at least `1.28`.

```diff
-tokio = { version = "1.0", features = ["time"] }
+tokio = { version = "1.32", features = ["time"] }
```

</blockquote></details>
<details>
<summary>frontend/src-tauri/src/lib.rs (2)</summary><blockquote>

`124-224`: **Consider two improvements to the update function**

The update implementation is solid, but could benefit from two improvements:

1. Use a proper error type instead of returning `Result<(), String>`. This would make error handling more robust.
2. The download progress logging currently logs every update, which could flood logs for large downloads. Consider logging at intervals (e.g., every 10% progress).


Example for error type implementation:

```diff
- async fn check_for_updates(app_handle: tauri::AppHandle) -> Result<(), String> {
+ #[derive(Debug, thiserror::Error)]
+ enum UpdateError {
+     #[error("Failed to get updater: {0}")]
+     GetUpdater(#[from] tauri::Error),
+     #[error("Failed to check for updates: {0}")]
+     CheckFailed(#[from] tauri_plugin_updater::Error),
+     #[error("Failed to download update: {0}")]
+     DownloadFailed(String),
+     #[error("Failed to install update: {0}")]
+     InstallFailed(String),
+ }
+ 
+ async fn check_for_updates(app_handle: tauri::AppHandle) -> Result<(), UpdateError> {
```

Example for progress logging at intervals:

```diff
     // Download the update
     let progress_fn = |downloaded: usize, total: Option<u64>| {
         if let Some(total) = total {
-            log::info!("Download progress: {}/{} bytes", downloaded, total);
+            // Only log at 10% intervals to avoid log flooding
+            let percentage = (downloaded as f64 / total as f64 * 100.0) as usize;
+            if percentage % 10 == 0 {
+                log::info!("Download progress: {}% ({}/{} bytes)", percentage, downloaded, total);
+            }
         } else {
-            log::info!("Download progress: {} bytes", downloaded);
+            // For unknown total size, log less frequently (e.g., every 100KB)
+            if downloaded % 102400 == 0 {
+                log::info!("Download progress: {} bytes", downloaded);
+            }
         }
     };
```

---

`146-152`: **Improve download progress logging to reduce log noise**

The current implementation logs every progress update, which could flood logs for large downloads. Consider logging at regular intervals instead.


```diff
let progress_fn = |downloaded: usize, total: Option<u64>| {
    if let Some(total) = total {
-        log::info!("Download progress: {}/{} bytes", downloaded, total);
+        // Only log at reasonable intervals (every 10%)
+        let percentage = (downloaded as f64 / total as f64 * 100.0) as usize;
+        if percentage % 10 == 0 || downloaded == total as usize {
+            log::info!("Download progress: {}% ({}/{} bytes)", percentage, downloaded, total);
+        }
    } else {
-        log::info!("Download progress: {} bytes", downloaded);
+        // For unknown total size, log less frequently
+        if downloaded % 102400 == 0 { // Every 100KB
+            log::info!("Download progress: {} KB", downloaded / 1024);
+        }
    }
};
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 459d9ef07f4a44d7a1d6b6f3e101e6f225b4515c and 146478d4c639325a558a66cf972791fc220ff2b0.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `frontend/src-tauri/Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `frontend/package.json` (1 hunks)
* `frontend/src-tauri/Cargo.toml` (1 hunks)
* `frontend/src-tauri/src/lib.rs` (1 hunks)
* `frontend/src-tauri/tauri.conf.json` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* frontend/src-tauri/tauri.conf.json

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* frontend/package.json

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: build-linux
* GitHub Check: build-macos (universal-apple-darwin)
* GitHub Check: Cloudflare Pages

</details>

<details>
<summary>🔇 Additional comments (7)</summary><blockquote>

<details>
<summary>frontend/src-tauri/Cargo.toml (3)</summary>

`24-24`: **LGTM - Updated tauri dependency**

The version upgrade from 2.2.4 to 2.4.1 supports the new auto-updater feature.

---

`26-26`: **LGTM - Updated tauri-plugin-updater dependency**

Upgraded from a release candidate (2.0.0-rc) to a stable version (2.7.0), which should provide more stability and features.

---

`27-28`: **LGTM - Added plugin dependencies**

The new dialog and plugin dependencies support the update notification system being implemented.

</details>
<details>
<summary>frontend/src-tauri/src/lib.rs (4)</summary>

`3-122`: **Well-structured conditional compilation for desktop vs. non-desktop environments**

The refactoring to separate desktop and non-desktop code paths is clean and well-organized. Both environments correctly include the updater plugin, while desktop includes additional functionality like dialogs and menus.

---

`14-25`: **LGTM - Properly implemented asynchronous update check**

Good implementation of automatic update checking with a 5-second delay using non-blocking `tokio::time::sleep`. This follows the recommendations from previous reviews to use non-blocking sleep.

---

`27-104`: **LGTM - Well-implemented platform-specific menus**

Excellent implementation of platform-specific menus with proper handlers for update checking. The code correctly differentiates between macOS and other platforms, following best practices for native UI experiences.

---

`169-200`: **LGTM - Well-implemented update dialog**

The dialog implementation for notifying users about updates is user-friendly and provides clear options. Good use of the dialog plugin to give users control over when to apply updates.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-02T20:38:01Z

Review comments:
diff_hunk: @@ -1,15 +1,122 @@
 #[cfg_attr(mobile, tauri::mobile_entry_point)]
 pub fn run() {
-  tauri::Builder::default()
-    .setup(|app| {
-      app.handle().plugin(
-        tauri_plugin_log::Builder::default()
-          .level(log::LevelFilter::Info)
-          .build(),
-      )?;
-      Ok(())
-    })
-    .plugin(tauri_plugin_updater::Builder::new().build())
-    .run(tauri::generate_context!())
-    .expect("error while running tauri application");
+    #[cfg(desktop)]
+    let app = tauri::Builder::default()
+        .setup(|app| {
+            // Set up logging
+            app.handle().plugin(
+                tauri_plugin_log::Builder::default()
+                    .level(log::LevelFilter::Info)
+                    .build(),
+            )?;
+
+            // Create the application menu with update options
+            #[cfg(desktop)]
+            {
+                // Set up a simple updater handler
+                log::info!("Setting up automatic updater");
+
+                // Setup update check on startup with delay
+                let app_handle = app.handle().clone();
+                tauri::async_runtime::spawn(async move {
+                    // Wait for app to fully initialize
+                    std::thread::sleep(std::time::Duration::from_secs(5));
path: frontend/src-tauri/src/lib.rs
user: login: greptile-apps[bot]
body: logic: Using std::thread::sleep in an async spawn can block the runtime. Consider using tauri::async_runtime::sleep(Duration::from_secs(5)) for non-blocking sleep.

```suggestion
                tauri::async_runtime::spawn(async move {
                    // Wait for app to fully initialize
                    tauri::async_runtime::sleep(std::time::Duration::from_secs(5)).await;
```
created_at: 2025-04-02T18:12:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,15 +1,122 @@
 #[cfg_attr(mobile, tauri::mobile_entry_point)]
 pub fn run() {
-  tauri::Builder::default()
-    .setup(|app| {
-      app.handle().plugin(
-        tauri_plugin_log::Builder::default()
-          .level(log::LevelFilter::Info)
-          .build(),
-      )?;
-      Ok(())
-    })
-    .plugin(tauri_plugin_updater::Builder::new().build())
-    .run(tauri::generate_context!())
-    .expect("error while running tauri application");
+    #[cfg(desktop)]
+    let app = tauri::Builder::default()
+        .setup(|app| {
+            // Set up logging
+            app.handle().plugin(
+                tauri_plugin_log::Builder::default()
+                    .level(log::LevelFilter::Info)
+                    .build(),
+            )?;
+
+            // Create the application menu with update options
+            #[cfg(desktop)]
+            {
+                // Set up a simple updater handler
+                log::info!("Setting up automatic updater");
+
+                // Setup update check on startup with delay
+                let app_handle = app.handle().clone();
+                tauri::async_runtime::spawn(async move {
+                    // Wait for app to fully initialize
+                    std::thread::sleep(std::time::Duration::from_secs(5));
+                    log::info!("Performing automatic update check on startup");
+
+                    // This will check for updates, download if available, and install them
+                    // The update will be applied silently in the background
+                    // It will take effect the next time the application is started
+                    let _ = check_for_updates(app_handle).await;
+                });
+
+                // We'll add Tauri menu integration when it's more stable
+            }
path: frontend/src-tauri/src/lib.rs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Use non-blocking async sleep instead of `std::thread::sleep`.**

Currently, the code runs `std::thread::sleep` inside the asynchronous runtime, which can block the thread. Consider using an asynchronous sleep mechanism (e.g., `tauri::async_runtime::sleep` or `tokio::time::sleep`) to avoid blocking:

```diff
- std::thread::sleep(std::time::Duration::from_secs(5));
+ tauri::async_runtime::sleep(std::time::Duration::from_secs(5)).await;
```



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
            // Create the application menu with update options
            #[cfg(desktop)]
            {
                // Set up a simple updater handler
                log::info!("Setting up automatic updater");

                // Setup update check on startup with delay
                let app_handle = app.handle().clone();
                tauri::async_runtime::spawn(async move {
                    // Wait for app to fully initialize
-                   std::thread::sleep(std::time::Duration::from_secs(5));
+                   tauri::async_runtime::sleep(std::time::Duration::from_secs(5)).await;
                    log::info!("Performing automatic update check on startup");

                    // This will check for updates, download if available, and install them
                    // The update will be applied silently in the background
                    // It will take effect the next time the application is started
                    let _ = check_for_updates(app_handle).await;
                });

                // We'll add Tauri menu integration when it's more stable
            }
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 812925b
created_at: 2025-04-02T18:15:54Z
author_association: NONE
diff_hunk: @@ -1,22 +1,56 @@
 {
-  description = "Cross-platform Bun development environment";
+  description = "Cross-platform Bun and Tauri development environment";
 
   inputs = {
     nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
     flake-utils.url = "github:numtide/flake-utils";
+    rust-overlay.url = "github:oxalica/rust-overlay";
   };
 
-  outputs = { self, nixpkgs, flake-utils }:
+  outputs = { self, nixpkgs, flake-utils, rust-overlay }:
     flake-utils.lib.eachDefaultSystem (system:
       let
-        pkgs = nixpkgs.legacyPackages.${system};
+        overlays = [ (import rust-overlay) ];
+        pkgs = import nixpkgs {
+          inherit system overlays;
+        };
+        
+        # Use specific rust version required by Tauri
+        rustToolchain = pkgs.rust-bin.stable."1.78.0".default.override {
+          extensions = [ "rust-src" ];
+        };
path: flake.nix
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Confirm Rust 1.78.0 requirement for Tauri.**

Pinning the Rust version to `1.78.0` may be outdated. Verify if Tauri `2.4.1` mandates a newer stable version.

---

🌐 Web query:

```web
What is the minimum Rust version required by Tauri v2.4.1 for building desktop apps on Linux?
```

💡 Result:

Tauri requires the latest stable Rust version for building desktop applications. The documentation consistently instructs developers to install Rust via `rustup`, which automatically provides the compatible stable version[1][7][8]. While the exact minimum version for Tauri v2.4.1 isn't explicitly stated in the provided sources, the setup process for all platforms (including Linux) uses:

```bash
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
```

This command installs the most recent stable Rust toolchain[1][7][8]. Developers should:
1. Keep Rust updated with `rustup update`[1][7]
2. Verify installation with `rustc --version`[1][7]
3. Use the MSVC toolchain on Windows (`stable-msvc`)[7]

The Tauri team maintains compatibility with Rust's stable releases rather than specific legacy versions, as shown by their CI/CD examples using `dtolnay/rust-toolchain@stable` in GitHub Actions workflows[6]. For production environments, they recommend building against older Linux distributions like Ubuntu 18.04 to ensure glibc compatibility, but this doesn't affect the Rust version requirement[5].

Citations:

- 1: https://jonaskruckenberg.github.io/tauri-docs-wip/prerequisites.html
- 2: https://tauri.app/v1/guides/getting-started/setup/vite/
- 3: https://crabnebula.dev/blog/building-a-desktop-pet-with-tauri/
- 4: https://v2.tauri.app/start/prerequisites/
- 5: https://tauri.app/v1/guides/building/linux/
- 6: https://tauri.app/v1/guides/building/cross-platform/
- 7: https://tauri.app/v1/guides/getting-started/prerequisites/
- 8: https://tauri.app/v1/guides/getting-started/prerequisites
- 9: https://www.firezone.dev/blog/using-tauri
- 10: https://docs.rs/tauri/latest/tauri/

---



</details>

**Action Required: Update Rust Version Pinning for Tauri Compatibility**

The Tauri documentation and setup instructions indicate that Tauri v2.4.1 expects developers to use the latest stable Rust toolchain (via rustup) rather than a fixed version such as 1.78.0. Pinning the Rust version to 1.78.0 may become outdated and does not align with Tauri’s guidance to always use the current stable release.

- **File:** `flake.nix` (Lines 19-21)
- **Recommendation:** Instead of hardcoding `rust-bin.stable."1.78.0"`, consider configuring the toolchain to track the latest stable version or update the pin to a more recent stable release to avoid compatibility issues.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-02T18:15:54Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-02T18:11:56Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request updates the project’s configuration and source files to support an expanded development environment featuring Tauri in addition to Bun. It introduces new Rust tooling via a rust overlay and specifies a Rust toolchain version. The changes refine ESLint settings to target files within the source directory, update dependency versions in Tauri’s Cargo files, and modify the application’s control flow for desktop update handling through asynchronous functions.

## Changes

| Files                                                       | Change Summary                                                                                                                                                                                                                                                                                                           |
|-------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `flake.nix`                                               | Expanded dev environment support to include Tauri; added `rust-overlay` dependency; introduced `rustToolchain` set to Rust 1.78.0; updated package list with additional dependencies (GTK, pkg-config, openssl, etc.); added macOS-specific dependency conditions and a `shellHook` for environment setup.             |
| `frontend/eslint.config.js`, <br>`frontend/package.json`   | Updated ESLint configuration: narrowed file matching to `src/**/*.{ts,tsx}` and expanded ignored directories (`dist`, `src-tauri`, `**/target`, `**/node_modules`); modified the lint script in package.json to target the updated file pattern.                                                             |
| `frontend/src-tauri/Cargo.toml`                             | Updated Tauri dependency version from 2.2.4 to 2.4.1; upgraded `tauri-plugin-updater` from 2.0.0-rc to 2.7.0; added new dependency `tauri-plugin` (version 2.1.1); introduced `tokio` dependency with version 1.0 and feature `time`.                                                                                   |
| `frontend/src-tauri/build.rs`, <br>`frontend/src-tauri/src/main.rs` | Adjusted indentation in the `tauri_build::build()` and `app_lib::run()` calls for consistency; no functional changes.                                                                                                                                                                                                 |
| `frontend/src-tauri/src/lib.rs`                             | Refactored the `run` function to differentiate between desktop and non-desktop environments; for desktop, added an asynchronous update check via a new `async fn check_for_updates(app_handle: tauri::AppHandle)` that logs update progress after a 5-second delay.                                           |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant App as Tauri App
    participant RunFunc as run()
    participant Updater as check_for_updates()

    App->>RunFunc: Initialize application
    alt Desktop Environment
        RunFunc->>App: Configure auto-update handler
        Note right of App: Wait 5 seconds post-init
        App->>Updater: Trigger update check asynchronously
        Updater->>App: Log update progress and errors
    else Non-desktop Environment
        RunFunc->>App: Proceed with basic initialization
    end
```

## Possibly related PRs
- OpenSecretCloud/Maple#23: The changes in the main PR related to enhancing the Tauri development environment and adding Rust tooling are directly connected to the updates in the retrieved PR, which also focuses on Tauri and its dependencies, including modifications to the `Cargo.toml` file. 

## Poem
> I’m a coding rabbit, swift on the run,  
> Hopping through updates under Rust’s sun.  
> With Tauri’s sparkle and Bun by my side,  
> My burrow of code is a joyful ride.  
> Debugging, updating with a twitch and a wink!  
> 🐰💻

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=OpenSecretCloud/Maple&utm_content=42):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: cloudflare-workers-and-pages[bot]
created_at: 2025-04-02T18:12:17Z
body: ## Deploying maple with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>146478d</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>&nbsp;✅&nbsp; Deploy successful!</td></tr>
<tr><td><strong>Preview URL:</strong></td><td>
<a href='https://6830215d.maple-ca8.pages.dev'>https://6830215d.maple-ca8.pages.dev</a>
</td></tr>
<tr><td><strong>Branch Preview URL:</strong></td><td>
<a href='https://auto-updater.maple-ca8.pages.dev'>https://auto-updater.maple-ca8.pages.dev</a>
</td></tr>
</table>

[View logs](https://dash.cloudflare.com/e6f61452146dfb34b56923b4de4bc098/pages/view/maple/6830215d-90f7-49c6-892f-92bf2eb16c66)

author_association: NONE