diff --git a/.vite/deps/_metadata.json b/.vite/deps/_metadata.json
new file mode 100644
index 0000000..c411a13
--- /dev/null
+++ b/.vite/deps/_metadata.json
@@ -0,0 +1,8 @@
+{
+ "hash": "26e02935",
+ "configHash": "f7e27824",
+ "lockfileHash": "e3b0c442",
+ "browserHash": "cf5a5f58",
+ "optimized": {},
+ "chunks": {}
+}
\ No newline at end of file
diff --git a/.vite/deps/package.json b/.vite/deps/package.json
new file mode 100644
index 0000000..3dbc1ca
--- /dev/null
+++ b/.vite/deps/package.json
@@ -0,0 +1,3 @@
+{
+ "type": "module"
+}
diff --git a/Cargo.lock b/Cargo.lock
index 195303b..7dfdb8d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,129 +2,12 @@
# It is not intended for manual editing.
version = 4
-[[package]]
-name = "ab_glyph"
-version = "0.2.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2"
-dependencies = [
- "ab_glyph_rasterizer",
- "owned_ttf_parser",
-]
-
-[[package]]
-name = "ab_glyph_rasterizer"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
-
-[[package]]
-name = "accesskit"
-version = "0.16.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99b76d84ee70e30a4a7e39ab9018e2b17a6a09e31084176cc7c0b2dec036ba45"
-
-[[package]]
-name = "accesskit_atspi_common"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5393c75d4666f580f4cac0a968bc97c36076bb536a129f28210dac54ee127ed"
-dependencies = [
- "accesskit",
- "accesskit_consumer",
- "atspi-common",
- "serde",
- "thiserror 1.0.69",
- "zvariant 4.2.0",
-]
-
-[[package]]
-name = "accesskit_consumer"
-version = "0.24.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a12dc159d52233c43d9fe5415969433cbdd52c3d6e0df51bda7d447427b9986"
-dependencies = [
- "accesskit",
- "immutable-chunkmap",
-]
-
-[[package]]
-name = "accesskit_macos"
-version = "0.17.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfc6c1ecd82053d127961ad80a8beaa6004fb851a3a5b96506d7a6bd462403f6"
-dependencies = [
- "accesskit",
- "accesskit_consumer",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
- "once_cell",
-]
-
-[[package]]
-name = "accesskit_unix"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be7f5cf6165be10a54b2655fa2e0e12b2509f38ed6fc43e11c31fdb7ee6230bb"
-dependencies = [
- "accesskit",
- "accesskit_atspi_common",
- "async-channel 2.5.0",
- "async-executor",
- "async-task",
- "atspi",
- "futures-lite 2.6.1",
- "futures-util",
- "serde",
- "zbus 4.4.0",
-]
-
-[[package]]
-name = "accesskit_windows"
-version = "0.23.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "974e96c347384d9133427167fb8a58c340cb0496988dacceebdc1ed27071023b"
-dependencies = [
- "accesskit",
- "accesskit_consumer",
- "paste",
- "static_assertions",
- "windows 0.58.0",
- "windows-core 0.58.0",
-]
-
-[[package]]
-name = "accesskit_winit"
-version = "0.22.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aea3522719f1c44564d03e9469a8e2f3a98b3a8a880bd66d0789c6b9c4a669dd"
-dependencies = [
- "accesskit",
- "accesskit_macos",
- "accesskit_unix",
- "accesskit_windows",
- "raw-window-handle",
- "winit",
-]
-
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
-[[package]]
-name = "aes"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
-dependencies = [
- "cfg-if",
- "cipher",
- "cpufeatures",
-]
-
[[package]]
name = "ahash"
version = "0.8.12"
@@ -132,7 +15,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
dependencies = [
"cfg-if",
- "getrandom 0.3.4",
"once_cell",
"version_check",
"zerocopy",
@@ -148,48 +30,20 @@ dependencies = [
]
[[package]]
-name = "aligned"
-version = "0.4.3"
+name = "alloc-no-stdlib"
+version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685"
-dependencies = [
- "as-slice",
-]
+checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
[[package]]
-name = "aligned-vec"
-version = "0.6.4"
+name = "alloc-stdlib"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b"
+checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195"
dependencies = [
- "equator",
+ "alloc-no-stdlib",
]
-[[package]]
-name = "android-activity"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd"
-dependencies = [
- "android-properties",
- "bitflags 2.13.0",
- "cc",
- "jni",
- "libc",
- "log",
- "ndk",
- "ndk-context",
- "ndk-sys 0.6.0+11769913",
- "num_enum",
- "thiserror 2.0.18",
-]
-
-[[package]]
-name = "android-properties"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
-
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -205,120 +59,6 @@ version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
-[[package]]
-name = "arbitrary"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
-
-[[package]]
-name = "arboard"
-version = "3.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf"
-dependencies = [
- "clipboard-win",
- "log",
- "objc2 0.6.4",
- "objc2-app-kit 0.3.2",
- "objc2-foundation 0.3.2",
- "parking_lot",
- "percent-encoding",
- "windows-sys 0.60.2",
- "x11rb",
-]
-
-[[package]]
-name = "arg_enum_proc_macro"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
-]
-
-[[package]]
-name = "arrayref"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
-
-[[package]]
-name = "arrayvec"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
-
-[[package]]
-name = "as-raw-xcb-connection"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
-
-[[package]]
-name = "as-slice"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516"
-dependencies = [
- "stable_deref_trait",
-]
-
-[[package]]
-name = "ash"
-version = "0.38.0+1.3.281"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
-dependencies = [
- "libloading",
-]
-
-[[package]]
-name = "ashpd"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2f3f79755c74fd155000314eb349864caa787c6592eace6c6882dad873d9c39"
-dependencies = [
- "async-fs 2.2.0",
- "async-net",
- "enumflags2",
- "futures-channel",
- "futures-util",
- "rand 0.9.4",
- "raw-window-handle",
- "serde",
- "serde_repr",
- "url",
- "wayland-backend",
- "wayland-client",
- "wayland-protocols",
- "zbus 5.16.0",
-]
-
-[[package]]
-name = "async-broadcast"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b"
-dependencies = [
- "event-listener 2.5.3",
- "futures-core",
-]
-
-[[package]]
-name = "async-broadcast"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
-dependencies = [
- "event-listener 5.4.1",
- "event-listener-strategy",
- "futures-core",
- "pin-project-lite",
-]
-
[[package]]
name = "async-channel"
version = "1.9.0"
@@ -350,35 +90,12 @@ checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a"
dependencies = [
"async-task",
"concurrent-queue",
- "fastrand 2.4.1",
- "futures-lite 2.6.1",
+ "fastrand",
+ "futures-lite",
"pin-project-lite",
"slab",
]
-[[package]]
-name = "async-fs"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
-dependencies = [
- "async-lock 2.8.0",
- "autocfg",
- "blocking",
- "futures-lite 1.13.0",
-]
-
-[[package]]
-name = "async-fs"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5"
-dependencies = [
- "async-lock 3.4.2",
- "blocking",
- "futures-lite 2.6.1",
-]
-
[[package]]
name = "async-global-executor"
version = "2.4.1"
@@ -387,33 +104,13 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c"
dependencies = [
"async-channel 2.5.0",
"async-executor",
- "async-io 2.6.0",
- "async-lock 3.4.2",
+ "async-io",
+ "async-lock",
"blocking",
- "futures-lite 2.6.1",
+ "futures-lite",
"once_cell",
]
-[[package]]
-name = "async-io"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
-dependencies = [
- "async-lock 2.8.0",
- "autocfg",
- "cfg-if",
- "concurrent-queue",
- "futures-lite 1.13.0",
- "log",
- "parking",
- "polling 2.8.0",
- "rustix 0.37.28",
- "slab",
- "socket2 0.4.10",
- "waker-fn",
-]
-
[[package]]
name = "async-io"
version = "2.6.0"
@@ -424,23 +121,14 @@ dependencies = [
"cfg-if",
"concurrent-queue",
"futures-io",
- "futures-lite 2.6.1",
+ "futures-lite",
"parking",
- "polling 3.11.0",
- "rustix 1.1.4",
+ "polling",
+ "rustix",
"slab",
"windows-sys 0.61.2",
]
-[[package]]
-name = "async-lock"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
-dependencies = [
- "event-listener 2.5.3",
-]
-
[[package]]
name = "async-lock"
version = "3.4.2"
@@ -464,81 +152,6 @@ dependencies = [
"url",
]
-[[package]]
-name = "async-net"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
-dependencies = [
- "async-io 2.6.0",
- "blocking",
- "futures-lite 2.6.1",
-]
-
-[[package]]
-name = "async-process"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88"
-dependencies = [
- "async-io 1.13.0",
- "async-lock 2.8.0",
- "async-signal",
- "blocking",
- "cfg-if",
- "event-listener 3.1.0",
- "futures-lite 1.13.0",
- "rustix 0.38.44",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "async-process"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
-dependencies = [
- "async-channel 2.5.0",
- "async-io 2.6.0",
- "async-lock 3.4.2",
- "async-signal",
- "async-task",
- "blocking",
- "cfg-if",
- "event-listener 5.4.1",
- "futures-lite 2.6.1",
- "rustix 1.1.4",
-]
-
-[[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.117",
-]
-
-[[package]]
-name = "async-signal"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485"
-dependencies = [
- "async-io 2.6.0",
- "async-lock 3.4.2",
- "atomic-waker",
- "cfg-if",
- "futures-core",
- "futures-io",
- "rustix 1.1.4",
- "signal-hook-registry",
- "slab",
- "windows-sys 0.61.2",
-]
-
[[package]]
name = "async-std"
version = "1.13.2"
@@ -547,13 +160,13 @@ checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b"
dependencies = [
"async-channel 1.9.0",
"async-global-executor",
- "async-io 2.6.0",
- "async-lock 3.4.2",
+ "async-io",
+ "async-lock",
"crossbeam-utils",
"futures-channel",
"futures-core",
"futures-io",
- "futures-lite 2.6.1",
+ "futures-lite",
"gloo-timers",
"kv-log-macro",
"log",
@@ -611,106 +224,12 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
-[[package]]
-name = "atspi"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be534b16650e35237bb1ed189ba2aab86ce65e88cc84c66f4935ba38575cecbf"
-dependencies = [
- "atspi-common",
- "atspi-connection",
- "atspi-proxies",
-]
-
-[[package]]
-name = "atspi-common"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1909ed2dc01d0a17505d89311d192518507e8a056a48148e3598fef5e7bb6ba7"
-dependencies = [
- "enumflags2",
- "serde",
- "static_assertions",
- "zbus 4.4.0",
- "zbus-lockstep",
- "zbus-lockstep-macros",
- "zbus_names 3.0.0",
- "zvariant 4.2.0",
-]
-
-[[package]]
-name = "atspi-connection"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "430c5960624a4baaa511c9c0fcc2218e3b58f5dbcc47e6190cafee344b873333"
-dependencies = [
- "atspi-common",
- "atspi-proxies",
- "futures-lite 2.6.1",
- "zbus 4.4.0",
-]
-
-[[package]]
-name = "atspi-proxies"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5e6c5de3e524cf967569722446bcd458d5032348554d9a17d7d72b041ab7496"
-dependencies = [
- "atspi-common",
- "serde",
- "zbus 4.4.0",
- "zvariant 4.2.0",
-]
-
[[package]]
name = "autocfg"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
-[[package]]
-name = "av-scenechange"
-version = "0.14.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394"
-dependencies = [
- "aligned",
- "anyhow",
- "arg_enum_proc_macro",
- "arrayvec",
- "log",
- "num-rational",
- "num-traits",
- "pastey",
- "rayon",
- "thiserror 2.0.18",
- "v_frame",
- "y4m",
-]
-
-[[package]]
-name = "av1-grain"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8"
-dependencies = [
- "anyhow",
- "arrayvec",
- "log",
- "nom",
- "num-rational",
- "v_frame",
-]
-
-[[package]]
-name = "avif-serialize"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38"
-dependencies = [
- "arrayvec",
-]
-
[[package]]
name = "base64"
version = "0.21.7"
@@ -718,25 +237,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
-name = "bit-set"
-version = "0.6.0"
+name = "base64"
+version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "bit-set"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
-version = "0.7.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"
-
-[[package]]
-name = "bit_field"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
+checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]]
name = "bitflags"
@@ -753,21 +272,6 @@ dependencies = [
"serde_core",
]
-[[package]]
-name = "bitstream-io"
-version = "4.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f"
-dependencies = [
- "no_std_io2",
-]
-
-[[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"
@@ -777,31 +281,13 @@ dependencies = [
"generic-array",
]
-[[package]]
-name = "block-padding"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "block2"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f"
-dependencies = [
- "objc2 0.5.2",
-]
-
[[package]]
name = "block2"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
dependencies = [
- "objc2 0.6.4",
+ "objc2",
]
[[package]]
@@ -813,15 +299,39 @@ dependencies = [
"async-channel 2.5.0",
"async-task",
"futures-io",
- "futures-lite 2.6.1",
+ "futures-lite",
"piper",
]
[[package]]
-name = "built"
-version = "0.8.1"
+name = "brotli"
+version = "8.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9"
+checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+ "brotli-decompressor",
+]
+
+[[package]]
+name = "brotli-decompressor"
+version = "5.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+]
+
+[[package]]
+name = "bs58"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
+dependencies = [
+ "tinyvec",
+]
[[package]]
name = "bumpalo"
@@ -834,20 +344,6 @@ name = "bytemuck"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
-dependencies = [
- "bytemuck_derive",
-]
-
-[[package]]
-name = "bytemuck_derive"
-version = "1.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
-]
[[package]]
name = "byteorder"
@@ -855,17 +351,14 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
-[[package]]
-name = "byteorder-lite"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
-
[[package]]
name = "bytes"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
+dependencies = [
+ "serde",
+]
[[package]]
name = "cairo-rs"
@@ -893,63 +386,45 @@ dependencies = [
]
[[package]]
-name = "calloop"
-version = "0.13.0"
+name = "camino"
+version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec"
+checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0"
dependencies = [
- "bitflags 2.13.0",
- "log",
- "polling 3.11.0",
- "rustix 0.38.44",
- "slab",
- "thiserror 1.0.69",
+ "serde_core",
]
[[package]]
-name = "calloop"
-version = "0.14.4"
+name = "cargo-platform"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7"
+checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea"
dependencies = [
- "bitflags 2.13.0",
- "polling 3.11.0",
- "rustix 1.1.4",
- "slab",
- "tracing",
+ "serde",
]
[[package]]
-name = "calloop-wayland-source"
-version = "0.3.0"
+name = "cargo_metadata"
+version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20"
+checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba"
dependencies = [
- "calloop 0.13.0",
- "rustix 0.38.44",
- "wayland-backend",
- "wayland-client",
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.18",
]
[[package]]
-name = "calloop-wayland-source"
-version = "0.4.1"
+name = "cargo_toml"
+version = "0.22.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa"
+checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77"
dependencies = [
- "calloop 0.14.4",
- "rustix 1.1.4",
- "wayland-backend",
- "wayland-client",
-]
-
-[[package]]
-name = "cbc"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
-dependencies = [
- "cipher",
+ "serde",
+ "toml 0.9.12+spec-1.1.0",
]
[[package]]
@@ -959,11 +434,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
dependencies = [
"find-msvc-tools",
- "jobserver",
- "libc",
"shlex",
]
+[[package]]
+name = "cesu8"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
+
+[[package]]
+name = "cfb"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f"
+dependencies = [
+ "byteorder",
+ "fnv",
+ "uuid",
+]
+
[[package]]
name = "cfg-expr"
version = "0.15.8"
@@ -980,27 +470,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
-[[package]]
-name = "cfg_aliases"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
-
-[[package]]
-name = "cfg_aliases"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
-
-[[package]]
-name = "cgl"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff"
-dependencies = [
- "libc",
-]
-
[[package]]
name = "chrono"
version = "0.4.45"
@@ -1010,74 +479,9 @@ dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
+ "serde",
"wasm-bindgen",
- "windows-link",
-]
-
-[[package]]
-name = "cipher"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
-dependencies = [
- "crypto-common",
- "inout",
-]
-
-[[package]]
-name = "clipboard-win"
-version = "5.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4"
-dependencies = [
- "error-code",
-]
-
-[[package]]
-name = "codespan-reporting"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
-dependencies = [
- "termcolor",
- "unicode-width",
-]
-
-[[package]]
-name = "color_quant"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
-
-[[package]]
-name = "com"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6"
-dependencies = [
- "com_macros",
-]
-
-[[package]]
-name = "com_macros"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5"
-dependencies = [
- "com_macros_support",
- "proc-macro2",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "com_macros_support"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
+ "windows-link 0.2.1",
]
[[package]]
@@ -1100,13 +504,13 @@ dependencies = [
]
[[package]]
-name = "core-foundation"
-version = "0.9.4"
+name = "cookie"
+version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
dependencies = [
- "core-foundation-sys",
- "libc",
+ "time",
+ "version_check",
]
[[package]]
@@ -1127,12 +531,12 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "core-graphics"
-version = "0.23.2"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
+checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97"
dependencies = [
- "bitflags 1.3.2",
- "core-foundation 0.9.4",
+ "bitflags 2.13.0",
+ "core-foundation",
"core-graphics-types",
"foreign-types 0.5.0",
"libc",
@@ -1140,12 +544,12 @@ dependencies = [
[[package]]
name = "core-graphics-types"
-version = "0.1.3"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
+checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
dependencies = [
- "bitflags 1.3.2",
- "core-foundation 0.9.4",
+ "bitflags 2.13.0",
+ "core-foundation",
"libc",
]
@@ -1176,37 +580,12 @@ dependencies = [
"crossbeam-utils",
]
-[[package]]
-name = "crossbeam-deque"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
-dependencies = [
- "crossbeam-epoch",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.9.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
-dependencies = [
- "crossbeam-utils",
-]
-
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
-[[package]]
-name = "crunchy"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
-
[[package]]
name = "crypto-common"
version = "0.1.7"
@@ -1218,26 +597,117 @@ dependencies = [
]
[[package]]
-name = "cursor-icon"
-version = "1.2.0"
+name = "cssparser"
+version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
+checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2"
+dependencies = [
+ "cssparser-macros",
+ "dtoa-short",
+ "itoa",
+ "phf",
+ "smallvec",
+]
[[package]]
-name = "data-url"
-version = "0.3.2"
+name = "cssparser-macros"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376"
+checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
+dependencies = [
+ "quote",
+ "syn 2.0.117",
+]
[[package]]
-name = "derivative"
-version = "2.2.0"
+name = "ctor"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98"
+dependencies = [
+ "ctor-proc-macro",
+ "dtor",
+]
+
+[[package]]
+name = "ctor-proc-macro"
+version = "0.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1"
+
+[[package]]
+name = "darling"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
+dependencies = [
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "dbus"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ab69f03cc8c4340c9c8e315114e1658e6775a9b16a04357973aa21cec22b32e"
+dependencies = [
+ "libc",
+ "libdbus-sys",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "deranged"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "derive_more"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
+dependencies = [
+ "derive_more-impl",
+]
+
+[[package]]
+name = "derive_more-impl"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "rustc_version",
+ "syn 2.0.117",
]
[[package]]
@@ -1248,7 +718,6 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
- "subtle",
]
[[package]]
@@ -1257,7 +726,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]]
@@ -1268,15 +746,21 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
- "redox_users",
+ "redox_users 0.4.6",
"windows-sys 0.48.0",
]
[[package]]
-name = "dispatch"
-version = "0.2.0"
+name = "dirs-sys"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
+checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
+dependencies = [
+ "libc",
+ "option-ext",
+ "redox_users 0.5.2",
+ "windows-sys 0.61.2",
+]
[[package]]
name = "dispatch2"
@@ -1285,9 +769,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
dependencies = [
"bitflags 2.13.0",
- "block2 0.6.2",
+ "block2",
"libc",
- "objc2 0.6.4",
+ "objc2",
]
[[package]]
@@ -1302,290 +786,113 @@ dependencies = [
]
[[package]]
-name = "dlib"
-version = "0.5.3"
+name = "dlopen2"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a"
+checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4"
dependencies = [
- "libloading",
+ "dlopen2_derive",
+ "libc",
+ "once_cell",
+ "winapi",
]
[[package]]
-name = "document-features"
-version = "0.2.12"
+name = "dlopen2_derive"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
+checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f"
dependencies = [
- "litrs",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
]
[[package]]
-name = "downcast-rs"
-version = "1.2.1"
+name = "dom_query"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
+checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89"
+dependencies = [
+ "bit-set",
+ "cssparser",
+ "foldhash 0.2.0",
+ "html5ever",
+ "precomputed-hash",
+ "selectors",
+ "tendril",
+]
[[package]]
name = "dpi"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
-
-[[package]]
-name = "duplicate"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e92f10a49176cbffacaedabfaa11d51db1ea0f80a83c26e1873b43cd1742c24"
dependencies = [
- "heck 0.5.0",
- "proc-macro2",
- "proc-macro2-diagnostics",
-]
-
-[[package]]
-name = "ecolor"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "775cfde491852059e386c4e1deb4aef381c617dc364184c6f6afee99b87c402b"
-dependencies = [
- "bytemuck",
- "emath",
-]
-
-[[package]]
-name = "eframe"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ac2645a9bf4826eb4e91488b1f17b8eaddeef09396706b2f14066461338e24f"
-dependencies = [
- "ahash",
- "bytemuck",
- "document-features",
- "egui",
- "egui-wgpu",
- "egui-winit",
- "egui_glow",
- "glow 0.14.2",
- "glutin",
- "glutin-winit",
- "image",
- "js-sys",
- "log",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
- "parking_lot",
- "percent-encoding",
- "raw-window-handle",
- "static_assertions",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
- "web-time",
- "winapi",
- "windows-sys 0.52.0",
- "winit",
-]
-
-[[package]]
-name = "egui"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53eafabcce0cb2325a59a98736efe0bf060585b437763f8c476957fb274bb974"
-dependencies = [
- "accesskit",
- "ahash",
- "emath",
- "epaint",
- "log",
- "nohash-hasher",
-]
-
-[[package]]
-name = "egui-wgpu"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d00fd5d06d8405397e64a928fa0ef3934b3c30273ea7603e3dc4627b1f7a1a82"
-dependencies = [
- "ahash",
- "bytemuck",
- "document-features",
- "egui",
- "epaint",
- "log",
- "thiserror 1.0.69",
- "type-map",
- "web-time",
- "wgpu",
- "winit",
-]
-
-[[package]]
-name = "egui-winit"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a9c430f4f816340e8e8c1b20eec274186b1be6bc4c7dfc467ed50d57abc36c6"
-dependencies = [
- "accesskit_winit",
- "ahash",
- "arboard",
- "egui",
- "log",
- "raw-window-handle",
- "smithay-clipboard",
- "web-time",
- "webbrowser",
- "winit",
-]
-
-[[package]]
-name = "egui_dock"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fe4e3414481dea5ed59fdfa88f2e00b6ea60fbe758ca7a8636d0dbed93ab9cf"
-dependencies = [
- "duplicate",
- "egui",
- "paste",
-]
-
-[[package]]
-name = "egui_extras"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf3c1f5cd8dfe2ade470a218696c66cf556fcfd701e7830fa2e9f4428292a2a1"
-dependencies = [
- "ahash",
- "egui",
- "enum-map",
- "image",
- "log",
- "mime_guess2",
- "resvg",
-]
-
-[[package]]
-name = "egui_glow"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e39bccc683cd43adab530d8f21a13eb91e80de10bcc38c3f1c16601b6f62b26"
-dependencies = [
- "ahash",
- "bytemuck",
- "egui",
- "glow 0.14.2",
- "log",
- "memoffset 0.9.1",
- "wasm-bindgen",
- "web-sys",
- "winit",
-]
-
-[[package]]
-name = "either"
-version = "1.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
-
-[[package]]
-name = "emath"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1fe0049ce51d0fb414d029e668dd72eb30bc2b739bf34296ed97bd33df544f3"
-dependencies = [
- "bytemuck",
-]
-
-[[package]]
-name = "endi"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
-
-[[package]]
-name = "enum-map"
-version = "2.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
-dependencies = [
- "enum-map-derive",
"serde",
]
[[package]]
-name = "enum-map-derive"
-version = "0.17.0"
+name = "dtoa"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
+checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590"
+
+[[package]]
+name = "dtoa-short"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87"
dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
+ "dtoa",
]
[[package]]
-name = "enumflags2"
-version = "0.7.12"
+name = "dtor"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef"
+checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4"
dependencies = [
- "enumflags2_derive",
- "serde",
+ "dtor-proc-macro",
]
[[package]]
-name = "enumflags2_derive"
-version = "0.7.12"
+name = "dtor-proc-macro"
+version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
+checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5"
+
+[[package]]
+name = "dunce"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
+
+[[package]]
+name = "dyn-clone"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
+
+[[package]]
+name = "embed-resource"
+version = "3.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbfdaacccebec3b28e4866b8973543c7647797db5ada1bdab552e48fe665fbbd"
dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
+ "cc",
+ "memchr",
+ "rustc_version",
+ "toml 1.1.2+spec-1.1.0",
+ "vswhom",
+ "winreg",
]
[[package]]
-name = "epaint"
-version = "0.29.1"
+name = "embed_plist"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a32af8da821bd4f43f2c137e295459ee2e1661d87ca8779dfa0eaf45d870e20f"
-dependencies = [
- "ab_glyph",
- "ahash",
- "bytemuck",
- "ecolor",
- "emath",
- "epaint_default_fonts",
- "log",
- "nohash-hasher",
- "parking_lot",
-]
-
-[[package]]
-name = "epaint_default_fonts"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "483440db0b7993cf77a20314f08311dbe95675092405518c0677aa08c151a3ea"
-
-[[package]]
-name = "equator"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc"
-dependencies = [
- "equator-macro",
-]
-
-[[package]]
-name = "equator-macro"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
-]
+checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
[[package]]
name = "equivalent"
@@ -1593,6 +900,17 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+[[package]]
+name = "erased-serde"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec"
+dependencies = [
+ "serde",
+ "serde_core",
+ "typeid",
+]
+
[[package]]
name = "errno"
version = "0.3.14"
@@ -1603,29 +921,12 @@ dependencies = [
"windows-sys 0.61.2",
]
-[[package]]
-name = "error-code"
-version = "3.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
-
[[package]]
name = "event-listener"
version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
-[[package]]
-name = "event-listener"
-version = "3.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2"
-dependencies = [
- "concurrent-queue",
- "parking",
- "pin-project-lite",
-]
-
[[package]]
name = "event-listener"
version = "5.4.1"
@@ -1647,21 +948,6 @@ dependencies = [
"pin-project-lite",
]
-[[package]]
-name = "exr"
-version = "1.74.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be"
-dependencies = [
- "bit_field",
- "half",
- "lebe",
- "miniz_oxide",
- "rayon-core",
- "smallvec",
- "zune-inflate",
-]
-
[[package]]
name = "fallible-iterator"
version = "0.3.0"
@@ -1674,27 +960,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
-[[package]]
-name = "fastrand"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
-dependencies = [
- "instant",
-]
-
[[package]]
name = "fastrand"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
-[[package]]
-name = "fax"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a"
-
[[package]]
name = "fdeflate"
version = "0.3.7"
@@ -1710,7 +981,7 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
dependencies = [
- "memoffset 0.9.1",
+ "memoffset",
"rustc_version",
]
@@ -1731,10 +1002,10 @@ dependencies = [
]
[[package]]
-name = "float-cmp"
-version = "0.9.0"
+name = "fnv"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
@@ -1742,6 +1013,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+[[package]]
+name = "foldhash"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
+
[[package]]
name = "foreign-types"
version = "0.3.2"
@@ -1825,28 +1102,13 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
-[[package]]
-name = "futures-lite"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
-dependencies = [
- "fastrand 1.9.0",
- "futures-core",
- "futures-io",
- "memchr",
- "parking",
- "pin-project-lite",
- "waker-fn",
-]
-
[[package]]
name = "futures-lite"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
dependencies = [
- "fastrand 2.4.1",
+ "fastrand",
"futures-core",
"futures-io",
"parking",
@@ -1950,6 +1212,47 @@ dependencies = [
"system-deps",
]
+[[package]]
+name = "gdkwayland-sys"
+version = "0.18.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69"
+dependencies = [
+ "gdk-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pkg-config",
+ "system-deps",
+]
+
+[[package]]
+name = "gdkx11"
+version = "0.18.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe"
+dependencies = [
+ "gdk",
+ "gdkx11-sys",
+ "gio",
+ "glib",
+ "libc",
+ "x11",
+]
+
+[[package]]
+name = "gdkx11-sys"
+version = "0.18.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d"
+dependencies = [
+ "gdk-sys",
+ "glib-sys",
+ "libc",
+ "system-deps",
+ "x11",
+]
+
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -1960,16 +1263,6 @@ dependencies = [
"version_check",
]
-[[package]]
-name = "gethostname"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8"
-dependencies = [
- "rustix 1.1.4",
- "windows-link",
-]
-
[[package]]
name = "getrandom"
version = "0.2.17"
@@ -2006,16 +1299,6 @@ dependencies = [
"wasip3",
]
-[[package]]
-name = "gif"
-version = "0.14.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159"
-dependencies = [
- "color_quant",
- "weezl",
-]
-
[[package]]
name = "gio"
version = "0.18.4"
@@ -2048,17 +1331,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "gl_generator"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
-dependencies = [
- "khronos_api",
- "log",
- "xml-rs",
-]
-
[[package]]
name = "glib"
version = "0.18.5"
@@ -2106,6 +1378,12 @@ dependencies = [
"system-deps",
]
+[[package]]
+name = "glob"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
+
[[package]]
name = "gloo-timers"
version = "0.3.0"
@@ -2118,96 +1396,6 @@ dependencies = [
"wasm-bindgen",
]
-[[package]]
-name = "glow"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1"
-dependencies = [
- "js-sys",
- "slotmap",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "glow"
-version = "0.14.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483"
-dependencies = [
- "js-sys",
- "slotmap",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "glutin"
-version = "0.32.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325"
-dependencies = [
- "bitflags 2.13.0",
- "cfg_aliases 0.2.1",
- "cgl",
- "dispatch2",
- "glutin_egl_sys",
- "glutin_glx_sys",
- "glutin_wgl_sys",
- "libloading",
- "objc2 0.6.4",
- "objc2-app-kit 0.3.2",
- "objc2-core-foundation",
- "objc2-foundation 0.3.2",
- "once_cell",
- "raw-window-handle",
- "wayland-sys",
- "windows-sys 0.52.0",
- "x11-dl",
-]
-
-[[package]]
-name = "glutin-winit"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f"
-dependencies = [
- "cfg_aliases 0.2.1",
- "glutin",
- "raw-window-handle",
- "winit",
-]
-
-[[package]]
-name = "glutin_egl_sys"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2"
-dependencies = [
- "gl_generator",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "glutin_glx_sys"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185"
-dependencies = [
- "gl_generator",
- "x11-dl",
-]
-
-[[package]]
-name = "glutin_wgl_sys"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e"
-dependencies = [
- "gl_generator",
-]
-
[[package]]
name = "gobject-sys"
version = "0.18.0"
@@ -2219,58 +1407,6 @@ dependencies = [
"system-deps",
]
-[[package]]
-name = "gpu-alloc"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45cf04b2726f02df5508c6de726acdc90cdf97ac771a9a0ffd8ba10a6e696bf9"
-dependencies = [
- "bitflags 2.13.0",
- "gpu-alloc-types",
-]
-
-[[package]]
-name = "gpu-alloc-types"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2bbed164dd10ed526c2e4fe3e721ca4a71c61730e5aafac6844b417b3227058"
-dependencies = [
- "bitflags 2.13.0",
-]
-
-[[package]]
-name = "gpu-allocator"
-version = "0.26.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7"
-dependencies = [
- "log",
- "presser",
- "thiserror 1.0.69",
- "winapi",
- "windows 0.52.0",
-]
-
-[[package]]
-name = "gpu-descriptor"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca"
-dependencies = [
- "bitflags 2.13.0",
- "gpu-descriptor-types",
- "hashbrown 0.15.5",
-]
-
-[[package]]
-name = "gpu-descriptor-types"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91"
-dependencies = [
- "bitflags 2.13.0",
-]
-
[[package]]
name = "gtk"
version = "0.18.2"
@@ -2324,15 +1460,10 @@ dependencies = [
]
[[package]]
-name = "half"
-version = "2.7.1"
+name = "hashbrown"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
-dependencies = [
- "cfg-if",
- "crunchy",
- "zerocopy",
-]
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
@@ -2349,7 +1480,7 @@ version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
- "foldhash",
+ "foldhash 0.1.5",
]
[[package]]
@@ -2367,21 +1498,6 @@ dependencies = [
"hashbrown 0.14.5",
]
-[[package]]
-name = "hassle-rs"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890"
-dependencies = [
- "bitflags 2.13.0",
- "com",
- "libc",
- "libloading",
- "thiserror 1.0.69",
- "widestring",
- "winapi",
-]
-
[[package]]
name = "heck"
version = "0.4.1"
@@ -2394,12 +1510,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-[[package]]
-name = "hermit-abi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
-
[[package]]
name = "hermit-abi"
version = "0.5.2"
@@ -2413,27 +1523,95 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
-name = "hexf-parse"
-version = "0.2.1"
+name = "html5ever"
+version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
-
-[[package]]
-name = "hkdf"
-version = "0.12.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2"
dependencies = [
- "hmac",
+ "log",
+ "markup5ever",
]
[[package]]
-name = "hmac"
-version = "0.12.1"
+name = "http"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"
dependencies = [
- "digest",
+ "bytes",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
+dependencies = [
+ "bytes",
+ "http",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http",
+ "http-body",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+
+[[package]]
+name = "hyper"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
+dependencies = [
+ "atomic-waker",
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "http",
+ "http-body",
+ "httparse",
+ "itoa",
+ "pin-project-lite",
+ "smallvec",
+ "tokio",
+ "want",
+]
+
+[[package]]
+name = "hyper-util"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
+dependencies = [
+ "base64 0.22.1",
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "http",
+ "http-body",
+ "hyper",
+ "ipnet",
+ "libc",
+ "percent-encoding",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
]
[[package]]
@@ -2460,6 +1638,16 @@ dependencies = [
"cc",
]
+[[package]]
+name = "ico"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371"
+dependencies = [
+ "byteorder",
+ "png 0.17.16",
+]
+
[[package]]
name = "icu_collections"
version = "2.2.0"
@@ -2548,6 +1736,12 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
[[package]]
name = "idna"
version = "1.1.0"
@@ -2570,58 +1764,14 @@ dependencies = [
]
[[package]]
-name = "image"
-version = "0.25.10"
+name = "indexmap"
+version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
- "bytemuck",
- "byteorder-lite",
- "color_quant",
- "exr",
- "gif",
- "image-webp",
- "moxcms",
- "num-traits",
- "png 0.18.1",
- "qoi",
- "ravif",
- "rayon",
- "rgb",
- "tiff",
- "zune-core",
- "zune-jpeg",
-]
-
-[[package]]
-name = "image-webp"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3"
-dependencies = [
- "byteorder-lite",
- "quick-error",
-]
-
-[[package]]
-name = "imagesize"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
-
-[[package]]
-name = "imgref"
-version = "1.12.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7"
-
-[[package]]
-name = "immutable-chunkmap"
-version = "2.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3e98b1520e49e252237edc238a39869da9f3241f2ec19dc788c1d24694d1e4"
-dependencies = [
- "arrayvec",
+ "autocfg",
+ "hashbrown 0.12.3",
+ "serde",
]
[[package]]
@@ -2637,54 +1787,19 @@ dependencies = [
]
[[package]]
-name = "inout"
-version = "0.1.4"
+name = "infer"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
+checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7"
dependencies = [
- "block-padding",
- "generic-array",
+ "cfb",
]
[[package]]
-name = "instant"
-version = "0.1.13"
+name = "ipnet"
+version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "interpolate_name"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
-]
-
-[[package]]
-name = "io-lifetimes"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
-dependencies = [
- "hermit-abi 0.3.9",
- "libc",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "itertools"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
-dependencies = [
- "either",
-]
+checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
[[package]]
name = "itoa"
@@ -2693,33 +1808,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
-name = "jni"
-version = "0.22.4"
+name = "javascriptcore-rs"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
+checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc"
dependencies = [
- "cfg-if",
- "combine",
- "jni-macros",
- "jni-sys 0.4.1",
- "log",
- "simd_cesu8",
- "thiserror 2.0.18",
- "walkdir",
- "windows-link",
+ "bitflags 1.3.2",
+ "glib",
+ "javascriptcore-rs-sys",
]
[[package]]
-name = "jni-macros"
-version = "0.22.4"
+name = "javascriptcore-rs-sys"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
+checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124"
dependencies = [
- "proc-macro2",
- "quote",
- "rustc_version",
- "simd_cesu8",
- "syn 2.0.117",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "system-deps",
+]
+
+[[package]]
+name = "jni"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
+dependencies = [
+ "cesu8",
+ "cfg-if",
+ "combine",
+ "jni-sys 0.3.1",
+ "log",
+ "thiserror 1.0.69",
+ "walkdir",
+ "windows-sys 0.45.0",
]
[[package]]
@@ -2750,16 +1874,6 @@ dependencies = [
"syn 2.0.117",
]
-[[package]]
-name = "jobserver"
-version = "0.1.34"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
-dependencies = [
- "getrandom 0.3.4",
- "libc",
-]
-
[[package]]
name = "js-sys"
version = "0.3.102"
@@ -2771,6 +1885,28 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "json-patch"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08"
+dependencies = [
+ "jsonptr",
+ "serde",
+ "serde_json",
+ "thiserror 1.0.69",
+]
+
+[[package]]
+name = "jsonptr"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "keyboard-types"
version = "0.7.0"
@@ -2782,46 +1918,6 @@ dependencies = [
"unicode-segmentation",
]
-[[package]]
-name = "keyring"
-version = "2.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "363387f0019d714aa60cc30ab4fe501a747f4c08fc58f069dd14be971bd495a0"
-dependencies = [
- "byteorder",
- "lazy_static",
- "linux-keyutils",
- "secret-service",
- "security-framework 2.11.1",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "khronos-egl"
-version = "6.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76"
-dependencies = [
- "libc",
- "libloading",
- "pkg-config",
-]
-
-[[package]]
-name = "khronos_api"
-version = "3.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
-
-[[package]]
-name = "kurbo"
-version = "0.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b"
-dependencies = [
- "arrayvec",
-]
-
[[package]]
name = "kv-log-macro"
version = "1.0.7"
@@ -2867,10 +1963,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
-name = "lebe"
-version = "0.5.3"
+name = "libappindicator"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
+checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a"
+dependencies = [
+ "glib",
+ "gtk",
+ "gtk-sys",
+ "libappindicator-sys",
+ "log",
+]
+
+[[package]]
+name = "libappindicator-sys"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf"
+dependencies = [
+ "gtk-sys",
+ "libloading",
+ "once_cell",
+]
[[package]]
name = "libc"
@@ -2879,23 +1993,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
-name = "libfuzzer-sys"
-version = "0.4.13"
+name = "libdbus-sys"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2"
+checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043"
dependencies = [
- "arbitrary",
- "cc",
+ "pkg-config",
]
[[package]]
name = "libloading"
-version = "0.8.9"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
- "windows-link",
+ "winapi",
]
[[package]]
@@ -2904,10 +2017,7 @@ version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3"
dependencies = [
- "bitflags 2.13.0",
"libc",
- "plain",
- "redox_syscall 0.8.1",
]
[[package]]
@@ -2935,25 +2045,6 @@ dependencies = [
"vcpkg",
]
-[[package]]
-name = "libxdo"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00333b8756a3d28e78def82067a377de7fa61b24909000aeaa2b446a948d14db"
-dependencies = [
- "libxdo-sys",
-]
-
-[[package]]
-name = "libxdo-sys"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212"
-dependencies = [
- "libc",
- "x11",
-]
-
[[package]]
name = "libz-sys"
version = "1.1.29"
@@ -2966,28 +2057,6 @@ dependencies = [
"vcpkg",
]
-[[package]]
-name = "linux-keyutils"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83270a18e9f90d0707c41e9f35efada77b64c0e6f3f1810e71c8368a864d5590"
-dependencies = [
- "bitflags 2.13.0",
- "libc",
-]
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
-
[[package]]
name = "linux-raw-sys"
version = "0.12.1"
@@ -3000,12 +2069,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
-[[package]]
-name = "litrs"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
-
[[package]]
name = "lock_api"
version = "0.4.14"
@@ -3015,35 +2078,6 @@ dependencies = [
"scopeguard",
]
-[[package]]
-name = "loflum"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "async-trait",
- "chrono",
- "dirs",
- "eframe",
- "egui",
- "egui_dock",
- "egui_extras",
- "futures-lite 2.6.1",
- "image",
- "keyring",
- "muda",
- "rfd",
- "rusqlite",
- "serde",
- "serde_json",
- "ssh2",
- "suppaftp",
- "thiserror 1.0.69",
- "tokio",
- "tracing",
- "tracing-subscriber",
- "uuid",
-]
-
[[package]]
name = "log"
version = "0.4.33"
@@ -3054,31 +2088,14 @@ dependencies = [
]
[[package]]
-name = "loop9"
-version = "0.1.5"
+name = "markup5ever"
+version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062"
+checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862"
dependencies = [
- "imgref",
-]
-
-[[package]]
-name = "malloc_buf"
-version = "0.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "maybe-rayon"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519"
-dependencies = [
- "cfg-if",
- "rayon",
+ "log",
+ "tendril",
+ "web_atoms",
]
[[package]]
@@ -3087,24 +2104,6 @@ version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
-[[package]]
-name = "memmap2"
-version = "0.9.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "memoffset"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
-dependencies = [
- "autocfg",
-]
-
[[package]]
name = "memoffset"
version = "0.9.1"
@@ -3114,39 +2113,12 @@ dependencies = [
"autocfg",
]
-[[package]]
-name = "metal"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21"
-dependencies = [
- "bitflags 2.13.0",
- "block",
- "core-graphics-types",
- "foreign-types 0.5.0",
- "log",
- "objc",
- "paste",
-]
-
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
-[[package]]
-name = "mime_guess2"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1706dc14a2e140dec0a7a07109d9a3d5890b81e85bd6c60b906b249a77adf0ca"
-dependencies = [
- "mime",
- "phf",
- "phf_shared",
- "unicase",
-]
-
[[package]]
name = "miniz_oxide"
version = "0.8.9"
@@ -3168,16 +2140,6 @@ dependencies = [
"windows-sys 0.61.2",
]
-[[package]]
-name = "moxcms"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
-dependencies = [
- "num-traits",
- "pxfm",
-]
-
[[package]]
name = "muda"
version = "0.19.3"
@@ -3188,38 +2150,17 @@ dependencies = [
"dpi",
"gtk",
"keyboard-types",
- "libxdo",
- "objc2 0.6.4",
- "objc2-app-kit 0.3.2",
+ "objc2",
+ "objc2-app-kit",
"objc2-core-foundation",
- "objc2-foundation 0.3.2",
+ "objc2-foundation",
"once_cell",
"png 0.18.1",
+ "serde",
"thiserror 2.0.18",
"windows-sys 0.61.2",
]
-[[package]]
-name = "naga"
-version = "22.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad"
-dependencies = [
- "arrayvec",
- "bit-set",
- "bitflags 2.13.0",
- "cfg_aliases 0.1.1",
- "codespan-reporting",
- "hexf-parse",
- "indexmap",
- "log",
- "rustc-hash 1.1.0",
- "spirv",
- "termcolor",
- "thiserror 1.0.69",
- "unicode-xid",
-]
-
[[package]]
name = "native-tls"
version = "0.2.18"
@@ -3232,7 +2173,7 @@ dependencies = [
"openssl-probe",
"openssl-sys",
"schannel",
- "security-framework 3.7.0",
+ "security-framework",
"security-framework-sys",
"tempfile",
]
@@ -3246,27 +2187,12 @@ dependencies = [
"bitflags 2.13.0",
"jni-sys 0.3.1",
"log",
- "ndk-sys 0.6.0+11769913",
+ "ndk-sys",
"num_enum",
"raw-window-handle",
"thiserror 1.0.69",
]
-[[package]]
-name = "ndk-context"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
-
-[[package]]
-name = "ndk-sys"
-version = "0.5.0+25.2.9519653"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691"
-dependencies = [
- "jni-sys 0.3.1",
-]
-
[[package]]
name = "ndk-sys"
version = "0.6.0+11769913"
@@ -3282,61 +2208,6 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
-[[package]]
-name = "nix"
-version = "0.26.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
-dependencies = [
- "bitflags 1.3.2",
- "cfg-if",
- "libc",
- "memoffset 0.7.1",
-]
-
-[[package]]
-name = "nix"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
-dependencies = [
- "bitflags 2.13.0",
- "cfg-if",
- "cfg_aliases 0.2.1",
- "libc",
- "memoffset 0.9.1",
-]
-
-[[package]]
-name = "no_std_io2"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "nohash-hasher"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
-
-[[package]]
-name = "nom"
-version = "8.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "noop_proc_macro"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
-
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
@@ -3347,79 +2218,10 @@ dependencies = [
]
[[package]]
-name = "num"
-version = "0.4.3"
+name = "num-conv"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
-dependencies = [
- "num-bigint",
- "num-complex",
- "num-integer",
- "num-iter",
- "num-rational",
- "num-traits",
-]
-
-[[package]]
-name = "num-bigint"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
-dependencies = [
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-complex"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "num-derive"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
-]
-
-[[package]]
-name = "num-integer"
-version = "0.1.46"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "num-iter"
-version = "0.1.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
-dependencies = [
- "autocfg",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-rational"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
-dependencies = [
- "num-bigint",
- "num-integer",
- "num-traits",
-]
+checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
[[package]]
name = "num-traits"
@@ -3452,31 +2254,6 @@ dependencies = [
"syn 2.0.117",
]
-[[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"
-
-[[package]]
-name = "objc2"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804"
-dependencies = [
- "objc-sys",
- "objc2-encode",
-]
-
[[package]]
name = "objc2"
version = "0.6.4"
@@ -3484,22 +2261,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
dependencies = [
"objc2-encode",
-]
-
-[[package]]
-name = "objc2-app-kit"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
-dependencies = [
- "bitflags 2.13.0",
- "block2 0.5.1",
- "libc",
- "objc2 0.5.2",
- "objc2-core-data",
- "objc2-core-image",
- "objc2-foundation 0.2.2",
- "objc2-quartz-core",
+ "objc2-exception-helper",
]
[[package]]
@@ -3509,47 +2271,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
dependencies = [
"bitflags 2.13.0",
- "block2 0.6.2",
- "objc2 0.6.4",
+ "block2",
+ "objc2",
"objc2-core-foundation",
- "objc2-core-graphics",
- "objc2-foundation 0.3.2",
+ "objc2-foundation",
]
[[package]]
name = "objc2-cloud-kit"
-version = "0.2.2"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
+checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
dependencies = [
"bitflags 2.13.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",
+ "objc2",
+ "objc2-foundation",
]
[[package]]
name = "objc2-core-data"
-version = "0.2.2"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
+checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
dependencies = [
- "bitflags 2.13.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
+ "objc2",
+ "objc2-foundation",
]
[[package]]
@@ -3560,7 +2306,7 @@ checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags 2.13.0",
"dispatch2",
- "objc2 0.6.4",
+ "objc2",
]
[[package]]
@@ -3571,33 +2317,41 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [
"bitflags 2.13.0",
"dispatch2",
- "objc2 0.6.4",
+ "objc2",
"objc2-core-foundation",
"objc2-io-surface",
]
[[package]]
name = "objc2-core-image"
-version = "0.2.2"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
+checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
- "objc2-metal",
+ "objc2",
+ "objc2-foundation",
]
[[package]]
name = "objc2-core-location"
-version = "0.2.2"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
+checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-contacts",
- "objc2-foundation 0.2.2",
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-core-text"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
+dependencies = [
+ "bitflags 2.13.0",
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
]
[[package]]
@@ -3607,16 +2361,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
[[package]]
-name = "objc2-foundation"
-version = "0.2.2"
+name = "objc2-exception-helper"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
+checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a"
dependencies = [
- "bitflags 2.13.0",
- "block2 0.5.1",
- "dispatch",
- "libc",
- "objc2 0.5.2",
+ "cc",
]
[[package]]
@@ -3626,7 +2376,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
"bitflags 2.13.0",
- "objc2 0.6.4",
+ "block2",
+ "libc",
+ "objc2",
"objc2-core-foundation",
]
@@ -3637,100 +2389,65 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
dependencies = [
"bitflags 2.13.0",
- "objc2 0.6.4",
+ "objc2",
"objc2-core-foundation",
]
-[[package]]
-name = "objc2-link-presentation"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
-dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
-]
-
-[[package]]
-name = "objc2-metal"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
-dependencies = [
- "bitflags 2.13.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
-]
-
[[package]]
name = "objc2-quartz-core"
-version = "0.2.2"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
+checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
dependencies = [
"bitflags 2.13.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
- "objc2-metal",
-]
-
-[[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",
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-foundation",
]
[[package]]
name = "objc2-ui-kit"
-version = "0.2.2"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
+checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
dependencies = [
"bitflags 2.13.0",
- "block2 0.5.1",
- "objc2 0.5.2",
+ "block2",
+ "objc2",
"objc2-cloud-kit",
"objc2-core-data",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
"objc2-core-image",
"objc2-core-location",
- "objc2-foundation 0.2.2",
- "objc2-link-presentation",
+ "objc2-core-text",
+ "objc2-foundation",
"objc2-quartz-core",
- "objc2-symbols",
- "objc2-uniform-type-identifiers",
"objc2-user-notifications",
]
[[package]]
-name = "objc2-uniform-type-identifiers"
-version = "0.2.2"
+name = "objc2-user-notifications"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
+checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
dependencies = [
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
+ "objc2",
+ "objc2-foundation",
]
[[package]]
-name = "objc2-user-notifications"
-version = "0.2.2"
+name = "objc2-web-kit"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
+checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f"
dependencies = [
"bitflags 2.13.0",
- "block2 0.5.1",
- "objc2 0.5.2",
- "objc2-core-location",
- "objc2-foundation 0.2.2",
+ "block2",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-foundation",
]
[[package]]
@@ -3788,35 +2505,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
-[[package]]
-name = "orbclient"
-version = "0.3.55"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747"
-dependencies = [
- "libc",
- "libredox",
-]
-
-[[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 = "owned_ttf_parser"
-version = "0.25.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b"
-dependencies = [
- "ttf-parser",
-]
-
[[package]]
name = "pango"
version = "0.18.3"
@@ -3866,23 +2554,11 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.5.18",
+ "redox_syscall",
"smallvec",
- "windows-link",
+ "windows-link 0.2.1",
]
-[[package]]
-name = "paste"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
-
-[[package]]
-name = "pastey"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec"
-
[[package]]
name = "percent-encoding"
version = "2.3.2"
@@ -3891,54 +2567,57 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "phf"
-version = "0.11.3"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
+checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
dependencies = [
"phf_macros",
"phf_shared",
+ "serde",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
]
[[package]]
name = "phf_generator"
-version = "0.11.3"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
+checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
dependencies = [
+ "fastrand",
"phf_shared",
- "rand 0.8.6",
]
[[package]]
name = "phf_macros"
-version = "0.11.3"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
+checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2",
"quote",
"syn 2.0.117",
- "unicase",
]
[[package]]
name = "phf_shared"
-version = "0.11.3"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
+checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
dependencies = [
- "siphasher 1.0.3",
- "unicase",
+ "siphasher",
]
-[[package]]
-name = "pico-args"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
-
[[package]]
name = "pin-project"
version = "1.1.13"
@@ -3978,7 +2657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1"
dependencies = [
"atomic-waker",
- "fastrand 2.4.1",
+ "fastrand",
"futures-io",
]
@@ -3989,10 +2668,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
[[package]]
-name = "plain"
-version = "0.2.3"
+name = "plist"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
+checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85"
+dependencies = [
+ "base64 0.22.1",
+ "indexmap 2.14.0",
+ "quick-xml",
+ "serde",
+ "time",
+]
[[package]]
name = "png"
@@ -4020,22 +2706,6 @@ dependencies = [
"miniz_oxide",
]
-[[package]]
-name = "polling"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
-dependencies = [
- "autocfg",
- "bitflags 1.3.2",
- "cfg-if",
- "concurrent-queue",
- "libc",
- "log",
- "pin-project-lite",
- "windows-sys 0.48.0",
-]
-
[[package]]
name = "polling"
version = "3.11.0"
@@ -4044,18 +2714,12 @@ checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
dependencies = [
"cfg-if",
"concurrent-queue",
- "hermit-abi 0.5.2",
+ "hermit-abi",
"pin-project-lite",
- "rustix 1.1.4",
+ "rustix",
"windows-sys 0.61.2",
]
-[[package]]
-name = "pollster"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
-
[[package]]
name = "potential_utf"
version = "0.1.5"
@@ -4066,19 +2730,16 @@ dependencies = [
]
[[package]]
-name = "ppv-lite86"
-version = "0.2.21"
+name = "powerfmt"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
-dependencies = [
- "zerocopy",
-]
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
-name = "presser"
-version = "0.3.1"
+name = "precomputed-hash"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
+checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "prettyplease"
@@ -4152,73 +2813,11 @@ dependencies = [
"unicode-ident",
]
-[[package]]
-name = "proc-macro2-diagnostics"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
- "version_check",
-]
-
-[[package]]
-name = "profiling"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5"
-dependencies = [
- "profiling-procmacros",
-]
-
-[[package]]
-name = "profiling-procmacros"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb"
-dependencies = [
- "quote",
- "syn 2.0.117",
-]
-
-[[package]]
-name = "pxfm"
-version = "0.1.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f"
-
-[[package]]
-name = "qoi"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
-dependencies = [
- "bytemuck",
-]
-
-[[package]]
-name = "quick-error"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
-
[[package]]
name = "quick-xml"
-version = "0.30.0"
+version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956"
-dependencies = [
- "memchr",
- "serde",
-]
-
-[[package]]
-name = "quick-xml"
-version = "0.39.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e"
+checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
dependencies = [
"memchr",
]
@@ -4244,156 +2843,12 @@ version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
-[[package]]
-name = "rand"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
-dependencies = [
- "libc",
- "rand_chacha 0.3.1",
- "rand_core 0.6.4",
-]
-
-[[package]]
-name = "rand"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
-dependencies = [
- "rand_chacha 0.9.0",
- "rand_core 0.9.5",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "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.5",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom 0.2.17",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
-dependencies = [
- "getrandom 0.3.4",
-]
-
-[[package]]
-name = "rav1e"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b"
-dependencies = [
- "aligned-vec",
- "arbitrary",
- "arg_enum_proc_macro",
- "arrayvec",
- "av-scenechange",
- "av1-grain",
- "bitstream-io",
- "built",
- "cfg-if",
- "interpolate_name",
- "itertools",
- "libc",
- "libfuzzer-sys",
- "log",
- "maybe-rayon",
- "new_debug_unreachable",
- "noop_proc_macro",
- "num-derive",
- "num-traits",
- "paste",
- "profiling",
- "rand 0.9.4",
- "rand_chacha 0.9.0",
- "simd_helpers",
- "thiserror 2.0.18",
- "v_frame",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "ravif"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45"
-dependencies = [
- "avif-serialize",
- "imgref",
- "loop9",
- "quick-error",
- "rav1e",
- "rayon",
- "rgb",
-]
-
[[package]]
name = "raw-window-handle"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
-[[package]]
-name = "rayon"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
-dependencies = [
- "either",
- "rayon-core",
-]
-
-[[package]]
-name = "rayon-core"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
-dependencies = [
- "crossbeam-deque",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "rctree"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f"
-
-[[package]]
-name = "redox_syscall"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
-dependencies = [
- "bitflags 1.3.2",
-]
-
[[package]]
name = "redox_syscall"
version = "0.5.18"
@@ -4403,15 +2858,6 @@ dependencies = [
"bitflags 2.13.0",
]
-[[package]]
-name = "redox_syscall"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b44b894f2a6e36457d665d1e08c3866add6ed5e70050c1b4ba8a8ddedb02ce7"
-dependencies = [
- "bitflags 2.13.0",
-]
-
[[package]]
name = "redox_users"
version = "0.4.6"
@@ -4423,6 +2869,37 @@ dependencies = [
"thiserror 1.0.69",
]
+[[package]]
+name = "redox_users"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
+dependencies = [
+ "getrandom 0.2.17",
+ "libredox",
+ "thiserror 2.0.18",
+]
+
+[[package]]
+name = "ref-cast"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
+dependencies = [
+ "ref-cast-impl",
+]
+
+[[package]]
+name = "ref-cast-impl"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
[[package]]
name = "regex"
version = "1.12.4"
@@ -4453,64 +2930,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
-name = "renderdoc-sys"
-version = "1.1.0"
+name = "reqwest"
+version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
-
-[[package]]
-name = "resvg"
-version = "0.37.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cadccb3d99a9efb8e5e00c16fbb732cbe400db2ec7fc004697ee7d97d86cf1f4"
+checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
dependencies = [
+ "base64 0.22.1",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
+ "js-sys",
"log",
- "pico-args",
- "rgb",
- "svgtypes",
- "tiny-skia",
- "usvg",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde",
+ "serde_json",
+ "sync_wrapper",
+ "tokio",
+ "tokio-util",
+ "tower",
+ "tower-http",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wasm-streams",
+ "web-sys",
]
[[package]]
name = "rfd"
-version = "0.15.4"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed"
+checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672"
dependencies = [
- "ashpd",
- "block2 0.6.2",
+ "block2",
"dispatch2",
+ "glib-sys",
+ "gobject-sys",
+ "gtk-sys",
"js-sys",
"log",
- "objc2 0.6.4",
- "objc2-app-kit 0.3.2",
+ "objc2",
+ "objc2-app-kit",
"objc2-core-foundation",
- "objc2-foundation 0.3.2",
- "pollster",
+ "objc2-foundation",
"raw-window-handle",
- "urlencoding",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
-[[package]]
-name = "rgb"
-version = "0.8.53"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4"
-dependencies = [
- "bytemuck",
-]
-
-[[package]]
-name = "roxmltree"
-version = "0.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
-
[[package]]
name = "rusqlite"
version = "0.31.0"
@@ -4525,12 +3001,6 @@ dependencies = [
"smallvec",
]
-[[package]]
-name = "rustc-hash"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
[[package]]
name = "rustc-hash"
version = "2.1.2"
@@ -4546,33 +3016,6 @@ dependencies = [
"semver",
]
-[[package]]
-name = "rustix"
-version = "0.37.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6"
-dependencies = [
- "bitflags 1.3.2",
- "errno",
- "io-lifetimes",
- "libc",
- "linux-raw-sys 0.3.8",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
-dependencies = [
- "bitflags 2.13.0",
- "errno",
- "libc",
- "linux-raw-sys 0.4.15",
- "windows-sys 0.59.0",
-]
-
[[package]]
name = "rustix"
version = "1.1.4"
@@ -4582,7 +3025,7 @@ dependencies = [
"bitflags 2.13.0",
"errno",
"libc",
- "linux-raw-sys 0.12.1",
+ "linux-raw-sys",
"windows-sys 0.61.2",
]
@@ -4611,10 +3054,55 @@ dependencies = [
]
[[package]]
-name = "scoped-tls"
-version = "1.0.1"
+name = "schemars"
+version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
+checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615"
+dependencies = [
+ "dyn-clone",
+ "indexmap 1.9.3",
+ "schemars_derive",
+ "serde",
+ "serde_json",
+ "url",
+ "uuid",
+]
+
+[[package]]
+name = "schemars"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
+dependencies = [
+ "dyn-clone",
+ "ref-cast",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "schemars"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
+dependencies = [
+ "dyn-clone",
+ "ref-cast",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "schemars_derive"
+version = "0.8.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde_derive_internals",
+ "syn 2.0.117",
+]
[[package]]
name = "scopeguard"
@@ -4622,51 +3110,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-[[package]]
-name = "sctk-adwaita"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec"
-dependencies = [
- "ab_glyph",
- "log",
- "memmap2",
- "smithay-client-toolkit 0.19.2",
- "tiny-skia",
-]
-
-[[package]]
-name = "secret-service"
-version = "3.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5204d39df37f06d1944935232fd2dfe05008def7ca599bf28c0800366c8a8f9"
-dependencies = [
- "aes",
- "cbc",
- "futures-util",
- "generic-array",
- "hkdf",
- "num",
- "once_cell",
- "rand 0.8.6",
- "serde",
- "sha2",
- "zbus 3.15.2",
-]
-
-[[package]]
-name = "security-framework"
-version = "2.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
-dependencies = [
- "bitflags 2.13.0",
- "core-foundation 0.9.4",
- "core-foundation-sys",
- "libc",
- "security-framework-sys",
-]
-
[[package]]
name = "security-framework"
version = "3.7.0"
@@ -4674,7 +3117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
"bitflags 2.13.0",
- "core-foundation 0.10.1",
+ "core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
@@ -4690,11 +3133,34 @@ dependencies = [
"libc",
]
+[[package]]
+name = "selectors"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c"
+dependencies = [
+ "bitflags 2.13.0",
+ "cssparser",
+ "derive_more",
+ "log",
+ "new_debug_unreachable",
+ "phf",
+ "phf_codegen",
+ "precomputed-hash",
+ "rustc-hash",
+ "servo_arc",
+ "smallvec",
+]
+
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
[[package]]
name = "serde"
@@ -4706,6 +3172,18 @@ dependencies = [
"serde_derive",
]
+[[package]]
+name = "serde-untagged"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058"
+dependencies = [
+ "erased-serde",
+ "serde",
+ "serde_core",
+ "typeid",
+]
+
[[package]]
name = "serde_core"
version = "1.0.228"
@@ -4726,6 +3204,17 @@ dependencies = [
"syn 2.0.117",
]
+[[package]]
+name = "serde_derive_internals"
+version = "0.29.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
[[package]]
name = "serde_json"
version = "1.0.150"
@@ -4760,14 +3249,75 @@ dependencies = [
]
[[package]]
-name = "sha1"
-version = "0.10.6"
+name = "serde_spanned"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
+ "serde_core",
+]
+
+[[package]]
+name = "serde_with"
+version = "3.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c"
+dependencies = [
+ "base64 0.22.1",
+ "bs58",
+ "chrono",
+ "hex",
+ "indexmap 1.9.3",
+ "indexmap 2.14.0",
+ "schemars 0.9.0",
+ "schemars 1.2.1",
+ "serde_core",
+ "serde_json",
+ "serde_with_macros",
+ "time",
+]
+
+[[package]]
+name = "serde_with_macros"
+version = "3.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "serialize-to-javascript"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5"
+dependencies = [
+ "serde",
+ "serde_json",
+ "serialize-to-javascript-impl",
+]
+
+[[package]]
+name = "serialize-to-javascript-impl"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "servo_arc"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930"
+dependencies = [
+ "stable_deref_trait",
]
[[package]]
@@ -4812,46 +3362,6 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
-[[package]]
-name = "simd_cesu8"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
-dependencies = [
- "rustc_version",
- "simdutf8",
-]
-
-[[package]]
-name = "simd_helpers"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6"
-dependencies = [
- "quote",
-]
-
-[[package]]
-name = "simdutf8"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
-
-[[package]]
-name = "simplecss"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c"
-dependencies = [
- "log",
-]
-
-[[package]]
-name = "siphasher"
-version = "0.3.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
-
[[package]]
name = "siphasher"
version = "1.0.3"
@@ -4864,103 +3374,12 @@ version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
-[[package]]
-name = "slotmap"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038"
-dependencies = [
- "version_check",
-]
-
[[package]]
name = "smallvec"
version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
-[[package]]
-name = "smithay-client-toolkit"
-version = "0.19.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
-dependencies = [
- "bitflags 2.13.0",
- "calloop 0.13.0",
- "calloop-wayland-source 0.3.0",
- "cursor-icon",
- "libc",
- "log",
- "memmap2",
- "rustix 0.38.44",
- "thiserror 1.0.69",
- "wayland-backend",
- "wayland-client",
- "wayland-csd-frame",
- "wayland-cursor",
- "wayland-protocols",
- "wayland-protocols-wlr",
- "wayland-scanner",
- "xkeysym",
-]
-
-[[package]]
-name = "smithay-client-toolkit"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0"
-dependencies = [
- "bitflags 2.13.0",
- "calloop 0.14.4",
- "calloop-wayland-source 0.4.1",
- "cursor-icon",
- "libc",
- "log",
- "memmap2",
- "rustix 1.1.4",
- "thiserror 2.0.18",
- "wayland-backend",
- "wayland-client",
- "wayland-csd-frame",
- "wayland-cursor",
- "wayland-protocols",
- "wayland-protocols-experimental",
- "wayland-protocols-misc",
- "wayland-protocols-wlr",
- "wayland-scanner",
- "xkeysym",
-]
-
-[[package]]
-name = "smithay-clipboard"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226"
-dependencies = [
- "libc",
- "smithay-client-toolkit 0.20.0",
- "wayland-backend",
-]
-
-[[package]]
-name = "smol_str"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "socket2"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
-dependencies = [
- "libc",
- "winapi",
-]
-
[[package]]
name = "socket2"
version = "0.6.4"
@@ -4972,12 +3391,51 @@ dependencies = [
]
[[package]]
-name = "spirv"
-version = "0.3.0+sdk-1.3.268.0"
+name = "softbuffer"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
+checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3"
dependencies = [
- "bitflags 2.13.0",
+ "bytemuck",
+ "js-sys",
+ "ndk",
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-foundation",
+ "objc2-quartz-core",
+ "raw-window-handle",
+ "redox_syscall",
+ "tracing",
+ "wasm-bindgen",
+ "web-sys",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "soup3"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f"
+dependencies = [
+ "futures-channel",
+ "gio",
+ "glib",
+ "libc",
+ "soup3-sys",
+]
+
+[[package]]
+name = "soup3-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27"
+dependencies = [
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "system-deps",
]
[[package]]
@@ -4999,25 +3457,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
-name = "static_assertions"
-version = "1.1.0"
+name = "string_cache"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "strict-num"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
+checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901"
dependencies = [
- "float-cmp",
+ "new_debug_unreachable",
+ "parking_lot",
+ "phf_shared",
+ "precomputed-hash",
]
[[package]]
-name = "subtle"
-version = "2.6.1"
+name = "string_cache_codegen"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "suppaftp"
@@ -5029,7 +3496,7 @@ dependencies = [
"async-std",
"async-trait",
"chrono",
- "futures-lite 2.6.1",
+ "futures-lite",
"lazy-regex",
"log",
"pin-project",
@@ -5037,13 +3504,14 @@ dependencies = [
]
[[package]]
-name = "svgtypes"
-version = "0.13.0"
+name = "swift-rs"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e44e288cd960318917cbd540340968b90becc8bc81f171345d706e7a89d9d70"
+checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7"
dependencies = [
- "kurbo",
- "siphasher 0.3.11",
+ "base64 0.21.7",
+ "serde",
+ "serde_json",
]
[[package]]
@@ -5053,7 +3521,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
- "quote",
"unicode-ident",
]
@@ -5068,6 +3535,15 @@ dependencies = [
"unicode-ident",
]
+[[package]]
+name = "sync_wrapper"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
+dependencies = [
+ "futures-core",
+]
+
[[package]]
name = "synstructure"
version = "0.13.2"
@@ -5088,36 +3564,359 @@ dependencies = [
"cfg-expr",
"heck 0.5.0",
"pkg-config",
- "toml",
+ "toml 0.8.2",
"version-compare",
]
+[[package]]
+name = "tao"
+version = "0.35.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9"
+dependencies = [
+ "bitflags 2.13.0",
+ "block2",
+ "core-foundation",
+ "core-graphics",
+ "crossbeam-channel",
+ "dbus",
+ "dispatch2",
+ "dlopen2",
+ "dpi",
+ "gdkwayland-sys",
+ "gdkx11-sys",
+ "gtk",
+ "jni",
+ "libc",
+ "log",
+ "ndk",
+ "ndk-sys",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
+ "objc2-ui-kit",
+ "once_cell",
+ "parking_lot",
+ "percent-encoding",
+ "raw-window-handle",
+ "tao-macros",
+ "unicode-segmentation",
+ "url",
+ "windows",
+ "windows-core 0.61.2",
+ "windows-version",
+ "x11-dl",
+]
+
+[[package]]
+name = "tao-macros"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
+[[package]]
+name = "tauri"
+version = "2.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5"
+dependencies = [
+ "anyhow",
+ "bytes",
+ "cookie",
+ "dirs 6.0.0",
+ "dunce",
+ "embed_plist",
+ "getrandom 0.3.4",
+ "glob",
+ "gtk",
+ "heck 0.5.0",
+ "http",
+ "jni",
+ "libc",
+ "log",
+ "mime",
+ "muda",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
+ "objc2-ui-kit",
+ "objc2-web-kit",
+ "percent-encoding",
+ "plist",
+ "raw-window-handle",
+ "reqwest",
+ "serde",
+ "serde_json",
+ "serde_repr",
+ "serialize-to-javascript",
+ "swift-rs",
+ "tauri-build",
+ "tauri-macros",
+ "tauri-runtime",
+ "tauri-runtime-wry",
+ "tauri-utils",
+ "thiserror 2.0.18",
+ "tokio",
+ "tray-icon",
+ "url",
+ "webkit2gtk",
+ "webview2-com",
+ "window-vibrancy",
+ "windows",
+]
+
+[[package]]
+name = "tauri-build"
+version = "2.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632"
+dependencies = [
+ "anyhow",
+ "cargo_toml",
+ "dirs 6.0.0",
+ "glob",
+ "heck 0.5.0",
+ "json-patch",
+ "schemars 0.8.22",
+ "semver",
+ "serde",
+ "serde_json",
+ "tauri-utils",
+ "tauri-winres",
+ "walkdir",
+]
+
+[[package]]
+name = "tauri-codegen"
+version = "2.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5"
+dependencies = [
+ "base64 0.22.1",
+ "brotli",
+ "ico",
+ "json-patch",
+ "plist",
+ "png 0.17.16",
+ "proc-macro2",
+ "quote",
+ "semver",
+ "serde",
+ "serde_json",
+ "sha2",
+ "syn 2.0.117",
+ "tauri-utils",
+ "thiserror 2.0.18",
+ "time",
+ "url",
+ "uuid",
+ "walkdir",
+]
+
+[[package]]
+name = "tauri-macros"
+version = "2.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45"
+dependencies = [
+ "heck 0.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+ "tauri-codegen",
+ "tauri-utils",
+]
+
+[[package]]
+name = "tauri-plugin"
+version = "2.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74be5dd4bed9afbd145e5716b5fa2ec28cbc29c34ffa61c258c9273d896c8020"
+dependencies = [
+ "anyhow",
+ "glob",
+ "plist",
+ "schemars 0.8.22",
+ "serde",
+ "serde_json",
+ "tauri-utils",
+ "walkdir",
+]
+
+[[package]]
+name = "tauri-plugin-dialog"
+version = "2.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65981abb771e74e571a38196c3baa11c459379164791eba0e67abc1a5fac9884"
+dependencies = [
+ "log",
+ "raw-window-handle",
+ "rfd",
+ "serde",
+ "serde_json",
+ "tauri",
+ "tauri-plugin",
+ "tauri-plugin-fs",
+ "thiserror 2.0.18",
+ "url",
+]
+
+[[package]]
+name = "tauri-plugin-fs"
+version = "2.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7ecc274121aca0c036a2b42d1cbe83d368d348f54e0bb8a735c2b1548e8f371"
+dependencies = [
+ "anyhow",
+ "dunce",
+ "glob",
+ "log",
+ "objc2-foundation",
+ "percent-encoding",
+ "schemars 0.8.22",
+ "serde",
+ "serde_json",
+ "serde_repr",
+ "tauri",
+ "tauri-plugin",
+ "tauri-utils",
+ "thiserror 2.0.18",
+ "toml 1.1.2+spec-1.1.0",
+ "url",
+]
+
+[[package]]
+name = "tauri-runtime"
+version = "2.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8"
+dependencies = [
+ "cookie",
+ "dpi",
+ "gtk",
+ "http",
+ "jni",
+ "objc2",
+ "objc2-ui-kit",
+ "objc2-web-kit",
+ "raw-window-handle",
+ "serde",
+ "serde_json",
+ "tauri-utils",
+ "thiserror 2.0.18",
+ "url",
+ "webkit2gtk",
+ "webview2-com",
+ "windows",
+]
+
+[[package]]
+name = "tauri-runtime-wry"
+version = "2.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f"
+dependencies = [
+ "gtk",
+ "http",
+ "jni",
+ "log",
+ "objc2",
+ "objc2-app-kit",
+ "once_cell",
+ "percent-encoding",
+ "raw-window-handle",
+ "softbuffer",
+ "tao",
+ "tauri-runtime",
+ "tauri-utils",
+ "url",
+ "webkit2gtk",
+ "webview2-com",
+ "windows",
+ "wry",
+]
+
+[[package]]
+name = "tauri-utils"
+version = "2.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887"
+dependencies = [
+ "anyhow",
+ "brotli",
+ "cargo_metadata",
+ "ctor",
+ "dom_query",
+ "dunce",
+ "glob",
+ "http",
+ "infer",
+ "json-patch",
+ "log",
+ "memchr",
+ "phf",
+ "plist",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "schemars 0.8.22",
+ "semver",
+ "serde",
+ "serde-untagged",
+ "serde_json",
+ "serde_with",
+ "swift-rs",
+ "thiserror 2.0.18",
+ "toml 1.1.2+spec-1.1.0",
+ "url",
+ "urlpattern",
+ "uuid",
+ "walkdir",
+]
+
+[[package]]
+name = "tauri-winres"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6"
+dependencies = [
+ "dunce",
+ "embed-resource",
+ "toml 1.1.2+spec-1.1.0",
+]
+
[[package]]
name = "tempfile"
version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
- "fastrand 2.4.1",
+ "fastrand",
"getrandom 0.4.2",
"once_cell",
- "rustix 1.1.4",
+ "rustix",
"windows-sys 0.61.2",
]
[[package]]
-name = "termcolor"
-version = "1.4.1"
+name = "tendril"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24"
dependencies = [
- "winapi-util",
+ "new_debug_unreachable",
+ "utf-8",
]
[[package]]
@@ -5170,43 +3969,33 @@ dependencies = [
]
[[package]]
-name = "tiff"
-version = "0.11.3"
+name = "time"
+version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52"
+checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50"
dependencies = [
- "fax",
- "flate2",
- "half",
- "quick-error",
- "weezl",
- "zune-jpeg",
+ "deranged",
+ "num-conv",
+ "powerfmt",
+ "serde_core",
+ "time-core",
+ "time-macros",
]
[[package]]
-name = "tiny-skia"
-version = "0.11.4"
+name = "time-core"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab"
-dependencies = [
- "arrayref",
- "arrayvec",
- "bytemuck",
- "cfg-if",
- "log",
- "png 0.17.16",
- "tiny-skia-path",
-]
+checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]]
-name = "tiny-skia-path"
-version = "0.11.4"
+name = "time-macros"
+version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93"
+checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f"
dependencies = [
- "arrayref",
- "bytemuck",
- "strict-num",
+ "num-conv",
+ "time-core",
]
[[package]]
@@ -5219,6 +4008,21 @@ dependencies = [
"zerovec",
]
+[[package]]
+name = "tinyvec"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
[[package]]
name = "tokio"
version = "1.52.3"
@@ -5231,7 +4035,7 @@ dependencies = [
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.6.4",
+ "socket2",
"tokio-macros",
"windows-sys 0.61.2",
]
@@ -5247,6 +4051,19 @@ dependencies = [
"syn 2.0.117",
]
+[[package]]
+name = "tokio-util"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
[[package]]
name = "toml"
version = "0.8.2"
@@ -5254,11 +4071,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d"
dependencies = [
"serde",
- "serde_spanned",
+ "serde_spanned 0.6.9",
"toml_datetime 0.6.3",
"toml_edit 0.20.2",
]
+[[package]]
+name = "toml"
+version = "0.9.12+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
+dependencies = [
+ "indexmap 2.14.0",
+ "serde_core",
+ "serde_spanned 1.1.1",
+ "toml_datetime 0.7.5+spec-1.1.0",
+ "toml_parser",
+ "toml_writer",
+ "winnow 0.7.15",
+]
+
+[[package]]
+name = "toml"
+version = "1.1.2+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
+dependencies = [
+ "indexmap 2.14.0",
+ "serde_core",
+ "serde_spanned 1.1.1",
+ "toml_datetime 1.1.1+spec-1.1.0",
+ "toml_parser",
+ "toml_writer",
+ "winnow 1.0.3",
+]
+
[[package]]
name = "toml_datetime"
version = "0.6.3"
@@ -5268,6 +4115,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "toml_datetime"
+version = "0.7.5+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
+dependencies = [
+ "serde_core",
+]
+
[[package]]
name = "toml_datetime"
version = "1.1.1+spec-1.1.0"
@@ -5283,7 +4139,7 @@ version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
- "indexmap",
+ "indexmap 2.14.0",
"toml_datetime 0.6.3",
"winnow 0.5.40",
]
@@ -5294,9 +4150,9 @@ version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
dependencies = [
- "indexmap",
+ "indexmap 2.14.0",
"serde",
- "serde_spanned",
+ "serde_spanned 0.6.9",
"toml_datetime 0.6.3",
"winnow 0.5.40",
]
@@ -5307,7 +4163,7 @@ version = "0.25.12+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7"
dependencies = [
- "indexmap",
+ "indexmap 2.14.0",
"toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
"winnow 1.0.3",
@@ -5322,13 +4178,63 @@ dependencies = [
"winnow 1.0.3",
]
+[[package]]
+name = "toml_writer"
+version = "1.1.1+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
+
+[[package]]
+name = "tower"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "pin-project-lite",
+ "sync_wrapper",
+ "tokio",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "tower-http"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
+dependencies = [
+ "bitflags 2.13.0",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "pin-project-lite",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "url",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
+
+[[package]]
+name = "tower-service"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
+
[[package]]
name = "tracing"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
- "log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -5381,19 +4287,38 @@ dependencies = [
]
[[package]]
-name = "ttf-parser"
-version = "0.25.1"
+name = "tray-icon"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
+checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc"
+dependencies = [
+ "crossbeam-channel",
+ "dirs 6.0.0",
+ "libappindicator",
+ "muda",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-foundation",
+ "once_cell",
+ "png 0.18.1",
+ "serde",
+ "thiserror 2.0.18",
+ "windows-sys 0.61.2",
+]
[[package]]
-name = "type-map"
-version = "0.5.1"
+name = "try-lock"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90"
-dependencies = [
- "rustc-hash 2.1.2",
-]
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
+[[package]]
+name = "typeid"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
[[package]]
name = "typenum"
@@ -5402,21 +4327,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
[[package]]
-name = "uds_windows"
-version = "1.2.1"
+name = "unic-char-property"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
+checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
dependencies = [
- "memoffset 0.9.1",
- "tempfile",
- "windows-sys 0.61.2",
+ "unic-char-range",
]
[[package]]
-name = "unicase"
-version = "2.9.0"
+name = "unic-char-range"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
+checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
+
+[[package]]
+name = "unic-common"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
+
+[[package]]
+name = "unic-ucd-ident"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987"
+dependencies = [
+ "unic-char-property",
+ "unic-char-range",
+ "unic-ucd-version",
+]
+
+[[package]]
+name = "unic-ucd-version"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
+dependencies = [
+ "unic-common",
+]
[[package]]
name = "unicode-ident"
@@ -5430,12 +4379,6 @@ version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
-[[package]]
-name = "unicode-width"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
-
[[package]]
name = "unicode-xid"
version = "0.2.6"
@@ -5456,54 +4399,22 @@ dependencies = [
]
[[package]]
-name = "urlencoding"
-version = "2.1.3"
+name = "urlpattern"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
-
-[[package]]
-name = "usvg"
-version = "0.37.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38b0a51b72ab80ca511d126b77feeeb4fb1e972764653e61feac30adc161a756"
+checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d"
dependencies = [
- "base64",
- "log",
- "pico-args",
- "usvg-parser",
- "usvg-tree",
- "xmlwriter",
+ "regex",
+ "serde",
+ "unic-ucd-ident",
+ "url",
]
[[package]]
-name = "usvg-parser"
-version = "0.37.0"
+name = "utf-8"
+version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bd4e3c291f45d152929a31f0f6c819245e2921bfd01e7bd91201a9af39a2bdc"
-dependencies = [
- "data-url",
- "flate2",
- "imagesize",
- "kurbo",
- "log",
- "roxmltree",
- "simplecss",
- "siphasher 0.3.11",
- "svgtypes",
- "usvg-tree",
-]
-
-[[package]]
-name = "usvg-tree"
-version = "0.37.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ee3d202ebdb97a6215604b8f5b4d6ef9024efd623cf2e373a6416ba976ec7d3"
-dependencies = [
- "rctree",
- "strict-num",
- "svgtypes",
- "tiny-skia-path",
-]
+checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf8_iter"
@@ -5523,17 +4434,6 @@ dependencies = [
"wasm-bindgen",
]
-[[package]]
-name = "v_frame"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2"
-dependencies = [
- "aligned-vec",
- "num-traits",
- "wasm-bindgen",
-]
-
[[package]]
name = "valuable"
version = "0.1.1"
@@ -5565,10 +4465,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
-name = "waker-fn"
-version = "1.2.0"
+name = "vswhom"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7"
+checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b"
+dependencies = [
+ "libc",
+ "vswhom-sys",
+]
+
+[[package]]
+name = "vswhom-sys"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150"
+dependencies = [
+ "cc",
+ "libc",
+]
[[package]]
name = "walkdir"
@@ -5580,6 +4494,15 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
@@ -5676,11 +4599,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
dependencies = [
"anyhow",
- "indexmap",
+ "indexmap 2.14.0",
"wasm-encoder",
"wasmparser",
]
+[[package]]
+name = "wasm-streams"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb"
+dependencies = [
+ "futures-util",
+ "js-sys",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
[[package]]
name = "wasmparser"
version = "0.244.0"
@@ -5689,145 +4625,10 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
"bitflags 2.13.0",
"hashbrown 0.15.5",
- "indexmap",
+ "indexmap 2.14.0",
"semver",
]
-[[package]]
-name = "wayland-backend"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d"
-dependencies = [
- "cc",
- "downcast-rs",
- "rustix 1.1.4",
- "scoped-tls",
- "smallvec",
- "wayland-sys",
-]
-
-[[package]]
-name = "wayland-client"
-version = "0.31.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144"
-dependencies = [
- "bitflags 2.13.0",
- "rustix 1.1.4",
- "wayland-backend",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-csd-frame"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
-dependencies = [
- "bitflags 2.13.0",
- "cursor-icon",
- "wayland-backend",
-]
-
-[[package]]
-name = "wayland-cursor"
-version = "0.31.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d"
-dependencies = [
- "rustix 1.1.4",
- "wayland-client",
- "xcursor",
-]
-
-[[package]]
-name = "wayland-protocols"
-version = "0.32.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f"
-dependencies = [
- "bitflags 2.13.0",
- "wayland-backend",
- "wayland-client",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-protocols-experimental"
-version = "20250721.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1"
-dependencies = [
- "bitflags 2.13.0",
- "wayland-backend",
- "wayland-client",
- "wayland-protocols",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-protocols-misc"
-version = "0.3.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8"
-dependencies = [
- "bitflags 2.13.0",
- "wayland-backend",
- "wayland-client",
- "wayland-protocols",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-protocols-plasma"
-version = "0.3.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91"
-dependencies = [
- "bitflags 2.13.0",
- "wayland-backend",
- "wayland-client",
- "wayland-protocols",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-protocols-wlr"
-version = "0.3.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234"
-dependencies = [
- "bitflags 2.13.0",
- "wayland-backend",
- "wayland-client",
- "wayland-protocols",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-scanner"
-version = "0.31.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a"
-dependencies = [
- "proc-macro2",
- "quick-xml 0.39.4",
- "quote",
-]
-
-[[package]]
-name = "wayland-sys"
-version = "0.31.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be"
-dependencies = [
- "dlib",
- "log",
- "once_cell",
- "pkg-config",
-]
-
[[package]]
name = "web-sys"
version = "0.3.102"
@@ -5839,143 +4640,120 @@ dependencies = [
]
[[package]]
-name = "web-time"
-version = "1.1.0"
+name = "web_atoms"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
+checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297"
dependencies = [
- "js-sys",
- "wasm-bindgen",
+ "phf",
+ "phf_codegen",
+ "string_cache",
+ "string_cache_codegen",
]
[[package]]
-name = "webbrowser"
-version = "1.2.1"
+name = "webkit2gtk"
+version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fc95580916af1e68ff6a7be07446fc5db73ebf71cf092de939bbf5f7e189f72"
+checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793"
dependencies = [
- "core-foundation 0.10.1",
- "jni",
- "log",
- "ndk-context",
- "objc2 0.6.4",
- "objc2-foundation 0.3.2",
- "url",
- "web-sys",
-]
-
-[[package]]
-name = "weezl"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
-
-[[package]]
-name = "wgpu"
-version = "22.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1d1c4ba43f80542cf63a0a6ed3134629ae73e8ab51e4b765a67f3aa062eb433"
-dependencies = [
- "arrayvec",
- "cfg_aliases 0.1.1",
- "document-features",
- "js-sys",
- "log",
- "parking_lot",
- "profiling",
- "raw-window-handle",
- "smallvec",
- "static_assertions",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
- "wgpu-core",
- "wgpu-hal",
- "wgpu-types",
-]
-
-[[package]]
-name = "wgpu-core"
-version = "22.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0348c840d1051b8e86c3bcd31206080c5e71e5933dabd79be1ce732b0b2f089a"
-dependencies = [
- "arrayvec",
- "bit-vec",
- "bitflags 2.13.0",
- "cfg_aliases 0.1.1",
- "document-features",
- "indexmap",
- "log",
- "naga",
- "once_cell",
- "parking_lot",
- "profiling",
- "raw-window-handle",
- "rustc-hash 1.1.0",
- "smallvec",
- "thiserror 1.0.69",
- "wgpu-hal",
- "wgpu-types",
-]
-
-[[package]]
-name = "wgpu-hal"
-version = "22.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6bbf4b4de8b2a83c0401d9e5ae0080a2792055f25859a02bf9be97952bbed4f"
-dependencies = [
- "android_system_properties",
- "arrayvec",
- "ash",
- "bitflags 2.13.0",
- "cfg_aliases 0.1.1",
- "core-graphics-types",
- "glow 0.13.1",
- "glutin_wgl_sys",
- "gpu-alloc",
- "gpu-allocator",
- "gpu-descriptor",
- "hassle-rs",
- "js-sys",
- "khronos-egl",
+ "bitflags 1.3.2",
+ "cairo-rs",
+ "gdk",
+ "gdk-sys",
+ "gio",
+ "gio-sys",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "gtk",
+ "gtk-sys",
+ "javascriptcore-rs",
"libc",
- "libloading",
- "log",
- "metal",
- "naga",
- "ndk-sys 0.5.0+25.2.9519653",
- "objc",
"once_cell",
- "parking_lot",
- "profiling",
- "raw-window-handle",
- "renderdoc-sys",
- "rustc-hash 1.1.0",
- "smallvec",
- "thiserror 1.0.69",
- "wasm-bindgen",
- "web-sys",
- "wgpu-types",
- "winapi",
+ "soup3",
+ "webkit2gtk-sys",
]
[[package]]
-name = "wgpu-types"
-version = "22.0.0"
+name = "webkit2gtk-sys"
+version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc9d91f0e2c4b51434dfa6db77846f2793149d8e73f800fa2e41f52b8eac3c5d"
+checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5"
dependencies = [
- "bitflags 2.13.0",
- "js-sys",
- "web-sys",
+ "bitflags 1.3.2",
+ "cairo-sys-rs",
+ "gdk-sys",
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "gtk-sys",
+ "javascriptcore-rs-sys",
+ "libc",
+ "pkg-config",
+ "soup3-sys",
+ "system-deps",
]
[[package]]
-name = "widestring"
-version = "1.2.1"
+name = "webview2-com"
+version = "0.38.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471"
+checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a"
+dependencies = [
+ "webview2-com-macros",
+ "webview2-com-sys",
+ "windows",
+ "windows-core 0.61.2",
+ "windows-implement",
+ "windows-interface",
+]
+
+[[package]]
+name = "webview2-com-macros"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "webview2-com-sys"
+version = "0.38.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c"
+dependencies = [
+ "thiserror 2.0.18",
+ "windows",
+ "windows-core 0.61.2",
+]
+
+[[package]]
+name = "wherry"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "async-trait",
+ "chrono",
+ "dirs 5.0.1",
+ "futures-lite",
+ "rusqlite",
+ "serde",
+ "serde_json",
+ "ssh2",
+ "suppaftp",
+ "tauri",
+ "tauri-build",
+ "tauri-plugin-dialog",
+ "thiserror 1.0.69",
+ "tokio",
+ "tracing",
+ "tracing-subscriber",
+ "uuid",
+]
[[package]]
name = "winapi"
@@ -6009,45 +4787,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
-name = "windows"
-version = "0.52.0"
+name = "window-vibrancy"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
+checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c"
dependencies = [
- "windows-core 0.52.0",
- "windows-targets 0.52.6",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-foundation",
+ "raw-window-handle",
+ "windows-sys 0.59.0",
+ "windows-version",
]
[[package]]
name = "windows"
-version = "0.58.0"
+version = "0.61.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
+checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
dependencies = [
- "windows-core 0.58.0",
- "windows-targets 0.52.6",
+ "windows-collections",
+ "windows-core 0.61.2",
+ "windows-future",
+ "windows-link 0.1.3",
+ "windows-numerics",
+]
+
+[[package]]
+name = "windows-collections"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
+dependencies = [
+ "windows-core 0.61.2",
]
[[package]]
name = "windows-core"
-version = "0.52.0"
+version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-core"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
-dependencies = [
- "windows-implement 0.58.0",
- "windows-interface 0.58.0",
- "windows-result 0.2.0",
- "windows-strings 0.1.0",
- "windows-targets 0.52.6",
+ "windows-implement",
+ "windows-interface",
+ "windows-link 0.1.3",
+ "windows-result 0.3.4",
+ "windows-strings 0.4.2",
]
[[package]]
@@ -6056,22 +4842,22 @@ version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
- "windows-implement 0.60.2",
- "windows-interface 0.59.3",
- "windows-link",
+ "windows-implement",
+ "windows-interface",
+ "windows-link 0.2.1",
"windows-result 0.4.1",
"windows-strings 0.5.1",
]
[[package]]
-name = "windows-implement"
-version = "0.58.0"
+name = "windows-future"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
+checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
+ "windows-core 0.61.2",
+ "windows-link 0.1.3",
+ "windows-threading",
]
[[package]]
@@ -6085,17 +4871,6 @@ dependencies = [
"syn 2.0.117",
]
-[[package]]
-name = "windows-interface"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
-]
-
[[package]]
name = "windows-interface"
version = "0.59.3"
@@ -6107,6 +4882,12 @@ dependencies = [
"syn 2.0.117",
]
+[[package]]
+name = "windows-link"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
+
[[package]]
name = "windows-link"
version = "0.2.1"
@@ -6114,12 +4895,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
-name = "windows-result"
+name = "windows-numerics"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
+checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
dependencies = [
- "windows-targets 0.52.6",
+ "windows-core 0.61.2",
+ "windows-link 0.1.3",
+]
+
+[[package]]
+name = "windows-result"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
+dependencies = [
+ "windows-link 0.1.3",
]
[[package]]
@@ -6128,17 +4919,16 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
- "windows-link",
+ "windows-link 0.2.1",
]
[[package]]
name = "windows-strings"
-version = "0.1.0"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
+checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
- "windows-result 0.2.0",
- "windows-targets 0.52.6",
+ "windows-link 0.1.3",
]
[[package]]
@@ -6147,7 +4937,16 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
- "windows-link",
+ "windows-link 0.2.1",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
]
[[package]]
@@ -6159,15 +4958,6 @@ dependencies = [
"windows-targets 0.48.5",
]
-[[package]]
-name = "windows-sys"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
[[package]]
name = "windows-sys"
version = "0.59.0"
@@ -6192,7 +4982,22 @@ version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
- "windows-link",
+ "windows-link 0.2.1",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
]
[[package]]
@@ -6232,7 +5037,7 @@ version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
- "windows-link",
+ "windows-link 0.2.1",
"windows_aarch64_gnullvm 0.53.1",
"windows_aarch64_msvc 0.53.1",
"windows_i686_gnu 0.53.1",
@@ -6243,6 +5048,30 @@ dependencies = [
"windows_x86_64_msvc 0.53.1",
]
+[[package]]
+name = "windows-threading"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
+dependencies = [
+ "windows-link 0.1.3",
+]
+
+[[package]]
+name = "windows-version"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631"
+dependencies = [
+ "windows-link 0.2.1",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
@@ -6261,6 +5090,12 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
@@ -6279,6 +5114,12 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
@@ -6309,6 +5150,12 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
@@ -6327,6 +5174,12 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
@@ -6345,6 +5198,12 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
@@ -6363,6 +5222,12 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
@@ -6381,58 +5246,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
-[[package]]
-name = "winit"
-version = "0.30.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d"
-dependencies = [
- "ahash",
- "android-activity",
- "atomic-waker",
- "bitflags 2.13.0",
- "block2 0.5.1",
- "bytemuck",
- "calloop 0.13.0",
- "cfg_aliases 0.2.1",
- "concurrent-queue",
- "core-foundation 0.9.4",
- "core-graphics",
- "cursor-icon",
- "dpi",
- "js-sys",
- "libc",
- "memmap2",
- "ndk",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
- "objc2-ui-kit",
- "orbclient",
- "percent-encoding",
- "pin-project",
- "raw-window-handle",
- "redox_syscall 0.4.1",
- "rustix 0.38.44",
- "sctk-adwaita",
- "smithay-client-toolkit 0.19.2",
- "smol_str",
- "tracing",
- "unicode-segmentation",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "wayland-backend",
- "wayland-client",
- "wayland-protocols",
- "wayland-protocols-plasma",
- "web-sys",
- "web-time",
- "windows-sys 0.52.0",
- "x11-dl",
- "x11rb",
- "xkbcommon-dl",
-]
-
[[package]]
name = "winnow"
version = "0.5.40"
@@ -6442,6 +5255,12 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "winnow"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+
[[package]]
name = "winnow"
version = "1.0.3"
@@ -6451,6 +5270,16 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "winreg"
+version = "0.55.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97"
+dependencies = [
+ "cfg-if",
+ "windows-sys 0.59.0",
+]
+
[[package]]
name = "wit-bindgen"
version = "0.51.0"
@@ -6485,7 +5314,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
dependencies = [
"anyhow",
"heck 0.5.0",
- "indexmap",
+ "indexmap 2.14.0",
"prettyplease",
"syn 2.0.117",
"wasm-metadata",
@@ -6516,7 +5345,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [
"anyhow",
"bitflags 2.13.0",
- "indexmap",
+ "indexmap 2.14.0",
"log",
"serde",
"serde_derive",
@@ -6535,7 +5364,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
dependencies = [
"anyhow",
"id-arena",
- "indexmap",
+ "indexmap 2.14.0",
"log",
"semver",
"serde",
@@ -6551,6 +5380,50 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
+[[package]]
+name = "wry"
+version = "0.55.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514"
+dependencies = [
+ "base64 0.22.1",
+ "block2",
+ "cookie",
+ "crossbeam-channel",
+ "dirs 6.0.0",
+ "dom_query",
+ "dpi",
+ "dunce",
+ "gdkx11",
+ "gtk",
+ "http",
+ "javascriptcore-rs",
+ "jni",
+ "libc",
+ "ndk",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-core-foundation",
+ "objc2-foundation",
+ "objc2-ui-kit",
+ "objc2-web-kit",
+ "once_cell",
+ "percent-encoding",
+ "raw-window-handle",
+ "sha2",
+ "soup3",
+ "tao-macros",
+ "thiserror 2.0.18",
+ "url",
+ "webkit2gtk",
+ "webkit2gtk-sys",
+ "webview2-com",
+ "windows",
+ "windows-core 0.61.2",
+ "windows-version",
+ "x11-dl",
+]
+
[[package]]
name = "x11"
version = "2.21.0"
@@ -6572,80 +5445,6 @@ dependencies = [
"pkg-config",
]
-[[package]]
-name = "x11rb"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414"
-dependencies = [
- "as-raw-xcb-connection",
- "gethostname",
- "libc",
- "libloading",
- "once_cell",
- "rustix 1.1.4",
- "x11rb-protocol",
-]
-
-[[package]]
-name = "x11rb-protocol"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
-
-[[package]]
-name = "xcursor"
-version = "0.3.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b"
-
-[[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 = "xkbcommon-dl"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5"
-dependencies = [
- "bitflags 2.13.0",
- "dlib",
- "log",
- "once_cell",
- "xkeysym",
-]
-
-[[package]]
-name = "xkeysym"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
-
-[[package]]
-name = "xml-rs"
-version = "0.8.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"
-
-[[package]]
-name = "xmlwriter"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
-
-[[package]]
-name = "y4m"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448"
-
[[package]]
name = "yoke"
version = "0.8.3"
@@ -6669,232 +5468,6 @@ dependencies = [
"synstructure",
]
-[[package]]
-name = "zbus"
-version = "3.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6"
-dependencies = [
- "async-broadcast 0.5.1",
- "async-executor",
- "async-fs 1.6.0",
- "async-io 1.13.0",
- "async-lock 2.8.0",
- "async-process 1.8.1",
- "async-recursion",
- "async-task",
- "async-trait",
- "blocking",
- "byteorder",
- "derivative",
- "enumflags2",
- "event-listener 2.5.3",
- "futures-core",
- "futures-sink",
- "futures-util",
- "hex",
- "nix 0.26.4",
- "once_cell",
- "ordered-stream",
- "rand 0.8.6",
- "serde",
- "serde_repr",
- "sha1",
- "static_assertions",
- "tracing",
- "uds_windows",
- "winapi",
- "xdg-home",
- "zbus_macros 3.15.2",
- "zbus_names 2.6.1",
- "zvariant 3.15.2",
-]
-
-[[package]]
-name = "zbus"
-version = "4.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725"
-dependencies = [
- "async-broadcast 0.7.2",
- "async-executor",
- "async-fs 2.2.0",
- "async-io 2.6.0",
- "async-lock 3.4.2",
- "async-process 2.5.0",
- "async-recursion",
- "async-task",
- "async-trait",
- "blocking",
- "enumflags2",
- "event-listener 5.4.1",
- "futures-core",
- "futures-sink",
- "futures-util",
- "hex",
- "nix 0.29.0",
- "ordered-stream",
- "rand 0.8.6",
- "serde",
- "serde_repr",
- "sha1",
- "static_assertions",
- "tracing",
- "uds_windows",
- "windows-sys 0.52.0",
- "xdg-home",
- "zbus_macros 4.4.0",
- "zbus_names 3.0.0",
- "zvariant 4.2.0",
-]
-
-[[package]]
-name = "zbus"
-version = "5.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eee682d202a77e4a9f3b2c2bdf48a7b28af5c08c34ddf66f98c93e5e39464285"
-dependencies = [
- "async-broadcast 0.7.2",
- "async-executor",
- "async-io 2.6.0",
- "async-lock 3.4.2",
- "async-process 2.5.0",
- "async-recursion",
- "async-task",
- "async-trait",
- "blocking",
- "enumflags2",
- "event-listener 5.4.1",
- "futures-core",
- "futures-lite 2.6.1",
- "hex",
- "libc",
- "ordered-stream",
- "rustix 1.1.4",
- "serde",
- "serde_repr",
- "tracing",
- "uds_windows",
- "uuid",
- "windows-sys 0.61.2",
- "winnow 1.0.3",
- "zbus_macros 5.16.0",
- "zbus_names 4.3.2",
- "zvariant 5.12.0",
-]
-
-[[package]]
-name = "zbus-lockstep"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca2c5dceb099bddaade154055c926bb8ae507a18756ba1d8963fd7b51d8ed1d"
-dependencies = [
- "zbus_xml",
- "zvariant 4.2.0",
-]
-
-[[package]]
-name = "zbus-lockstep-macros"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
- "zbus-lockstep",
- "zbus_xml",
- "zvariant 4.2.0",
-]
-
-[[package]]
-name = "zbus_macros"
-version = "3.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5"
-dependencies = [
- "proc-macro-crate 1.3.1",
- "proc-macro2",
- "quote",
- "regex",
- "syn 1.0.109",
- "zvariant_utils 1.0.1",
-]
-
-[[package]]
-name = "zbus_macros"
-version = "4.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e"
-dependencies = [
- "proc-macro-crate 3.5.0",
- "proc-macro2",
- "quote",
- "syn 2.0.117",
- "zvariant_utils 2.1.0",
-]
-
-[[package]]
-name = "zbus_macros"
-version = "5.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adf1bd45a81a103745b1757754762a26e8cd01e4532e4d6c8ec431624b80d1d6"
-dependencies = [
- "proc-macro-crate 3.5.0",
- "proc-macro2",
- "quote",
- "syn 2.0.117",
- "zbus_names 4.3.2",
- "zvariant 5.12.0",
- "zvariant_utils 3.4.0",
-]
-
-[[package]]
-name = "zbus_names"
-version = "2.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d"
-dependencies = [
- "serde",
- "static_assertions",
- "zvariant 3.15.2",
-]
-
-[[package]]
-name = "zbus_names"
-version = "3.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c"
-dependencies = [
- "serde",
- "static_assertions",
- "zvariant 4.2.0",
-]
-
-[[package]]
-name = "zbus_names"
-version = "4.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d"
-dependencies = [
- "serde",
- "winnow 1.0.3",
- "zvariant 5.12.0",
-]
-
-[[package]]
-name = "zbus_xml"
-version = "4.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab3f374552b954f6abb4bd6ce979e6c9b38fb9d0cd7cc68a7d796e70c9f3a233"
-dependencies = [
- "quick-xml 0.30.0",
- "serde",
- "static_assertions",
- "zbus_names 3.0.0",
- "zvariant 4.2.0",
-]
-
[[package]]
name = "zerocopy"
version = "0.8.52"
@@ -6974,143 +5547,3 @@ name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
-
-[[package]]
-name = "zune-core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9"
-
-[[package]]
-name = "zune-inflate"
-version = "0.2.54"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
-dependencies = [
- "simd-adler32",
-]
-
-[[package]]
-name = "zune-jpeg"
-version = "0.5.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
-dependencies = [
- "zune-core",
-]
-
-[[package]]
-name = "zvariant"
-version = "3.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db"
-dependencies = [
- "byteorder",
- "enumflags2",
- "libc",
- "serde",
- "static_assertions",
- "zvariant_derive 3.15.2",
-]
-
-[[package]]
-name = "zvariant"
-version = "4.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe"
-dependencies = [
- "endi",
- "enumflags2",
- "serde",
- "static_assertions",
- "zvariant_derive 4.2.0",
-]
-
-[[package]]
-name = "zvariant"
-version = "5.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a192a0bde63360d77a7523c833d4b4ce6070a927e2c53246e4c540b1a3e27be0"
-dependencies = [
- "endi",
- "enumflags2",
- "serde",
- "url",
- "winnow 1.0.3",
- "zvariant_derive 5.12.0",
- "zvariant_utils 3.4.0",
-]
-
-[[package]]
-name = "zvariant_derive"
-version = "3.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9"
-dependencies = [
- "proc-macro-crate 1.3.1",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "zvariant_utils 1.0.1",
-]
-
-[[package]]
-name = "zvariant_derive"
-version = "4.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449"
-dependencies = [
- "proc-macro-crate 3.5.0",
- "proc-macro2",
- "quote",
- "syn 2.0.117",
- "zvariant_utils 2.1.0",
-]
-
-[[package]]
-name = "zvariant_derive"
-version = "5.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bc6cde9c01c511074be97f7ccb6c19d0da89e3f8662e812e999dcfd4638737"
-dependencies = [
- "proc-macro-crate 3.5.0",
- "proc-macro2",
- "quote",
- "syn 2.0.117",
- "zvariant_utils 3.4.0",
-]
-
-[[package]]
-name = "zvariant_utils"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "zvariant_utils"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.117",
-]
-
-[[package]]
-name = "zvariant_utils"
-version = "3.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e8535915cfa75547e559d8c68e8139909a4aeee076831e4ef7fc59d8172c4d6"
-dependencies = [
- "proc-macro2",
- "quote",
- "serde",
- "syn 2.0.117",
- "winnow 1.0.3",
-]
diff --git a/LoFlum - Standalone.html b/LoFlum - Standalone.html
deleted file mode 100644
index ae16ea4..0000000
--- a/LoFlum - Standalone.html
+++ /dev/null
@@ -1,179 +0,0 @@
-
-
-
-
- Bundled Page
-
-
-
-
-
- Unpacking...
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index b2f0113..262a913 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# LoFlum
+# Wherry


diff --git a/Wherry New Design (standalone).html b/Wherry New Design (standalone).html
new file mode 100644
index 0000000..e212a5f
--- /dev/null
+++ b/Wherry New Design (standalone).html
@@ -0,0 +1,181 @@
+
+
+
+
+ Bundled Page
+
+
+
+
+
+
+
+ Unpacking...
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/TAURI_BACKEND_API.md b/docs/TAURI_BACKEND_API.md
new file mode 100644
index 0000000..5bef9dc
--- /dev/null
+++ b/docs/TAURI_BACKEND_API.md
@@ -0,0 +1,79 @@
+# Wherry Tauri backend API (design)
+
+Goal: keep everything under `src/domain`, `src/fs`, `src/protocols`, `src/storage`, `src/transfer` as the Tauri backend. All of it already speaks in `serde` (camelCase) structs, so this is mostly a thin `#[tauri::command]` wrapper layer plus an event bus to replace the current per-frame egui polling.
+
+State the current egui frontend polls every frame that the new frontend instead gets pushed to it via Tauri events (see "Events" below): `state.queue_tasks` (`TransferQueue::all()`), `state.tabs[].status` (`ConnectionStatus`).
+
+## Managed state (`tauri::State`)
+
+Same objects `lib.rs::run()` already builds, handed to Tauri via `.manage(...)` instead of into `FileManagerApp`:
+
+- `Arc>` — sqlite db (sites/bookmarks/history/settings)
+- `Arc` — live `connection_id -> Arc` map
+- `TransferQueue` — shared transfer task list
+- `Arc` — max_concurrent, mutated live by Settings → Transfers
+
+`transfer::worker::spawn_worker` keeps running as-is inside `tauri::Builder::setup`, using the app handle to `emit` progress instead of the queue being polled.
+
+## Commands
+
+### Connections (`src/protocols`, `src/fs/remote.rs`)
+
+- `connect(params: ConnectionParams) -> Result` — dispatches to `FtpClient::connect` / `SftpClient::connect_password|connect_key|connect_auto` based on `params.protocol`/`password`/`key_path`; on success `RemoteRegistry::insert(id, fs)`, `db::add_history_entry(...)`, returns `connection_id`. Emits `connection-status` (`Connecting` then `Connected`/`Error`) — see Events.
+- `disconnect(connection_id: String)` — `RemoteRegistry::remove`.
+
+### Remote file ops (`RemoteFs` trait, per `connection_id`)
+
+- `remote_list(connection_id: String, path: String) -> Result, String>`
+- `remote_stat(connection_id: String, path: String) -> Result`
+- `remote_mkdir(connection_id: String, path: String) -> Result<(), String>`
+- `remote_rename(connection_id: String, from: String, to: String) -> Result<(), String>`
+- `remote_delete(connection_id: String, path: String) -> Result<(), String>`
+
+All resolve `Arc` from `RemoteRegistry::get`, return `"connection not found"` error if missing (mirrors `worker.rs` behavior).
+
+### Local file ops (`src/fs/local.rs` — already sync, no connection_id)
+
+- `local_list(path: String) -> Result, String>`
+- `local_home_dir() -> String`
+- `local_mkdir(path: String) -> Result<(), String>`
+- `local_rename(from: String, to: String) -> Result<(), String>`
+- `local_delete(path: String) -> Result<(), String>`
+- `local_open(path: String) -> Result<(), String>` — reveal/open in system app
+- `local_move_into(src_path: String, dest_dir: String) -> Result<(), String>` — drag&drop move
+
+### Transfers (`src/transfer`)
+
+- `enqueue_transfer(kind: TransferKind, connection_id: String, local_path: String, remote_path: String, file_name: String, total_bytes: u64) -> String` — builds `TransferTask::new(...)`, `queue.push(task)`, returns task id. Worker picks it up same as today.
+- `list_tasks() -> Vec` — for initial load / reconnect after frontend refresh; live updates come from events, not polling.
+- `pause_task(id: String)` / `resume_task(id: String)` — `queue.update_state(id, TaskState::Paused/Queued)` (worker's progress callback already checks for `Paused`/`Cancelled` each callback tick).
+- `cancel_task(id: String)` — `queue.update_state(id, TaskState::Cancelled)`.
+- `remove_task(id: String)` — `queue.remove(id)` (for clearing completed/failed rows).
+- `set_max_concurrent(n: u32)` — stores atomically + persists via `db::set_u32`.
+
+### Sites / bookmarks / history / settings (`src/storage/db`)
+
+- `list_sites`, `save_site(site: Site)`, `delete_site(id: String)`
+- `list_bookmarks() -> Vec<(i64, String, String)>` (id, name, path), `add_bookmark(name, path) -> i64`, `remove_bookmark(id: i64)`
+- `list_history() -> Vec`, `clear_history()`, `find_history_conn_id(host, port, username) -> Option`
+- `get_pref_bool/str/u32(key)`, `set_pref_bool/str/u32(key, value)` — thin wrapper over `storage::db::settings`, used for confirm-before-delete, default local folder, language, transfer concurrency, panel visibility persistence if we decide to persist that (currently session-only in egui, per `state/mod.rs` comment) — confirm with FRONTEND_SPEC.md once written.
+
+Credentials: `keyring` crate stays as-is; password storage keyed by `ConnectionParams.id` (stable id from history/sites), unchanged from current behavior — no new command needed beyond what `connect` already resolves internally.
+
+## Events (app -> frontend, `app_handle.emit(...)`)
+
+Replaces per-frame polling of `queue.all()` / `tabs[].status` in the egui loop:
+
+- `transfer-progress` payload `{ id, transferredBytes, speed, etaSecs }` — emitted from the same throttled callback in `worker.rs::run_transfer` (already rate-limited to ~10/s via `ProgressThrottle`), just add `app_handle.emit(...)` next to `queue.update_progress(...)`.
+- `transfer-state-changed` payload `{ id, state: TaskState }` — emitted next to every `queue.update_state(...)` call (queued->running->completed/failed/cancelled/paused).
+- `connection-status-changed` payload `{ connectionId, status: ConnectionStatus }` — emitted from `connect`/`disconnect` and on unexpected drop (if/when we add liveness detection — not present today, egui doesn't detect mid-session drops either, so parity-only for v1).
+
+Frontend subscribes once via `@tauri-apps/api/event.listen`, keeps a local task/connection map updated from these — no polling loop needed like `queue.all()` was in egui.
+
+## Serialization note
+
+Every domain type already derives `Serialize`/`Deserialize` with `#[serde(rename_all = "camelCase")]` (`ConnectionParams`, `FileEntry`, `Site`, `TransferTask`, `TaskState`, `Protocol`, `EntryKind`, `ConnectionStatus`) — these cross the Tauri IPC boundary unchanged, no adapter layer needed. `anyhow::Error` doesn't implement `Serialize`, so every command returns `Result` (`.map_err(|e| e.to_string())`), matching the existing convention of stringly-typed errors already used in `TaskState::Failed(String)`.
+
+## Open question for scaffolding phase (task #3)
+
+Whether to keep `src/` as a single crate with a new `src-tauri/` binary depending on it (`wherry_lib` is already `staticlib/cdylib/rlib`, so this fits cleanly), or fold `src-tauri` in place of `main.rs`/`lib.rs::run()`. Recommend the former — cleanest separation, no changes to `domain`/`fs`/`protocols`/`storage`/`transfer` needed at all, only `lib.rs::run()` and `main.rs` get replaced by Tauri's builder.
diff --git a/frontend/css/components.css b/frontend/css/components.css
new file mode 100644
index 0000000..44cf84f
--- /dev/null
+++ b/frontend/css/components.css
@@ -0,0 +1,859 @@
+/* Reusable widgets — every interactive control lives here so nothing in a
+ screen-level stylesheet ever hand-rolls its own button/row look. */
+
+/* ---------- icon ---------- */
+.icon {
+ display: inline-block;
+ flex-shrink: 0;
+ color: inherit;
+ vertical-align: middle;
+}
+/* The duotone "background" layer — each tier gets its own semi-transparent
+ soft fill so the two-tone effect is visible no matter the icon color.
+ Using color-mix() instead of real alpha avoids muddy compositing on
+ colorful backgrounds (see icons.ts). */
+.icon {
+ --icon-soft: color-mix(in srgb, var(--text-primary) 30%, transparent);
+}
+.icon .icon-soft {
+ fill: var(--icon-soft);
+}
+
+/* ---- Icon color tiers ----
+ Unselected / not important → white (default)
+ More important → orange (--accent)
+ Inactive / other → gray (--text-dim)
+ On orange button (CTA) → accent-color soft layer
+*/
+.icon { color: inherit; }
+.icon--important {
+ color: var(--accent);
+ --icon-soft: color-mix(in srgb, var(--accent) 30%, transparent);
+}
+.icon--inactive {
+ color: var(--text-dim);
+ --icon-soft: color-mix(in srgb, var(--text-dim) 30%, transparent);
+}
+.icon--on-accent-bg {
+ color: var(--accent);
+ --icon-soft: color-mix(in srgb, var(--accent) 30%, transparent);
+}
+
+/* ---------- buttons ---------- */
+.btn {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
+ border: none;
+ border-radius: var(--radius-md);
+ padding: 0 12px;
+ height: 32px;
+ font-size: 12.5px;
+ cursor: pointer;
+ background: transparent;
+ color: var(--text-primary);
+ transition:
+ background-color 0.1s var(--ease-out),
+ color 0.1s var(--ease-out),
+ transform 0.06s var(--ease-out);
+ white-space: nowrap;
+}
+.btn:disabled {
+ cursor: default;
+ opacity: 0.4;
+}
+.btn:active:not(:disabled) {
+ transform: scale(0.97);
+}
+
+.btn-ghost:not(:disabled):hover {
+ background: rgba(255, 255, 255, 0.06);
+}
+.btn-ghost:not(:disabled):active {
+ background: rgba(255, 255, 255, 0.1);
+}
+
+.btn-accent {
+ background: var(--accent);
+ color: var(--on-accent);
+ font-weight: 600;
+}
+.btn-accent:not(:disabled):hover {
+ background: var(--accent-hover);
+}
+.btn-accent:not(:disabled):active {
+ background: var(--accent-dim);
+}
+
+.btn-accent-dim {
+ background: var(--accent-soft);
+ color: var(--text-primary);
+}
+.btn-accent-dim:not(:disabled):hover {
+ background: color-mix(in srgb, var(--accent) 24%, transparent);
+}
+
+.btn-danger {
+ background: var(--red);
+ color: var(--on-accent);
+ font-weight: 600;
+}
+.btn-danger:not(:disabled):hover {
+ background: var(--red-hover);
+}
+
+.btn-toggle.active {
+ color: var(--accent);
+ background: var(--accent-soft);
+}
+.btn-toggle:not(.active):not(:disabled):hover {
+ background: rgba(255, 255, 255, 0.06);
+}
+
+.icon-btn {
+ width: 32px;
+ height: 32px;
+ padding: 0;
+ border-radius: var(--radius-md);
+}
+
+.btn-sep {
+ width: 1px;
+ height: 20px;
+ background: var(--border);
+ margin: 0 8px;
+ flex-shrink: 0;
+}
+
+/* ---------- clickable rows (sidebar / recent-connections list) ---------- */
+.row {
+ display: flex;
+ align-items: center;
+ margin: 1px 10px;
+ padding: 0 10px;
+ height: 30px;
+ border-radius: var(--radius-sm);
+ cursor: pointer;
+ color: var(--text-primary);
+ transition: background-color 0.1s var(--ease-out);
+}
+.row:hover {
+ background: var(--bg-row-hover);
+}
+.row:active {
+ background: var(--bg-row-sel);
+}
+.row.active {
+ background: var(--accent-soft);
+}
+.row .row-spacer {
+ flex: 1;
+}
+
+/* ---------- spinner ---------- */
+.spinner {
+ width: 14px;
+ height: 14px;
+ border-radius: 50%;
+ border: 2px solid color-mix(in srgb, var(--text-primary) 18%, transparent);
+ border-top-color: var(--accent);
+ animation: spin 0.7s linear infinite;
+ flex-shrink: 0;
+}
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+/* ---------- keyboard shortcut chip ---------- */
+.kbd {
+ display: inline-flex;
+ align-items: center;
+ font-family: var(--font-sans);
+ font-size: 10px;
+ font-weight: 600;
+ line-height: 1.5;
+ color: var(--text-dim);
+ background: rgba(255, 255, 255, 0.06);
+ border: 1px solid var(--border);
+ border-radius: 4px;
+ padding: 1px 5px;
+ white-space: nowrap;
+}
+.kbd-on-accent {
+ color: var(--on-accent);
+ background: rgba(255, 255, 255, 0.24);
+ border-color: transparent;
+}
+
+/* ---------- protocol badge (saved sites / history rows) ---------- */
+.proto-badge {
+ flex-shrink: 0;
+ font-size: 9.5px;
+ font-weight: 700;
+ letter-spacing: 0.03em;
+ color: var(--text-dim);
+ border: 1px solid var(--border);
+ border-radius: 4px;
+ padding: 2px 5px;
+}
+
+/* ---------- status dot ---------- */
+.status-dot {
+ font-size: 10px;
+ line-height: 1;
+}
+.status-dot.connected {
+ color: var(--green);
+}
+.status-dot.connecting {
+ color: var(--yellow);
+}
+.status-dot.error {
+ color: var(--red);
+}
+.status-dot.disconnected {
+ color: var(--text-hint);
+}
+
+/* ---------- form fields ---------- */
+.field {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+.field-label {
+ font-size: 11px;
+ color: var(--text-dim);
+}
+.field-input {
+ height: 32px;
+ border-radius: var(--radius-md);
+ border: 1px solid var(--border);
+ background: var(--bg-content);
+ color: var(--text-primary);
+ padding: 0 10px;
+ font-size: 13px;
+ outline: none;
+ transition: border-color 0.1s var(--ease-out), box-shadow 0.1s var(--ease-out);
+ width: 100%;
+}
+.field-input::placeholder {
+ color: var(--text-hint);
+}
+.field-input:hover {
+ border-color: var(--accent-dim);
+}
+.field-input:focus {
+ border-color: var(--accent);
+ box-shadow: 0 0 0 3px var(--accent-ring);
+}
+.field-hint {
+ font-size: 10px;
+ color: var(--text-hint);
+ line-height: 1.4;
+}
+.field-row {
+ display: flex;
+ gap: 8px;
+ align-items: flex-end;
+}
+.field-with-btn {
+ display: flex;
+ gap: 8px;
+}
+.field-with-icon {
+ position: relative;
+}
+.field-with-icon .field-input {
+ padding-right: 34px;
+}
+.field-icon-btn {
+ position: absolute;
+ right: 4px;
+ top: 4px;
+ width: 24px;
+ height: 24px;
+ border-radius: var(--radius-sm);
+ border: none;
+ background: transparent;
+ color: var(--text-dim);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+}
+.field-icon-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--text-primary);
+}
+
+/* ---------- segmented control ---------- */
+.segmented {
+ display: flex;
+ gap: 4px;
+ padding: 3px;
+ border: 1px solid var(--border);
+ border-radius: var(--radius-md);
+ background: var(--bg-content);
+}
+.segmented-item {
+ flex: 1;
+ height: 26px;
+ border: none;
+ border-radius: var(--radius-sm);
+ background: transparent;
+ color: var(--text-dim);
+ font-size: 11.5px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background-color 0.1s var(--ease-out), color 0.1s var(--ease-out);
+}
+.segmented-item:hover:not(.active) {
+ background: rgba(255, 255, 255, 0.05);
+}
+.segmented-item.active {
+ background: var(--accent);
+ color: var(--on-accent);
+}
+
+/* ---------- error box ---------- */
+.error-box {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ background: var(--red-soft);
+ border: 1px solid color-mix(in srgb, var(--red) 40%, transparent);
+ border-radius: var(--radius-md);
+ padding: 8px 10px;
+ color: var(--red);
+ font-size: 11px;
+ animation: shake 0.32s var(--ease-out);
+}
+@keyframes shake {
+ 0%,
+ 100% {
+ transform: translateX(0);
+ }
+ 25% {
+ transform: translateX(-4px);
+ }
+ 75% {
+ transform: translateX(4px);
+ }
+}
+
+/* ---------- overlay / dialog ---------- */
+.overlay {
+ position: fixed;
+ inset: 0;
+ background: color-mix(in srgb, var(--bg-base) 62%, transparent);
+ backdrop-filter: blur(2px);
+ -webkit-backdrop-filter: blur(2px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 100;
+ opacity: 0;
+ animation: overlay-in 0.16s var(--ease-out) forwards;
+}
+.overlay.closing {
+ animation: overlay-out 0.12s var(--ease-out) forwards;
+}
+@keyframes overlay-in {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+@keyframes overlay-out {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+
+.dialog {
+ background: var(--bg-panel);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-lg);
+ box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
+ padding: 22px;
+ width: 340px;
+ transform: translateY(0) scale(1);
+ opacity: 1;
+ animation: dialog-in 0.18s var(--ease-out);
+}
+@keyframes dialog-in {
+ from {
+ opacity: 0;
+ transform: translateY(6px) scale(0.98);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+.dialog-header {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 18px;
+}
+.dialog-title {
+ font-size: 15.5px;
+ font-weight: 600;
+ color: var(--text-primary);
+ flex: 1;
+}
+.dialog-close {
+ width: 24px;
+ height: 24px;
+ border-radius: var(--radius-sm);
+ border: none;
+ background: transparent;
+ color: var(--text-dim);
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.dialog-close:hover {
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--text-primary);
+}
+.dialog-body > * + * {
+ margin-top: 10px;
+}
+.dialog-footer {
+ display: flex;
+ align-items: center;
+ margin-top: 18px;
+}
+.dialog-footer .btn {
+ min-width: 90px;
+}
+.dialog-footer .spacer {
+ flex: 1;
+}
+
+/* small confirm-style dialog */
+.dialog.dialog-sm {
+ width: 300px;
+}
+
+/* Settings dialog: fixed-width nav column + scrolling content column */
+.dialog.dialog-settings {
+ width: 640px;
+}
+.settings-body {
+ display: flex;
+ align-items: flex-start;
+ gap: 18px;
+ height: 420px;
+}
+.settings-nav {
+ width: 150px;
+ flex-shrink: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ height: 100%;
+ overflow-y: auto;
+ border-right: 1px solid var(--border);
+ padding-right: 12px;
+}
+.settings-nav-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ height: 30px;
+ padding: 0 10px;
+ border-radius: var(--radius-sm);
+ color: var(--text-dim);
+ font-size: 12px;
+ cursor: pointer;
+ text-align: left;
+ transition: background-color 0.1s var(--ease-out), color 0.1s var(--ease-out);
+}
+.settings-nav-item:hover {
+ background: rgba(255, 255, 255, 0.05);
+ color: var(--text-primary);
+}
+.settings-nav-item.active {
+ background: var(--accent-soft);
+ color: var(--accent);
+}
+.settings-content {
+ flex: 1;
+ min-width: 0;
+ height: 100%;
+ overflow-y: auto;
+ padding-right: 4px;
+}
+.settings-section-title {
+ font-size: 13px;
+ font-weight: 700;
+ color: var(--text-primary);
+ margin-bottom: 4px;
+}
+.settings-label {
+ font-size: 12.5px;
+ font-weight: 600;
+ color: var(--text-primary);
+}
+.settings-hint {
+ font-size: 10.5px;
+ color: var(--text-hint);
+ line-height: 1.5;
+ margin-top: 2px;
+}
+.settings-row {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+.settings-check-row {
+ display: flex;
+ align-items: flex-start;
+ gap: 10px;
+ cursor: pointer;
+}
+.settings-block + .settings-block {
+ margin-top: 20px;
+}
+
+.settings-select {
+ appearance: auto;
+ background: var(--card-bg);
+ border: 1px solid var(--border-subtle);
+ border-radius: var(--radius-md);
+ padding: 6px 10px;
+ font-size: 12px;
+ color: var(--text-primary);
+ cursor: pointer;
+ min-width: 180px;
+}
+.settings-select:hover {
+ border-color: var(--accent);
+}
+.settings-select:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 1px;
+}
+
+/* ---------- theme picker (settings > appearance) ---------- */
+.theme-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ gap: 10px;
+}
+.theme-card {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 6px;
+ padding: 12px 8px 10px;
+ border-radius: var(--radius-md);
+ border: 1.5px solid var(--border);
+ background: var(--bg-content);
+ cursor: pointer;
+ transition:
+ border-color 0.15s var(--ease-out),
+ background-color 0.15s var(--ease-out),
+ transform 0.06s var(--ease-out);
+}
+.theme-card:hover {
+ border-color: var(--text-hint);
+ background: var(--bg-panel);
+}
+.theme-card.active {
+ border-color: var(--accent);
+ background: var(--accent-soft);
+}
+.theme-card:active {
+ transform: scale(0.96);
+}
+.theme-card-label {
+ font-size: 10px;
+ text-align: center;
+ line-height: 1.3;
+ color: var(--text-dim);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 100%;
+}
+.theme-card.active .theme-card-label {
+ color: var(--accent);
+ font-weight: 600;
+}
+.theme-swatch {
+ width: 100%;
+ height: 44px;
+ border-radius: var(--radius-sm);
+ border: 1px solid var(--border);
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+}
+
+/* Swatch previews — mimic each theme's palette */
+.theme-swatch--ember {
+ background: linear-gradient(135deg, #0b0d11 40%, #181c24 70%, #d9804f 100%);
+}
+.theme-swatch--frost {
+ background: linear-gradient(135deg, #f4f6fa 40%, #ffffff 70%, #4a8fe0 100%);
+}
+.theme-swatch--midnight {
+ background: linear-gradient(135deg, #0d0e17 40%, #161827 70%, #8b7cf7 100%);
+}
+.theme-swatch--forest {
+ background: linear-gradient(135deg, #0b120e 40%, #141f17 70%, #5bba70 100%);
+}
+.theme-swatch--dawn {
+ background: linear-gradient(135deg, #faf6f3 40%, #ffffff 70%, #d9735a 100%);
+}
+.theme-swatch--ash {
+ background: linear-gradient(135deg, #0a0a0c 40%, #141416 70%, #c0c4cc 100%);
+}
+.settings-list-row {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 6px 0;
+ border-bottom: 1px solid var(--separator);
+}
+.settings-list-row:last-child {
+ border-bottom: none;
+}
+.settings-list-row-main {
+ min-width: 0;
+ flex: 1;
+}
+.settings-list-row-title {
+ font-size: 12.5px;
+ color: var(--text-primary);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.settings-list-row-sub {
+ font-size: 10.5px;
+ color: var(--text-hint);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.settings-value-row {
+ display: flex;
+ justify-content: space-between;
+ gap: 10px;
+ padding: 5px 0;
+ font-size: 12px;
+}
+.settings-value-row .k {
+ color: var(--text-dim);
+}
+.settings-value-row .v {
+ color: var(--text-primary);
+ font-family: var(--font-mono);
+ font-size: 11px;
+ text-align: right;
+ overflow-wrap: anywhere;
+}
+.settings-empty {
+ color: var(--text-hint);
+ font-size: 12px;
+ padding: 10px 0;
+}
+.dialog-text {
+ font-size: 12.5px;
+ color: var(--text-dim);
+ line-height: 1.5;
+}
+
+/* ---------- context menu ---------- */
+.context-menu {
+ position: fixed;
+ z-index: 200;
+ min-width: 180px;
+ background: var(--bg-panel);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-md);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
+ padding: 4px;
+ animation: menu-in 0.12s var(--ease-out);
+}
+@keyframes menu-in {
+ from {
+ opacity: 0;
+ transform: scale(0.97);
+ }
+ to {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+.context-menu-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ width: 100%;
+ border: none;
+ background: transparent;
+ color: var(--text-primary);
+ font-size: 12px;
+ padding: 6px 10px;
+ border-radius: var(--radius-sm);
+ cursor: pointer;
+ text-align: left;
+}
+.context-menu-item:hover {
+ background: rgba(255, 255, 255, 0.07);
+}
+.context-menu-item.danger {
+ color: var(--red);
+}
+.context-menu-sep {
+ height: 1px;
+ background: var(--separator);
+ margin: 4px 6px;
+}
+
+/* ---------- popover (history) ---------- */
+.popover {
+ position: fixed;
+ z-index: 90;
+ width: 270px;
+ background: var(--bg-panel);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-lg);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
+ padding: 10px;
+ opacity: 0;
+ transform: translateY(-4px);
+ animation: pop-in 0.14s var(--ease-out) forwards;
+}
+@keyframes pop-in {
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+.popover-header {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ padding: 2px 4px 8px;
+ color: var(--text-dim);
+ font-size: 11px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.02em;
+}
+.popover-empty {
+ color: var(--text-hint);
+ padding: 6px 4px;
+ font-size: 12px;
+}
+.popover-list {
+ max-height: 220px;
+ overflow-y: auto;
+}
+.popover-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ width: 100%;
+ height: 30px;
+ padding: 0 8px;
+ border: none;
+ background: transparent;
+ border-radius: var(--radius-sm);
+ color: var(--text-primary);
+ font-size: 12px;
+ cursor: pointer;
+ text-align: left;
+}
+.popover-row:hover {
+ background: rgba(255, 255, 255, 0.06);
+}
+
+/* ---------- toggle switch (settings) ---------- */
+.switch {
+ position: relative;
+ width: 34px;
+ height: 20px;
+ border-radius: 10px;
+ background: var(--border);
+ border: none;
+ cursor: pointer;
+ flex-shrink: 0;
+ transition: background-color 0.14s var(--ease-out);
+}
+.switch::after {
+ content: "";
+ position: absolute;
+ top: 2px;
+ left: 2px;
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background: var(--text-primary);
+ transition: transform 0.14s var(--ease-out);
+}
+.switch.on {
+ background: var(--accent);
+}
+.switch.on::after {
+ transform: translateX(14px);
+ background: var(--on-accent);
+}
+
+/* ---------- progress bar ---------- */
+.progress {
+ flex: 1;
+ height: 6px;
+ border-radius: 3px;
+ background: rgba(255, 255, 255, 0.06);
+ overflow: hidden;
+}
+.progress-fill {
+ height: 100%;
+ border-radius: 3px;
+ background: var(--accent);
+ transition: width 0.15s linear;
+}
+.progress-fill.running {
+ background: var(--accent);
+}
+.progress-fill.completed {
+ background: var(--green);
+}
+.progress-fill.failed {
+ background: var(--red);
+}
+.progress-fill.paused {
+ background: var(--text-hint);
+}
+
+/* ---------- empty state ---------- */
+.empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ color: var(--text-hint);
+ gap: 8px;
+ font-size: 12.5px;
+}
diff --git a/frontend/css/layout.css b/frontend/css/layout.css
new file mode 100644
index 0000000..d49b920
--- /dev/null
+++ b/frontend/css/layout.css
@@ -0,0 +1,896 @@
+/* Screen-level layout: welcome screen and the main browsing shell. */
+
+#screen-root {
+ flex: 1;
+ min-height: 0;
+ position: relative;
+}
+
+.screen {
+ position: absolute;
+ inset: 0;
+ opacity: 0;
+ animation: screen-in 0.2s var(--ease-out) forwards;
+}
+@keyframes screen-in {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+/* ================= Welcome screen ================= */
+.welcome {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: flex-start;
+ padding-top: 11vh;
+ text-align: center;
+ overflow-y: auto;
+ /* soft ember glow behind the hero so the screen isn't a flat void */
+ background:
+ radial-gradient(560px 300px at 50% -60px, var(--accent-soft), transparent 70%),
+ var(--bg-base);
+}
+.welcome-hero {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+.welcome-logo {
+ width: 76px;
+ height: 76px;
+ border-radius: 20px;
+ background: linear-gradient(145deg, var(--accent-hover), var(--accent-dim));
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--on-accent);
+ box-shadow:
+ 0 12px 36px color-mix(in srgb, var(--accent) 28%, transparent),
+ inset 0 1px 0 rgba(255, 255, 255, 0.25);
+}
+.welcome-title {
+ margin-top: 16px;
+ font-size: 22px;
+ font-weight: 700;
+ letter-spacing: -0.01em;
+ color: var(--text-primary);
+}
+.welcome-subtitle {
+ margin-top: 4px;
+ font-size: 12.5px;
+ color: var(--text-hint);
+}
+.welcome-actions {
+ margin-top: 24px;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+.welcome-cta {
+ height: 32px;
+ padding: 0 14px;
+}
+.welcome-actions .kbd {
+ margin-left: 4px;
+}
+.welcome-status {
+ margin-top: 14px;
+ min-height: 20px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+.welcome-columns {
+ margin-top: 24px;
+ width: min(720px, 90vw);
+ display: flex;
+ align-items: flex-start;
+ justify-content: center;
+ gap: 14px;
+ flex-wrap: wrap;
+ padding-bottom: 48px;
+}
+.welcome-card {
+ flex: 1 1 300px;
+ min-width: 280px;
+ max-width: 352px;
+ background: color-mix(in srgb, var(--bg-panel) 72%, transparent);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-card);
+ padding: 12px 8px 8px;
+ text-align: left;
+}
+.welcome-card-title {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ padding: 0 10px 8px;
+ font-size: 10.5px;
+ font-weight: 700;
+ letter-spacing: 0.05em;
+ text-transform: uppercase;
+ color: var(--text-hint);
+}
+.recent-row {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ height: 34px;
+ padding: 0 10px;
+ border-radius: var(--radius-sm);
+ cursor: pointer;
+ transition: background-color 0.1s var(--ease-out);
+}
+.recent-row:hover {
+ background: var(--bg-row-hover);
+}
+/* Shared by both the welcome screen's recent-connections list (.recent-row)
+ and the toolbar's history popover (.popover-row) -- unscoped so it applies
+ in either parent. */
+.recent-label {
+ flex: 1;
+ min-width: 0;
+ font-size: 12.5px;
+ color: var(--text-primary);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.recent-time {
+ flex-shrink: 0;
+ margin-left: auto;
+ font-size: 10.5px;
+ color: var(--text-hint);
+ white-space: nowrap;
+}
+
+/* ================= Main shell ================= */
+.app-shell {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+/* Toolbar — now floats above the body with uniform rounding */
+.toolbar {
+ height: var(--toolbar-h);
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0 16px;
+ margin: 8px 14px 0;
+ background: var(--bg-toolbar);
+ border-radius: var(--radius-card) var(--radius-card) 0 0;
+ position: relative;
+ z-index: 3;
+}
+.toolbar-spacer {
+ flex: 1;
+}
+
+/* Body row: sidebar + main content, floating in a padded, gapless frame so
+ the two panels read as one rounded pill (sidebar rounds its left corners,
+ the content card rounds its right corners — see mockup "new shell
+ concept"). */
+.app-body {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ padding: 0 14px 14px;
+ gap: 0;
+ background: var(--bg-base);
+}
+
+.sidebar {
+ width: var(--sidebar-w);
+ min-width: 140px;
+ max-width: 260px;
+ flex-shrink: 0;
+ display: flex;
+ flex-direction: column;
+ background: var(--bg-panel);
+ border: 1px solid rgba(255, 255, 255, 0.04);
+ border-right: none;
+ border-radius: 0 0 0 var(--radius-card);
+ overflow-y: auto;
+ padding: 16px 0;
+ margin-top: -8px;
+ position: relative;
+ z-index: 1;
+}
+.sidebar-logo {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0 16px;
+ margin-bottom: 18px;
+ flex-shrink: 0;
+}
+.sidebar-logo-badge {
+ width: 26px;
+ height: 26px;
+ border-radius: var(--radius-sm);
+ flex-shrink: 0;
+ background: linear-gradient(145deg, var(--accent), var(--accent-dim));
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--on-accent);
+ font-weight: 800;
+ font-size: 13px;
+}
+.sidebar-logo-text {
+ font-weight: 700;
+ font-size: 14px;
+ color: var(--text-primary);
+}
+.sidebar-section-title {
+ padding: 0 16px;
+ font-size: 10.5px;
+ font-weight: 700;
+ color: var(--text-hint);
+ letter-spacing: 0.02em;
+ flex-shrink: 0;
+}
+.sidebar-divider {
+ height: 1px;
+ background: var(--separator);
+ margin: 10px 8px;
+ flex-shrink: 0;
+}
+.sidebar-spacer {
+ flex: 1;
+}
+.sidebar-footer {
+ padding: 0 16px;
+ font-size: 10px;
+ color: var(--text-hint);
+ flex-shrink: 0;
+}
+
+.main-content {
+ flex: 1;
+ min-width: 0;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+ background: var(--bg-content);
+ border-radius: 0 0 var(--radius-card) 0;
+ box-shadow:
+ 0 12px 32px rgba(0, 0, 0, 0.45),
+ inset 0 1px 0 rgba(255, 255, 255, 0.06);
+ overflow: hidden;
+ position: relative;
+ z-index: 1;
+}
+
+/* Tab bar (Local + one per connection) */
+.tabbar {
+ height: var(--tabbar-h);
+ flex-shrink: 0;
+ display: flex;
+ align-items: stretch;
+ background: var(--bg-panel);
+ border-bottom: 1px solid var(--border);
+ overflow-x: auto;
+}
+.tab {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ padding: 0 12px;
+ height: 100%;
+ border: none;
+ border-right: 1px solid var(--border);
+ background: var(--bg-tab-idle);
+ color: var(--text-dim);
+ font-size: 12px;
+ cursor: pointer;
+ white-space: nowrap;
+ flex-shrink: 0;
+ transition: background-color 0.1s var(--ease-out), color 0.1s var(--ease-out);
+}
+.tab:hover {
+ background: var(--bg-row-hover);
+}
+.tab.active {
+ background: var(--bg-tab-active);
+ color: var(--text-primary);
+}
+.tab-close {
+ width: 16px;
+ height: 16px;
+ border-radius: 4px;
+ border: none;
+ background: transparent;
+ color: var(--text-hint);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 12px;
+ line-height: 1;
+ cursor: pointer;
+}
+.tab-close:hover {
+ background: rgba(255, 255, 255, 0.12);
+ color: var(--text-primary);
+}
+
+/* localPane.js/remotePane.js render straight into this element (there's no
+ separate .pane wrapper -- renderActivePane() swaps the one visible pane's
+ content in place rather than stacking multiple absolutely-positioned
+ panes), so it has to be the flex column container itself. */
+.tab-panes {
+ flex: 1;
+ min-height: 0;
+ position: relative;
+ display: flex;
+ flex-direction: column;
+}
+
+/* Path bar (top of each pane) */
+.path-bar {
+ height: 32px;
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0 16px;
+ background: var(--bg-base);
+ border-bottom: 1px solid var(--border);
+}
+.path-bar-label {
+ font-size: 10.5px;
+ font-weight: 700;
+ color: var(--text-dim);
+ flex-shrink: 0;
+}
+.breadcrumbs {
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ overflow: hidden;
+ flex: 1;
+ min-width: 0;
+}
+.breadcrumb-seg {
+ border: none;
+ background: transparent;
+ color: var(--text-dim);
+ font-size: 12px;
+ padding: 3px 5px;
+ border-radius: var(--radius-sm);
+ cursor: pointer;
+ flex-shrink: 0;
+}
+.breadcrumb-seg:hover {
+ background: rgba(255, 255, 255, 0.06);
+ color: var(--text-primary);
+}
+.breadcrumb-seg.current {
+ color: var(--text-primary);
+ font-weight: 600;
+ cursor: default;
+}
+.breadcrumb-seg.current:hover {
+ background: none;
+}
+.breadcrumb-sep {
+ color: var(--text-hint);
+ font-size: 12px;
+}
+.path-bar-right {
+ margin-left: auto;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ color: var(--text-hint);
+ font-size: 10.5px;
+ flex-shrink: 0;
+}
+
+/* File table */
+.file-table-wrap {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+}
+.file-table-header {
+ display: grid;
+ grid-template-columns: 1fr 140px 60px 80px;
+ align-items: center;
+ height: 26px;
+ padding: 0 16px;
+ background: var(--bg-header);
+ border-bottom: 1px solid var(--border);
+ flex-shrink: 0;
+}
+.sort-header {
+ appearance: none;
+ border: none;
+ background: transparent;
+ color: var(--text-dim);
+ font-size: 10.5px;
+ font-weight: 700;
+ text-align: left;
+ padding: 0;
+ cursor: pointer;
+ height: 20px;
+ justify-self: start;
+}
+.file-table-header .sort-header:nth-child(2),
+.file-table-header .sort-header:nth-child(3),
+.file-table-header .sort-header:nth-child(4) {
+ justify-self: end;
+ text-align: right;
+}
+.sort-header:hover {
+ color: var(--text-primary);
+}
+.sort-header.active {
+ color: var(--accent);
+}
+.file-table-body {
+ flex: 1;
+ min-height: 0;
+ overflow-y: auto;
+ padding: 2px 0;
+}
+.file-row {
+ display: grid;
+ grid-template-columns: 1fr 140px 60px 80px;
+ align-items: center;
+ height: var(--row-h);
+ padding: 0 16px;
+ margin: 0 8px;
+ border-radius: var(--radius-sm);
+ cursor: default;
+ transition: background-color 0.08s var(--ease-out);
+ border: 1px solid transparent;
+}
+.file-row:hover {
+ background: var(--bg-row-hover);
+}
+.file-row.selected {
+ background: var(--bg-row-sel);
+}
+.file-row.dragging {
+ opacity: 0.35;
+}
+/* A dragged file/folder hovering a folder row (or "..") -- it'll spring
+ open into that folder after HOVER_OPEN_DELAY, see makeDropTarget in
+ dnd.js. */
+.file-row.drag-hover {
+ background: var(--accent-soft);
+ outline: 1px dashed var(--accent-ring);
+ outline-offset: -1px;
+}
+.file-row-name {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ min-width: 0;
+}
+.file-row-name span {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: 12.5px;
+}
+.file-row-modified {
+ font-size: 10.5px;
+ color: var(--text-hint);
+ text-align: right;
+ padding-right: 12px;
+}
+.file-row-type {
+ font-size: 11px;
+ color: var(--text-dim);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.file-row-size {
+ font-size: 11px;
+ color: var(--text-dim);
+ text-align: right;
+ font-variant-numeric: tabular-nums;
+}
+
+/* Footer (below table) */
+.pane-footer {
+ height: 28px;
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0 8px 0 16px;
+ background: var(--bg-tab-idle);
+ border-top: 1px solid var(--border);
+}
+.pane-footer-right {
+ margin-left: auto;
+ display: flex;
+ align-items: center;
+}
+
+
+/* Queue panel */
+.queue-panel {
+ flex-shrink: 0;
+ background: var(--bg-queue);
+ border-top: 1px solid var(--border);
+ overflow: hidden;
+ height: var(--queue-collapsed-h);
+ transition: height 0.18s var(--ease-out);
+}
+.queue-panel.expanded {
+ height: var(--queue-expanded-h);
+}
+.queue-header {
+ height: var(--queue-collapsed-h);
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0 16px;
+ cursor: pointer;
+}
+.queue-header-title {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ color: var(--text-primary);
+ font-size: 11.5px;
+ font-weight: 600;
+}
+.queue-header-right {
+ margin-left: auto;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 11px;
+}
+.queue-list {
+ overflow-y: auto;
+ height: calc(var(--queue-expanded-h) - var(--queue-collapsed-h));
+ padding: 2px 0;
+}
+.queue-task {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ height: 36px;
+ padding: 0 16px;
+}
+.queue-task-name {
+ width: 150px;
+ flex-shrink: 0;
+ font-size: 12px;
+ color: var(--text-primary);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.queue-task-pct {
+ width: 38px;
+ flex-shrink: 0;
+ text-align: right;
+ font-size: 11px;
+ color: var(--text-dim);
+ font-variant-numeric: tabular-nums;
+}
+.queue-task-state {
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ font-size: 10.5px;
+ min-width: 90px;
+ justify-content: flex-end;
+}
+.queue-task-actions {
+ display: flex;
+ gap: 2px;
+ flex-shrink: 0;
+}
+
+/* Status bar */
+.status-bar {
+ height: var(--status-h);
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 0 16px;
+ background: var(--bg-base);
+ border-top: 1px solid var(--border);
+ font-size: 11px;
+ color: var(--text-dim);
+}
+.status-bar-right {
+ margin-left: auto;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+/* ================= Per-platform adjustments ================= */
+/* initPlatform() stamps data-platform (mac/windows/linux), data-desktop
+ (kde/gnome/hyprland/…) and data-tiling on — see js/platform.js. */
+
+/* Tiling compositors (Hyprland, sway, i3, …): the window fills its slot
+ edge-to-edge, so the decorative floating-card gutter reads as wasted
+ space — tighten it and square off the shell slightly. */
+html[data-tiling="true"] .app-body {
+ padding: 8px;
+}
+
+/* Windows: Segoe UI sits a touch lower on the line box than SF/Noto;
+ antialiased smoothing also renders it too thin on ClearType displays. */
+html[data-platform="windows"] body {
+ -webkit-font-smoothing: auto;
+}
+
+/* GNOME/KDE ship overlay scrollbars — a permanently-reserved 9px gutter
+ looks foreign there; slim it down. */
+html[data-platform="linux"] ::-webkit-scrollbar {
+ width: 7px;
+ height: 7px;
+}
+
+/* ── Split-pane grid ─────────────────────────────────────────────────── */
+.pane-grid {
+ flex: 1;
+ min-height: 0;
+}
+.pane-cell {
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ min-height: 0;
+ background: var(--bg-content);
+ position: relative;
+ overflow: hidden;
+}
+.pane-cell + .pane-cell {
+ border-left: 1px solid var(--border);
+}
+.pane-cell.drop-zone {
+ background: var(--bg-panel);
+ outline: 2px solid var(--accent);
+ outline-offset: -2px;
+ z-index: 2;
+}
+.pane-cell.dragging {
+ opacity: 0.5;
+}
+
+/* Pane header */
+.pane-header {
+ display: flex;
+ align-items: center;
+ height: 28px;
+ padding: 0 8px 0 12px;
+ background: var(--bg-tab-idle);
+ border-bottom: 1px solid var(--border);
+ cursor: grab;
+ flex-shrink: 0;
+ gap: 6px;
+ user-select: none;
+}
+.pane-header:active {
+ cursor: grabbing;
+}
+.pane-label {
+ font-size: 11px;
+ font-weight: 600;
+ color: var(--text-dim);
+ flex: 1;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.pane-actions {
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ flex-shrink: 0;
+}
+.pane-split-btn,
+.pane-close-btn {
+ width: 18px;
+ height: 18px;
+ border: none;
+ border-radius: 3px;
+ background: transparent;
+ color: var(--text-hint);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ font-size: 10px;
+ padding: 0;
+}
+.pane-split-btn:hover,
+.pane-close-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--text-primary);
+}
+.pane-body {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+}
+
+/* Pane count badge in tab bar */
+.tab-pane-count {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 18px;
+ height: 18px;
+ padding: 0 4px;
+ border-radius: 4px;
+ background: var(--accent-soft);
+ color: var(--accent);
+ font-size: 10px;
+ font-weight: 700;
+ margin: 0 4px 0 8px;
+ flex-shrink: 0;
+}
+
+/* ── Pane edge drop zones ────────────────────────────────────────────── */
+.pane-zone {
+ position: absolute;
+ opacity: 0;
+ transition: opacity 0.1s ease, background 0.1s ease;
+ pointer-events: none;
+ z-index: 5;
+}
+.pane-zone--left { left: 0; top: 0; bottom: 0; width: 22%; }
+.pane-zone--right { right: 0; top: 0; bottom: 0; width: 22%; }
+.pane-zone--top { left: 0; right: 0; top: 0; height: 22%; }
+.pane-zone--bottom { left: 0; right: 0; bottom: 0; height: 22%; }
+.pane-zone--center { left: 22%; right: 22%; top: 22%; bottom: 22%; }
+.pane-zone--swap { left: 0; right: 0; top: 28px; bottom: 0; } /* below header */
+
+.pane-cell.drop-active[data-drop-zone="left"] .pane-zone--left,
+.pane-cell.drop-active[data-drop-zone="right"] .pane-zone--right,
+.pane-cell.drop-active[data-drop-zone="top"] .pane-zone--top,
+.pane-cell.drop-active[data-drop-zone="bottom"] .pane-zone--bottom,
+.pane-cell.drop-active[data-drop-zone="center"] .pane-zone--center {
+ opacity: 1;
+ background: var(--accent-soft);
+}
+.pane-cell.drop-active[data-drop-zone="center"] .pane-zone--center {
+ background: color-mix(in srgb, var(--accent) 30%, transparent);
+}
+
+/* Pane "spring-loading": shown while a dragged tab hovers a pane that
+ hasn't opened as a drop target yet (see HOVER_OPEN_DELAY in dnd.js) --
+ distinct from .drop-active so the pause before zones appear still reads
+ as a response to the hover, not a stall. */
+.pane-cell.drop-pending {
+ outline: 2px dashed var(--accent-ring);
+ outline-offset: -2px;
+}
+
+/* Tab dragging visual */
+.tab-dragging {
+ opacity: 0.45;
+}
+.pane-dragging {
+ opacity: 0.4;
+}
+
+/* ── Panel show/hide animations ──────────────────────────────────────── */
+
+/* Sidebar: collapse width + fade */
+.sidebar {
+ transition: width 0.25s var(--ease-out),
+ min-width 0.25s var(--ease-out),
+ padding-left 0.25s var(--ease-out),
+ padding-right 0.25s var(--ease-out),
+ border-width 0.25s var(--ease-out),
+ opacity 0.2s var(--ease-out);
+}
+.sidebar.hidden {
+ width: 0 !important;
+ min-width: 0 !important;
+ padding-left: 0 !important;
+ padding-right: 0 !important;
+ border: none !important;
+ opacity: 0;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+/* Toolbar: collapse height + fade */
+.toolbar {
+ transition: height 0.25s var(--ease-out),
+ margin 0.25s var(--ease-out),
+ padding 0.25s var(--ease-out),
+ opacity 0.2s var(--ease-out);
+}
+.toolbar.hidden {
+ height: 0 !important;
+ margin: 0 14px !important;
+ padding-top: 0 !important;
+ padding-bottom: 0 !important;
+ border: none !important;
+ opacity: 0;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+/* Status bar: collapse height + fade */
+.status-bar {
+ transition: height 0.25s var(--ease-out),
+ opacity 0.2s var(--ease-out);
+}
+.status-bar.hidden {
+ height: 0 !important;
+ opacity: 0;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+/* Queue panel: collapse height + fade */
+.queue-panel {
+ transition: height 0.22s var(--ease-out),
+ opacity 0.18s var(--ease-out);
+}
+.queue-panel.hidden {
+ height: 0 !important;
+ opacity: 0;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+/* ── Main-content corner rounding ────────────────────────────────────── */
+.main-content {
+ transition: border-radius 0.25s var(--ease-out);
+}
+/* Default: bottom-right only (sidebar left + toolbar top are flat) */
+.main-content:not(.no-sidebar):not(.no-toolbar):not(.no-status) {
+ border-radius: 0 0 var(--radius-card) 0;
+}
+/* Sidebar hidden -- round left side */
+.main-content.no-sidebar:not(.no-toolbar):not(.no-status) {
+ border-radius: 0 var(--radius-card) var(--radius-card) 0;
+}
+/* Toolbar hidden -- round top */
+.main-content.no-toolbar:not(.no-sidebar):not(.no-status) {
+ border-radius: var(--radius-card) var(--radius-card) 0 0;
+}
+/* Bottom hidden -- round bottom */
+.main-content.no-status:not(.no-sidebar):not(.no-toolbar) {
+ border-radius: 0 0 var(--radius-card) var(--radius-card);
+}
+/* Sidebar + Toolbar hidden */
+.main-content.no-sidebar.no-toolbar:not(.no-status) {
+ border-radius: var(--radius-card) var(--radius-card) var(--radius-card) 0;
+}
+/* Sidebar + Bottom hidden */
+.main-content.no-sidebar.no-status:not(.no-toolbar) {
+ border-radius: 0 var(--radius-card) var(--radius-card) var(--radius-card);
+}
+/* Toolbar + Bottom hidden */
+.main-content.no-toolbar.no-status:not(.no-sidebar) {
+ border-radius: var(--radius-card) var(--radius-card) var(--radius-card) var(--radius-card);
+}
+/* All three hidden -- fully rounded */
+.main-content.no-sidebar.no-toolbar.no-status {
+ border-radius: var(--radius-card);
+}
diff --git a/frontend/css/theme.css b/frontend/css/theme.css
new file mode 100644
index 0000000..41aa121
--- /dev/null
+++ b/frontend/css/theme.css
@@ -0,0 +1,371 @@
+/* ── Wherry Themes ─────────────────────────────────────────────────────────
+ Six themes: Ember (dark · copper), Frost (light · blue), Midnight
+ (dark · indigo), Forest (dark · green), Dawn (light · peach), Ash
+ (high-contrast dark · neutral).
+ Every colour the UI uses is a token; component styles never hardcode a
+ hex. Soft/hover variants are derived with color-mix() so the whole
+ palette can be retuned by touching only the base tokens.
+
+ The active theme is selected via `data-theme="…"` on the element.
+ ──────────────────────────────────────────────────────────────────────── */
+
+/* ══════════════ 1. Ember (default dark · copper accent) ═══════════════ */
+:root,
+[data-theme="ember"] {
+ --bg-base: #0b0d11;
+ --bg-panel: #181c24;
+ --bg-content: #12151b;
+ --bg-toolbar: #12151b;
+ --bg-tab-active: #12151b;
+ --bg-tab-idle: #14171e;
+ --bg-queue: #0f1116;
+ --bg-header: #10131a;
+ --bg-row-hover: rgba(255, 255, 255, 0.055);
+ --bg-row-sel: color-mix(in srgb, var(--accent) 17%, transparent);
+
+ --accent: #d9804f;
+ --accent-hover: #e28e5d;
+ --accent-dim: #9c5433;
+ --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
+ --accent-ring: color-mix(in srgb, var(--accent) 32%, transparent);
+ --on-accent: #221208;
+
+ --green: #7dc98f;
+ --green-soft: color-mix(in srgb, var(--green) 14%, transparent);
+ --red: #e2604c;
+ --red-hover: #e97561;
+ --red-soft: color-mix(in srgb, var(--red) 14%, transparent);
+ --yellow: #e3b341;
+ --yellow-soft: color-mix(in srgb, var(--yellow) 14%, transparent);
+ --blue: #6aa9e9;
+ --blue-soft: color-mix(in srgb, var(--blue) 14%, transparent);
+
+ --text-primary: #eceef2;
+ --text-dim: #99a0ac;
+ --text-hint: #656c79;
+
+ --border: #232833;
+ --separator: #262b35;
+}
+
+/* ══════════════ 2. Frost (light · cool blue accent) ════════════════════ */
+[data-theme="frost"] {
+ --bg-base: #f4f6fa;
+ --bg-panel: #ffffff;
+ --bg-content: #fafbfd;
+ --bg-toolbar: #ffffff;
+ --bg-tab-active: #ffffff;
+ --bg-tab-idle: #f0f2f6;
+ --bg-queue: #f8f9fc;
+ --bg-header: #edf0f5;
+ --bg-row-hover: rgba(0, 0, 0, 0.04);
+ --bg-row-sel: color-mix(in srgb, var(--accent) 14%, transparent);
+
+ --accent: #4a8fe0;
+ --accent-hover: #5d9de8;
+ --accent-dim: #3570b0;
+ --accent-soft: color-mix(in srgb, var(--accent) 12%, transparent);
+ --accent-ring: color-mix(in srgb, var(--accent) 28%, transparent);
+ --on-accent: #ffffff;
+
+ --green: #38a169;
+ --green-soft: color-mix(in srgb, var(--green) 12%, transparent);
+ --red: #d95c4a;
+ --red-hover: #e06d5c;
+ --red-soft: color-mix(in srgb, var(--red) 12%, transparent);
+ --yellow: #c9952e;
+ --yellow-soft: color-mix(in srgb, var(--yellow) 12%, transparent);
+ --blue: #4a8fe0;
+ --blue-soft: color-mix(in srgb, var(--blue) 12%, transparent);
+
+ --text-primary: #1a1d23;
+ --text-dim: #5f6672;
+ --text-hint: #9098a5;
+
+ --border: #dce0e8;
+ --separator: #e2e6ee;
+}
+
+/* ══════════════ 3. Midnight (dark · indigo accent) ══════════════════════ */
+[data-theme="midnight"] {
+ --bg-base: #0d0e17;
+ --bg-panel: #161827;
+ --bg-content: #10121e;
+ --bg-toolbar: #10121e;
+ --bg-tab-active: #10121e;
+ --bg-tab-idle: #131523;
+ --bg-queue: #0e0f1a;
+ --bg-header: #0f111d;
+ --bg-row-hover: rgba(255, 255, 255, 0.055);
+ --bg-row-sel: color-mix(in srgb, var(--accent) 17%, transparent);
+
+ --accent: #8b7cf7;
+ --accent-hover: #9d90f9;
+ --accent-dim: #6355c9;
+ --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
+ --accent-ring: color-mix(in srgb, var(--accent) 32%, transparent);
+ --on-accent: #110e24;
+
+ --green: #6fcb8a;
+ --green-soft: color-mix(in srgb, var(--green) 14%, transparent);
+ --red: #e06070;
+ --red-hover: #e87481;
+ --red-soft: color-mix(in srgb, var(--red) 14%, transparent);
+ --yellow: #dbb84a;
+ --yellow-soft: color-mix(in srgb, var(--yellow) 14%, transparent);
+ --blue: #6a8ce8;
+ --blue-soft: color-mix(in srgb, var(--blue) 14%, transparent);
+
+ --text-primary: #e8eaf2;
+ --text-dim: #949ab0;
+ --text-hint: #5e6480;
+
+ --border: #222540;
+ --separator: #262948;
+}
+
+/* ══════════════ 4. Forest (dark · green accent) ═════════════════════════ */
+[data-theme="forest"] {
+ --bg-base: #0b120e;
+ --bg-panel: #141f17;
+ --bg-content: #0e1611;
+ --bg-toolbar: #0e1611;
+ --bg-tab-active: #0e1611;
+ --bg-tab-idle: #111a13;
+ --bg-queue: #0c130f;
+ --bg-header: #0d1510;
+ --bg-row-hover: rgba(255, 255, 255, 0.055);
+ --bg-row-sel: color-mix(in srgb, var(--accent) 17%, transparent);
+
+ --accent: #5bba70;
+ --accent-hover: #6ec982;
+ --accent-dim: #3d8f4f;
+ --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
+ --accent-ring: color-mix(in srgb, var(--accent) 32%, transparent);
+ --on-accent: #0c1e10;
+
+ --green: #5bba70;
+ --green-soft: color-mix(in srgb, var(--green) 14%, transparent);
+ --red: #d96050;
+ --red-hover: #e07262;
+ --red-soft: color-mix(in srgb, var(--red) 14%, transparent);
+ --yellow: #d4ad40;
+ --yellow-soft: color-mix(in srgb, var(--yellow) 14%, transparent);
+ --blue: #5b94c9;
+ --blue-soft: color-mix(in srgb, var(--blue) 14%, transparent);
+
+ --text-primary: #e2efe5;
+ --text-dim: #91a899;
+ --text-hint: #5c7565;
+
+ --border: #1e3325;
+ --separator: #223b29;
+}
+
+/* ══════════════ 5. Dawn (light · warm peach accent) ═════════════════════ */
+[data-theme="dawn"] {
+ --bg-base: #faf6f3;
+ --bg-panel: #ffffff;
+ --bg-content: #fdfaf8;
+ --bg-toolbar: #ffffff;
+ --bg-tab-active: #ffffff;
+ --bg-tab-idle: #f6f0ea;
+ --bg-queue: #fbf7f4;
+ --bg-header: #f2ebe5;
+ --bg-row-hover: rgba(0, 0, 0, 0.04);
+ --bg-row-sel: color-mix(in srgb, var(--accent) 14%, transparent);
+
+ --accent: #d9735a;
+ --accent-hover: #e0846c;
+ --accent-dim: #b05a44;
+ --accent-soft: color-mix(in srgb, var(--accent) 12%, transparent);
+ --accent-ring: color-mix(in srgb, var(--accent) 28%, transparent);
+ --on-accent: #ffffff;
+
+ --green: #4b8b5e;
+ --green-soft: color-mix(in srgb, var(--green) 12%, transparent);
+ --red: #c95a4a;
+ --red-hover: #d86c5c;
+ --red-soft: color-mix(in srgb, var(--red) 12%, transparent);
+ --yellow: #b8993a;
+ --yellow-soft: color-mix(in srgb, var(--yellow) 12%, transparent);
+ --blue: #5a80b8;
+ --blue-soft: color-mix(in srgb, var(--blue) 12%, transparent);
+
+ --text-primary: #2c2420;
+ --text-dim: #736760;
+ --text-hint: #9f928a;
+
+ --border: #e6dbd3;
+ --separator: #ede2da;
+}
+
+/* ══════════════ 6. Ash (high-contrast dark · neutral gray) ══════════════ */
+[data-theme="ash"] {
+ --bg-base: #0a0a0c;
+ --bg-panel: #141416;
+ --bg-content: #0e0e10;
+ --bg-toolbar: #0e0e10;
+ --bg-tab-active: #0e0e10;
+ --bg-tab-idle: #111113;
+ --bg-queue: #0c0c0e;
+ --bg-header: #0d0d0f;
+ --bg-row-hover: rgba(255, 255, 255, 0.07);
+ --bg-row-sel: color-mix(in srgb, var(--accent) 20%, transparent);
+
+ --accent: #c0c4cc;
+ --accent-hover: #d4d8e0;
+ --accent-dim: #8a8e98;
+ --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
+ --accent-ring: color-mix(in srgb, var(--accent) 35%, transparent);
+ --on-accent: #0a0a0c;
+
+ --green: #8fd4a0;
+ --green-soft: color-mix(in srgb, var(--green) 16%, transparent);
+ --red: #f07060;
+ --red-hover: #f58476;
+ --red-soft: color-mix(in srgb, var(--red) 16%, transparent);
+ --yellow: #e8c860;
+ --yellow-soft: color-mix(in srgb, var(--yellow) 16%, transparent);
+ --blue: #80b4e8;
+ --blue-soft: color-mix(in srgb, var(--blue) 16%, transparent);
+
+ --text-primary: #f0f2f5;
+ --text-dim: #b0b4be;
+ --text-hint: #787c88;
+
+ --border: #2c2e36;
+ --separator: #32343c;
+}
+
+/* ══════════════ Shared base styles ════════════════════════════════════════ */
+
+/* Sizes — identical across all themes */
+:root {
+ --sidebar-w: 216px;
+ --toolbar-h: 52px;
+ --tabbar-h: 36px;
+ --queue-collapsed-h: 34px;
+ --queue-expanded-h: 192px;
+ --status-h: 28px;
+ --row-h: 32px;
+
+ --radius-sm: 6px;
+ --radius-md: 8px;
+ --radius-lg: 10px;
+ --radius-card: 14px;
+
+ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
+ "Segoe UI", "Noto Sans", "Ubuntu", "Cantarell", "DejaVu Sans", sans-serif;
+ --font-mono: "SF Mono", ui-monospace, Menlo, Consolas, "Noto Sans Mono",
+ "DejaVu Sans Mono", monospace;
+ --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
+
+ /* Transition for theme switching — animates colour changes smoothly */
+ --theme-transition: background-color 0.3s var(--ease-out),
+ color 0.3s var(--ease-out),
+ border-color 0.3s var(--ease-out),
+ box-shadow 0.3s var(--ease-out);
+}
+
+/* Apply theme transitions when [data-theme] changes */
+html.theme-transitioning,
+html.theme-transitioning *,
+html.theme-transitioning *::before,
+html.theme-transitioning *::after {
+ transition: var(--theme-transition) !important;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+html,
+body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ background: var(--bg-base);
+ color: var(--text-primary);
+ font-family: var(--font-sans);
+ font-size: 13px;
+ overflow: hidden;
+ -webkit-font-smoothing: antialiased;
+ user-select: none;
+}
+
+#app {
+ height: 100vh;
+ width: 100vw;
+ display: flex;
+ flex-direction: column;
+}
+
+button,
+input,
+select {
+ font-family: inherit;
+ color: inherit;
+}
+
+button {
+ appearance: none;
+ background: none;
+ border: none;
+ padding: 0;
+ cursor: pointer;
+ font-size: inherit;
+}
+
+p {
+ margin: 0;
+}
+
+::selection {
+ background: var(--accent-ring);
+ color: var(--text-primary);
+}
+
+:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 1px;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ }
+}
+
+::-webkit-scrollbar {
+ width: 9px;
+ height: 9px;
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--border);
+ border-radius: 5px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--text-hint);
+}
+
+::-webkit-scrollbar-track {
+ background: transparent;
+}
+
+/* ── Utility text-colour classes ─────────────────────────────────────────── */
+.text-primary { color: var(--text-primary); }
+.text-dim { color: var(--text-dim); }
+.text-hint { color: var(--text-hint); }
+.text-accent { color: var(--accent); }
+.text-green { color: var(--green); }
+.text-red { color: var(--red); }
+.text-yellow { color: var(--yellow); }
+.text-blue { color: var(--blue); }
+.mono { font-family: var(--font-mono); }
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..cd614c1
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Wherry
+
+
+
+
+
+
+
+
+
diff --git a/frontend/js/components/breadcrumbs.js b/frontend/js/components/breadcrumbs.js
new file mode 100644
index 0000000..be1c684
--- /dev/null
+++ b/frontend/js/components/breadcrumbs.js
@@ -0,0 +1,33 @@
+/** Renders a `/`-separated path as clickable breadcrumb segments into `container`. */
+export function renderBreadcrumbs(container, path, onNavigate) {
+ container.innerHTML = "";
+ const parts = path.split("/").filter(Boolean);
+
+ const root = document.createElement("button");
+ root.type = "button";
+ root.className = "breadcrumb-seg";
+ root.textContent = "/";
+ root.addEventListener("click", () => onNavigate("/"));
+ container.appendChild(root);
+
+ let acc = "";
+ parts.forEach((part, i) => {
+ acc += `/${part}`;
+ const isLast = i === parts.length - 1;
+ const seg = document.createElement(isLast ? "span" : "button");
+ seg.className = `breadcrumb-seg ${isLast ? "current" : ""}`;
+ seg.textContent = part;
+ if (!isLast) {
+ const target = acc;
+ seg.type = "button";
+ seg.addEventListener("click", () => onNavigate(target));
+ }
+ container.appendChild(seg);
+ if (!isLast) {
+ const sep = document.createElement("span");
+ sep.className = "breadcrumb-sep";
+ sep.textContent = "/";
+ container.appendChild(sep);
+ }
+ });
+}
diff --git a/frontend/js/components/connectDialog.js b/frontend/js/components/connectDialog.js
new file mode 100644
index 0000000..a0a5fef
--- /dev/null
+++ b/frontend/js/components/connectDialog.js
@@ -0,0 +1,233 @@
+// "New Connection" modal — src/ui/dialogs/connection/{view,form}.rs equivalent.
+import { state, notify } from "../store.js";
+import { t } from "../i18n.js";
+import { iconMarkup } from "../icons.js";
+import { buildParamsFromForm, spawnConnect, DEFAULT_PORTS } from "../connectActions.js";
+import { escapeHtml as escapeAttr } from "../dom.js";
+
+const PROTOCOLS = ["sftp", "ftp", "ftps"];
+const PROTOCOL_LABELS = { sftp: "SFTP", ftp: "FTP", ftps: "FTPS" };
+
+let form = emptyForm();
+let overlayEl = null;
+let lastOpenSig = null;
+
+function emptyForm() {
+ return {
+ protocol: "sftp",
+ host: "",
+ port: "",
+ username: "",
+ password: "",
+ keyPath: "",
+ label: "",
+ };
+}
+
+/** Called by the toolbar "New Connection" button and the welcome screen CTA. */
+export function openNew() {
+ form = emptyForm();
+ state.connectError = "";
+ state.showConnectDialog = true;
+ notify();
+}
+
+/** Called from history "Edit" — prefills everything. */
+export function openForEdit(entry) {
+ form = {
+ protocol: entry.protocol,
+ host: entry.host,
+ port: String(entry.port),
+ username: entry.username,
+ password: "",
+ keyPath: entry.keyPath ?? "",
+ label: "",
+ };
+ state.connectError = "";
+ state.showConnectDialog = true;
+ notify();
+}
+
+function close() {
+ if (state.connectLoading) return;
+ state.showConnectDialog = false;
+ notify();
+}
+
+async function submit() {
+ if (state.connectLoading) return;
+ const result = buildParamsFromForm(form);
+ if (!result.ok) {
+ state.connectError = t(result.error);
+ notify();
+ return;
+ }
+ await spawnConnect(result.params);
+}
+
+async function browseKeyFile() {
+ try {
+ const dialog = window.__TAURI__.dialog;
+ const path = await dialog.open({ title: "Choose SSH key", multiple: false, directory: false });
+ if (typeof path === "string") {
+ form.keyPath = path;
+ const input = overlayEl?.querySelector("[data-field=keyPath]");
+ if (input) input.value = path;
+ }
+ } catch {
+ /* dialog plugin unavailable / user cancelled */
+ }
+}
+
+function build() {
+ const overlay = document.createElement("div");
+ overlay.className = "overlay";
+ overlay.addEventListener("mousedown", (e) => {
+ if (e.target === overlay) close();
+ });
+
+ const dialog = document.createElement("div");
+ dialog.className = "dialog";
+ dialog.addEventListener("mousedown", (e) => e.stopPropagation());
+
+ dialog.innerHTML = `
+
+
+
+ ${PROTOCOLS.map((p) => ``).join("")}
+
+
+
+ ${t("connect.host")}
+
+
+
+
+
+
+
${t("connect.password")}
+
+
+
+
+
+
+
+
${t("connect.keyHint")}
+
+
${t("connect.keyFile")}
+
+
+
+
+
+
+
+
+ ${t("connect.label")}
+
+
+
+
+
+
+ `;
+
+ overlay.appendChild(dialog);
+
+ dialog.querySelectorAll('[data-action="close"]').forEach((el) =>
+ el.addEventListener("click", close),
+ );
+ dialog.querySelector('[data-action="submit"]').addEventListener("click", submit);
+ dialog.querySelector('[data-action="browse"]').addEventListener("click", browseKeyFile);
+
+ dialog.querySelectorAll("[data-field]").forEach((input) => {
+ input.addEventListener("input", () => {
+ form[input.dataset.field] = input.value;
+ });
+ });
+
+ const passInput = dialog.querySelector('[data-field="password"]');
+ dialog.querySelector('[data-action="toggle-pass"]').addEventListener("click", (e) => {
+ const showing = passInput.type === "text";
+ passInput.type = showing ? "password" : "text";
+ e.currentTarget.innerHTML = iconMarkup(showing ? "eye" : "eyeClosed", 15);
+ });
+
+ dialog.querySelectorAll("[data-protocol]").forEach((btn) => {
+ btn.addEventListener("click", () => {
+ const proto = btn.dataset.protocol;
+ form.protocol = proto;
+ if (!form.port) {
+ dialog.querySelector('[data-field="port"]').placeholder = String(DEFAULT_PORTS[proto]);
+ }
+ dialog.querySelectorAll("[data-protocol]").forEach((b) => b.classList.toggle("active", b === btn));
+ dialog.querySelector('[data-role="key-section"]').style.display = proto === "sftp" ? "block" : "none";
+ });
+ });
+
+ dialog.addEventListener("keydown", (e) => {
+ if (e.key === "Enter") submit();
+ });
+
+ return { overlay, dialog };
+}
+
+function updateDynamic(dialog) {
+ const errRole = dialog.querySelector('[data-role="error"]');
+ errRole.innerHTML = state.connectError
+ ? `${iconMarkup("dangerTriangle", 14)}${escapeAttr(state.connectError)}
`
+ : "";
+
+ const submitBtn = dialog.querySelector('[data-action="submit"]');
+ submitBtn.disabled = state.connectLoading;
+ submitBtn.textContent = state.connectLoading ? t("connect.connecting") : t("connect.connect");
+ const cancelBtn = dialog.querySelector('[data-action="close"]');
+ cancelBtn.disabled = state.connectLoading;
+
+ dialog.querySelector('[data-role="spinner"]').innerHTML = state.connectLoading
+ ? ''
+ : "";
+}
+
+export function renderConnectDialog() {
+ const sig = JSON.stringify([state.showConnectDialog]);
+ if (!state.showConnectDialog) {
+ if (overlayEl) {
+ overlayEl.remove();
+ overlayEl = null;
+ }
+ lastOpenSig = sig;
+ return;
+ }
+
+ if (sig !== lastOpenSig || !overlayEl) {
+ if (overlayEl) overlayEl.remove();
+ const { overlay, dialog } = build();
+ document.body.appendChild(overlay);
+ overlayEl = overlay;
+ overlayEl._dialog = dialog;
+ setTimeout(() => dialog.querySelector('[data-field="host"]').focus(), 0);
+ lastOpenSig = sig;
+ }
+
+ updateDynamic(overlayEl._dialog);
+}
diff --git a/frontend/js/components/contextMenu.js b/frontend/js/components/contextMenu.js
new file mode 100644
index 0000000..e42b68a
--- /dev/null
+++ b/frontend/js/components/contextMenu.js
@@ -0,0 +1,58 @@
+import { iconMarkup } from "../icons.js";
+
+let openMenuEl = null;
+
+function closeOpenMenu() {
+ if (openMenuEl) {
+ openMenuEl.remove();
+ openMenuEl = null;
+ document.removeEventListener("mousedown", onOutsideClick, true);
+ document.removeEventListener("keydown", onKeydown, true);
+ }
+}
+
+function onOutsideClick(e) {
+ if (openMenuEl && !openMenuEl.contains(e.target)) closeOpenMenu();
+}
+
+function onKeydown(e) {
+ if (e.key === "Escape") closeOpenMenu();
+}
+
+/**
+ * items: Array<{ label, icon?, danger?, onClick } | 'sep'>
+ */
+export function showContextMenu(x, y, items) {
+ closeOpenMenu();
+ const menu = document.createElement("div");
+ menu.className = "context-menu";
+ for (const item of items) {
+ if (item === "sep") {
+ const sep = document.createElement("div");
+ sep.className = "context-menu-sep";
+ menu.appendChild(sep);
+ continue;
+ }
+ const btn = document.createElement("button");
+ btn.className = "context-menu-item" + (item.danger ? " danger" : "");
+ btn.innerHTML = `${item.icon ? iconMarkup(item.icon, 14) : ""}${item.label}`;
+ btn.addEventListener("click", () => {
+ closeOpenMenu();
+ item.onClick();
+ });
+ menu.appendChild(btn);
+ }
+ document.body.appendChild(menu);
+
+ const rect = menu.getBoundingClientRect();
+ const vw = window.innerWidth;
+ const vh = window.innerHeight;
+ menu.style.left = `${Math.min(x, vw - rect.width - 8)}px`;
+ menu.style.top = `${Math.min(y, vh - rect.height - 8)}px`;
+
+ openMenuEl = menu;
+ setTimeout(() => {
+ document.addEventListener("mousedown", onOutsideClick, true);
+ document.addEventListener("keydown", onKeydown, true);
+ }, 0);
+}
diff --git a/frontend/js/components/fileTable.js b/frontend/js/components/fileTable.js
new file mode 100644
index 0000000..d5c738c
--- /dev/null
+++ b/frontend/js/components/fileTable.js
@@ -0,0 +1,176 @@
+// Reusable file listing table shared by the Local and Remote panes — mirrors
+// the old src/ui/panels/file_pane module (table.rs/row.rs/sort.rs collapsed
+// into one file since there's no split-module pressure in JS).
+import { t } from "../i18n.js";
+import { iconMarkup, fileIconFor } from "../icons.js";
+import { formatSize, formatTime } from "../format.js";
+import { makeDraggable, makeDropTarget } from "../dnd.js";
+import { showContextMenu } from "./contextMenu.js";
+import { escapeHtml } from "../dom.js";
+
+function sortEntries(entries, sort) {
+ const dotdotIdx = entries.findIndex((e) => e.name === "..");
+ const dotdot = dotdotIdx >= 0 ? entries[dotdotIdx] : null;
+ const rest = entries.filter((e) => e.name !== "..");
+
+ rest.sort((a, b) => {
+ const aDir = a.kind === "dir";
+ const bDir = b.kind === "dir";
+ if (aDir !== bDir) return aDir ? -1 : 1;
+
+ let cmp = 0;
+ switch (sort.col) {
+ case "size":
+ cmp = (a.size ?? 0) - (b.size ?? 0);
+ break;
+ case "kind":
+ cmp = a.kind.localeCompare(b.kind);
+ break;
+ case "modified":
+ cmp = (a.modified ?? 0) - (b.modified ?? 0);
+ break;
+ default:
+ cmp = a.name.toLowerCase().localeCompare(b.name.toLowerCase());
+ }
+ return sort.dir === "desc" ? -cmp : cmp;
+ });
+
+ return dotdot ? [dotdot, ...rest] : rest;
+}
+
+function rowIcon(entry) {
+ if (entry.name === "..") return ["arrowUp", "icon--inactive"];
+ if (entry.kind === "dir") return ["folder", "icon--important"];
+ if (entry.kind === "symlink") return ["link", "icon--important"];
+ return fileIconFor(entry.name);
+}
+
+function typeLabel(entry) {
+ if (entry.kind === "dir") return t("panels.typeDir");
+ if (entry.kind === "symlink") return t("panels.typeLink");
+ return t("panels.typeFile");
+}
+
+function sortHeaderHtml(label, col, sort) {
+ const active = sort.col === col;
+ const arrow = active ? (sort.dir === "asc" ? " ↑" : " ↓") : "";
+ return ``;
+}
+
+/**
+ * opts:
+ * - entries: FileEntry[]
+ * - selected: string[] (names of selected entries)
+ * - anchor: string|null (name shift-click range selection extends from)
+ * - sort: { col, dir }
+ * - onSort(nextSort)
+ * - onSelect(names, anchor)
+ * - onOpen(name)
+ * - dragPayload(entry) => payload|null
+ * - onDropOnEntry(entry, payload) only called for dir/".." rows
+ * - onHoverOpen(entry) spring-loaded open: fires after a drag lingers on
+ * a dir/".." row for HOVER_OPEN_DELAY, without
+ * ending the drag -- only called for dir/".." rows
+ * - contextMenuItems(entry, selectedEntries) => menu items for showContextMenu, or null to skip
+ */
+export function renderFileTable(container, opts) {
+ const scrollPos = container.querySelector(".file-table-body")?.scrollTop ?? 0;
+ container.innerHTML = "";
+ container.classList.add("file-table-wrap");
+
+ const header = document.createElement("div");
+ header.className = "file-table-header";
+ header.innerHTML = `
+ ${sortHeaderHtml(t("panels.colName"), "name", opts.sort)}
+ ${sortHeaderHtml(t("panels.colModified"), "modified", opts.sort)}
+ ${sortHeaderHtml(t("panels.colType"), "kind", opts.sort)}
+ ${sortHeaderHtml(t("panels.colSize"), "size", opts.sort)}
+ `;
+ header.querySelectorAll(".sort-header").forEach((btn) => {
+ btn.addEventListener("click", () => {
+ const col = btn.dataset.col;
+ const next =
+ opts.sort.col === col
+ ? { col, dir: opts.sort.dir === "asc" ? "desc" : "asc" }
+ : { col, dir: "asc" };
+ opts.onSort(next);
+ });
+ });
+ container.appendChild(header);
+
+ const body = document.createElement("div");
+ body.className = "file-table-body";
+ container.appendChild(body);
+
+ const sorted = sortEntries(opts.entries, opts.sort);
+ const selectableNames = sorted.filter((e) => e.name !== "..").map((e) => e.name);
+
+ for (const entry of sorted) {
+ const row = document.createElement("div");
+ row.className = "file-row";
+ if (opts.selected.includes(entry.name)) row.classList.add("selected");
+
+ const [iconName, iconColor] = rowIcon(entry);
+ const nameCol = entry.name === ".." ? "text-hint" : "text-primary";
+
+ row.innerHTML = `
+
+ ${iconMarkup(iconName, 15)}
+ ${escapeHtml(entry.name)}
+
+ ${formatTime(entry.modified)}
+ ${typeLabel(entry)}
+ ${formatSize(entry.size)}
+ `;
+
+ row.addEventListener("click", (e) => {
+ if (entry.name === "..") {
+ opts.onSelect([], null);
+ return;
+ }
+ const idx = selectableNames.indexOf(entry.name);
+ if (e.shiftKey && opts.anchor && selectableNames.includes(opts.anchor)) {
+ const anchorIdx = selectableNames.indexOf(opts.anchor);
+ const [lo, hi] = anchorIdx < idx ? [anchorIdx, idx] : [idx, anchorIdx];
+ opts.onSelect(selectableNames.slice(lo, hi + 1), opts.anchor);
+ } else if (e.ctrlKey || e.metaKey) {
+ const next = new Set(opts.selected);
+ if (next.has(entry.name)) next.delete(entry.name);
+ else next.add(entry.name);
+ opts.onSelect(selectableNames.filter((n) => next.has(n)), entry.name);
+ } else {
+ opts.onSelect([entry.name], entry.name);
+ }
+ });
+ row.addEventListener("dblclick", () => opts.onOpen(entry.name));
+
+ if (entry.name !== "..") {
+ row.addEventListener("contextmenu", (e) => {
+ e.preventDefault();
+ let selection = opts.selected;
+ if (!selection.includes(entry.name)) {
+ selection = [entry.name];
+ opts.onSelect(selection, entry.name);
+ }
+ const selectedEntries = sorted.filter((en) => selection.includes(en.name));
+ const items = opts.contextMenuItems?.(entry, selectedEntries);
+ if (items) showContextMenu(e.clientX, e.clientY, items);
+ });
+
+ const payload = opts.dragPayload?.(entry);
+ if (payload) makeDraggable(row.querySelector(".file-row-name"), entry, payload);
+ }
+
+ if (entry.kind === "dir" || entry.name === "..") {
+ makeDropTarget(row, {
+ onDrop: (payload) => opts.onDropOnEntry?.(entry, payload),
+ onHoverChange: (hover) => row.classList.toggle("drag-hover", hover),
+ onHoverHold: () => opts.onHoverOpen?.(entry),
+ });
+ }
+
+ body.appendChild(row);
+ }
+
+ body.scrollTop = scrollPos;
+}
diff --git a/frontend/js/components/historyList.js b/frontend/js/components/historyList.js
new file mode 100644
index 0000000..2485381
--- /dev/null
+++ b/frontend/js/components/historyList.js
@@ -0,0 +1,47 @@
+// Shared "recent connections" row renderer used by both the welcome screen
+// and the toolbar's History popover.
+import { iconMarkup } from "../icons.js";
+import { t } from "../i18n.js";
+import { showContextMenu } from "./contextMenu.js";
+import { reconnectFromHistory, saveHistoryAsSite } from "../connectActions.js";
+import { openForEdit } from "./connectDialog.js";
+
+/** entries: HistoryEntry[]; rowClass defaults to "recent-row". */
+export function renderHistoryRows(container, entries, { rowClass = "recent-row", onAfterClick } = {}) {
+ container.innerHTML = "";
+ for (const entry of entries) {
+ const row = document.createElement("div");
+ row.className = rowClass;
+ row.innerHTML = `
+ ${iconMarkup("serverSquare", 13)}
+ ${entry.username}@${entry.host}:${entry.port}
+ ${entry.connectedAt}
+ `;
+ row.addEventListener("click", () => {
+ reconnectFromHistory(entry);
+ onAfterClick?.();
+ });
+ row.addEventListener("contextmenu", (e) => {
+ e.preventDefault();
+ showContextMenu(e.clientX, e.clientY, [
+ {
+ label: t("common.edit"),
+ icon: "pen",
+ onClick: () => {
+ openForEdit(entry);
+ onAfterClick?.();
+ },
+ },
+ {
+ label: t("common.save"),
+ icon: "star",
+ onClick: () => {
+ saveHistoryAsSite(entry);
+ onAfterClick?.();
+ },
+ },
+ ]);
+ });
+ container.appendChild(row);
+ }
+}
diff --git a/frontend/js/components/historyPopup.js b/frontend/js/components/historyPopup.js
new file mode 100644
index 0000000..4359f6d
--- /dev/null
+++ b/frontend/js/components/historyPopup.js
@@ -0,0 +1,68 @@
+import { state, notify } from "../store.js";
+import { t } from "../i18n.js";
+import { iconMarkup } from "../icons.js";
+import { renderHistoryRows } from "./historyList.js";
+
+let popoverEl = null;
+let pendingAnchorRect = null;
+
+function close() {
+ state.showHistoryPopup = false;
+ notify();
+}
+
+export function toggle(anchorEl) {
+ // Measure the anchor before notify() -- the toolbar re-renders itself
+ // synchronously inside notify() (its computeSig() includes
+ // showHistoryPopup), which discards and recreates this exact button. A
+ // rect read after that point, or against a stale element reference, would
+ // measure a detached node and yield an all-zero rect.
+ pendingAnchorRect = anchorEl.getBoundingClientRect();
+ state.showHistoryPopup = !state.showHistoryPopup;
+ notify();
+ if (state.showHistoryPopup) positionNear(pendingAnchorRect);
+}
+
+function positionNear(rect) {
+ if (!popoverEl || !rect) return;
+ popoverEl.style.top = `${rect.bottom + 6}px`;
+ popoverEl.style.right = `${window.innerWidth - rect.right}px`;
+}
+
+function onOutsideClick(e) {
+ if (popoverEl && !popoverEl.contains(e.target) && !e.target.closest("[data-history-toggle]")) {
+ close();
+ }
+}
+
+export function renderHistoryPopup() {
+ if (!state.showHistoryPopup) {
+ if (popoverEl) {
+ document.removeEventListener("mousedown", onOutsideClick, true);
+ popoverEl.remove();
+ popoverEl = null;
+ }
+ return;
+ }
+ if (!popoverEl) {
+ popoverEl = document.createElement("div");
+ popoverEl.className = "popover";
+ document.body.appendChild(popoverEl);
+ setTimeout(() => document.addEventListener("mousedown", onOutsideClick, true), 0);
+ }
+
+ popoverEl.innerHTML = `
+
+ ${state.history.length === 0 ? `${t("history.noHistory")}
` : ''}
+ `;
+
+ if (state.history.length > 0) {
+ renderHistoryRows(popoverEl.querySelector('[data-role="list"]'), state.history, {
+ rowClass: "popover-row",
+ onAfterClick: close,
+ });
+ }
+}
diff --git a/frontend/js/components/localPane.js b/frontend/js/components/localPane.js
new file mode 100644
index 0000000..b051f5a
--- /dev/null
+++ b/frontend/js/components/localPane.js
@@ -0,0 +1,140 @@
+import { state, notify, activeTab } from "../store.js";
+import { t } from "../i18n.js";
+import { iconMarkup } from "../icons.js";
+import { formatSize } from "../format.js";
+import { renderFileTable } from "./fileTable.js";
+import { renderBreadcrumbs } from "./breadcrumbs.js";
+import { makeDropTarget } from "../dnd.js";
+import { showContextMenu } from "./contextMenu.js";
+import { openRename, openDelete } from "./opDialogs.js";
+import {
+ navigateLocal,
+ openLocalEntry,
+ addBookmark,
+ handleDropOnLocal,
+ queueUpload,
+ queueUploadMany,
+} from "../fsActions.js";
+
+export function renderLocalPane(container) {
+ container.innerHTML = `
+
+
${t("panels.localLabel")}
+
+
+
+
+ `;
+
+ container.querySelector('[data-action="bookmark"]').addEventListener("click", () => {
+ const path = state.local.path;
+ const name = path.split("/").filter(Boolean).pop() ?? "Bookmark";
+ addBookmark(name, path);
+ });
+
+ makeDropTarget(container, {
+ onDrop: (payload) => handleDropOnLocal(payload, state.local.path),
+ onHoverChange: (hover) => container.classList.toggle("drag-over", hover),
+ });
+
+ updateLocalPane(container);
+}
+
+export function updateLocalPane(container) {
+ renderBreadcrumbs(container.querySelector('[data-role="breadcrumbs"]'), state.local.path || "/", navigateLocal);
+
+ const tab = activeTab();
+ const connected = tab?.status === "connected";
+
+ renderFileTable(container.querySelector('[data-role="table"]'), {
+ entries: state.local.entries,
+ selected: state.local.selected,
+ anchor: state.local.selectAnchor,
+ sort: state.local.sort,
+ onSort: (next) => {
+ state.local.sort = next;
+ notify();
+ },
+ onSelect: (names, anchor) => {
+ state.local.selected = names;
+ state.local.selectAnchor = anchor;
+ state.activePane = "local";
+ notify();
+ },
+ onOpen: (name) => openLocalEntry(name),
+ onHoverOpen: (entry) => openLocalEntry(entry.name),
+ dragPayload: (entry) => {
+ if (entry.name === "..") return null;
+ const group =
+ state.local.selected.includes(entry.name) && state.local.selected.length > 1
+ ? state.local.entries.filter((e) => state.local.selected.includes(e.name))
+ : [entry];
+ return {
+ source: "local",
+ items: group.map((e) => ({ path: e.path, name: e.name, kind: e.kind })),
+ };
+ },
+ onDropOnEntry: (entry, payload) => handleDropOnLocal(payload, entry.path),
+ contextMenuItems: (entry, selectedEntries) => {
+ if (selectedEntries.length > 1) {
+ const files = selectedEntries.filter((e) => e.kind === "file");
+ return [
+ {
+ label: t("common.delete") + ` (${selectedEntries.length})`,
+ icon: "trash",
+ danger: true,
+ onClick: () => openDeleteLocal(selectedEntries),
+ },
+ ...(files.length > 0 && connected
+ ? [
+ "sep",
+ {
+ label: t("panels.uploadToServer") + ` (${files.length})`,
+ icon: "upload",
+ onClick: () => queueUploadMany(tab, files),
+ },
+ ]
+ : []),
+ ];
+ }
+ return [
+ { label: t("common.open"), icon: "folder", onClick: () => openLocalEntry(entry.name) },
+ { label: t("common.rename"), icon: "pen", onClick: () => openRenameLocal(entry) },
+ { label: t("common.delete"), icon: "trash", danger: true, onClick: () => openDeleteLocal([entry]) },
+ "sep",
+ ...(entry.kind === "dir"
+ ? [{ label: t("panels.addToBookmarks"), icon: "star", onClick: () => addBookmark(entry.name, entry.path) }]
+ : []),
+ { label: t("common.copyPath"), icon: "copy", onClick: () => copyPath(entry.path) },
+ ...(entry.kind === "file" && connected
+ ? ["sep", { label: t("panels.uploadToServer"), icon: "upload", onClick: () => queueUpload(tab, entry) }]
+ : []),
+ ];
+ },
+ });
+
+ const count = state.local.entries.filter((e) => e.name !== "..").length;
+ const totalSize = state.local.entries.reduce((sum, e) => sum + (e.size ?? 0), 0);
+ container.querySelector('[data-role="count"]').textContent = t("panels.countItems", { n: count });
+ container.querySelector('[data-role="size"]').textContent = totalSize > 0 ? `(${formatSize(totalSize)})` : "";
+}
+
+function openRenameLocal(entry) {
+ state.opTarget = "local";
+ openRename(entry.name);
+}
+function openDeleteLocal(entries) {
+ state.opTarget = "local";
+ openDelete(entries.map((e) => e.name));
+}
+function copyPath(path) {
+ navigator.clipboard?.writeText(path);
+ state.statusMessage = t("panels.pathCopied");
+ notify();
+}
diff --git a/frontend/js/components/opDialogs.js b/frontend/js/components/opDialogs.js
new file mode 100644
index 0000000..cbaa3be
--- /dev/null
+++ b/frontend/js/components/opDialogs.js
@@ -0,0 +1,158 @@
+// New Folder / Rename / Delete-confirm modals — shared by local and remote
+// panes, applied to whichever side is `state.opTarget`.
+import { state, notify } from "../store.js";
+import { t } from "../i18n.js";
+import { iconMarkup } from "../icons.js";
+import { doMkdir, doRename, doDelete } from "../fsActions.js";
+import { escapeHtml as escapeAttr } from "../dom.js";
+
+let overlayEl = null;
+let lastSig = null;
+
+export function openMkdir() {
+ state.dialog = { kind: "mkdir", value: "" };
+ notify();
+}
+
+export function openRename(name) {
+ state.dialog = { kind: "rename", oldName: name, value: name };
+ notify();
+}
+
+export function openDelete(names) {
+ // Settings → General → "Confirm before delete" off skips the modal
+ // entirely instead of just pre-answering it.
+ if (!state.settings.confirmBeforeDelete) {
+ doDelete(names);
+ return;
+ }
+ state.dialog = { kind: "delete", names };
+ notify();
+}
+
+export function closeDialog() {
+ state.dialog = null;
+ notify();
+}
+
+async function submit() {
+ const d = state.dialog;
+ if (!d) return;
+ if (d.kind === "mkdir") {
+ const name = d.value.trim();
+ if (!name) return;
+ closeDialog();
+ await doMkdir(name);
+ } else if (d.kind === "rename") {
+ const name = d.value.trim();
+ if (!name || name === d.oldName) {
+ closeDialog();
+ return;
+ }
+ closeDialog();
+ await doRename(d.oldName, name);
+ } else if (d.kind === "delete") {
+ closeDialog();
+ await doDelete(d.names);
+ }
+ notify();
+}
+
+function buildMkdirOrRename(d) {
+ const isRename = d.kind === "rename";
+ const overlay = document.createElement("div");
+ overlay.className = "overlay";
+ overlay.addEventListener("mousedown", (e) => {
+ if (e.target === overlay) closeDialog();
+ });
+ const dialog = document.createElement("div");
+ dialog.className = "dialog dialog-sm";
+ dialog.addEventListener("mousedown", (e) => e.stopPropagation());
+ dialog.innerHTML = `
+
+
+
+
+
+ `;
+ overlay.appendChild(dialog);
+ dialog.querySelector('[data-action="close"]').addEventListener("click", closeDialog);
+ dialog.querySelector('[data-action="submit"]').addEventListener("click", submit);
+ const input = dialog.querySelector('[data-field="value"]');
+ input.addEventListener("input", () => {
+ state.dialog.value = input.value;
+ });
+ dialog.addEventListener("keydown", (e) => {
+ if (e.key === "Enter") submit();
+ });
+ document.body.appendChild(overlay);
+ setTimeout(() => {
+ input.focus();
+ if (isRename) {
+ const dot = input.value.lastIndexOf(".");
+ input.setSelectionRange(0, dot > 0 ? dot : input.value.length);
+ } else {
+ input.select();
+ }
+ }, 0);
+ return overlay;
+}
+
+function buildDelete(d) {
+ const overlay = document.createElement("div");
+ overlay.className = "overlay";
+ overlay.addEventListener("mousedown", (e) => {
+ if (e.target === overlay) closeDialog();
+ });
+ const dialog = document.createElement("div");
+ dialog.className = "dialog dialog-sm";
+ dialog.addEventListener("mousedown", (e) => e.stopPropagation());
+ const title =
+ d.names.length === 1
+ ? t("dialogs.deleteTitle", { name: escapeAttr(d.names[0]) })
+ : t("dialogs.deleteTitleMulti", { n: d.names.length });
+ dialog.innerHTML = `
+
+
+
${t("dialogs.deleteBody")}
+
+
+ `;
+ overlay.appendChild(dialog);
+ dialog.querySelector('[data-action="close"]').addEventListener("click", closeDialog);
+ dialog.querySelector('[data-action="submit"]').addEventListener("click", submit);
+ document.body.appendChild(overlay);
+ return overlay;
+}
+
+export function renderOpDialogs() {
+ const sig = JSON.stringify(
+ state.dialog ? { kind: state.dialog.kind, names: state.dialog.names, oldName: state.dialog.oldName } : null,
+ );
+ if (sig === lastSig) return;
+ lastSig = sig;
+
+ if (overlayEl) {
+ overlayEl.remove();
+ overlayEl = null;
+ }
+ if (!state.dialog) return;
+
+ overlayEl =
+ state.dialog.kind === "delete" ? buildDelete(state.dialog) : buildMkdirOrRename(state.dialog);
+}
diff --git a/frontend/js/components/paneLayout.js b/frontend/js/components/paneLayout.js
new file mode 100644
index 0000000..2e959b9
--- /dev/null
+++ b/frontend/js/components/paneLayout.js
@@ -0,0 +1,319 @@
+// Split-pane layout — tabs dragged from tab bar into panes create splits.
+// Direction-aware: drop left edge = split left, right edge = split right,
+// center = replace. Panes can also be reordered by dragging headers.
+import { state, notify } from "../store.js";
+import { renderLocalPane, updateLocalPane } from "./localPane.js";
+import { renderRemotePane, updateRemotePane } from "./remotePane.js";
+import { iconMarkup } from "../icons.js";
+import { HOVER_OPEN_DELAY, getDraggedTabId } from "../dnd.js";
+
+const paneRefs = new Map();
+
+function paneKind(p) { return p.tabId ?? "local"; }
+function paneLabel(p) { return p.tabId === null ? "Local" : (state.tabs.find((t) => t.id === p.tabId)?.label ?? "?"); }
+
+/* Render the full pane grid */
+export function renderPanes(container) {
+ container.innerHTML = "";
+ paneRefs.clear();
+
+ const wrap = document.createElement("div");
+ wrap.className = "pane-grid";
+ wrap.style.cssText = `display:grid;grid-template-columns:${buildGrid()};flex:1;min-height:0;`;
+ wrap.addEventListener("dragover", (e) => { e.preventDefault(); });
+ wrap.addEventListener("drop", (e) => {
+ // Drop on empty area (after last pane) → append
+ e.preventDefault();
+ const tabId = e.dataTransfer.getData("tab-id");
+ if (!tabId) return;
+ stopDropHighlight();
+ addPane(parsedTabId(tabId), state.layout.panes.length);
+ });
+ container.appendChild(wrap);
+
+ for (const pane of state.layout.panes) {
+ const cell = createPaneCell(pane);
+ wrap.appendChild(cell);
+ }
+}
+
+function createPaneCell(pane) {
+ const cell = document.createElement("div");
+ cell.className = "pane-cell";
+ cell.dataset.paneId = pane.id;
+
+ // Edge drop zones
+ const zones = ["left","right","top","bottom","center","swap"].map((z) => {
+ const d = document.createElement("div");
+ d.className = `pane-zone pane-zone--${z}`;
+ d.dataset.zone = z;
+ return d;
+ });
+
+ // Header
+ const header = document.createElement("div");
+ header.className = "pane-header";
+ header.draggable = true;
+ header.dataset.paneId = pane.id;
+ header.innerHTML = `${paneLabel(pane)}`;
+ header.addEventListener("dragstart", onHeaderDragStart);
+ header.addEventListener("dragend", onHeaderDragEnd);
+
+ // Close btn
+ if (state.layout.panes.length > 1) {
+ const closeBtn = document.createElement("button");
+ closeBtn.className = "pane-close-btn";
+ closeBtn.title = "Close";
+ closeBtn.innerHTML = iconMarkup("close", 10);
+ closeBtn.addEventListener("click", (e) => { e.stopPropagation(); closePane(pane.id); });
+ header.appendChild(closeBtn);
+ }
+
+ // Body
+ const body = document.createElement("div");
+ body.className = "pane-body";
+
+ cell.appendChild(header);
+ cell.appendChild(body);
+ zones.forEach((z) => cell.appendChild(z));
+
+ // Drag events on the cell
+ cell.addEventListener("dragover", onPaneDragOver);
+ cell.addEventListener("dragleave", onPaneDragLeave);
+ cell.addEventListener("drop", onPaneDrop);
+
+ // Render file table
+ if (pane.tabId === null) {
+ renderLocalPane(body);
+ } else {
+ const tab = state.tabs.find((t) => t.id === pane.tabId);
+ if (tab) renderRemotePane(body, tab);
+ }
+ paneRefs.set(pane.id, { kind: paneKind(pane), bodyEl: body });
+
+ return cell;
+}
+
+function buildGrid() {
+ const n = state.layout.panes.length;
+ if (n <= 1) return "1fr";
+ return state.layout.panes.map(() => "1fr").join(" ");
+}
+
+/* In-place update (avoids full rebuild on every tick) */
+export function updatePanes(container) {
+ const wrap = container.querySelector(".pane-grid");
+ if (!wrap) return renderPanes(container);
+ const cells = wrap.querySelectorAll(".pane-cell");
+ if (cells.length !== state.layout.panes.length) return renderPanes(container);
+ const ids = Array.from(cells).map((c) => c.dataset.paneId);
+ const expected = state.layout.panes.map((p) => p.id);
+ if (ids.join(",") !== expected.join(",")) return renderPanes(container);
+
+ wrap.style.gridTemplateColumns = buildGrid();
+
+ for (const pane of state.layout.panes) {
+ const ref = paneRefs.get(pane.id);
+ if (!ref || ref.kind !== paneKind(pane)) return renderPanes(container);
+ const cell = wrap.querySelector(`[data-pane-id="${pane.id}"]`);
+ if (cell) {
+ const label = cell.querySelector(".pane-label");
+ if (label) label.textContent = paneLabel(pane);
+ }
+ if (pane.tabId === null) updateLocalPane(ref.bodyEl);
+ else { const tab = state.tabs.find((t) => t.id === pane.tabId); if (tab) updateRemotePane(ref.bodyEl, tab); }
+ }
+}
+
+// ── Drag & Drop: tab bar → pane ─────────────────────────────────────────
+
+/* Tab bar tabs become draggable — set data "tab-id" on dragstart. Pane cells
+ get visual drop zones (left/right/top/bottom/center), but two rules keep
+ it from feeling random:
+ 1. The pane already showing the dragged tab never offers itself as a
+ target -- there's nowhere sensible to put a tab inside its own pane.
+ 2. Every other pane needs a beat of sustained hover (HOVER_OPEN_DELAY)
+ before it "opens" as a drop target. Zones appearing the instant the
+ pointer crosses into a pane read as jumpy; the pause makes hovering
+ read as an intentional choice instead. */
+
+let activeZone = null; // "-" of the currently shown zone overlay
+let holdTimer = null; // pending "open" timer for the pane below
+let holdPaneId = null; // pane the hold timer is counting for
+let openPaneId = null; // pane that passed the hold and is now a live drop target
+
+function computeZone(cell, clientX, clientY) {
+ const rect = cell.getBoundingClientRect();
+ const x = (clientX - rect.left) / rect.width;
+ const y = (clientY - rect.top) / rect.height;
+ if (x < 0.22) return "left";
+ if (x > 0.78) return "right";
+ if (y < 0.22) return "top";
+ if (y > 0.78) return "bottom";
+ return "center";
+}
+
+function showZone(cell, zone) {
+ const key = `${cell.dataset.paneId}-${zone}`;
+ if (activeZone === key) return;
+ document.querySelectorAll(".pane-cell.drop-active").forEach((c) => {
+ if (c !== cell) {
+ c.classList.remove("drop-active");
+ delete c.dataset.dropZone;
+ }
+ });
+ activeZone = key;
+ cell.classList.add("drop-active");
+ cell.dataset.dropZone = zone;
+}
+
+function clearHold() {
+ clearTimeout(holdTimer);
+ holdTimer = null;
+ holdPaneId = null;
+}
+
+function stopDropHighlight() {
+ document.querySelectorAll(".pane-cell").forEach((c) => {
+ c.classList.remove("drop-active", "drop-pending");
+ delete c.dataset.dropZone;
+ });
+ activeZone = null;
+}
+
+function resetPaneDrag() {
+ clearHold();
+ openPaneId = null;
+ stopDropHighlight();
+}
+
+function onPaneDragOver(e) {
+ if (!e.dataTransfer.types.includes("tab-id")) return;
+ const cell = e.currentTarget;
+ const paneId = cell.dataset.paneId;
+ const pane = state.layout.panes.find((p) => p.id === paneId);
+
+ // Dragging a tab over the pane that already shows it -- never a valid
+ // target. Stop the event here so it doesn't bubble to the grid wrap's
+ // unconditional preventDefault(), which would otherwise still allow a
+ // drop (routed to the "append at end" handler) at this pointer position.
+ if (pane && pane.tabId === getDraggedTabId()) {
+ e.stopPropagation();
+ return;
+ }
+
+ e.preventDefault();
+ e.stopPropagation();
+ e.dataTransfer.dropEffect = "move";
+
+ if (openPaneId === paneId) {
+ showZone(cell, computeZone(cell, e.clientX, e.clientY));
+ return;
+ }
+
+ if (holdPaneId !== paneId) {
+ clearHold();
+ holdPaneId = paneId;
+ cell.classList.add("drop-pending");
+ holdTimer = setTimeout(() => {
+ holdTimer = null;
+ cell.classList.remove("drop-pending");
+ openPaneId = paneId;
+ showZone(cell, computeZone(cell, e.clientX, e.clientY));
+ }, HOVER_OPEN_DELAY);
+ }
+}
+
+function onPaneDragLeave(e) {
+ const cell = e.currentTarget;
+ if (cell.contains(e.relatedTarget)) return;
+ cell.classList.remove("drop-pending");
+ if (holdPaneId === cell.dataset.paneId) clearHold();
+ if (openPaneId === cell.dataset.paneId) {
+ openPaneId = null;
+ cell.classList.remove("drop-active");
+ delete cell.dataset.dropZone;
+ activeZone = null;
+ }
+}
+
+function onPaneDrop(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ const tabId = e.dataTransfer.getData("tab-id");
+ const cell = e.currentTarget;
+ const paneId = cell.dataset.paneId;
+ const wasOpen = openPaneId === paneId;
+ const zone = cell.dataset.dropZone || "center";
+ resetPaneDrag();
+ if (!tabId || !wasOpen) return; // released before this pane "opened" -- ignore
+
+ const idx = state.layout.panes.findIndex((p) => p.id === paneId);
+ if (idx === -1) return;
+ const tid = parsedTabId(tabId);
+
+ switch (zone) {
+ case "left": addPane(tid, idx); break;
+ case "right": addPane(tid, idx + 1); break;
+ case "top": addPane(tid, idx + 1); break; // in flat layout, left/right suffices
+ case "bottom": addPane(tid, idx + 1); break; // top/bottom = same as right
+ case "center": // replace this pane (but don't add duplicate)
+ if (!state.layout.panes.some((p) => p.tabId === tid && p.id !== paneId)) {
+ state.layout.panes[idx].tabId = tid;
+ }
+ break;
+ }
+ notify();
+}
+
+// A drag can end (dropped, cancelled, Escaped) outside every pane cell --
+// clean up hold/zone state unconditionally so it never gets stuck.
+window.addEventListener("dragend", resetPaneDrag);
+
+// ── Header drag (reorder) ───────────────────────────────────────────────
+
+let headerDragId = null;
+function onHeaderDragStart(e) {
+ headerDragId = e.currentTarget.dataset.paneId;
+ e.dataTransfer.effectAllowed = "move";
+ e.dataTransfer.setData("text/plain", headerDragId);
+ e.target.closest(".pane-cell")?.classList.add("pane-dragging");
+}
+function onHeaderDragEnd(e) {
+ e.target.closest(".pane-cell")?.classList.remove("pane-dragging");
+ stopDropHighlight();
+ headerDragId = null;
+}
+
+// ── Helpers ─────────────────────────────────────────────────────────────
+
+function parsedTabId(raw) {
+ return raw === "local" ? null : raw;
+}
+
+function addPane(tabId, index) {
+ // If this tab is already in another pane, remove it
+ const existing = state.layout.panes.findIndex((p) => p.tabId === tabId);
+ if (existing !== -1) {
+ state.layout.panes.splice(existing, 1);
+ if (existing < index) index--;
+ }
+ state.layout.panes.splice(index, 0, { id: `pane-${Date.now()}`, tabId });
+}
+
+function closePane(paneId) {
+ if (state.layout.panes.length <= 1) return;
+ state.layout.panes = state.layout.panes.filter((p) => p.id !== paneId);
+ notify();
+}
+
+// ── Public API: open a tab in a pane from outside ───────────────────────
+export function openInPane(tabId) {
+ // If already visible, do nothing (it's already in some pane)
+ if (state.layout.panes.some((p) => p.tabId === tabId)) return;
+
+ // Replace the first pane (single-pane UX — click = switch, not split)
+ // Splitting only happens via drag-and-drop into edge zones.
+ state.layout.panes[0].tabId = tabId;
+ notify();
+}
diff --git a/frontend/js/components/queuePanel.js b/frontend/js/components/queuePanel.js
new file mode 100644
index 0000000..2215202
--- /dev/null
+++ b/frontend/js/components/queuePanel.js
@@ -0,0 +1,130 @@
+import { state, notify } from "../store.js";
+import { t } from "../i18n.js";
+import { iconMarkup } from "../icons.js";
+import { formatSize, taskStateKind, taskStateDetail, progressPct } from "../format.js";
+import * as ipc from "../ipc.js";
+import { escapeHtml } from "../dom.js";
+
+const STATE_LABEL_KEY = {
+ queued: "queue.stateQueued",
+ completed: "queue.stateComplete",
+ failed: "queue.stateFailed",
+ paused: "queue.statePaused",
+ cancelled: "queue.stateCancelled",
+ retrying: "queue.stateRetrying",
+};
+
+function stateBadge(task) {
+ const kind = taskStateKind(task.state);
+ if (kind === "running") {
+ if (task.speed) return { text: `${formatSize(task.speed)}/s`, cls: "text-green" };
+ const verb = task.kind === "upload" ? "queue.stateUploading" : "queue.stateDownloading";
+ return { text: t(verb), cls: "text-accent" };
+ }
+ const cls = { completed: "text-green", failed: "text-red", paused: "text-yellow" }[kind] ?? "text-hint";
+ return { text: t(STATE_LABEL_KEY[kind] ?? "queue.stateQueued"), cls };
+}
+
+function taskRow(task) {
+ const row = document.createElement("div");
+ row.className = "queue-task";
+ const kind = taskStateKind(task.state);
+ const pct = progressPct(task);
+ const badge = stateBadge(task);
+ const err = kind === "failed" ? taskStateDetail(task.state) : "";
+
+ row.innerHTML = `
+ ${iconMarkup(task.kind === "upload" ? "upload" : "download", 15)}
+ ${escapeHtml(task.fileName)}
+
+ ${pct.toFixed(0)}%
+ ${badge.text}
+
+ `;
+
+ const actions = row.querySelector('[data-role="actions"]');
+ if (kind === "running") {
+ actions.appendChild(iconActionBtn("pauseCircle", () => ipc.pauseTask(task.id)));
+ actions.appendChild(iconActionBtn("closeCircle", () => ipc.cancelTask(task.id)));
+ } else if (kind === "paused" || kind === "queued") {
+ actions.appendChild(iconActionBtn("playCircle", () => ipc.resumeTask(task.id)));
+ actions.appendChild(iconActionBtn("closeCircle", () => ipc.cancelTask(task.id)));
+ } else {
+ actions.appendChild(iconActionBtn("closeCircle", () => ipc.removeTask(task.id)));
+ }
+
+ return row;
+}
+
+function iconActionBtn(icon, onClick) {
+ const btn = document.createElement("button");
+ btn.type = "button";
+ btn.className = "btn icon-btn btn-ghost";
+ btn.style.width = "22px";
+ btn.style.height = "22px";
+ btn.innerHTML = iconMarkup(icon, 13);
+ btn.addEventListener("click", onClick);
+ return btn;
+}
+
+let lastSig = null;
+
+export function renderQueuePanel(container) {
+ const tasks = state.queueTasks;
+ const pending = tasks.filter((tk) => ["running", "queued"].includes(taskStateKind(tk.state)));
+ const n = pending.length > 0 ? pending.length : tasks.length;
+ const expanded = state.showQueue && tasks.length > 0;
+
+ container.classList.toggle("expanded", expanded);
+
+ const aggSpeed = tasks
+ .filter((tk) => taskStateKind(tk.state) === "running")
+ .reduce((sum, tk) => sum + (tk.speed ?? 0), 0);
+ const done = tasks.filter((tk) => taskStateKind(tk.state) === "completed").length;
+ const failed = tasks.filter((tk) => taskStateKind(tk.state) === "failed").length;
+
+ let rightHtml = "";
+ if (aggSpeed > 0) {
+ rightHtml = `${formatSize(aggSpeed)}/s`;
+ } else if (tasks.length > 0) {
+ rightHtml = `${t("queue.doneSuffix", { done, total: tasks.length })}`;
+ if (failed > 0) rightHtml += `${t("queue.failedSuffix", { n: failed })}`;
+ }
+
+ container.innerHTML = `
+
+
+ `;
+
+ container.querySelector('[data-role="header"]').addEventListener("click", () => {
+ state.showQueue = !state.showQueue;
+ notify();
+ });
+
+ const list = container.querySelector('[data-role="list"]');
+ if (tasks.length === 0) {
+ list.innerHTML = `${t("queue.empty")}
`;
+ } else {
+ for (const task of tasks) list.appendChild(taskRow(task));
+ }
+
+ lastSig = computeSig();
+}
+
+function computeSig() {
+ return JSON.stringify([
+ state.showQueue,
+ state.queueTasks.map((tk) => [tk.id, tk.transferredBytes, tk.speed, JSON.stringify(tk.state)]),
+ ]);
+}
+
+export function updateQueuePanelIfNeeded(container) {
+ if (computeSig() === lastSig) return;
+ renderQueuePanel(container);
+}
+
+const escapeAttr = escapeHtml;
diff --git a/frontend/js/components/remotePane.js b/frontend/js/components/remotePane.js
new file mode 100644
index 0000000..64dd32c
--- /dev/null
+++ b/frontend/js/components/remotePane.js
@@ -0,0 +1,145 @@
+import { state, notify } from "../store.js";
+import { t } from "../i18n.js";
+import { iconMarkup } from "../icons.js";
+import { formatSize } from "../format.js";
+import { renderFileTable } from "./fileTable.js";
+import { renderBreadcrumbs } from "./breadcrumbs.js";
+import { makeDropTarget } from "../dnd.js";
+import { openRename, openDelete } from "./opDialogs.js";
+import {
+ navigateRemote,
+ openRemoteEntry,
+ handleDropOnRemote,
+ refreshRemote,
+ queueDownload,
+ queueDownloadMany,
+} from "../fsActions.js";
+
+const STATUS_ICON = { connected: "●", connecting: "◐", error: "×", disconnected: "○" };
+const STATUS_CLASS = { connected: "connected", connecting: "connecting", error: "error", disconnected: "disconnected" };
+
+export function renderRemotePane(container, tab) {
+ container.innerHTML = `
+
+
${t("panels.remoteLabel", { host: tab.params.host })}
+
${STATUS_ICON[tab.status] ?? "○"}
+
+
+
+
+
+ `;
+
+ container.querySelector('[data-action="refresh"]').addEventListener("click", () => {
+ if (!tab.loading) refreshRemote(tab);
+ });
+
+ makeDropTarget(container, {
+ onDrop: (payload) => handleDropOnRemote(tab, payload, tab.remotePath),
+ onHoverChange: (hover) => container.classList.toggle("drag-over", hover),
+ });
+
+ updateRemotePane(container, tab);
+}
+
+export function updateRemotePane(container, tab) {
+ renderBreadcrumbs(container.querySelector('[data-role="breadcrumbs"]'), tab.remotePath || "/", (path) =>
+ navigateRemote(tab, path),
+ );
+
+ container.querySelector('[data-role="loading"]').innerHTML = tab.loading
+ ? `${t("panels.loading")}`
+ : "";
+
+ renderFileTable(container.querySelector('[data-role="table"]'), {
+ entries: tab.remoteEntries,
+ selected: tab.remoteSelected,
+ anchor: tab.remoteSelectAnchor,
+ sort: tab.sort,
+ onSort: (next) => {
+ tab.sort = next;
+ notify();
+ },
+ onSelect: (names, anchor) => {
+ tab.remoteSelected = names;
+ tab.remoteSelectAnchor = anchor;
+ state.activePane = "remote";
+ notify();
+ },
+ onOpen: (name) => openRemoteEntry(tab, name),
+ onHoverOpen: (entry) => openRemoteEntry(tab, entry.name),
+ dragPayload: (entry) => {
+ if (entry.name === ".." || tab.status !== "connected") return null;
+ const group =
+ tab.remoteSelected.includes(entry.name) && tab.remoteSelected.length > 1
+ ? tab.remoteEntries.filter((e) => tab.remoteSelected.includes(e.name))
+ : [entry];
+ return {
+ source: "remote",
+ connectionId: tab.id,
+ items: group.map((e) => ({ path: e.path, name: e.name, kind: e.kind })),
+ };
+ },
+ onDropOnEntry: (entry, payload) => handleDropOnRemote(tab, payload, entry.path),
+ contextMenuItems: (entry, selectedEntries) => {
+ if (selectedEntries.length > 1) {
+ const files = selectedEntries.filter((e) => e.kind === "file");
+ return [
+ {
+ label: t("common.delete") + ` (${selectedEntries.length})`,
+ icon: "trash",
+ danger: true,
+ onClick: () => openDeleteRemote(selectedEntries),
+ },
+ ...(files.length > 0
+ ? [
+ "sep",
+ {
+ label: t("panels.downloadToLocal") + ` (${files.length})`,
+ icon: "download",
+ onClick: () => queueDownloadMany(tab, files),
+ },
+ ]
+ : []),
+ ];
+ }
+ return [
+ { label: t("common.open"), icon: "folder", onClick: () => openRemoteEntry(tab, entry.name) },
+ { label: t("common.rename"), icon: "pen", onClick: () => openRenameRemote(entry) },
+ { label: t("common.delete"), icon: "trash", danger: true, onClick: () => openDeleteRemote([entry]) },
+ "sep",
+ { label: t("common.copyPath"), icon: "copy", onClick: () => copyPath(entry.path) },
+ ...(entry.kind === "file"
+ ? [{ label: t("panels.downloadToLocal"), icon: "download", onClick: () => queueDownload(tab, entry) }]
+ : []),
+ ];
+ },
+ });
+
+ const count = tab.remoteEntries.filter((e) => e.name !== "..").length;
+ const totalSize = tab.remoteEntries.reduce((sum, e) => sum + (e.size ?? 0), 0);
+ container.querySelector('[data-role="count"]').textContent = tab.loading
+ ? t("panels.loading")
+ : t("panels.countItems", { n: count });
+ container.querySelector('[data-role="size"]').textContent = totalSize > 0 ? `(${formatSize(totalSize)})` : "";
+}
+
+function openRenameRemote(entry) {
+ state.opTarget = "remote";
+ openRename(entry.name);
+}
+function openDeleteRemote(entries) {
+ state.opTarget = "remote";
+ openDelete(entries.map((e) => e.name));
+}
+function copyPath(path) {
+ navigator.clipboard?.writeText(path);
+ state.statusMessage = t("panels.pathCopied");
+ notify();
+}
diff --git a/frontend/js/components/settingsDialog.js b/frontend/js/components/settingsDialog.js
new file mode 100644
index 0000000..4d90902
--- /dev/null
+++ b/frontend/js/components/settingsDialog.js
@@ -0,0 +1,496 @@
+// Settings dialog — nav list left, section content right. Mirrors the old
+// src/ui/app/settings/{general,connections,transfers,about}.rs sections
+// (Security folded in here too). Unlike connectDialog/opDialogs there are no
+// free-text inputs in here, so the whole content pane can just be rebuilt
+// from scratch on every render -- no focus/caret state to preserve.
+import { state, notify } from "../store.js";
+import { t } from "../i18n.js";
+import { iconMarkup } from "../icons.js";
+import { escapeHtml } from "../dom.js";
+import {
+ setConfirmBeforeDelete,
+ useCurrentFolderAsDefault,
+ resetDefaultFolder,
+ setMaxConcurrent,
+ setAutoClearCompletedSecs,
+ togglePanel,
+ clearHistory,
+ deleteSite,
+ forgetPassword,
+ forgetAllPasswords,
+ revealDatabase,
+ setLanguage,
+ setTheme,
+} from "../settingsActions.js";
+
+const LANG_OPTIONS = [
+ ["en", "English"],
+ ["ru", "Русский"],
+ ["es", "Español"],
+ ["fr", "Français"],
+ ["de", "Deutsch"],
+ ["it", "Italiano"],
+ ["pt", "Português"],
+ ["pl", "Polski"],
+ ["zh", "简体中文"],
+ ["ja", "日本語"],
+ ["ko", "한국어"],
+ ["tr", "Türkçe"],
+];
+
+const SECTIONS = [
+ { id: "general", icon: "settings", labelKey: "settings.navGeneral" },
+ { id: "appearance", icon: "monitor", labelKey: "settings.navAppearance" },
+ { id: "connections", icon: "serverSquare", labelKey: "settings.navConnections" },
+ { id: "history", icon: "history", labelKey: "settings.navHistory" },
+ { id: "security", icon: "shieldKeyhole", labelKey: "settings.navSecurity" },
+ { id: "transfers", icon: "clock", labelKey: "settings.navTransfers" },
+ { id: "about", icon: "documentText", labelKey: "settings.navAbout" },
+];
+
+let overlayEl = null;
+let activeSection = "general";
+let historyClearConfirm = false;
+
+export function openSettings() {
+ activeSection = "general";
+ historyClearConfirm = false;
+ state.showSettingsDialog = true;
+ notify();
+}
+
+function close() {
+ state.showSettingsDialog = false;
+ notify();
+}
+
+function switchSection(id) {
+ activeSection = id;
+ historyClearConfirm = false;
+ renderContent();
+ renderNav();
+}
+
+// A plain , not a