Radish alpha
r
rad:z4D5UCArafTzTQpDZNQRuqswh3ury
Radicle desktop app
Radicle
Git
Refactor the tauri setup hook into individual commands
Open did:key:z6MkkfM3...sVz5 opened 1 year ago

This allows us for onboarding to e.g. fail if there is no profile around and guide new users through identity creation.

Also it makes the tauri run function easier to understand

Also:

  • Update rust toolchain to 1.84
  • Update rust dependencies

checkcheck-unit-testcheck-e2e

👉 Workflow runs 👉 Branch on GitHub

10 files changed +419 -156 15bb0353 e5f09330
modified Cargo.lock
@@ -675,23 +675,23 @@ dependencies = [

[[package]]
name = "cargo_metadata"
-
version = "0.18.1"
+
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037"
+
checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924"
dependencies = [
 "camino",
 "cargo-platform",
 "semver",
 "serde",
 "serde_json",
-
 "thiserror 1.0.69",
+
 "thiserror 2.0.7",
]

[[package]]
name = "cargo_toml"
-
version = "0.17.2"
+
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719"
+
checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472"
dependencies = [
 "serde",
 "toml 0.8.19",
@@ -1247,7 +1247,16 @@ version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
-
 "dirs-sys",
+
 "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]]
@@ -1258,11 +1267,23 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
 "libc",
 "option-ext",
-
 "redox_users",
+
 "redox_users 0.4.6",
 "windows-sys 0.48.0",
]

[[package]]
+
name = "dirs-sys"
+
version = "0.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
+
dependencies = [
+
 "libc",
+
 "option-ext",
+
 "redox_users 0.5.0",
+
 "windows-sys 0.59.0",
+
]
+

+
[[package]]
name = "dispatch"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1336,7 +1357,7 @@ dependencies = [
 "bumpalo",
 "hashbrown 0.14.5",
 "indexmap 2.7.0",
-
 "rustc-hash",
+
 "rustc-hash 1.1.0",
 "serde",
 "unicode-width",
]
@@ -1362,7 +1383,7 @@ dependencies = [
 "dprint-core",
 "dprint-core-macros",
 "percent-encoding",
-
 "rustc-hash",
+
 "rustc-hash 1.1.0",
 "serde",
]

@@ -1375,7 +1396,7 @@ dependencies = [
 "allocator-api2",
 "bumpalo",
 "num-bigint",
-
 "rustc-hash",
+
 "rustc-hash 1.1.0",
 "swc_atoms",
 "swc_common",
 "swc_ecma_ast",
@@ -1942,8 +1963,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
 "cfg-if",
+
 "js-sys",
 "libc",
 "wasi 0.11.0+wasi-snapshot-preview1",
+
 "wasm-bindgen",
]

[[package]]
@@ -2228,7 +2251,7 @@ dependencies = [
 "new_debug_unreachable",
 "once_cell",
 "phf 0.11.2",
-
 "rustc-hash",
+
 "rustc-hash 1.1.0",
 "triomphe",
]

@@ -2313,6 +2336,24 @@ dependencies = [
]

[[package]]
+
name = "hyper-rustls"
+
version = "0.27.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
+
dependencies = [
+
 "futures-util",
+
 "http",
+
 "hyper",
+
 "hyper-util",
+
 "rustls",
+
 "rustls-pki-types",
+
 "tokio",
+
 "tokio-rustls",
+
 "tower-service",
+
 "webpki-roots",
+
]
+

+
[[package]]
name = "hyper-util"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2570,15 +2611,6 @@ dependencies = [
]

[[package]]
-
name = "instant"
-
version = "0.1.13"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
-
dependencies = [
-
 "cfg-if",
-
]
-

-
[[package]]
name = "ipnet"
version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3964,6 +3996,58 @@ dependencies = [
]

[[package]]
+
name = "quinn"
+
version = "0.11.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef"
+
dependencies = [
+
 "bytes",
+
 "pin-project-lite",
+
 "quinn-proto",
+
 "quinn-udp",
+
 "rustc-hash 2.1.1",
+
 "rustls",
+
 "socket2",
+
 "thiserror 2.0.7",
+
 "tokio",
+
 "tracing",
+
]
+

+
[[package]]
+
name = "quinn-proto"
+
version = "0.11.9"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
+
dependencies = [
+
 "bytes",
+
 "getrandom 0.2.15",
+
 "rand 0.8.5",
+
 "ring",
+
 "rustc-hash 2.1.1",
+
 "rustls",
+
 "rustls-pki-types",
+
 "slab",
+
 "thiserror 2.0.7",
+
 "tinyvec",
+
 "tracing",
+
 "web-time",
+
]
+

+
[[package]]
+
name = "quinn-udp"
+
version = "0.5.10"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944"
+
dependencies = [
+
 "cfg_aliases",
+
 "libc",
+
 "once_cell",
+
 "socket2",
+
 "tracing",
+
 "windows-sys 0.59.0",
+
]
+

+
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4276,6 +4360,17 @@ dependencies = [
]

[[package]]
+
name = "redox_users"
+
version = "0.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
+
dependencies = [
+
 "getrandom 0.2.15",
+
 "libredox",
+
 "thiserror 2.0.7",
+
]
+

+
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4327,6 +4422,7 @@ dependencies = [
 "http-body",
 "http-body-util",
 "hyper",
+
 "hyper-rustls",
 "hyper-util",
 "ipnet",
 "js-sys",
@@ -4335,11 +4431,16 @@ dependencies = [
 "once_cell",
 "percent-encoding",
 "pin-project-lite",
+
 "quinn",
+
 "rustls",
+
 "rustls-pemfile",
+
 "rustls-pki-types",
 "serde",
 "serde_json",
 "serde_urlencoded",
 "sync_wrapper",
 "tokio",
+
 "tokio-rustls",
 "tokio-util",
 "tower-service",
 "url",
@@ -4347,6 +4448,7 @@ dependencies = [
 "wasm-bindgen-futures",
 "wasm-streams",
 "web-sys",
+
 "webpki-roots",
 "windows-registry",
]

@@ -4384,6 +4486,20 @@ dependencies = [
]

[[package]]
+
name = "ring"
+
version = "0.17.9"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24"
+
dependencies = [
+
 "cc",
+
 "cfg-if",
+
 "getrandom 0.2.15",
+
 "libc",
+
 "untrusted",
+
 "windows-sys 0.52.0",
+
]
+

+
[[package]]
name = "rkyv"
version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4462,6 +4578,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"

[[package]]
+
name = "rustc-hash"
+
version = "2.1.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+

+
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4484,6 +4606,49 @@ dependencies = [
]

[[package]]
+
name = "rustls"
+
version = "0.23.23"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395"
+
dependencies = [
+
 "once_cell",
+
 "ring",
+
 "rustls-pki-types",
+
 "rustls-webpki",
+
 "subtle",
+
 "zeroize",
+
]
+

+
[[package]]
+
name = "rustls-pemfile"
+
version = "2.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
+
dependencies = [
+
 "rustls-pki-types",
+
]
+

+
[[package]]
+
name = "rustls-pki-types"
+
version = "1.11.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
+
dependencies = [
+
 "web-time",
+
]
+

+
[[package]]
+
name = "rustls-webpki"
+
version = "0.102.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
+
dependencies = [
+
 "ring",
+
 "rustls-pki-types",
+
 "untrusted",
+
]
+

+
[[package]]
name = "rustversion"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5115,7 +5280,7 @@ checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125"
dependencies = [
 "hstr",
 "once_cell",
-
 "rustc-hash",
+
 "rustc-hash 1.1.0",
 "serde",
]

@@ -5133,7 +5298,7 @@ dependencies = [
 "new_debug_unreachable",
 "num-bigint",
 "once_cell",
-
 "rustc-hash",
+
 "rustc-hash 1.1.0",
 "serde",
 "siphasher 0.3.11",
 "swc_atoms",
@@ -5297,9 +5462,9 @@ dependencies = [

[[package]]
name = "tao"
-
version = "0.30.8"
+
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da"
+
checksum = "3731d04d4ac210cd5f344087733943b9bfb1a32654387dad4d1c70de21aee2c9"
dependencies = [
 "bitflags 2.6.0",
 "cocoa",
@@ -5312,7 +5477,6 @@ dependencies = [
 "gdkwayland-sys",
 "gdkx11-sys",
 "gtk",
-
 "instant",
 "jni",
 "lazy_static",
 "libc",
@@ -5370,13 +5534,13 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"

[[package]]
name = "tauri"
-
version = "2.1.1"
+
version = "2.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "e545de0a2dfe296fa67db208266cd397c5a55ae782da77973ef4c4fac90e9f2c"
+
checksum = "58a998b6be84104ca05c7e9a21f2180ddec020c8b84ea59a8fc8530a2a19588d"
dependencies = [
 "anyhow",
 "bytes",
-
 "dirs",
+
 "dirs 6.0.0",
 "dunce",
 "embed_plist",
 "futures-util",
@@ -5421,13 +5585,13 @@ dependencies = [

[[package]]
name = "tauri-build"
-
version = "2.0.3"
+
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "7bd2a4bcfaf5fb9f4be72520eefcb61ae565038f8ccba2a497d8c28f463b8c01"
+
checksum = "8e950124f6779c6cf98e3260c7a6c8488a74aa6350dd54c6950fdaa349bca2df"
dependencies = [
 "anyhow",
 "cargo_toml",
-
 "dirs",
+
 "dirs 5.0.1",
 "glob",
 "heck 0.5.0",
 "json-patch",
@@ -5444,9 +5608,9 @@ dependencies = [

[[package]]
name = "tauri-codegen"
-
version = "2.0.3"
+
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "bf79faeecf301d3e969b1fae977039edb77a4c1f25cc0a961be298b54bff97cf"
+
checksum = "f77894f9ddb5cb6c04fcfe8c8869ebe0aded4dabf19917118d48be4a95599ab5"
dependencies = [
 "base64 0.22.1",
 "brotli",
@@ -5471,9 +5635,9 @@ dependencies = [

[[package]]
name = "tauri-macros"
-
version = "2.0.3"
+
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c52027c8c5afb83166dacddc092ee8fff50772f9646d461d8c33ee887e447a03"
+
checksum = "3240a5caed760a532e8f687be6f05b2c7d11a1d791fb53ccc08cfeb3e5308736"
dependencies = [
 "heck 0.5.0",
 "proc-macro2",
@@ -5502,9 +5666,9 @@ dependencies = [

[[package]]
name = "tauri-plugin-clipboard-manager"
-
version = "2.2.0"
+
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5be2c6f5d82396c1a86d5b16052cc97976a82e92244bf074dd6e2f6272d8619d"
+
checksum = "54de1e3a2ea008687954d5d72952800e87b09f6fbea6d0960d99e58050537642"
dependencies = [
 "arboard",
 "log",
@@ -5558,16 +5722,16 @@ dependencies = [

[[package]]
name = "tauri-plugin-log"
-
version = "2.2.0"
+
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "eddd784c138c08a43954bc3e735402e6b2b2ee8d8c254a7391f4e77c01273dd5"
+
checksum = "367a28a5e0ca39eac98005699466e8906edc4a2a8f8e13a5f1a71dc0bea6c677"
dependencies = [
 "android_logger",
 "byte-unit",
-
 "cocoa",
 "fern",
 "log",
-
 "objc",
+
 "objc2",
+
 "objc2-foundation",
 "serde",
 "serde_json",
 "serde_repr",
@@ -5601,9 +5765,9 @@ dependencies = [

[[package]]
name = "tauri-plugin-window-state"
-
version = "2.2.0"
+
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "234dd891cc7960fa28f93ea911f3e0d9ce8375ebf9ff303831bdd7a3443d5714"
+
checksum = "35e344b512b0d99d9d06225f235d87d6c66d89496a3bf323d9b578d940596e6c"
dependencies = [
 "bitflags 2.6.0",
 "log",
@@ -5616,9 +5780,9 @@ dependencies = [

[[package]]
name = "tauri-runtime"
-
version = "2.2.0"
+
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "cce18d43f80d4aba3aa8a0c953bbe835f3d0f2370aca75e8dbb14bd4bab27958"
+
checksum = "2274ef891ccc0a8d318deffa9d70053f947664d12d58b9c0d1ae5e89237e01f7"
dependencies = [
 "dpi",
 "gtk",
@@ -5635,9 +5799,9 @@ dependencies = [

[[package]]
name = "tauri-runtime-wry"
-
version = "2.2.0"
+
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "9f442a38863e10129ffe2cec7bd09c2dcf8a098a3a27801a476a304d5bb991d2"
+
checksum = "3707b40711d3b9f6519150869e358ffbde7c57567fb9b5a8b51150606939b2a0"
dependencies = [
 "gtk",
 "http",
@@ -5661,9 +5825,9 @@ dependencies = [

[[package]]
name = "tauri-utils"
-
version = "2.1.0"
+
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "9271a88f99b4adea0dc71d0baca4505475a0bbd139fb135f62958721aaa8fe54"
+
checksum = "96fb10e7cc97456b2d5b9c03e335b5de5da982039a303a20d10006885e4523a0"
dependencies = [
 "aes-gcm",
 "brotli",
@@ -5914,6 +6078,16 @@ dependencies = [
]

[[package]]
+
name = "tokio-rustls"
+
version = "0.26.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
+
dependencies = [
+
 "rustls",
+
 "tokio",
+
]
+

+
[[package]]
name = "tokio-util"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6078,7 +6252,7 @@ checksum = "d48a05076dd272615d03033bf04f480199f7d1b66a8ac64d75c625fc4a70c06b"
dependencies = [
 "core-graphics 0.24.0",
 "crossbeam-channel",
-
 "dirs",
+
 "dirs 5.0.1",
 "libappindicator",
 "muda",
 "objc2",
@@ -6444,6 +6618,12 @@ dependencies = [
]

[[package]]
+
name = "untrusted"
+
version = "0.9.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+

+
[[package]]
name = "url"
version = "2.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6727,6 +6907,16 @@ dependencies = [
]

[[package]]
+
name = "web-time"
+
version = "1.1.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
+
dependencies = [
+
 "js-sys",
+
 "wasm-bindgen",
+
]
+

+
[[package]]
name = "webkit2gtk"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6771,10 +6961,19 @@ dependencies = [
]

[[package]]
+
name = "webpki-roots"
+
version = "0.26.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9"
+
dependencies = [
+
 "rustls-pki-types",
+
]
+

+
[[package]]
name = "webview2-com"
-
version = "0.33.0"
+
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c"
+
checksum = "823e7ebcfaea51e78f72c87fc3b65a1e602c321f407a0b36dbb327d7bb7cd921"
dependencies = [
 "webview2-com-macros",
 "webview2-com-sys",
@@ -6797,9 +6996,9 @@ dependencies = [

[[package]]
name = "webview2-com-sys"
-
version = "0.33.0"
+
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886"
+
checksum = "7a82bce72db6e5ee83c68b5de1e2cd6ea195b9fbff91cb37df5884cbe3222df4"
dependencies = [
 "thiserror 1.0.69",
 "windows",
@@ -7206,9 +7405,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"

[[package]]
name = "wry"
-
version = "0.47.2"
+
version = "0.48.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "61ce51277d65170f6379d8cda935c80e3c2d1f0ff712a123c8bddb11b31a4b73"
+
checksum = "a2e33c08b174442ff80d5c791020696f9f8b4e4a87b8cfc7494aad6167ec44e1"
dependencies = [
 "base64 0.22.1",
 "block2",
@@ -7236,7 +7435,7 @@ dependencies = [
 "sha2",
 "soup3",
 "tao-macros",
-
 "thiserror 1.0.69",
+
 "thiserror 2.0.7",
 "url",
 "webkit2gtk",
 "webkit2gtk-sys",
modified crates/radicle-tauri/Cargo.toml
@@ -23,15 +23,15 @@ radicle-types = { version = "0.1.0", path = "../radicle-types" }
radicle-surf = { version = "0.22.1", features = ["serde"] }
serde = { version = "1.0.210", features = ["derive"] }
serde_json = { version = "1.0.132" }
-
tauri = { version = "2.0.4", features = ["isolation"] }
-
tauri-plugin-clipboard-manager = { version = "2.0.1" }
-
tauri-plugin-log = { version = "2.0.0" }
-
tauri-plugin-shell = { version = "2.0.1" }
-
tauri-plugin-window-state = { version = "2.0.1" }
+
tauri = { version = "2.2.5", features = ["isolation"] }
+
tauri-plugin-clipboard-manager = { version = "2.2.1" }
+
tauri-plugin-dialog = { version = "2.2.0" }
+
tauri-plugin-log = { version = "2.2.1" }
+
tauri-plugin-shell = { version = "2.2.0" }
+
tauri-plugin-window-state = { version = "2.2.1" }
thiserror = { version = "1.0.64" }
-
ts-rs = { version = "10.0.0", features = ["serde-json-impl", "no-serde-warnings"] }
tokio = { version = "1.40.0", features = ["time"] }
-
tauri-plugin-dialog = { version = "2.2.0" }
+
ts-rs = { version = "10.0.0", features = ["serde-json-impl", "no-serde-warnings"] }

[features]
# by default Tauri runs in production mode
modified crates/radicle-tauri/src/commands.rs
@@ -2,6 +2,7 @@ pub mod auth;
pub mod cob;
pub mod diff;
pub mod inbox;
+
pub mod init;
pub mod profile;
pub mod repo;
pub mod thread;
added crates/radicle-tauri/src/commands/init.rs
@@ -0,0 +1,112 @@
+
use std::collections::BTreeMap;
+

+
use radicle::identity::RepoId;
+
use radicle::node::{Handle, Node};
+
use radicle::storage::ReadStorage;
+
use tauri::{AppHandle, Emitter, Manager};
+

+
use radicle_types::config::Config;
+
use radicle_types::error::Error;
+
use radicle_types::traits::Profile;
+
use radicle_types::AppState;
+

+
#[tauri::command]
+
pub(crate) fn load_profile(app: AppHandle) -> Result<Config, Error> {
+
    let profile = match radicle::Profile::load() {
+
        Ok(profile) => Ok::<radicle::Profile, Error>(profile),
+
        Err(radicle::profile::Error::NotFound(path)) => Err(Error::WithHint {
+
            err: anyhow::anyhow!("Radicle profile not found in '{}'.", path.display()),
+
            hint: "To setup your radicle profile, run `rad auth`.",
+
        }),
+
        Err(e) => Err(Error::WithHint {
+
            err: e.into(),
+
            hint: "Could not load radicle profile",
+
        }),
+
    }?;
+

+
    let state = AppState { profile };
+

+
    app.manage(state.clone());
+

+
    Ok(state.config())
+
}
+

+
#[tauri::command]
+
pub(crate) fn node_status_events(app: AppHandle, ctx: tauri::State<AppState>) -> Result<(), Error> {
+
    let app_handle = app.clone();
+

+
    let node = Node::new(ctx.profile.socket());
+
    let node_status = node.clone();
+

+
    tauri::async_runtime::spawn(async move {
+
        loop {
+
            let _ = app_handle.emit("node_running", node_status.is_running());
+
            tokio::time::sleep(std::time::Duration::from_secs(2)).await;
+
        }
+
    });
+

+
    Ok(())
+
}
+

+
#[tauri::command]
+
pub(crate) fn repo_sync_events(app: AppHandle, ctx: tauri::State<AppState>) -> Result<(), Error> {
+
    let profile = &ctx.profile;
+
    let repositories = profile.storage.repositories()?;
+

+
    let app_handle = app.clone();
+
    let public_key = profile.public_key;
+

+
    let node = Node::new(profile.socket());
+
    let mut node_seeds = node.clone();
+

+
    tauri::async_runtime::spawn(async move {
+
        loop {
+
            let mut sync_status =
+
                BTreeMap::<RepoId, Option<radicle_types::cobs::repo::SyncStatus>>::new();
+
            for repo in &repositories {
+
                if let Ok(seeds) = node_seeds.seeds(repo.rid).map(Into::<Vec<_>>::into) {
+
                    if let Some(status) =
+
                        seeds
+
                            .iter()
+
                            .find_map(|radicle::node::Seed { nid, sync, .. }| {
+
                                (*nid == public_key).then_some(sync.clone())
+
                            })
+
                    {
+
                        sync_status.insert(repo.rid, status.map(Into::into));
+
                    } else {
+
                        // The local node wasn't found in the seed nodes table.
+
                        sync_status.insert(repo.rid, None);
+
                    }
+
                }
+
            }
+
            let _ = app_handle.emit("sync_status", sync_status);
+
            tokio::time::sleep(std::time::Duration::from_secs(10)).await;
+
        }
+
    });
+

+
    Ok(())
+
}
+

+
#[tauri::command]
+
pub(crate) fn node_events(app: AppHandle, ctx: tauri::State<AppState>) -> Result<(), Error> {
+
    let app_handle = app.clone();
+
    let node = Node::new(ctx.profile.socket());
+

+
    tauri::async_runtime::spawn(async move {
+
        loop {
+
            if node.is_running() {
+
                log::debug!("node: spawned node event subscription.");
+
                while let Ok(events) = node.subscribe(std::time::Duration::MAX) {
+
                    for event in events.into_iter().flatten() {
+
                        let _ = app_handle.emit("event", event);
+
                    }
+
                }
+
                log::debug!("node: event subscription loop has exited.");
+
            }
+

+
            tokio::time::sleep(std::time::Duration::from_secs(2)).await;
+
        }
+
    });
+

+
    Ok(())
+
}
modified crates/radicle-tauri/src/lib.rs
@@ -1,19 +1,12 @@
mod commands;

-
use std::collections::BTreeMap;
-

-
use tauri::{Emitter, Manager};
-

use radicle::cob::cache::COBS_DB_FILE;
-
use radicle::identity::RepoId;
-
use radicle::node::{Handle, Node, NOTIFICATIONS_DB_FILE};
-
use radicle::storage::ReadStorage;
+
use radicle::node::NOTIFICATIONS_DB_FILE;
+
use tauri::{Listener, Manager};

-
use radicle_types::domain;
-
use radicle_types::error::Error;
-
use radicle_types::AppState;
+
use radicle_types::{domain, AppState};

-
use commands::{auth, cob, diff, inbox, profile, repo, thread};
+
use commands::{auth, cob, diff, inbox, init, profile, repo, thread};

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
@@ -26,84 +19,30 @@ pub fn run() {

    builder
        .setup(|app| {
-
            let profile: radicle::Profile = match radicle::Profile::load() {
-
                Ok(profile) => Ok::<radicle::Profile, Error>(profile),
-
                Err(radicle::profile::Error::NotFound(path)) => Err(Error::WithHint {
-
                    err: anyhow::anyhow!("Radicle profile not found in '{}'.", path.display()),
-
                    hint: "To setup your radicle profile, run `rad auth`.",
-
                }),
-
                Err(e) => Err(Error::WithHint {
-
                    err: e.into(),
-
                    hint: "Could not load radicle profile",
-
                }),
-
            }?;
-
            let public_key = profile.public_key;
-
            let repositories = profile.storage.repositories()?;
-

-
            let inbox_db = radicle_types::outbound::sqlite::Sqlite::reader(
-
                profile.node().join(NOTIFICATIONS_DB_FILE),
-
            )?;
-
            let inbox_service = domain::inbox::service::Service::new(inbox_db);
-

-
            let patch_db =
-
                radicle_types::outbound::sqlite::Sqlite::reader(profile.cobs().join(COBS_DB_FILE))?;
-
            let patch_service = domain::patch::service::Service::new(patch_db);
-

-
            let events_handler = app.handle().clone();
-
            let node_handler = app.handle().clone();
-
            let seed_handler = app.handle().clone();
-

-
            let node = Node::new(profile.socket());
-
            let node_status = node.clone();
-
            let mut node_seeds = node.clone();
-

-
            app.manage(inbox_service);
-
            app.manage(patch_service);
-
            app.manage(AppState { profile });
-

-
            tauri::async_runtime::spawn(async move {
-
                loop {
-
                    let _ = node_handler.emit("node_running", node_status.is_running());
-
                    tokio::time::sleep(std::time::Duration::from_secs(2)).await;
-
                }
-
            });
-

-
            tauri::async_runtime::spawn(async move {
-
                loop {
-
                    let mut sync_status =
-
                        BTreeMap::<RepoId, Option<radicle_types::cobs::repo::SyncStatus>>::new();
-
                    for repo in &repositories {
-
                        if let Ok(seeds) = node_seeds.seeds(repo.rid).map(Into::<Vec<_>>::into) {
-
                            if let Some(status) = seeds.iter().find_map(
-
                                |radicle::node::Seed { nid, sync, .. }| {
-
                                    (*nid == public_key).then_some(sync.clone())
-
                                },
-
                            ) {
-
                                sync_status.insert(repo.rid, status.map(Into::into));
-
                            } else {
-
                                // The local node wasn't found in the seed nodes table.
-
                                sync_status.insert(repo.rid, None);
-
                            }
-
                        }
+
            let main_window = app.get_webview_window("main").unwrap();
+
            let handle = app.handle().clone();
+

+
            main_window.listen("profile-loaded", move |_| {
+
                let ctx = handle.state::<AppState>();
+

+
                match radicle_types::outbound::sqlite::Sqlite::reader(
+
                    ctx.profile.node().join(NOTIFICATIONS_DB_FILE),
+
                ) {
+
                    Ok(inbox_db) => {
+
                        let inbox_service = domain::inbox::service::Service::new(inbox_db);
+
                        handle.manage(inbox_service);
                    }
-
                    let _ = seed_handler.emit("sync_status", sync_status);
-
                    tokio::time::sleep(std::time::Duration::from_secs(10)).await;
-
                }
-
            });
-

-
            tauri::async_runtime::spawn(async move {
-
                loop {
-
                    if node.is_running() {
-
                        log::debug!("node: spawned node event subscription.");
-
                        while let Ok(events) = node.subscribe(std::time::Duration::MAX) {
-
                            for event in events.into_iter().flatten() {
-
                                let _ = events_handler.emit("event", event);
-
                            }
-
                        }
-
                        log::debug!("node: event subscription loop has exited.");
+
                    Err(err) => log::error!("Not able to create inbox service: {}", err),
+
                };
+

+
                match radicle_types::outbound::sqlite::Sqlite::reader(
+
                    ctx.profile.cobs().join(COBS_DB_FILE),
+
                ) {
+
                    Ok(patch_db) => {
+
                        let patch_service = domain::patch::service::Service::new(patch_db);
+
                        handle.manage(patch_service);
                    }
-

-
                    tokio::time::sleep(std::time::Duration::from_secs(2)).await;
+
                    Err(err) => log::error!("Not able to create patch service: {}", err),
                }
            });

@@ -113,6 +52,10 @@ pub fn run() {
        .plugin(tauri_plugin_clipboard_manager::init())
        .plugin(tauri_plugin_window_state::Builder::default().build())
        .invoke_handler(tauri::generate_handler![
+
            init::load_profile,
+
            init::node_status_events,
+
            init::repo_sync_events,
+
            init::node_events,
            auth::authenticate,
            repo::repo_count,
            repo::list_repos,
modified crates/radicle-types/src/cobs/stream.rs
@@ -121,7 +121,7 @@ impl<'a, A> Stream<'a, A> {
    }
}

-
impl<'a, A> HasRoot for Stream<'a, A> {
+
impl<A> HasRoot for Stream<'_, A> {
    fn root(&self) -> Oid {
        self.range.root()
    }
modified crates/radicle-types/src/cobs/stream/iter.rs
@@ -182,7 +182,7 @@ impl<'a, A> ActionsIter<'a, A> {
    }
}

-
impl<'a, A> Iterator for ActionsIter<'a, A>
+
impl<A> Iterator for ActionsIter<'_, A>
where
    A: for<'de> Deserialize<'de>,
    A: Debug,
@@ -278,7 +278,7 @@ impl<'a, A> TreeActionsIter<'a, A> {
    }
}

-
impl<'a, A> Iterator for TreeActionsIter<'a, A>
+
impl<A> Iterator for TreeActionsIter<'_, A>
where
    A: for<'de> Deserialize<'de>,
{
modified crates/radicle-types/src/lib.rs
@@ -17,6 +17,7 @@ pub mod syntax;
pub mod test;
pub mod traits;

+
#[derive(Clone)]
pub struct AppState {
    pub profile: radicle::Profile,
}
modified rust-toolchain
@@ -1 +1 @@
-
1.81
+
1.84
modified src/App.svelte
@@ -1,4 +1,5 @@
<script lang="ts">
+
  import type { Config } from "@bindings/config/Config";
  import type { UnlistenFn } from "@tauri-apps/api/event";
  import type { SyncStatus } from "@bindings/repo/SyncStatus";

@@ -6,7 +7,7 @@
  import { onDestroy, onMount } from "svelte";

  import { invoke } from "@app/lib/invoke";
-
  import { listen } from "@tauri-apps/api/event";
+
  import { emit, listen } from "@tauri-apps/api/event";

  import * as router from "@app/lib/router";
  import { nodeRunning, syncStatus } from "@app/lib/events";
@@ -30,6 +31,12 @@
  let unlistenSyncStatus: UnlistenFn | undefined = undefined;

  onMount(async () => {
+
    // Load profile into state before using it in other commands.
+
    await invoke<Config>("load_profile");
+
    if (window.__TAURI_INTERNALS__) {
+
      await emit("profile-loaded");
+
    }
+

    if (window.__TAURI_INTERNALS__) {
      unlistenEvents = await listen("event", () => {
        // Add handler for incoming events