From cffcec72b84523b75e5a0b434bb46a986f70ffdf Mon Sep 17 00:00:00 2001 From: grendervill Date: Tue, 22 Sep 2026 21:46:01 +0300 Subject: [PATCH] =?UTF-8?q?feat(desktop):=20=D0=BE=D0=B1=D1=91=D1=80=D1=82?= =?UTF-8?q?=D0=BA=D0=B0=20Tauri=202=20=D0=B2=D0=BE=D0=BA=D1=80=D1=83=D0=B3?= =?UTF-8?q?=20=D0=B2=D0=B5=D0=B1-=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Первый инкремент Фазы 6 (docs/client-tauri.md): окно с тем же веб-клиентом (по умолчанию https://gl.mhspx.su, адрес настраивается), трей с меню и индикатором непрочитанных, нативные уведомления, глобальный push-to-talk и переключение микрофона/deafen, автозапуск, single-instance, сохранение геометрии окна, deep links glchat://…, автообновление по подписанному манифесту. Связь страницы с обёрткой — через платформенный адаптер (web/src/lib/platform.ts) и минимальный типизированный набор команд; в веб-клиенте появились системные уведомления об упоминаниях и личных сообщениях и переключатель в настройках. В web/src/stores/gateway.ts вместе с вызовом уведомления лежат правки по дефектам realtime (READY и сессии) из параллельной волны: файл коммитится целиком по договорённости с координатором. --- desktop/src-tauri/.gitignore | 4 + desktop/src-tauri/Cargo.lock | 6098 +++++++++++++++++ desktop/src-tauri/Cargo.toml | 41 + desktop/src-tauri/build.rs | 3 + .../src-tauri/capabilities/instance-page.json | 10 + .../capabilities/local-settings.json | 7 + desktop/src-tauri/icons/128x128.png | Bin 0 -> 9980 bytes desktop/src-tauri/icons/128x128@2x.png | Bin 0 -> 18607 bytes desktop/src-tauri/icons/32x32.png | Bin 0 -> 1442 bytes desktop/src-tauri/icons/64x64.png | Bin 0 -> 3511 bytes desktop/src-tauri/icons/Square107x107Logo.png | Bin 0 -> 7418 bytes desktop/src-tauri/icons/Square142x142Logo.png | Bin 0 -> 11212 bytes desktop/src-tauri/icons/Square150x150Logo.png | Bin 0 -> 11892 bytes desktop/src-tauri/icons/Square284x284Logo.png | Bin 0 -> 22636 bytes desktop/src-tauri/icons/Square30x30Logo.png | Bin 0 -> 1176 bytes desktop/src-tauri/icons/Square310x310Logo.png | Bin 0 -> 25100 bytes desktop/src-tauri/icons/Square44x44Logo.png | Bin 0 -> 1955 bytes desktop/src-tauri/icons/Square71x71Logo.png | Bin 0 -> 3882 bytes desktop/src-tauri/icons/Square89x89Logo.png | Bin 0 -> 5111 bytes desktop/src-tauri/icons/StoreLogo.png | Bin 0 -> 2444 bytes desktop/src-tauri/icons/icon.icns | Bin 0 -> 152014 bytes desktop/src-tauri/icons/icon.ico | Bin 0 -> 32665 bytes desktop/src-tauri/icons/icon.png | Bin 0 -> 4251 bytes desktop/src-tauri/src/autostart.rs | 25 + desktop/src-tauri/src/bridge.rs | 68 + desktop/src-tauri/src/commands.rs | 128 + desktop/src-tauri/src/deeplink.rs | 47 + desktop/src-tauri/src/instance.rs | 59 + desktop/src-tauri/src/lib.rs | 243 + desktop/src-tauri/src/main.rs | 6 + desktop/src-tauri/src/notifications.rs | 68 + desktop/src-tauri/src/settings.rs | 94 + desktop/src-tauri/src/shortcuts.rs | 67 + desktop/src-tauri/src/state.rs | 68 + desktop/src-tauri/src/tray.rs | 157 + desktop/src-tauri/src/updates.rs | 154 + desktop/src-tauri/src/window.rs | 135 + desktop/src-tauri/tauri.conf.json | 56 + desktop/src-tauri/ui/index.html | 90 + desktop/src-tauri/ui/settings.css | 154 + desktop/src-tauri/ui/settings.js | 165 + web/src/App.tsx | 3 + web/src/components/DesktopBridge.tsx | 79 + web/src/i18n/locales/en.json | 7 +- web/src/i18n/locales/ru.json | 7 +- web/src/lib/desktopNotifications.ts | 114 + web/src/lib/platform.ts | 199 + .../settings/NotificationsSettingsSection.tsx | 49 +- web/src/stores/gateway.ts | 48 +- web/tests/desktopNotifications.test.ts | 126 + web/tests/platform.test.ts | 86 + web/tests/settings.test.tsx | 10 +- 52 files changed, 8659 insertions(+), 16 deletions(-) create mode 100644 desktop/src-tauri/.gitignore create mode 100644 desktop/src-tauri/Cargo.lock create mode 100644 desktop/src-tauri/Cargo.toml create mode 100644 desktop/src-tauri/build.rs create mode 100644 desktop/src-tauri/capabilities/instance-page.json create mode 100644 desktop/src-tauri/capabilities/local-settings.json create mode 100644 desktop/src-tauri/icons/128x128.png create mode 100644 desktop/src-tauri/icons/128x128@2x.png create mode 100644 desktop/src-tauri/icons/32x32.png create mode 100644 desktop/src-tauri/icons/64x64.png create mode 100644 desktop/src-tauri/icons/Square107x107Logo.png create mode 100644 desktop/src-tauri/icons/Square142x142Logo.png create mode 100644 desktop/src-tauri/icons/Square150x150Logo.png create mode 100644 desktop/src-tauri/icons/Square284x284Logo.png create mode 100644 desktop/src-tauri/icons/Square30x30Logo.png create mode 100644 desktop/src-tauri/icons/Square310x310Logo.png create mode 100644 desktop/src-tauri/icons/Square44x44Logo.png create mode 100644 desktop/src-tauri/icons/Square71x71Logo.png create mode 100644 desktop/src-tauri/icons/Square89x89Logo.png create mode 100644 desktop/src-tauri/icons/StoreLogo.png create mode 100644 desktop/src-tauri/icons/icon.icns create mode 100644 desktop/src-tauri/icons/icon.ico create mode 100644 desktop/src-tauri/icons/icon.png create mode 100644 desktop/src-tauri/src/autostart.rs create mode 100644 desktop/src-tauri/src/bridge.rs create mode 100644 desktop/src-tauri/src/commands.rs create mode 100644 desktop/src-tauri/src/deeplink.rs create mode 100644 desktop/src-tauri/src/instance.rs create mode 100644 desktop/src-tauri/src/lib.rs create mode 100644 desktop/src-tauri/src/main.rs create mode 100644 desktop/src-tauri/src/notifications.rs create mode 100644 desktop/src-tauri/src/settings.rs create mode 100644 desktop/src-tauri/src/shortcuts.rs create mode 100644 desktop/src-tauri/src/state.rs create mode 100644 desktop/src-tauri/src/tray.rs create mode 100644 desktop/src-tauri/src/updates.rs create mode 100644 desktop/src-tauri/src/window.rs create mode 100644 desktop/src-tauri/tauri.conf.json create mode 100644 desktop/src-tauri/ui/index.html create mode 100644 desktop/src-tauri/ui/settings.css create mode 100644 desktop/src-tauri/ui/settings.js create mode 100644 web/src/components/DesktopBridge.tsx create mode 100644 web/src/lib/desktopNotifications.ts create mode 100644 web/src/lib/platform.ts create mode 100644 web/tests/desktopNotifications.test.ts create mode 100644 web/tests/platform.test.ts diff --git a/desktop/src-tauri/.gitignore b/desktop/src-tauri/.gitignore new file mode 100644 index 0000000..502406b --- /dev/null +++ b/desktop/src-tauri/.gitignore @@ -0,0 +1,4 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ +/gen/schemas diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock new file mode 100644 index 0000000..d8629ba --- /dev/null +++ b/desktop/src-tauri/Cargo.lock @@ -0,0 +1,6098 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[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.119", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "atk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "auto-launch" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f012b8cc0c850f34117ec8252a44418f2e34a2cf501de89e29b241ae5f79471" +dependencies = [ + "dirs 4.0.0", + "thiserror 1.0.69", + "winreg 0.10.1", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" +dependencies = [ + "serde_core", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "blocking" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "brotli" +version = "8.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +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" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" + +[[package]] +name = "byteorder" +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.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.13.2", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror 1.0.69", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "camino" +version = "1.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.20", +] + +[[package]] +name = "cargo_toml" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" +dependencies = [ + "serde", + "toml 0.9.12+spec-1.1.0", +] + +[[package]] +name = "cc" +version = "1.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54413ede23c2daf518f35156dfde027feb2374004d63bd497f983c8db9c0e313" +dependencies = [ + "find-msvc-tools", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link 0.2.1", +] + +[[package]] +name = "combine" +version = "4.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "cookie" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87" +dependencies = [ + "time", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.13.2", + "core-foundation 0.10.1", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.13.2", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ctor" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 3.0.6", +] + +[[package]] +name = "darling_macro" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" +dependencies = [ + "darling_core", + "quote", + "syn 3.0.6", +] + +[[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 = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.20", +] + +[[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_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[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", + "rustc_version", + "syn 2.0.119", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys 0.5.0", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users 0.4.6", + "winapi", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.5.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.2", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "dlopen2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "dom_query" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" +dependencies = [ + "bit-set", + "cssparser", + "foldhash", + "html5ever", + "precomputed-hash", + "selectors", + "tendril", +] + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +dependencies = [ + "serde", +] + +[[package]] +name = "dtoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dtor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = [ + "cc", + "memchr", + "rustc_version", + "toml 1.1.6+spec-1.1.0", + "vswhom", + "winreg 0.55.0", +] + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "equivalent" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25905e51abafe4dcea6c15fec58c57b601cdbd0ee53d22ea1d3016c587d39b" + +[[package]] +name = "flate2" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +dependencies = [ + "crc32fast", + "miniz_oxide 0.9.1", + "zlib-rs", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[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.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-executor" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "futures-sink" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gdk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix", + "windows-link 0.2.1", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glchat-desktop" +version = "0.1.0" +dependencies = [ + "log", + "serde", + "serde_json", + "tauri", + "tauri-build", + "tauri-plugin-autostart", + "tauri-plugin-deep-link", + "tauri-plugin-dialog", + "tauri-plugin-global-shortcut", + "tauri-plugin-log", + "tauri-plugin-notification", + "tauri-plugin-opener", + "tauri-plugin-single-instance", + "tauri-plugin-store", + "tauri-plugin-updater", + "tauri-plugin-window-state", + "url", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.13.2", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "global-hotkey" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c386b0a4a70cb2d39fffd74480f985b6f0bfbcb934b6a6b6b7e630e448f242e" +dependencies = [ + "crossbeam-channel", + "keyboard-types", + "objc2", + "objc2-app-kit", + "once_cell", + "serde", + "thiserror 2.0.20", + "windows-sys 0.59.0", + "x11rb", + "xkeysym", +] + +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html5ever" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" +dependencies = [ + "log", + "markup5ever", +] + +[[package]] +name = "http" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" +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.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[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", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry 0.6.1", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +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.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" + +[[package]] +name = "icu_properties" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" + +[[package]] +name = "icu_provider" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png 0.18.1", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + +[[package]] +name = "ipnet" +version = "2.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0" + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jiff" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "windows-link 0.2.1", +] + +[[package]] +name = "jiff-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" +dependencies = [ + "defmt", + "log", +] + +[[package]] +name = "jiff-static" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + +[[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]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.20", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "js-sys" +version = "0.3.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e" +dependencies = [ + "cfg-if", + "futures-util", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.13.2", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libdbus-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" +dependencies = [ + "pkg-config", +] + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libredox" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" +dependencies = [ + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "mac-notification-sys" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd604973958ddcc11b561193c0fb96ba146506ef2f231ef2e7c35fd2cbc9beca" +dependencies = [ + "cc", + "log", + "objc2", + "objc2-foundation", + "time", + "uuid", +] + +[[package]] +name = "markup5ever" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" +dependencies = [ + "log", + "tendril", + "web_atoms", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minisign-verify" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f9645cb765ea72b8111f36c522475d2daa0d22c957a9826437e97534bc4e9e" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" +dependencies = [ + "libc", + "wasi", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "once_cell", + "png 0.18.1", + "serde", + "thiserror 2.0.20", + "windows-sys 0.61.2", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.13.2", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "notify-rust" +version = "4.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b4c1b4f2aa9f25f63a7a49d3dd0ed567b3670da15330a66b29434be899b891" +dependencies = [ + "futures-lite", + "log", + "mac-notification-sys", + "serde", + "tauri-winrt-notification", + "zbus", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", + "objc2-exception-helper", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.13.2", + "block2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.13.2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.2", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.13.2", + "dispatch2", + "objc2", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "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.2", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-exception-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" +dependencies = [ + "cc", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.2", + "block2", + "libc", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.13.2", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-osa-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f112d1746737b0da274ef79a23aac283376f335f4095a083a267a082f21db0c0" +dependencies = [ + "bitflags 2.13.2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.13.2", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-web-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" +dependencies = [ + "bitflags 2.13.2", + "block2", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "open" +version = "5.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa576c76302b7b808eecc68061e67336c47833ef9d22caa74dda10fa9675eebc" +dependencies = [ + "dunce", + "is-wsl", + "libc", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "osakit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b" +dependencies = [ + "objc2", + "objc2-foundation", + "objc2-osa-kit", + "serde", + "serde_json", + "thiserror 2.0.20", +] + +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] +name = "plist" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896bade328c13f7042a297ea5ac5b0951f6cf989dea5f32c2fd98da398195cb" +dependencies = [ + "base64 0.23.1", + "indexmap 2.14.2", + "quick-xml", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.15+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + +[[package]] +name = "quick-xml" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[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", +] + +[[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 = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "redox_users" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" +dependencies = [ + "libredox", + "thiserror 2.0.20", +] + +[[package]] +name = "ref-cast" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reqwest" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" +dependencies = [ + "base64 0.23.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "rfd" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672" +dependencies = [ + "block2", + "dispatch2", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.60.2", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rust-ini" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" +dependencies = [ + "bitflags 2.13.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni 0.22.4", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.103.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +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.119", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.13.2", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" +dependencies = [ + "bitflags 2.13.2", + "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" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "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.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[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.119", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_with" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "935177bb8c0cd8ca1a4e6d1a2ac8988bea69cab4f9d3a31311e012ad27868ea4" +dependencies = [ + "base64 0.23.1", + "bs58", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.2", + "jiff", + "schemars 0.9.0", + "schemars 1.2.2", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d607aa01a3cb0ad757d6fd216136910db3c97b102fe686585689615a02dbcdc" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[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.119", +] + +[[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]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" + +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "softbuffer" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" +dependencies = [ + "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]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "string_cache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "string_cache_codegen" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "swift-rs" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e45c444e496845d3f2a351146bff59aae4975b2280238df1dfaa0c7d1846f38e" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "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.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.13.2", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "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.2", + "block2", + "core-foundation 0.10.1", + "core-graphics", + "crossbeam-channel", + "dbus", + "dispatch2", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni 0.21.1", + "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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7eeb6d99155545da6150a1795945f16ac9c178deb2a5f2e74d776107bd5849" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tar" +version = "0.4.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa5bacdb9bbad5954af3d1bd6cf6ae9192cab1b2e270f4a07f904610b9e85f4" +dependencies = [ + "anyhow", + "bytes", + "cookie", + "dirs 6.0.0", + "dunce", + "embed_plist", + "getrandom 0.3.4", + "glob", + "gtk", + "heck 0.5.0", + "http", + "image", + "jni 0.21.1", + "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.20", + "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.119", + "tauri-utils", + "thiserror 2.0.20", + "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.119", + "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-autostart" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459383cebc193cdd03d1ba4acc40f2c408a7abce419d64bdcd2d745bc2886f70" +dependencies = [ + "auto-launch", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.20", +] + +[[package]] +name = "tauri-plugin-deep-link" +version = "2.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d489b8ecceae1cd09f6e1f7606f2095ac721cc8d54cf2f0e6bb377cc52cff6" +dependencies = [ + "dunce", + "plist", + "rust-ini", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-utils", + "thiserror 2.0.20", + "tracing", + "url", + "windows-registry 0.5.3", + "windows-result 0.3.4", +] + +[[package]] +name = "tauri-plugin-dialog" +version = "2.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61854a36651aa48381e5e209f69a01273b77f3f9f91f0c430b1b98d33bd47229" +dependencies = [ + "log", + "raw-window-handle", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror 2.0.20", + "url", +] + +[[package]] +name = "tauri-plugin-fs" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de22eef34fd78c0da050e748710edd50bf127e651d02ea1b2bfada1523cc5c51" +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.20", + "toml 1.1.6+spec-1.1.0", + "url", +] + +[[package]] +name = "tauri-plugin-global-shortcut" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4dd9f4c5136c09cd962da0c86dc4accd4666db2ea591cf16e6597435843bd2b" +dependencies = [ + "global-hotkey", + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.20", +] + +[[package]] +name = "tauri-plugin-log" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f2e3c40b77fd1eb7f8e1b6900fb036aee2da1ea2d3783c91255a82c636649d" +dependencies = [ + "android_logger", + "fern", + "log", + "objc2", + "objc2-foundation", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror 2.0.20", + "time", +] + +[[package]] +name = "tauri-plugin-notification" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad2fd40946aef810c4be9fd33a2d1b9b397cb79042b2d21c81a0a8f204354fd1" +dependencies = [ + "log", + "notify-rust", + "rand", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "thiserror 2.0.20", + "time", + "url", +] + +[[package]] +name = "tauri-plugin-opener" +version = "2.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60d60366174b745b4ef5824b8bbc1c457fd08f0ce101ff643c0a49181a9f4e91" +dependencies = [ + "dunce", + "glob", + "objc2-app-kit", + "objc2-foundation", + "open", + "schemars 0.8.22", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.20", + "url", + "windows", + "zbus", +] + +[[package]] +name = "tauri-plugin-single-instance" +version = "2.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db817fe9295e19b7d8357e900af31edb93703dd9fb6de524b007b47b6afc63b0" +dependencies = [ + "serde", + "serde_json", + "tauri", + "thiserror 2.0.20", + "tokio", + "tracing", + "windows-sys 0.60.2", + "zbus", +] + +[[package]] +name = "tauri-plugin-store" +version = "2.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c7c771d3ce796b48c6e52b2fac38087d479a3c58e0424d3850cc21db6b4a69" +dependencies = [ + "dunce", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.20", + "tokio", + "tracing", +] + +[[package]] +name = "tauri-plugin-updater" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5cad8ed5948d988e1018ecd31e27cacedbf72ce3fb972940c3e4bf51639e4b" +dependencies = [ + "base64 0.22.1", + "dirs 6.0.0", + "flate2", + "futures-util", + "http", + "infer", + "log", + "minisign-verify", + "osakit", + "percent-encoding", + "reqwest", + "rustls", + "semver", + "serde", + "serde_json", + "tar", + "tauri", + "tauri-plugin", + "tempfile", + "thiserror 2.0.20", + "time", + "tokio", + "url", + "windows-sys 0.60.2", + "zip", +] + +[[package]] +name = "tauri-plugin-window-state" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73736611e14142408d15353e21e3cca2f12a3cfb523ad0ce85999b6d2ef1a704" +dependencies = [ + "bitflags 2.13.2", + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.20", +] + +[[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 0.21.1", + "objc2", + "objc2-ui-kit", + "objc2-web-kit", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror 2.0.20", + "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 0.21.1", + "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.20", + "toml 1.1.6+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.6+spec-1.1.0", +] + +[[package]] +name = "tauri-winrt-notification" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed071c670382e85fc2f48ae706492d8c338f4f89bf72520d32f8abfe880aade" +dependencies = [ + "thiserror 2.0.20", + "windows", + "windows-version", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "tendril" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08" +dependencies = [ + "new_debug_unreachable", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl 2.0.20", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" + +[[package]] +name = "tokio" +version = "1.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c85f2c3ef0b1cd58b36682f4b17aaa995f0e5db534d85692b4903abce21f67" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "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.2", + "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.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a" +dependencies = [ + "indexmap 2.14.2", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.4", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.14.2", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.14.2", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.15+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" +dependencies = [ + "indexmap 2.14.2", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.4", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[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.2", + "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 = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tray-icon" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "045979e3f037cd18ad1cb2a419dfda133c5c29c9f3453370079f2255d46c257e" +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.20", + "windows-sys 0.61.2", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] + +[[package]] +name = "urlpattern" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" +dependencies = [ + "regex", + "serde", + "unic-ucd-ident", + "url", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" +dependencies = [ + "getrandom 0.4.3", + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef4c5d3d2cdf5c54f4231181768f5510842e350db025faf1f7163b1030ed928" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.6", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e" +dependencies = [ + "unicode-ident", +] + +[[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 = "web-sys" +version = "0.3.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbddc4a036f00ec4f18c83445bd3115cb306a91da554919a099d9222fe4a7f8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web_atoms" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8b815c1b593dc0baf78dd0f4fc8fdb2de53198fb1163738093e9a311c33fb3" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5" +dependencies = [ + "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 = "webpki-root-certs" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webview2-com" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.119", +] + +[[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.20", + "windows", + "windows-core 0.61.2", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window-vibrancy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" +dependencies = [ + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "raw-window-handle", + "windows-sys 0.59.0", + "windows-version", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "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.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-registry" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +dependencies = [ + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[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]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "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]] +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "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]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[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.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[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 0.21.1", + "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.20", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "gethostname", + "rustix", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33811428bee40dbceb6d545e95754741d17a6aef9a4849f0fd62e2ba4f412a78" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db4be7c075cb421e4b7ee645541604239bd243ba7c357511f4ff3a74b555907" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow 1.0.4", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2990635d09ade6df1868f72f8cac69a876a90981e8bd3c40b1be413f8dc88f40" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 3.0.6", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e" +dependencies = [ + "serde", + "winnow 1.0.4", + "zvariant", +] + +[[package]] +name = "zcheapstr" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1afec51604565183aeb5c54c20aeab286120d4e4460f7f76e3e8bb8c0d99473" +dependencies = [ + "serde", +] + +[[package]] +name = "zerocopy" +version = "0.8.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "zip" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" +dependencies = [ + "arbitrary", + "crc32fast", + "indexmap 2.14.2", + "memchr", +] + +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[package]] +name = "zvariant" +version = "5.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d34c27cc6cdd1f458427519dd6b8612f7b7e3f7b9a0b2355d041dda9869147" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow 1.0.4", + "zcheapstr", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864155e69b4352db0c7f374917bf45d1e0c8d17659c8b3dbf9795f3673f8c497" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 3.0.6", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad0294361a320b694a328460dc73add56c306150f5cb6bfafc44446120008a3" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 3.0.6", + "winnow 1.0.4", +] diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml new file mode 100644 index 0000000..abda125 --- /dev/null +++ b/desktop/src-tauri/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "glchat-desktop" +version = "0.1.0" +description = "glchat — desktop-обёртка вокруг веб-клиента (Tauri 2)" +authors = ["glchat"] +license = "AGPL-3.0-or-later" +repository = "https://gt.mhspx.su/grendervill/glchat" +edition = "2021" +rust-version = "1.77.2" + +[lib] +name = "glchat_desktop_lib" +crate-type = ["staticlib", "cdylib", "rlib"] + +[build-dependencies] +tauri-build = { version = "2", features = [] } + +[dependencies] +tauri = { version = "2", features = ["tray-icon", "image-png"] } +tauri-plugin-autostart = "2" +tauri-plugin-deep-link = "2" +tauri-plugin-dialog = "2" +tauri-plugin-global-shortcut = "2" +tauri-plugin-log = "2" +tauri-plugin-notification = "2" +tauri-plugin-opener = "2" +tauri-plugin-single-instance = "2" +tauri-plugin-store = "2" +tauri-plugin-updater = "2" +tauri-plugin-window-state = "2" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +log = "0.4" +url = "2" + +[profile.release] +codegen-units = 1 +lto = true +opt-level = "s" +panic = "abort" +strip = true diff --git a/desktop/src-tauri/build.rs b/desktop/src-tauri/build.rs new file mode 100644 index 0000000..795b9b7 --- /dev/null +++ b/desktop/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/desktop/src-tauri/capabilities/instance-page.json b/desktop/src-tauri/capabilities/instance-page.json new file mode 100644 index 0000000..7ae8502 --- /dev/null +++ b/desktop/src-tauri/capabilities/instance-page.json @@ -0,0 +1,10 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "instance-page", + "description": "Веб-клиент инстанса. IPC разрешён только для домена инстанса (docs/client-tauri.md §6): команды обёртки — минимальные и типизированные, плагины напрямую странице не доступны.", + "windows": ["main"], + "remote": { + "urls": ["https://gl.mhspx.su"] + }, + "permissions": ["core:default"] +} diff --git a/desktop/src-tauri/capabilities/local-settings.json b/desktop/src-tauri/capabilities/local-settings.json new file mode 100644 index 0000000..005bd11 --- /dev/null +++ b/desktop/src-tauri/capabilities/local-settings.json @@ -0,0 +1,7 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "local-settings", + "description": "Локальная страница настроек обёртки (tauri://localhost) в главном окне: команды обёртки, работа с окном и хранилищем.", + "windows": ["main"], + "permissions": ["core:default", "store:default", "dialog:default", "opener:default"] +} diff --git a/desktop/src-tauri/icons/128x128.png b/desktop/src-tauri/icons/128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..a0c01e9c88b12be92ad84652f62fdd135a4caeff GIT binary patch literal 9980 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

WWItti;w}DJp>mz9=kcv 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 L$=&gZJt^hiU5%yf literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/32x32.png b/desktop/src-tauri/icons/32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..e2609d2139884c38dba9e83060e3271b3b638ed6 GIT binary patch literal 1442 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 DcdM>T literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/Square107x107Logo.png b/desktop/src-tauri/icons/Square107x107Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bdb437d5dfd994e30cb97ccbf68c54f39519984c GIT binary patch literal 7418 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 ZQ;0o_`e5?rt4kM7URp&8EMfBfe*j(8NnHQ{ literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/Square150x150Logo.png b/desktop/src-tauri/icons/Square150x150Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2b205983d0dac98e834820d6ed860f4e12cf7cd7 GIT binary patch literal 11892 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 RbDI2%q^O)owUB<`{{vOlm;C?$ literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/Square284x284Logo.png b/desktop/src-tauri/icons/Square284x284Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1ac5ef0bc345ffab91c1254c68fc048a5dfd54e7 GIT binary patch literal 22636 zcmZ_$bx<7L7cGF|?(V_eT>=DmcXxLfoFKv7-95Mk8{FO9EjWST4sY`P?tOLtcyFqv ztEapA)ZXXx>0W!SbtY0-Q3@G>009gP3|U56Tonuqoao;d4hD1t`wnpz3{0CtMqEVQ zYyHo6#1wsv%**ZL#i}n$xlnMF-yq1yq5h)(2t>vB_6=)J2P1MfLi)tLj-&X%tBXHQ zadg+qy|egWQs1hEI^w4>sY@*RkHBv~#>F6_jK3iTK}l0eCtaRNbxp55em)3wQ~_m1 z`N}J+s(>E>HM0uto`Mh0Jy&m6!erW@4*?~-5Cjem4mHvL-TeRF{qOw$zf)-*DH>IN zR>z8a2-nt=R@#h5ljz%LOK~&hW2#I^@de+_pIr|xbxZEJj4VlRj1&-r-Zxe5y@#}f zaYtjic?o}f=6C5-x}TSfXobUvmxe|T`S(~S&Ij&v>WqH}CxkMV9!am#gpa&pG30Y* zv>B!njWkh3r&+IJ$p2`G{&*P9UcM7@$jkqTk0`&^vL79R{5m=C!`?RH$P zpVMivr|XW2C7fZrI``Dl=le@y6d62v^fxtyuW*sCKQUdl6z24k_=Wz|F0-3tac*hh z&np`z)S~E>HNeX`BJUjArxxmaDUGJr6p7CvVMvPS+^5yphYJy%p^mS@mD1zAx?K8p zc71+iw{4LrPb?^nLQ_U`LbKB=Bh{=YLR=%hznZsIXSDl?GwAElKR%MBJs4%EF-4&j zQQ(FcaN$1ZU7_hhN=D@F1P;ls<2mCc)#%`lk|I+MC{OE_GLq9Q_@ABN`Ev)$9{pA>$raURk+E>9J&jt-@G}!Tvhii7Qc7+9&)E{Elq*I8W^$`d zCMNwR@PFuQisa{fw?00G4g!C5D&6xNIx-91(Lod`?dr=w9bn)z2S6mz;lQBR+=r5( zs5GdSY~LDlX8BR+pQ?De|w=47*) zRvLZLnX1LbM41TMXM@YSTrd4S9IMza%HH8?ApDF@_09ojhl@@geJal#nvZ=W7O~Lp z_c!*Fyj-naOh*khBAJmb%4h;mrk633%P^0sI@o?*>Uw#bGw-=_KSS_yFyL+QVoj9{ zZ_4EhHBp)iWm8`50J-ND5HtGWT283Nx0_|la~AuBwqcYmGtM5>l(}?X8O`ciE<_Yc ze!VI!>W3VFWV{dz{fR5{VwtV*&Dt?x`oP5JL?G_Q-{qjy%Av}7{O3RgeLJA+cvLlWld7%&vOo?0ZVR`0 zDf==7;Zd6+c$(L3L?POoT!MLJ_tyM6hJr-D&f@ig!_1`L#x&YeVrQFb+_SdmVoc^V zF3-DERpjYVbZygt@R(U6c~m=<<-M5PNQF^@E(obIzH1#@OzW<_@4RB%jII*1%=EZn zoOCCjfPCH&x2rQ*nkH%N7i|oRWBJ9(!Tfcd?uM`#rruY1-Wo|xBY8@8Tz4tKk>*N;Zkua$+LaIl~mJXIoZy}Y!q@6IO<&X!H}zKuEd{cDimT*=_+!)-!SM_)VUgCIY(;c9uHA74MMO>*OauwhR9JA;X`+3B z9?SA%z>W~=1aB#6m*G>@&rb2rxI7xpK5dL2%BCY|-;l>mK5?!_ZW)#lN1>taE<74t zlZMyZufVBVdI~s2kX4*sE(MQnOBRlfMb+WP9%%$-83ENosnh(}`!11QKyHQ3Wkz}4 zqH7(RW!Ll zc~UrXePAR#kh>6zqy!FQqhpZ`7w6t0j9yPQ7lwp z=PHzaIXcaN6*fB^@{(!3WyaPQ2&YXBWJ^|mzefzs@Xf$F&S$#6>MaUFRAtoM%y9MY z?4Z&u@mK{a)LU2krpw~vqT`_YA3t=Yu3pnnebf)N89e#b=af)!YCJw_6mi#@^KU8i z9d3FUy%=fu8fgb>Vr>GBCUvH!ia?_lx76o9zr7>`c+P`Xm->94zPvaMor3`H1S^tR z#9Ri;q(+(1rUl#Ha|`ADaG!6J7H5T>;v^lcIzq(89Wq?f?5USkZ`6Be>U)`MAboj3 z81l*6ved7q`TRK;Er2w)@9FISfOJk|$lT$`pLr=AomjXD8F&2s33g>_lV3#&^klLn zphl6$#kfq4O!CGkR@ zyj#qSV;SM_?a#Vh6AQjwc=!m%-lFx=EL2xdi4CBNAJ{k&6Nlt;Kgq8%|IHYy^6M)a z+4cht9S(DX=`|tJ7^x;Cnno+5>-o_Wj%EUfsQ_udR6zM)T8-@6*^2Ci&)Q%m8e<*L zH7VQd+}c4L%5h#{P*jzT=-%V%x=DW|S27G2E@!wU$yDL9eOc4%!4P?6@U0JwoB>3y zNE-YyLbs8qPN}yPoXa%36p>FvgRx|A8}dE|v!_N^S#PfE54S&~coRodZsIIG`i zRM;&eS|L=ycHS(0QP|sa@O(}=Wsj#=(1^dlL01|p1T&JdO2;E1=?pu%_JdJ_t8u)> zHt7$N9M`Ct5-P*~4q2Y0`9Ys~;SxR6m!*eZeGXML1}pBitrMsHph;(Wm&J$>^-yWX z$Czw&|4sR81k$o0fh2IxpX#!01Wk#WG*8!nX@fpd_MTF%R3sklp{4n~3-vTtzlxQ% zxhopl!nZ@26P7BY&GUM^E5DqL^K+M)J@>@7a;Y*%bwhT0AkunTFgfDrk2t5GNZOcL zQKsy^3{+^aFKncjf5l+#4X$>(v+;#bjr|lF!asv4mp>W2mKx@l~tfv@<5_|5}F)hpo0r{Vykwq%6 zJ|t4yR%wVlFoWI?NO=40kb_NX%DxhRbeO8-47POGQYN-s7qapm6&3}lbGT1}fftPq zr{{IT{7TuhEG4kZZIRProj0^=6!iG%2*Ztv-o=A7#4JM=4DvZJbWY~Ef4w*s8|0yq zm@6kPg7wYsE;1aKH%D%N-`4q0jb-&=Y5=mO`%9+LciR1HSV#g?Pe;%X5*u-NAE~s5R%y=Jc35F4iXRS7um#=?SOVx2CizsQs{yu=cOUuH{r+AZ7d`1Wne* z!&p?k;H`>@Vk`RhNgYGM9S0^8eg-yWGSepDLBa+O$2BMvRU6vCZT(X!hC?PAO+ zi(mv(O0nnWOh|er(W(Kj@A)1Y5KFB)f9&ch(t>!02YOUqUR~~r=ntqwlj}GPtNt?W zYm|4c4c3hZ$$5XQO>2Wa)~}gXkMkS-^!qZ>UzuK2+N32u>$zDqh{z*wyO;GWkLS|KH32@D38~fO-^aY; zh^84KG}^*b~EA;j76#b2k@grmfcIdpcLA_LVJ6m?-Y!t<`|sMM~c93gY(e`SgRt zpd}}9f+D>m%J{a%qyh%!tTrnb@)%e>LFy9~VH_qYKiksOWXh(lhaxL~>0H%Ndmovm z{ny=m(67wVCqM_nO{sP4Y)`N-9qBUWTs>mK){z2Y&I^^)9F21HRjM^P`#uE2z~Jb* z?O5^)PrjlR$B^IUUbCIg_B=BadZPimN}9bjuO_-(RdKlyl6Aq~Hin)9PCB6*5vds~ zk$g4sIXtx;#R14wu=y#aLK_w9b7FqGC7}cgs|3MKY9)2< zXQ?D8}|{Y*K2W+yTl5Y&)>aw7$uo-uU4| zv0UHUnyM@?j@iPG`iF)_x`|LiIgsIYPssCq_0k+VB;X;GmN(=^o}b9V`soTG={n1Y;}0rgCcVUDEV+veHhG( zN?@i`&Nt)CGKY`C18B@Lya zex9FJ7a4y|Lgn4xy5jVdUtC%gV72cvef7NfIk{0$=sdAJu6%ul&C2-ND(RBvVg1$* zt$r>R+vver^~Ww7X+LNp7D(JV>>#YQKm6r|-@VqU_4y6;iJ5J)%!FB&B9cd|)Y-RSE#M@&Oh%4EeAH)-|P2;{#M!!S2N%`W`y zdRP857VUA|u}!6_?*~pxr?=Sw)r0QBf8Dc$Q==UJ%yLQLeN&X0Pn73Q6)<-k&G^mm z(U0y_LO{4tt2`r6q;NpqjFSI3eBbSLqJo(}=g#ivR#vB%=w&~Jb>{c&qMSKxKPh@r zT%zQcL#9ZV?~-$qSB$Ou@<*#nWYg9h)8eTtzbpUZ+NwR4DYvY+XEB(oHqLE4)_!!p z$Gs#}oBBOtRV%m&?UzlC3vJ-NqEQ{cNSGK89E?Dk_F2^~d&E8ILIkz|ZqE6MfuVD- zb8>~JG5%1Db49(*{#n5NV9RmrA!aV%WSI|Vfo-iyvu+`Ap>P^BIf05+#UV*5kb@Bu z1q7Z#?(UxyiO5)xBEvqzc7PR^a6WtU++Cr*SWyERt1@=Na0^#x{F=nhiqjxpXdXlz zri8DIlRiM5h;vf-K*BZQAV5nt{h2G@v^YyeLKpq-a2BU~e&V&4E)_@t>)AP?8N&Ob zlJ1(i_{jxP)ovEFHRBq%w-2ApHUES(iHeU~7KF3T2X|uR@qKj4yiNCJ#(l13N{Zg- z2du^G&hSQEDH3J?Lxl2u*GI&NiN#cU1fb=s9lP$FncKMA7D_tIz@JVVg{w`?%dVuF z^?Rlt9--ou=P9l(w5lrk3QPw(MJsaG!YrP@^vs&@?tugD(6K2iTiSG?QWs%noKu(w z4J%MJ^yx;X%pZT9-x>9@Lqh}}jaHsbZ@S7WZgf1#PcAg9TEnNeXrw@xiQE%MhFO{9Axp|< z)LuQALvr8-4eE|bG9+68BO4x1jCu~$uG4ioE!B$Txr-`R#&!wzboYGq1@y)ACocI7 zgio}|S8>3%f>A_qt6IauLhKQMs7PRlORL6+Qj2`=4wh)25zI+Z?7S1h_6c#d)Y(3p z?emC8s;D-)poZc2d0Gb>tBAjRsv31mDE-DYm`C7Sn9Id``X@b5t@CmmC)l z1Ab@>^j^KP)&A0$KWx;{Y+uD6>^3UOq%4)r#&%{?F^E!h8ni!?;XZL$@6w8}>pqVj zvHqyR+#D;4J2JOvT#Yk>gLTQ_na??65Z;f_;h-1PbEhDVIxRRL(l}P3PZHt%Dz z^LsVsx2Cqp0q1KHuo6GL)wHD1}x7|@|G?SmOq&qRzHTMNN+^IAcCjSjqJ&FGN<8Aw+%}WhJSwLG$ z+i=@*+fm!Y{U|rEPaNWe8o-Im_l*g&7pfjSM%}E;hDmB}u%o-~Jw140HDWFI&oi%v z4vs{~-J^C#|JQ}uz#j~48qFC4Egghqtn*ttBEg1QHOX%}xH=|6C}Y?-MN( z-&?P5Y1}C(pK_IBkhwkKpxZ|A^dfwH;UJvF$V@-;t!0gP+LZ2QYp0WEUDc-6kEF|4 z5mP9KX!EfGb>iTrv$il(X_QqfIr@L9f=7v49P|3$6mW{g2 zgD_Paq^zTeHLMlpPs_Mai4{X5BGK_QUBSyB0@ZrBsJAS7&wks!8c(X-NRHa~8+YkX zI_Jrzz6f~0_YE5-u0&)Vt`0-)sK2XMsd+BstBp2#kFrpD@`Z@Akp^6`I5pabvl=Ii z09<~eAq_~$Kx|`})rw&Z%(&G6SY977=5E*Bx7yk~hUg({2SmmC9F&13))|C{2gWp{aN^VIL;yfC6@UXoBqkY^=+J>+=tZiBL;{!V z#loES*QfinnascyZ~go-hu%fNj?N_=(@>DHSl&v{+ngM$@l&|R^dmp|SzG)b4q+bt zB&>^UNtSh(teDK^_Ws+7BUdo|Nqq~~BO%Q| zIXvh%L&Sb%bvfIs94y$#AAdSpd53vT)>X zeVK{>9c5xbr;KsQiANYo%62rVepMew*ksaZQV|NUjXYf~e4e#9;RF!!lW3L)5gWs4 zLzD&9Si02YRCtzZ+GyDhVYiFfgq&BBE3lPE_?E13TWj=g(^k9U*O-*WI%=F$4%%nf zYwsta0De|6_;;f6BN>D#inSIVs5ln=pOl81bq{|D?pQvGkpLLh+cdYem9~fOk0Ux!yu_!VUN;>kZ2a#R#s} zyUbhN%&=F$3qSccH;BvNF@`LA(JtZHsq1GZwvR6>qZOo$IYQqiTKE*-lq7Abd-DOdYiFa zzYEXvc`8aX)2Ou2etA*)Jc}Nwn8Os?>E9%pd)NiqM4e)_KJsoMzJdgwO35UCwO`(3p{QSXQ4R7g zM}OFh>hS%c-P5C6sILEIb~XbroSUs?qC!C$s&?<}F;%(S9P z6KhkK1Wrf+a}{JtNQ_{ZD#xUdzQf~dRW&)19?3ixq1;e)5)(|-?#2BW$m1O2v{S#X58(Nt-T^) ze^CBU+_hL89zJaz$DiNW8lLvttUE}j5}1ansaq5>SMOsF&6+H4^a*j;O5Fej!Lt%4 z=9|Rsy{vn}_n$sE!j9~|IPm$UZvT2(#C+XzC zL=zOufmu}HNx%fk5Rqz)r?iUXE|Bnh!!s(i@< z!;mWPJUEQ|6}bt;XWdjBsjA^Q(y2igB9Lhmtn+I^Os>O@0-X1<!j zbX|_Hu~b`JXSzJr=cgZ8hRTH$>fQQ%wb7e!-YN+rw%K`@1g8xczUJ6h-EFV?osI@e zSG(_?@?~dNJ-;Kjd?#)9Ax}FmDV5BBCU^erY~|@d6V$}%V6xb&*0mUAWaDW4CYv5+ zhb^A58Y|@YGI}L6GRGl4&W5tH%|)_VGRQHLWwHpGr&AZYBA}>e*LauP45`tOk{~^z z$kcvYV$s!~lE7DMnzfd~Sq+30%qmr|P^$TGdGWo4uqU5IA3*F~^3c_HWSV;fGYFj)^-N}Cas|ErU5W=8;Q#fdZtPYX8BvO?)86x(sBx~zgs z8)Pfn$tv=FMCUUlU7W8$XCB>CPsGDc8;L+K9b!Tx?z5GNP06=^@#&m6O2x!f{%L^l z2rQg6Qz&)xRPLo`MZ8ed><~2Ib zBpw-;eV1#WGH0nk7Qc;|?^Bma3{g7b=gn6G&3TuW%bJ?R$G_X!C2=M=UaAW4goF1?ao_QeucO&; zLxhaBKJ3!8DV_k5Ekw>qDB?k+1y<;f3W@(0Usc2AuaMxap$KQAn})61(*WFgU4)W# z^9*&vG~GK~=7`o=#rS;Egk*N%?KQqXCJNkdVSX5{EaG)sot#WhKfIf=$y+q!a#ZtR4a4CGh=d+GEXF7O zjxtTN5#|36ObMV+gT`WfT1jX&Rv#A}!;;GbeqbrXQMMms?9fMnQ2xS%GtT=<{AaE6 z*{R=a1?L{0q+970OQ=waRUStfEy$e!ASD7tMF1qW%1@=P3F%8S?8SAomw;G>4jVB6 zKEu(RbH-td|ASy{_Z9RNpLXt(mF#Yq815$VAz)1!>> zI<&RtLEqE%l)az#?fR)sfKeD$B2dQkxtMJ6%d!c+iz0&xqr567v=n=j{vRAvbSiWR zgBkucvll|xh=K$;(F+jVqA$-YrX^yL3d^P+XWKYz4jwYTTwy7>Tz+PEW%%)>1jVzP za!@Tmor@*X$^>0OHyLs(EKY2t@K$9%r$qw-4|4ezjq~nkB?7BHXGZPLC_=f=>E8nP zK9&3;*&+3xXZxhYLXWI;COe#ETS4F#cYbrH#N2mFKC=0kb?QJyijIvmN(U2Tz zuC4NNAq62*xe%nU@g~}9!{<`j6k)+Ibsry8rO~yk9SN%d3$i*~;ZOwdSCLIBO$)Zn z%p(<5`9(HuL7@38R3_!%%QLDxQcJXd6oSz zzDj!JLqDF&Xk~^o_M(b@x<+Crl?p-uQF7z6^bYb5(F>typ5wekT=#xXd2NabMk+&stC-(PUX%(Bxa#v zgk0$L;94$EaZY2>v)$Q@L?PEDD|83^&_Bmu{#U)^It=6trj=iU&AX?`;blmi^eBNh(-Ind%hUSb|6P~qH z=m>`Wpqvz7u?>^az{`#dD@nWCS%jKf@OGD9#qFIcBgy3@A)otlFt=JIZK`@!h2BKRiG3GYejFCZTwLh&0 zY{8Ly&3tRWn}57bZLbXymWLH@=j+^SMtFboMpL~!O%MpqEBlXS5N#0kb`~}1A_ix z?rbiOyJ|CVd&q;OjC@r@DH#o<1NAtC$Mb%VZ}{FG4T8>-u=oUfm(FPq7bO3Hu!>Wg z$1+>J6^Dju7-E(tt57J;^s2h250422n+J?yH(EX`JO0=umYiOPM(;QMeu#(uso{#K z-_|iJ-D78?o?)4U65cp@i+=PjdNL9pH8k) zwoOQWcy*ey?6B;vQi`F zqP_?sd!zt9QREy94ei!dr(dB5ur&UP8Ti8lop?~3h$^lJx-vA|&^X9MR}qhXe;MgM z_P11%NjfwcF`YtYBX@+DhoS{EerL$mnB(e{2iL=Z$_~*U)Zc8Y_#?gi?~fy*gRKBl z%xRF7GX5D)=?@-okpZ_iXgcTw!*Vk*T+XH6MOBZ^C5s!=@jwRF6Jk?BQnGzD;c!W8 zmtR1k8!PXzvdjUqyxk|AP$VMN`ale3ROkjwi!(vJzI(9FhK=!>9{ zGg%drP&-$Bun6qxt8mwYY{*kbC;wgie9{tGjo`txUTSKBKDB_}Y zyUyJ=SS{Ke@-|Alj;J~XuDJ!PyZBt3hfE?S&JQQerhAf%n;BG4vTgd zgIx}K)_qXtNF3J(?@N2YtI(AKUDEMy})*cvQe>;pe2!;wN-X)LcC zW=sVPlLM3e>i_Zu_@qa1HROd#$PeTmfXdlDZu8q}WL7yVSzW?^4&4mr|GW8rcK&3aM5wQV(jHhOe>k^{2MBIA(k)7)~JkOuiqSCcpTSdJLX{ z{f=1rLB`QN92U0ISLk<@7Cr7=V;yZ>ar3}PJj_pZ@iVaDdw@v)8!w7A)ZSz!Mdz-; z4ln;#UP=q{MOP%MNqbX#w?_Ohp{Dx!h{{3_`sG1kd}EbR62(Mm@bljPUAD>=%u{pv zJ!^Z6Aubte>n9{CBF287lzKIGX$w_;XlN<7{A%i2uW1IfPjAaGuL*HR>p>_X(Eytn z%-FmvUTq@m9iK_k`v)Diw^`Zd%p)VC!==j5Ff?e&gz04~+{Uo2WYjy3AS%hsdfnSP z*oE%cD>^k%VCJ%`FDd?R97#h#j5eG-fj&<%?|jxHh^GJA4vMWa1IU;vCSYoRA``k< zQA}=?dC}4fEhXbJo?VJZvKIupOd0bW_e~$5z zQ@pBAa6VEin{pIjoKY>_v?6d!fOeFtc;qR+v5!tVqabgF&O1$u#m4@Z;ixerLOqx~ z76Q3CW0`J#5a@mtKhZEF#G^qhht0@O(&%{zW$8BEh2cs4VAx^VRp>k#QKYh2f0dJc zjjIdDU3>)=vvQzR&M~JN@=BJ6yia(2+UqpPccPy`$41hvdS6KdD0B?r;6dROE|B4k zcw*YDOyD|#9odoPipO4NDCNH~^Z)HBLcLrdYpa9ar0iPH_e8wD@F3fEhH&^G6hxCy za44(1$xD5@+E6#Iijnvw0dB}{1EA!CF2O8T*V5zZ-DLUz=PaX})1bt%h*`YI5P23gaa^EFPU_lIcA-hIi18fi zF72rtIu4b%VFqgFJ2Vx-kaZa;3Q#)0ZPlJE zt!oOMB8R{V{ZA&wf6SC<1K!m7N?~MCpK%*u_f4RKF_AXxQP4YG#emK)={2Y>q@7fg zqTi!0PizOQ&z%@T<>fl-yx6EngYH9tf?HChMfO{q_g!Wg`C0wKguH1LtS)Bf7=0za z9vx9c<_kxZ-cC|8=|vqJLM9FMzg(-~{*#APC6#`F`Su#~rpqh#K4DD{taYyW>C=CE zi%Qum>V@mQ+@=^5Tja%A8V}-&SSME3wrnE532FkNzWAO0IJzLeL8R1X$3Q`2)5YQ7x{amtUBoTYx z)HAA-c&n1FC}Hl*=|83tQ72ptrYz`RPuEe2Y2YGStu>ZD+?K@Zm5P4ZTs~I+txH5i z0Ac7PoXT%;OgL<{Z(;*mG>3_KM7XsgVnpMEjPeh0j=wS28-NfeRSq&Cw=T?g(bkR$ z$lKZ}b(4K2q&%# zafKy7?U|~RkH)?OY_emti&O*iT;)yuC`>lZV@x?UW_n~z-_#d9sC_o~PlyF5^V(q_ z5I~Kdmr1HShWFkL!fZkP-KQY?nw*Ij6N~6PsRHnl(UeSkKs(_F7!KpLK*xaF_2&GM z`pP;=1TPP{QN;J4ni+KV{d;!Od0lQpsL*N_po}n|RsC%f9wC0eo{Ktf%#VWe*=ODtN0+0v!p{Pve=wh$)o^0BhF_1@%(pV9KwUbN3*D(lz%R z<4q<~>tQe>gIWQ7(MFD_X*T+Rm(ld4)+!KGvwg=_SaImY0+noldTrvTx zx>SM|m;3t?WcmjXR2VzNd{rJYhkZ^8SQYIe{;jwFN*e-MCWU4{T_{TQ$Pc;^%UT7X ziNkAgO=AwBTLM9-edm?zEgo!uF8CB-ID4?PpVHH)_BXmR5$4Eg(yCSryB3v0Q!)pm1P`H@k> zC?EfbD%H)XUVj2rO)C)6`zBu9ov4@xDj<4|L_2kEu5asr(NxzX{GWglYTAi`2CCST z$-+mWIAXZcsv5S`Ll$VI{xI_Q*^+@Of3o7-X{pQ0ZIFRBF# zF4*yja;YlPWNxbGtooMze@b?;51$8@);=6o97mWq)m~;+Bt|W>jtaQ)ea$I?0tX&c zIU01^oi-$tqs(J@sIAC$2K-wQqHs{HaeAmIQeL>>!bnIn3I(axn}PJ0h45eD?gLbF zrzXlUjHiY$Iu)n@K!mHKG}DBudi3~>wrQxKF2gKM^BSBL(N4ncjho@H5&M)Ql+B_7 ziD~GH1OprU(((jLMc)FH?+)xK{SLe0oA>*1R&~j-wzV9FdZs(nAXQ*j? zF&dV@CnL?xi3ASLoPBT$f@HdT!Ag8U%@6Stp*i3|Wu>S=K~5z|5mx-eUZ*a#A=}M*GrV{{-3T>YxdzYPl+dR7Uq8NS6*kQp zoH%b@xA(>kCq#u1Pj=5`)C@bzp`pmLiMKgvFWmo7-A3k&&-G@ED(xNXBwdRG}b zBkm(MNtv9LV|E=p$4&Ciir10{(F4+RWZ?7vBwsij0vlN#Ri^6&`H0P!RTj08P`R1sx>gBWGjwz(mHg6!?vURyya70wiAWv7^i zkY6KZ(#OxK=H#VTmZ4jt^#@9vR3HA>0#8-JPWYI9gd|5mqBQD!Zw?|#0d}qv-|#-9 zdQ6WdNLGB~TLut2tv9n>0fT`8luz$1L>D;nc*MO4o)L%y{J_%)js3Obf~vz8e67!* zKe(B2D%QuC$m@v=x^)BNoI$n*EFeN|tee~5Ef_6XHq$>=g8Qq zT=wU1BN^&@p&D1(R(gDGz8-a8#MrHAoMj2iRiS@MUbRl_crCV^T8%$hZiu6(RB8mS z6VyLh2s%S1v~H0FGP(EPXea`?c-C0zU7G1$7Br_%b|1uxDDbJ%4q%&HFFRLoePQ}F z<+}NA;;lau!x69J7JiV^d(>!Wji&xk6y+%_E-t=iuk3|kg{TJO@E=`821TlSK5W`t z3J?3S3&La2!Sj<1Bg8!LmRcq?Ik=Dv}o7MgXqzQPWlYg#A%kKg#TGZ z_;|5q4qF}2dPk$ts|k(Kw4tbj6pR7vW<1E0IcJRypY%Hnb3q|)_7~#40uk+rXVFdj zfNG4W-;lV{iGOhPgC@zd3XAYSl3Mlh94|v%P^zZNKIVBb6Clcgm^xVE z5N1)D14|WmEw6rKNIaSH{(Uj;Uef=K&B-q^qR~cDD#aL|<_6dP&=F(yhX=Upr)1gB z=mj$imd0tAoT~^mob2d}M!TVTW0yZu@&A+l+-{pP^`jAuDeXtWR}rhTtEw9KYT!ly zi43i#hj+c>bW+zEPF-TBKg!yE80(^DHe3nkAJNX=?tQVU(I&`BMYu!Zhcmd-csqu~ z35>LEP}mw~wcG+rPF@;jJ!H#~WgKbNjKd6_3TV|ytRtu!8Q(T=mhwJ`RP`&Gv1c>y zHnI6#O?X1|PZYHq$njc61`$ReO|#nHcv_q1a!Jhv2APWJDROxHbY4@jtazjlk~XwU z;G3hi)%_fJXY(Xg6x?uW0=S)6*`idVfj!#oA>pi~o; z7TwTzKJD-AWDI$`=rhoQeK;;7k$t=%NMXs5gOG42RaC7=f!QnlpB`*nT$4@L5MC+NvOI<+@f-jUQ1GkWYr7Dt z8n8sXPXEH`Njz3Epla0^#4pkcYPp&BwRAW!&I%AfD@srNKaF0IrFs!0(j!X6+-t+P z_UzC-&wtti#U8c2O?0}`eU$tkLojx_*5Xr8Hg}{|v5daoiIuGhG>1@LO&!G^5 zl&ekhzkWck_C*Duu|PiKItP7vw!#tFKi^HJMwKsv#2Yz&r3N>b8vGvl*cVX?1{3Cv zv$MDo%^)k1u?j8zZtnQqxI*e20szksz4aq*s5$SxXyjK#`#)k-P`J|_(jMHbSGU-w zEGy1=wzUCp+NHkdWjc4=iF&S{i$#BtJJ51(^!nXMOM6)q!;!V^1oA4Cb6;hcc^JeA zX-JgKQk^Vr2d%Rgf>aA$z*d|Nyj>)uTJJwI1-M)6Nv5r6KUvw9mt}k1jMB$0FjFtp zNOxmyEx4Fba;@w34F!nC^W<}_rO!~#Ulz>Rzd0b!MO!|hv%lF{ATUdIqB_M!xWm{S z3<9Oaf9%yHj1m6Vy^gX>Jr&*G+>WXretdo2`L`CwWmBHM+AcJBB@e7Y* z<>oYXP|@4Lr|VE3Z07qnd45KfQ5b&6tsoSUblc3nke<;0>@=Bx6bRuMl&O+HI%7Mc z<+7WYvKM6g%{G-F?>eJo{I7ezXa0y9`Bk({Q@JyID4b|r8_hXit zjc%L_mT<^KE}V*fjYySZZ559SfY1M~T3^dktqA#leNMgF961^bzs-&&*%IAm=)Q9a zvp+S8Ed=#X3fIORzuDj_RDZTth}MQfu$|Tql4bjxAb`A5ASn@}bE8lvtsh=l|(s(AcxUB>F6 z4?9#eD)}6sT>v=??JJgL0NXexVmklN#l>stlJ8L(h;IxF!cSR4skXBH=sx8QF2#PQ z-^K+0*#-I#dce=eS;v)pdO-<#kxE;ja-pci_hcV@w%6GZp=9aruNploZMa3Jul^K$HfM}10kYy#SQgxJ1J>u&74CJZSr40UE*_d9NQbbZ$Lc=Nv(fAafnz()%+ z0GkA@(xdj&4n3Y;CIYB$?;fL;%lWft_b=^gFIm5ohTejFi(@ls`($UHQnGnWxepEY zt}Q(DKS^77+OkH&09;b$Zd{2|Eyq*N_tu*2jPCAMTc&IQOA0HK+K3mM-*1ytIr7XF zjtpAfUW7YA{}XWh&*Rt)ay#DbgQSMU8(9nBjiU8@VaMi&SI zG!SO~z-D#((?g_>qww{<-h1egicEjNYbX`6V^jQ?%+MRk;(MgDT>k??!*2yu{reu` zCiR&bB^uUh!V;#>TV12K4^-L73lm&BexP#3V)&j;hE*^+W+*?h{eZn0R;J-SOZV!X z-h4j3N-~i+cjPpb$^K#U%H4EcM5ZNH`Is8`;x1o{KcF--JV#y}o_yox@02*4=VtL8 z^h4(hEybl*_ze0!N5G$m)?9LlF^)1;r{D~d4Qyv77X=pwmspn?m#OprPa$U+6=m0` zVQHjg=$0<&F6kJM7L<-5q$GwGlx~o25TqG~MskpDMi>DZ7!Y`gkyJuL;EdmQzO~Ld zf6o5Bf9>a4YsY3wb<TJ$g#I&l`;$I%XZW-=iOZs@1OL~g*W)#H(e8Vne6@!J;?UvI;~zk&^$W+n_>zqb z9um%^%0Y&@Pgnh)N7MRc>v=6eei}*fX}VCMZr9K_dB@Q{wBE&62YZS&Fh9SnU4+7s z)wee_(#kUD;+df>+@2v*hcGjKT-?w|Y$5KFos@-d*6ZUGD#A?_WKQG(cgZzs)8x;G z#d+SREKCr>O)L70YgLtgzyB0?oWH*WXKepwH(1-shW&b~%^bq?$Dcn_vGP5uV0vJ7 zvW8qP0A0l8e~U9-E)*yd5|}E%8Rd1#y5{x<%uB214|jYgZHZ6R4A>iDCnDj%i8=3K zV>ozUr=_4jc5Y>28I?!6S|bCB0&aq11q=ThD-wGIzyQW<3q4?ExdhWCzU@tl`R#-n zNy$qBuA5SI1rfi~tLyeB$_YJ@-1GZhXXmckyrP!!GcF6?3wkl+kx>7z)f{G* zhE^4Z+x~c0@6&;O&46~k+hT2hp2?97(U$zgK4VWUnesYH`gPl0UpsHU( zN2LOqbq6J=U=c5DsNvf|Mm+(@CgmYP{JElyxkOvTI=5Y%xt|#SkUJO~MtqY=kyygT zvZt7eInLNr+?ClJA4(BOb~lFar&)+lorfhPUjL;Bs@MwRy|Q+@nZ3Fcx-;E8cl3vq zb&KB$@TV|8W1t%;4Fu>wt};|(`jao8@#4C%8Uj=K4KRPud*7~b6>T22cC}jIW}+_h zPjs5R!`g=PjSK8WX#rb~cVz2m{?>sHsrM7_XWpLPDNHYIiI+MAteD#bri&g8b&vEu zod0_?U?!Iws`=8<;>}<0%uC&glVoMbT-9Z(xf1=Vds;PocCrQV|I%_)qJ2~^t{IrTX#!t(SwM%Bt2I-z9G zBOQ5t$yJ@IeG*xV=Q`YWNF+L{=L#KI0Xl_%MEgIzJ}k&zdQtp(dw*`;p*r74Ax@iT z#UNk6iu;?qzUh3#FJ?cgk=VOI!NRf5xsbq^m4>8vM!Sral>IPNW(-xBOLZ_S(^jo* zGCrHuvu6Z&uMDgON4RLyHT>ceP&IPh2IX~wOiv`}L?fWbn5v0%{vJrJmdDs}Qv1>J zKk*(R&{tIxVV=4&=bX&Etcg9b+A6};_(&sA_2Nc!B{9KLbfW1%4dDmHP>{GM zq04;*0M+N~A(DUeF89sn#~RskpNXYw))03dOb=g@^p0k}HQm&(!1KLPgnesSpr9Nl zIF3W02|5gYO4#TrCI|6Ui{8?-a~Q^-UoPc0PADjs*-E)cX6FmQr*j?ZJQQ-w zSjnHE5i~l^b6_yXUukW$&N zHYh<=fpzg$vA}duZ@}O#(h057(352!&-cNRme*#!g{dXNBlOjbN#LNbxEuS-6i{vk zlu)Kb=*MvN?Cto84digEW;Ve}EdO3H8YqRx@E*-fov;bsrbMANIj9NrS0AO2jA_sU zi#72cv1y9rTQWgZ1MynP?)7dJElW+hQ+N4%`zlPD-_+scAfD_vHc;LySctI!&Kk;6 zod=AJnG~k}kcBI~l#c#!$>`t_ax3IHJe(m1V%YEBzM#kyFJSHeV;7FOaCj|f}J)WFNM>GNh7RG0$<|0Sx{5LIYHdXA8Dh$0l3FK{6 zEl{)uN>7Fnmf37d)Vzq#BhidTw}B0s$~i9%@(25dwVFzQe#0|ndJFkt!nDiewraTg z09ZL{P26di_O$j4`Wmu6^OfSeRu4AXIRos+^TWf-0&)AV1u5`We_otg^P^9Uv{av8 zewD|zOM|y?>(K7H@+pB9A%TLcWA)A3GFhRmX zQIriTCgnGQJ7p=cdQ|C?yw@zY7gAbdE;L5D{kI2AVxIW}ptRtTn?VVsQb^(Pn$@f4 z2_5^P>}PLK@h?$~3qSm&JfF!dE#vi8>9FdTl0Z80BF#kGnIna^f zvDg+_6k3(9a(ZD>$^Bwwj(qS_!Tz`=Nin3NXD<2X<4X1=3Q(muvZy!G9YIlDg;>^; zT-I}$s`4b%Io|gnXAi7OCZrC3JMFCW z^rGa50?8Lil_Nj+adWg&NB6YMe0~mJI7GrNGHP;$?n-dfu~a+YF5V}oB|2L zRMrB39Jt4=Nb6T;U4u?Tgqc0ZCYzXB@bxX*_Tg2tHSg`T1bmd9Wl~W+wBNvedySWy z=_k^9C!}O{dhPW*fvpY)1J^UXBngh-P3x5^kPC&fkhPcd!G|DkiFG;?+k=k~o0`O= zxXZ{}7CuYsVBLzK8x(ALN*~l3_=N%hGY5DL8GXuio6<=&7Xd9QbIN@5RhHW=JkB-Vyq<@nrbvgJGZ3sXwCdSLan5b68vF(6elRFlHi%#!Q~NDB>p-SIOPeIxe zB79dnzhvfq%<#j#X@5mvSF48hwDh%w_|_D_KlNd?qNE|z;tA&;*S;yM1Y535#WpE_ z3iO0}k-r3h7{9rKZdg1wepkVb*XqKoR=~vbL2g2I^Glvp5<^+oM)(2$=}783SK|q! z{8=_Sj=$Pial-i37mnyY(jJ&U#5vn=1}2^Ouv#TDZ2IXMTl_CQnorLQfGzg5DdMexoa+eS*fP(5%cJWF8Akh=46ICrJYKMWk2n3PIFEt z;8)6(+Sx%iwWw(lxuNwpluqrllA$eMVDDteC(o+o91%YjNyc$@6D~<+PZO#|?2QuE z6`)`OS+Rg|g@upTa`6jU|3j_eYWwx@(9{+q^4P4Nm42N=>Hi3HIQ?%x3B@W*sdj0j zG|vLT>9UZkmvn=T9i0YCU~d&UIkPjjSTuzk=uz9S3aU2j4!j(6Q(1h7S_$+#83|xu zjzFQhVO4I5x((`%ztv^ExHZ^+aj32TDw;Q+s9R1&7HA}8xm9OLW0W-py0|ap-|FCe zGxG;KrO`9fSBPSVKyyvto@w3XIi`M6=`$;9?62NsQ6;^);c!#^(iR`y(9G!$aPF$& zp8~hc8K#@%yc*Z=8EQ@(*X$PkWADI6E6xx8<=w;rXyHwx zwFMOhq?$l3cbRmCeEkbS#hl%z@N1aAFVvq@#E$XZf2Ppn(PV}z;QoO9jFMSR!;hzb z?mhXcNbxqm`CXOu_?QJJ8|e#?CbRD>5g?Xel4lU$?~I6|LwY3teh4KgNgd{0OlL#! z;KD{A>-3X*;|vV9JYQTZ$YViddSU0%_a2aKRz6%0wO9?nuL%+mX}nZrW5kY zJMU@?ux(->6;;*r61$mAUdnNmgl_qowxb(=JX}g1AG?{>LtQ!Tn_5~;^BlyciGXO= z1>RHw)@rm4K!L?j=`5Q-E1|dn?dVek%8AdIpABLi6sn zqEiogRqf-Cz(m8DkefaHSKhhgo3i6z`-O?sAJW zY=BPgxQ2dz;eNgu8w{zU6 zTEMa7F{7dlc?NaVaq|@MY24(%B3`FyKI5QmB$L4=V4 ze$wtg()R3SVnW{(Y7+>k+X4im_2IMvQBX1ohw>bB*aF;LAows;xryl*NB#65V2l0y zLi;D7Q?}jQciGrT>vdivW9XWWbtVMt@GjO-HXe~Rb!C~g1%Y+--^?W}l{9~j=3r2` zVAtRSqmFyaUk4@p>Jv7LA0zQ@bTM=9A8M#GoA`X#f;e%Wk>JE}$PbLB7fUT2a!}sb zcsQ0%&7Z>rVf^T3NOtpSv9A?`Q+{=8QguSMNV58vBw_t7a$X(RVY#nbY(XTOsUO=} zEG~K(0>IC&o?jL%Pfra!N8Ul70U9NV0kc`N$N_VC1W04uhMmPFIVky8>f$Q@BNq=I zLDm(K#Ks(}lS>tepf|H+&RNlF&In%80c@-RNkoo;UZUv$^hu{GTOJw1-FBvIWIC<9 zt?_0yYSf{b6Z8^nXYP{vz0qLGk)WMy zAl^nUu~Ra4iC)rfyH#PcX}1U(^g_M`$mmg|wfJ}nv?VUJ5-r?h@qW$xhAwk%Ja`IO zUX~k3iB=cOud+K~lLi0sVK1o9bItQsuU|O!V1q0_!lly^`74y;yV{-4FX7O2GJQgO zW>{r`|8_xsl%2b*%EgvbtTJjfN<45?;*l+o3X`eg+zipO4}Yb~vYwlU92+|&PU1mD`*bHYJE(Hf%N`IPEM@~N46Ro&y| zXXDSOqg=f{l!n#z^7Jg=znf7OoRt&Zh)2I@?@i!0&P{$^VS_RH5fYh{XmFm|cVm@m z*4wnQR0h0BTNUcpw*EmVL3~s~M0>}TL*q22Q^_Q)A6G?m?!7LiJD_}=H6KI@BaK7Uq7jOJ~c#9oVfaIRtTyEE$aGN49 zA$%nS*BZYr^ADZX$Qw|F=9WyEjFXq0XhcNeQn-?oqE%I$9LEX2ddi#9aU$})?3Dub z;oR(7&WdyJFp0RGo;;|z=frf$6KZ(HU$G@h@Y=?W#@Y%hb({OU)@E#KrZP@RgH7H4 z07xX)BO#?mdyK|6Xfw-$EDbXgdHID~Y^SXJvmw$5yfJG;qhY(zOjA z3T%~MJfDhiGjDG^o*OQbeY)Wc#KPz{$SCCj#-Ig>jSg=)0IrC=&~bU$c(xya-sbaTChXsp!{kwC_hdnlupIQh3bVB$ z3dX9Ymi5Yoj+uq2d^aSfM4+rTIxiY_@kL-=8Phz!eVg+~DJY`x3-@Gc;%zc^^ItKm zNy?U}o{V6*tU%FY!h+3uW|IEDcr!Qa~OOlK?Ae?*!3VoV+feARdx$}vB;bCtr? z(yxdN_}&>-df@}TbQ-jO<-?9_*G9X;1W)R0o;`?{UYdFqeC~%wLmx8JHoYcD4ZtiV zF?rgOXnBx>qu{|^lgLI>Q{eSq!*P7m8BSDyUh-MO#oPR*G%?SlF$bl8xIc_|aBM zD+Prn3$uy}nueY6Hm6ScvCY=8hP91gs!f3O)Ra;qBg*5wwZ1<3S|PhyF}+^R-pBt;O#Qtr z;mw`@C_ST;_T5IU$>ppa9(M1yL_84eesWmX`1{Bkw;o+yF|X8o8B8XmFOyD7D&^Ld zN+S6}LCO`GjcFO*(dAvZ_`&v{>oFQ4jsi};{a5$z^YM3;P8`VgrR0%^Ym)1)$gZ8% zYj0PUwZ)=Ui%ZH(O(*1+Ut=;eTN3M6Mjz^_zIFPY`xiDM{}1uNz(j0va)0gc>-nLT zRr^{0o=n@&^SABZCn&ele=J%(zaX-_;@0oz66xs{d2p8s%4+?qKUg#NMW>p+mcP@r zO}%*O!^~KOxgl}1yO)mVUoBVD=k`5WlH)IXRijmW{A(*$zOypFV8inI*2U-mfwK2> zE7|vylEG(`c)qQk{lvtte4mnJym0K(vzd?UGgtMbWLhkxKOcJTwj4gBz3EvoXD)g& zb6q4J7YWW-wElOM{2nMRpz^@%bE11vDXhJ(-H zq~0|Y331?_a#D0JjbyEBq-I{kf&mtoV8a0yoT2_AgUN*ILmb>awPAzQf_;?A($tem zx+Vh)Ot4WsxPp&=3yIO*Ou8dbq%|)nk13bkZXehwGBl`NxmAOVL4qc*iLr5CZY;Sg zhTvp(TQ87Wvszs1y-SSXBLc|a@`?>Rl+Mhgl{~#yNhN3$)gUn?rnx4*RkCoyVWDzh z!?Buo<`R<@J+a8zkU<0=?L`b|kbJ?)H&<;_r6x9PH0AUhY&hV$ON^i13ao8$$(Ww* zps|v!v^W10dGDOxbaSx*$T1Nd4Ex;PX6Hfy;Rhy;pJHve41$jU#DZ;gb~N`Q77Vb! z1RD;xLSn`hCI?I$KShyo8M=|IX|iTs#DW19m|(*J7o5RpGisf$dKWNp{1j`$We|L0 zwq9mphy?>IFu{hy>Gi19BO`}AW+cWHCI?I$KgHS*0It$j$XQDav0#7&CfIPm1*dk} zX~V1;SC||yar_i()B0ZK`hPl`&!S9;Ar=gmX1Cx9rju}-nMk0Z|PT< q`Y&yaE5jS?e*Kp=#DROd8R$QEy<9z>#ejYQ0000BR*jeTdI_pSTwez;RL|4Pl& zoSf6$)&0Zi2*n?g$Ow1{U|?X#(o$l|U|`^!|K4ygpij;^y2`-7jOL`pgjGFOFMQzB z^wg3sH;>lK4ueS*<9AR+h zN-xKXMxUSaDk4={dr7;`ghcNsfaEPesP8a5Wf!8&LfXD;kC{OA^KFrd(CLZNmmHOv z&!kL`!|!NZ+*i2hQ-WbWBnV&>F!x!RaXY;1Id zZDd%qYzo}U*0=R&{MYaX&&W0MkdUZ4;(Wi_ZkPGeYpD1?Q;_$m1hMzLQ`=jc;hKfGV}*Hg0uJ0)G+qnzw(d|2e%KxHM)ZePgd zRue#a46m(r^Ef*`c%&}posY=Z?d#DL@<$5_kR*$Y!U!($xHB6Gp?HJ3fO*&o7ZHLq{uItamq9AAil5iLHaTxKlF8c$H zg_R%9(>w0N2(fcvYK~(iPA(;<=I&T-9E=9=43m+@GXGQbP zaqgXV%u)W7+8k$LtjZQBGG1}7Cm^dAZsC9?(Ld%S9&m9=*!rBj0u*ZLj;XS)j z$WZ99@Fs}s-3v;N5gWLhz6x+Mggjc;u$1?8c6OdmvH$=J^b@+Z9&_F&JoPl|FJ$2C z*_IbBh|hsEseeb*TKAJ_gv<}*e90<8k9(}77HESPOu6EJ6wlJe-DLWD6-k})>#J4!w2&rvPDHJnx>70S=XfUpnvo*Cy< zNgaJ*Z+00MRnQkHx06sbTU9)kIWG9a;IiPTR|6CN=EYURt#Yd_*KR_`3^WIrYga6y zep&_w2F45JE6@O*XCdy`S;>;bIgW3MC(AXubZ6y;Wz3p^_#*p$A38(O za)rDYr3mft8v9N`Q`28B|FG}N(^p@%nEc*eEcW#Dlqoidp|1dqxbayC*tb@fvU(oN z_q@Tg_BlEq^rF6Rh4>4rv#asfudUzBV#*LWz52T25z$|0ca%Q$A>O?T$X`fVMN;1* zJ0=W1Zj0Dnnq99z``m!4eU{!YRG{D5>-Xo$8V1G zxqnsRp5VSfbj6Li5Cry=>W)P?wJH`8DAvVSq&areEz}BUx56f+(zn^solvp9bbfUT zidE{}!B=&7vMhpK+St%Jw4%dYOJab_YPHz5kmUAK`8by?Q#}$s7GYH0MAF0K#j^TC z=Fe7L9od}%-=rEGeL)g1S1LuTYd-!AsTjHR9m^;Z#q+x;B`t9ne7FedE7ZXb(|z#c z8}fMD<&g*^=Gr_Q&l0`mfe*0D&=5O1_7OvcVWdHMj{zWBmUJt(i3BNPCBk1Lv-`Ix zs}!T3d>&05@0IJxQzsLx{YnN(BW8zvM#t?WyZepqz1m2$FlD}!m3CFT`R^(_1nS6ABPO}4tb?u>S4oMketmy`}OGfmFvyN|Taj&6&^H3?mZ z-g#TPb7@#)M?GmaAGsp+~y7rXx&Q(y4rb`%36PP*Xd5grK-RrkL-Q!oUI5KJ|r7ve_*Pe0v|*qeRcZ(u&MMSvQE(b0b0& z7Ir8P#Jah8;!mX<_gIkLlo5F%ESq0Gx>>viysuilkAXN6hge5sY?K*$VQ%?xj=9QWx`6IC`*1q62 zY9kmYe0&eCu_bI!kapaUC+B$2#6{y&6{7Hd zk35+R=6+X|CP~S!h$^%z!DU88?dCXPGQ9;d+MN0PX#o%1tc}28gZ=&>v+fdwfq$|` z{bAF=i^f--+ZoE?TNEOe&q!G&s5)V8`Ey*S&Uoc6*D(qXQ>XuM=Fm^MkuT&tc6F6+ zYUBVxm45u0Il_;(Cp5hY86xkeWY~>JjG&y=mCa(8@_7UKFB%?5m;Jd&U$wbxGR7`b zp-OQeqfmZ>JD=1NTHg6#Q%Xiig-kBu@MKH6oD34Gsr{XD zHnHBl56{3e7gbZ}ND*mls5n)U>@&X}aEbz>s?6ANfX> z3D%XMjNOkOROHNkUsDvhu`+&m-jse($NWy)%Ilj~*d)!ze2hoI!Up$}umu7k-72LW z;S)y;tshi6iAA$;tQlK*Y`5|Z4ZQdUTuY&>>(P z=k|9C&lKraYt`2jvQeBMRVC-VJpHXG5#au)1h4=WCS-Lwo@Rp8H1s?^dWslrvs3pY z>8mZbLVVbnRVPXI7;{0-V+h6gZ!&`sGbKBKBh9cN>1iP;muIw(V-6o7I_P+mBfF zt9exkTXAjeM0j1QtkS2tCME^8hNpIiHco13!e;q602cc%NY6$R) zMcp4NS+{!4gN&&XvW`vm%ZFMX22Y=Bk158n8)$aC#x(+R=wNDm8>xralNCIp@QK3% zKEi`o;$dI)F|dj~cPUR}U&n7Hmf-YrY$0Om1qS3BD8>$ESSh*GXMQZyx779wU~71j z9es;qN1;SC&+fiKDq5GFO^*@1EuNW;8keny1`p5>0ms?fa6_ati4FR zN>#kq8Zv!ZEEu9UJ&H3sd(=hm=$H1dAl^{`5+(28atgACu|>a!WGq%mmIWNL(e$*# z?PIFEL}2{@G?^$b7?k^&ee#n^?kpqa_4%&#mlul;KWkp(PFd_Qm92!qY?JE^bUzr4FtBcm0g8ieUBv1gJlX;b%cD}0xqd7Zjl z)W?m<_6^gPGfGY)2qheDru6ye^&UFBW~&HaXJN>{#hCUk-u7YoK~ff=rrW|H6X6NQ zu4mW^TRhPhHTin4+4f9;S6kWVarQ^t(qR6K&H<8XDD?}qeeF`Ut?b~%7-OtFC;uk|%#DD+jK6OA!>RFcK)rk?MHGc|LC}`IquSBYP_8LeQ`tpX zk>b6s$7XRqZCPV5XGnLA=0wWgv^3%eXfpi^)XBVsrn>qOG5&Eyo9}PGj_$W$Ii*DBFV<_FV1z5m9d}pF5#CQ9PHw^ zH%jb}ZIaEj)jeLB@ z!?&t*TsrX(Z8ZO^n`6X=^^=FKav$WFBWg0wh_D??z?+vd|9bds)ddIHO)v>~Tw<^f z5de+JkMCi2d&p}H1QgH0JN)>$7J6Cx_!~CmZznSvgTBs|3j4R`1o)!MuBkX&jBOl7 z5pL-3RuO-KNjs_ze*a8UDQW@+v`MGKRVuP>;t-+1?Xk#&LLf?AdRXa7&tVIinV3}hw(yoYx-Je6_F0*ARTB#gin$l^B<~k6N^mE<8b#Cz z6JS0DG42@#0)Io%kPk9RA6GDz zD-noQ>dNfI{p6dEwh}VlA18M|WpGRrPxKBO1L3N^a-gGPdtC{eK^BrZJ)`o^NII8} z`HhHmW#;_g#hzi=o<6zePP|V+022Qr?9*mCtR!I2d%!B@ zb)$%*9FRI0=d9&%UQ@hgX7SyUQkRD_AfVm+Al>0TKFsTD;}nTss*IBUt=Qc8Zx$MF zWWRNI5^gVSW@pdOei_}a`MITTO1=0!BzsEF@6`O?Vi#B?t2I|2n2B~lat6RD#T#znf@N()hDfp;-weT3u)EDi=_&f99FEQ{zv}WaF4Zv9&$@$&uTK z%qy4$`k0k=@ZWXbA_0!zeh(j#I+<_EWkciuX8fjeFNhgZg>YuHoHaqVqBL1VOSgg$ z_ScTd_1t{o>Oh;*U%A(?kFYgYFZcpC^j4_C;kG4s`Ei+N#h49=ZmQBZ5gP7in$=#c zC7NtCS&@lQh}g*MGmA67lnGcxxx*C;HbStoz3&(#k9-str@o#hE&)gYb-W}D9XYT> zYP&?M4|k`YlsN|GA|xHM9&D?7H>U;9Lh)t-yt>2}$)3KOi3r^7z_?xR)oR!IJmre> zK*LG~)lMP_-p3Ty3x*N%4~tf6eI0vMzXB|5I@7pN*n0PB-9--ja(TLuG6}1BpdufKwLZMABQm0wva=Yd#1=yw@+!+k$;qnfScRTx zeCWEECBzcD)HUhgqW8t6WiQGXX)9vmSQwH2!J|BGN)9iw>%V6iEBa)#+WzZhOO|kR z`HOoa1v^g8{`Ks4iwZx5DoAU7#v(|xcNEn7I0 zO?-Z5rM(lhc04r8piJL_fhh}nI--;l)%gzmcpWpV_{^Wm6`R}1q|Yc{V*H+|B@=&t zA*}pTrWK3WjR-an4n+KBqSIF5ZnoO!Y-(>6mH`MU2QK4@oa_5c%@l?-x8nx%Lz?_- z5PZac#Ogj1`WT-pC#CVll9jVl$ynY+5xOAtbq+!co9lV``dL!{OlvSs&E1!%?qPh_ zPIScdeZ4<4*Pvdgu5}J_ z$_7?`4scgbWnN%G#o6C=XhqF4?tep-l6RrOTBwV(8bv0e;J?pR)(IDg+7X>A+i4vg zZHo|KQtns54|_z+b!%u24PDcgM>|%c{@XW;Tfc{~$JL!LPWE1t&XQj?oj-G2MLuHd zb|vy2dBtJkw0w~97$RbQ|EFI|RP@jFfJb;?9Mzl<6+@^x4XuRHy7obTKb%u6T^>Kf2&PWwYl_meT-3Ax&l(n)8DKV2q4q6-)dn<(L6S0U|jMf-sdp+eE--TWB z^rTnTC;`Vv)ZR-YjOgp^73k~i6X@^k7nl#pa(W|W0TKa8fMmczs&-|lWYazvW{65K zww{|+J_T7TN9ss=e70O)^k z9)~Xqkn?U=UDy)J$Kmx#r(MFIO7M=BqKtcoB4*g;{p$va$yTd6?5GKkdixE5XG}?BU*)fT5&iT&i&6?HKVd<9;epr}es- zjw&*edP177p1qQUdIBM-YEd)1STW4(vGXIJuZ@zgKPIy*aTL(^G$O=?Xj7fXNJk5D ztwswDmz)z5g`XFX%bsUNN!57iq>*7UVOcN7jt+N@8p>Ss9HUE0V2WKGM`)>}Kad|C zFws$pzcTSpeH9%UHsEReqQXydWB6Od&ZL|KT8V0u{J52)9iztPp$VnHo1R=6HJX~E zA{(2!OiP~KC3(v&6+`H)tOPahg3g@U_V2#ixeLPOgM!jNEv1HBp z3dF*$nT`pZ!baHH?{H*B)uGp(XIi;2qvU|5^<$>Vc7_0VY?u!o>|3$q$V4;X8T#y0D*`- zzm2rKf#irzLsvLVWJyJq^AaWP4CUi7JLN=6z^Foe+>Xlq)!5MR7_90u-ra%6*kNL84Rt&nBH9SSf%xLEj%H*c#466B1R>j*lx8JCF!EUWeg9V0Vr zC7PEB;qmKnFaBg#pU+d*dm0vyc|{X38cc$+sHZ0C@3ptCQNm0_11D9C%xlXacEqx= z3aIJM+koezy07^V>$Uh@7^;Nt;YZRqE)@^%V@2Ru7fnr+1)qhSg`V{#E8UnyaCabm zXk`fZaei67#*nDk#h=9xIjv%V1T!gf zdT_?u`gP7N?T5mcpr{p`qzeDuXj8OmhyXq}JvSRSpJN%}o?I+(_bfdro0PYSGH*>hyN~QY zlD(!u-zf(z-*R3Cu+@m>vFC3|Jd!B~^6~B%&#<6!+ zwZwl{lV!e=D$`PNG@T~C|0{x9RAi|3sD~@dG0QdUSC)?2xg-t1ej;qonr$<_DsZuw$h)@?nlC}AjdQvxF}ZKS<$s8`Tz<-WEyW@}=heY+vxZP(4y6M1j*pq_f6FfXo?limiQ?10Sz<-k+L9y2*NF?G|KBtG=X@A_E%EY9}7E zr7lRQh@_N3zvbo9&e8wF1Qb9s0_Tw)1ZK!{sEZpYi2yZ2>}A_RI?JGBtL#nP>ObvE z5L+Ie)L$7NQq9HAHAGP$goevqjyIqzb7%}PF?sX+*(_j>9622&3K{~y$a@fcQED+` z5|XT$&+eRJHZh) zx*qaqjbBf@6G{`Nn3{L#P|n7#N`cLb>V(1C@*+!*4w*dMB?zg_7<0O#6?m8>I**2h z9Hkiz%VSToRhNU8Y4KfvD@#60DQiKF*Hg;Md8|iy1(8>bNzd>r4onI?K;R&J5@{O9 zl=W*fvwk#Fz~m?Q8MNhI}Hxh5yoLdk*a^k|akqK5{U8saU(3{jU`x{LT)8sxU> z$|Q~ISQljOdR{s?YPh2oQ0o2Gxr@r1e8Gocpdt4d{XgX40cghVB54Wb`k$fcprXICmc*hU z>SU`TY#~%b71H|p?EhZKy_@~j!BW{8xMhG`+)^-L}{I zqUMc*2;|H+R-V1UsufY?+&G8-f~gJ2D}eITKx$JBtwsKyNG=1R&nzPu44NG$^Zi-&@duC6DTU=Sei7_CrWw=annn`z z<940AdOrva4QnY#SQswJW+%dU^%%zGLjJa{#5}xl6fl>{erfQ)LFv8oqnmStV>Dn) z7sy+v@F6-rT675+f>*GyJT3irhm_&JCE(hvlfN9&`wu%j*B=V z>H+07oE}SovJOVS%N@hX+{Ah+t>UhZax~&#ruXAiY{<;N?f%gSl{lZ{6d>xfv zwl0f~hmH?AY%}7t0fUCWIJN8K(qJEY!SC_v%Xt7sg?;Wa-zJVE#Nuvf>1TXi%6?E( zaje7ryi0&^fe@^3GzJp5Od)oV5%yk_^>2-<~@01(7NMGB5q zugpiOg_DEGT;Lih;Fj6Y6KV2Cq-)KijkpLv_LF`=ZY^nUaH9y6!&^=^DVcP3S#nNN z#NygcZO$0T*+omTE&pZLMaIO8X4<6v*m!_M6;zeao(Q)M<{(VT#ZCw?%Ku!vy37?i z3hc$b>pDDemLgFvX*HwIn@(MI^mOQLzu8>%L8Z+$nNDCL2&{`JD|rh5B?gA5)WK

L6lKV$m$rti2lKR0Zf-0_SJ7y%#YfJI?4XE<&`ZJ;hSmV zv13|(`a4|nA-WF0QLu9k3E3l(L{RUF?LSE(P}C#H4WIpxx6g z`kP&PvcLLJoSZZJUzGm~w<=<1nAlZ_UJL&lCZ2tkz_24J$B|%$V4%t4rr&Mb$CqyI zmxFYyqFS^1lnZS^C4)F=;dwK%@XgOQljsuj4b85g=#|L{9|+7IiRCz~G$_shC3Fkl zq{X`v^a@~5FR~f)$Ij0=w6&q=uwNfNuMD(7jtIt2gxgiFBhwMSeDtt0onQ4?I~{b{ z4Ka1arvC$_H1)GjT0JzicoeYJ=WdLz^idP568;;XB|C8R7?j=Jw%*X1D^RjM`j6)c`_&GGhiHn>D#_1nFy;I5# z+9Ddsw+YJa7Aft(BmWb4XKNBBmAd#9ffGTfw={}Bb8oQ{E3a(iy0#0wDHuRJ4?d;*FiTh zB#9jrr1t5J#YSdv**Gv@}7@SKr7Qa3{d{j3}f3)nm{|litmk z!wsPe4g_-_Xk`@SG|m*%<1v$3OkY`D43HFAuqAr#kpAxGnqD+Q7KruN`79}Jy?tm% z{a%re8B?5&I1Sn@V8>hV`x>kxR0~9w(kLmixXs3f$g7l#&%+#q%YwS-yKfq(k7Eya z5bc>`9SiAx^REsiCrWtvIMBvMrK<#)Z2=O7&z6+48N32CHeS~O;I9f1e$F*S74dXQ&xSbXbWZ>N)!j`YDujVv7AI>Kh+F>KL>D$*Q4Et-LMg6c! z`7|@B(B~vb19$V!V-~OlC4z_qIlgeTDy6aHF!*N&Wkz!lvVBAA0d=alD~XehSlhIa zQH}<0aQjF1O);9EM^-ss<$muFwp0=1e?e3ScBndCX#HzotHI3u`F7W_h!FwzkNEc} zp2-Fi4KBQQ#!4g>7? zoK_FsCC(lO%Z%vtv?_-99v~uJVh`R_M{9xROF7xJa{@YLZ2Z$t`{-!KK4nMhj9@{~ ze}$auY0}VRKD7XnT%u`@14=9q;AUWUvyY=&EzTU~)1&H#OLTY@nD*<{M*Y{ID`C&g zv73Xn!YjWBTf#M8(NgBTSB%!Mv;qJjaN_WMJ!l|o{flm0#MBTst(s_R78*1fJ*3+h z{j|u+UtH1E@Z_m*2i`YqHE7*dw1N@HZHa-r3B0}+t}lGwY>Z40m!?vfK?JJrEi}j`vyE=-9kYg}3?3z^l3+%);rIeW zlc@T4V=~{8>{gg!nWAe_MrOjl0!ZOQq)qxeTt`%Wz_bvxzy1t2ov3u3Z?5^AoqGZ; zOhNICzzx!Sq46eL1WnItbjlckS&aeLJ{|()P@3;HhjE(`)JiG{3t4QYpOcVi$etKe7o} zFmoJjU=hZE8Up<0;*RSA?A8oV^C?tVEJ z9p{h+BFuM+L(jVo1Sg4I;7CipF86}U6tUr!#iX*XK}zW>S6E|$HGBzvlyV%lB7bS? z)Wzq9T;BmTK=)A6r;O$X=`2?Ah^nPDHC;KRkq8vy_5oosDoN z0I{|Ti6}3PybYk$VuGHeY*12me6+*03bQC`2Nr_%+{`XH+`4!8|CscjsI=jhpAZ5~ zB{{2E2J5}VmE~=dCXad{9#bIX3w1H;w`N9%uE%ZITYMbx)49Wo5i%wcL#K) z;2#*3R8zknF*53g{xqow0oS41?V5Ff=UtJi6EFX;%Dwxr?;dBXulGh-SvGc70*%3V zJZ5~qdj8Jh)q89uTJNWcNv6%vz!2#5-{b%F99XO^b|-cUV#3c1Zx>#Qm$Sh%Yvt!U zt^-8iu^(I6aMaJuO&EK;UhGZP|J$DiC9Ha|Y8NKRsxhf`uw1P<^zJ~7B@O%tw|MwE z-m7?^FHOG^D@@2_nk6$TOAt|xtq~KN%9#9Dxe|?p2_F_ewQkdhlJlWQ#DOf|)}M{L z&m5WNUROr-*V%ir6c={)RLa4XWh?3%LQ7J)RRcJc_eZQ=(B|iW&;m`sMoP3+sg)`1 z6Xd9+wy-v5;HwtCwV_aPtF5`487(hY{Kc0MX06BLUgv`Ao5m({j1HCEdycBzpVM;L zZr8N^NrOubGIXaEK>51($j}hg?u1boGQ$7r7aRUaY(tdMwai)`0n+f*c67A;)Z9hg zXjI!nmYkeT7YxRy$Gf||CR5EO;zBZf7%QWI~nxrw0^}Jl{SX=xB64G zLsxXP`~ZMA_J2i^Wr+>ucB4)0QN!}=zfbtE;Uw!0LiFhfp|B2N57*(cyVuJY zGuTu$0PBQY;E~hIds_2tbC4*=7ws-SE+Y~Br8E1ZT?h!+|Ih>yjw|{Is(g0o_O(iHZ!|P2U%&p0QE|QtO zShZhL*8NXhdKBkBhesW=SmQ;nWseoU*%qS$Yu#=fm&K@ITw@Exj{fE%-cY%AQzYI` zIqy6s%OFWKJ*_dGzViv2@m(4+L)(Nfj)dqn@DGuOs^E!l6wo8lS~Tkfcl(#_BE^FC z^^ALxI>6w&KTN1Ur6Gcscz@+~qAyKV-(@*PBmN##5M}g4bu_EWp8N zF&bczdD6SlJ27mw(wm#!OJ+;phFNYXdtV}v9GIkUvfha!ip-@e`p)PNg zbnbVcMyc<$@g{IQIE@@~=aSYMhSq*=lYz*yH8_M_&GHrWdjwLteC(+nR%Sw|scj?& zNgfHo$hRQ%s=&Vq)b^UIzubMI95vi5@Jp~Te_5mwxt8I>(&yXPgkoL# z#q`s{yK+~(nf#d*bYBNBE@&opPd|`HvP@R0?By#X8A=QfnG#@GV`VSznZXv$cMaIV zkmL}f;q~#1{S?VM5iZ%dF8+8!;#dyt_@jPc@^Qkd$~`_r)v_RJ0*g~uPL$`M$*PI6 z_-O`i4Z0p7i|4=G)-JwcU;CZNrK#+e=ydu&Ib*jiuZ!8w${_ zc$fEAT5_YKt6umyKq@?#Xozt`Zi%xsxVLzjm%#yZOF@Dxp4GelVKjsIa-FE9bkT)# zclKAGn=hnxt%;##Yi|J$Xayv3%zb0b>@ZG3pmlNoZry`a3yBnxjt*@Wpl67qS?&8n zRVJ677s;J{{Y5~MQEQh+=vjX$Q?>P7opmKfAtewkF_PJ&_;s8AZb~ZthjR`H)W+e6 zuY%?UfsNS8yek<_?l+|aGze&bqeK)qpj8YnZhh1JgcS@bhwId-(WZoKsfiUT8wiyr zQ}ouCwn=m3yB90V_s;2g{R4*xjVzeUHM(+0b;&O&B=lNcD#uwd6F9wA4yP6qeN z=C&pt*=ZiC0d8uNNoPd!Unhmp{gVGb+XVT6jpQURV3Re54=)y^9r~J;inZk~K^m$~ zRy9eY@_Og!a}cL=XQu%0#1#B^ zzMHeWE1V8#`zF33rggvs#V=61{_!E1)HPxR56=ZZ83=nR88L&-L{5byNxKbmGZAfj9Y^CY#75tj|~7oXL6D@l0;u@% z@pb&6L6#&OVW_8>5h61k#09FFsRKAS_><`#f%| z62Ivf_ly?#_cY8TNghwt*@2iKMhib65Z2+ z=$~{rLn7b04W^-in^j{siY_l^qk1;|N$KV%kc#g;O2Ut2YNeLCdPu!`0V21e%ix* zBbo5*L~kR$SXyg#ys}N}>sO*NNP9b^S@Qb(Oos_{Wdaxfbg^wRh|IJ=amfE1kzDs`icdXtu5`eHF)8UfDww#$6I4r?zik2g|GWOTmfVvuG!ym475MSZ)N!J zBn#%ST?BGV(?lm{<<_!Hia__!YSAdylF$+cKyJ$vOx6+B-r^a!R}V?;GM*s}zUCv# zCjm%aSBzSjZo|wpI?hQ@*xI_Kr&UAMUO_mSY^LAv!YnF}$XyV2w)OKg!?ZYJ{;_F0a1~W+zMtRn5t>Oi>D`2E!B?t`J3M@= z>ft1)<-6t)09zZY@tB)<>OyNUb062Xk0yjqd%$Ft{vg#V5&Wz()MM!4|{XF zYU8mMW9y~MoU^k6j9hgTrCAln(`K*^=pJ(vSp2wrErI>*A>qUDjjJ$eAyzX2;G3@F zS8-RVQy8k(wnNx3^<4k8E%5obZ5eocdXNJ7Xk2r4d|Pa7T%g(Tph zEzdW;HS92f-Sg9?`I#$4!HQ<8ES!VqcdD`*8%xiaj?t86h*`dI$IkbGljvobtjEa` zvC8*9wqF6(n9CNP5i%$+t4dh-AFS9+&X0~x>wWwabT*dpAq`YS;)eM#>ue&f4 zD|Y?IU-jF4Mf5%UdDA@U#-OdaAy=p-X_C#nDOMmmDAAVR$M@jYJp{F1N770D#q*?m zpr!h0mw!FR=L{sj2w0_kfSSet{`LFUu-_G!o_gbmb>{n_Orb6)b=Jh zLBb=j(r<&}qoC~^_HksAek5&uIU{}k{8T#Yq?8u>zes^nn6{gLQEV`W0$dFRfs9wk zk~X!Mm-_E8mKBo;PPD|O;b6b8Xb||D)FbeHchb9>!c!5M9zu?IUeK^S$O5XgzBXVX z$L}yuW6t;zfp`PR*v(MCQS6O`>EUG7k9hXf-k3YIUaXwqJ)-x``qg=)m+R+MTok1( z^jDm=!uq{dzWvx=@D9!VcHJCDq|Vf_Wo52JI-A0@Cb|kY0-0#xmpR|=g_mTM;GG=J z11?&ZZ$}?u2O9jIN_q-V48ZKY@waHM8e*~g^BwcFOW9Jy&_JfXblmT@d!{ZnZd^K=7KLg zqZK%iK>naHkl-7@SZf%QUB=Cau4?b5oG&4{n}Z17DM!aVhgpd!cft2{pfzUM>)WRI z*rG0XTj#6_T%||7)=U@VyMk~%GHCYiadNG2jDsfAb~L2M#s98`ZcFnC zQ^Ps2M_)%@rI25-^*oYgWdrKb44%xF8WJ5InRJ3O1xmQMrwD^75CDZ!<<1sYrelmcak@B8=sM|)=HASao5C$lD* zx!3dD*R_g6kB}>UnvaWkEtkJAR?Vl(l>G~=>YBM_*=S8FE4UJYzzoc zBgxEWx*vedh)vCPXh^zkD6yA|PINK$!(>kp=H|3a&oPc=K`{j(qSsBeB7m;{oJY&V zgG}|P>hdr0l!MI!$Wu|rF0-&*bpS#_g{}A2KO0~JfsGTMLT*G%Y6l9}Q(QH-s-cWd zDYNDAz@*tRNg41!sBfm1>QwpG&Kr6Y}Uf#9xFETtgTIu zArx86MeL?7&G{_d%lOGM?iBF#XQ-orm!IQ$D z;+W&ldW(mUNbU)<7wtF|0`q6+XYE2F7m>}cVqL_Q^$SkUHbE*c^;7M(l5-EXA#;`Tc^I$q(U^BZ^FTqrV;pA zBLAMxw1qAE?+$Q@tq2z*{4sTAm&*H2sVJTTq@JF?`|F%)7fBGjFpyxgv@}tI>c=@2lYwGDh!LxS%)!g1zVAqw_em z*Ps0@HuQp0O#y?YiLB*-P$tGtjMM)r_4C*k@X!g@DapJI#6yx{_4lqZ=o zE68khbsjtMRq1@%^I%l!p16^HfJeWkXAxQF^*&u(1YpZzIw?Apmgn2<6t-lko7DI&FWXkU22IcFL`a( zcw@@Ox6N-G8=ELwj9&7gJQUiM7=^_wXgNm$f z;o!L6eIw)x4G*D4RaI)v5@fnKGlpP%DI_OR>?gL^yRbikFCp!QZbeF5enR7{Wsq zYGxOZq6AeK#2%@FXgqjcebKJ>O+lgP6Fr{xfa3b*bwSG+0;5Mq`C*2X?8@TUmDe0Z z|1`~Y`RP%W>|}iO6XEqi*jeh`rC-8dRXB4hk=40Vqdm{&myRt7G44!Y#{fX+(8Lv| zK#4W{00(!1p;>Bm+RxnWc`Q2rh|VU<>Pl>o*Nmi_fS<8==}c+tZ8UpIbKE(VxH;Sa zp=s&@n1+|h`*T=fE)fb_>v_T)#`>+_(nZd8Y85I&zp_C#m^gUs9FH`1U)NuMZ!SLo z#rD{}p1`zmJwb#eS}t0N)5PVwp4$cgXi#NdhIPLhSGs?*+KAFG%tp+Ai*5_Um2~5DF-DzsD?I-G+%IKsD{bnw>mzy@ zVarMzc<8-P?$NT@2hbTr4#u_+-??@7i-g=K^%1gT{&={rB1fz1HQo5|EvSrktTK_L z!-q*HPbmMjA1vXeG^S+b3)-?g2+ONVx`C~YCS&ut8wuIFh8N0c0WJ`s2xD*w7Vpc| z50>_(l1VsJ*QZ*G+ETA(thX&#Euvg5z^^n}c!+=7bMBhZCY{s{F*>az7Ez#;6 zAk1KyyZoEVD4Z+dno8TVj}6+P8EL*mpu`K}r`HI;PHe9p_%m3?7nZQkj)ShNGR^_C zacGtBbqWCCO}FU~8Wno8>2ySQR!N}g$_ zkw_r1Bg@)`Bdge=kwlU-GT?E`gnd;9@MPuV1?Jzp%8rYnKE*HzfA4f1rik3%5Y2W7 zvsmVKUr%_*&xdlN_0D|m96zY=WpVljb;jfdn903yT}C1BO2OFY#A#k`tH&g^G3U%$ z4@7s0GiI^Kl{E~3_}WB9)jc$ymsjPQ;Aws}-+L~g-IXe#9^Q5^7S^Q0096&n(fihx z8&kNZD-aBsT6i0K%lUmo{ne%hcG(zc6^WDsqaQ?ir-H-4jS4HJfYY+ z(avX;eXUygEp$SaIOJC}W+t6Of+U;a8`Pqyegik*fW3+~->lYR<1emO@zIq%cwSsU zeS*v8)pV#&mWm<0f0Z(e7%g|(FnYgrCewB(+P;1^>bkUzC0=;*Fut|}NRvULk9dfd>3va!(X>*dS4`hBd?KsrPZ3FiwAHzL zX=$%BxA!O0)I?H8Y>;}X%a)h5#3YjKlirSgnbBbk@t-WZ(>$8g4?`qM$9g82vf3eu zfA9)(c+u5lXG_m_g2&^E2}POHaa3+{_ADDu?Od;S z7?Xxl&JmqY^8+lGHv1u_EjiGPo;H|rm`wYa(t={k_c~x}z*yswg1%6bv7VB$()KAm z^)Y8TIN+GAA34kFw`jvXDhspmp|2$Phpxnx!eQJ4-_h~Qo1 zG6Z+AXgvg!*=wAIr--y?h$3nR(02Td9xS4z=0RH#sdz-EONaV7*t~Mh@PPH^K}JZ& z6%k;K_VtgTrr8!vGj5{%M*7ybc5$j7|A9nQF14DPS6uq(3%e^N;%N@F-`O~?C4%E%Qeh1+8)WfuG( zhcs%GJp6>TTbE@iCr1^j4J+*GL#T+_-KVSIEi3X$6@EzX1m`Q4W#%Sxf*?08y7`H^ z^$7MGJUy4+)Ar^9-V;kAb}_Dq?w){p{EmrxLpbmQd#(Tp%xDnfx&891Vy+Qa0+F|h zcBieLJd7hj8^LxuLAgyMTRjcxNrKTA9Q%l3kHr;aJd$*|HN;a+|4Y%yLfxGV2} zk>}}Q9SUE|2&yg;@*vGVvY2DRK9IZ4j%G82s_3T$xd?o3`P82tWZugfF{B1YlG-PS1xqHv_V>(;a}9fbv! z_S}q4l3@~CZQho70k5e3o_gm6GuA%0?-0L3b;!A`AgXRJ?%!YMJVR3Au?(jsr+);~ zc>>NeBwQ-np;yu{ugIE>TIQS12@THO&et)kz))YiW5VGd{`Qyc+NO9t?y%;ZCGp_* z73tUg2cJs0^}SYo^36xVT%0mz`)+h&3kb=gG9@Sdcw`S!St$=@f^aG0lKv&`NM%HB z6DvUD7`eMiZk4h$6_pujkq9=khnZ`7b^ew9%V>k~&h4f$Uq>BYTPgdp3bBCGS@I-b zomHdj>*cR41B&?MexLl+Yb1N)dF>S(LA}6m1NEijzHHX#VjV! zS#X8?)@@FBmUYsFO%-jr7N-d2ax(dQhv0bCzk`ncryQ zcZ+e}x7c&OzFs|cz>y1yUIdUh*xz`9sko&L}!j|V(qBROiG{|!pbjzI1m zmCgPB!Z~(TYG>jB7a!k|J>jkuhxV^v-f0!0)wILT89@0bjztWNwci~JnNbn5jM6)a z2qFW?ABTHC?rf-%0RY@m8~|cvN6~;JwPngfaNA7X;2@AdRbe92dC*;s=;p2;r9!ZJ z`{te6O+|^kDabWQo3r+qRmcIqh8E&a3HQq+VBg`*qr*9QK~Zm8z)K4bmV4&V zgTlC}8@M^c3-i-(!?c=F;sutW&FmIWQYZrX+ue3TAqtsOh0 zF{3vi`@lSET-Wx9cpEizf$r_1oTVdQ`k@cg9zJZDd_f}sB>1aLpf>vV7f^&F<_(4P zy^MM}=I0m1nTniNUXtQFLwcCEWrbL%+644(SzN1@vbN7U#6haRY0o`Ic1*-07Vdl1 zonja8s|$->#VjM?{hKxo|64=jyFhcwogS^?zqM1kkO+J9jT1=JY!3K-^|Tv7Z}I?f z^h&grfGYF1vw^xntEWHQn2NpzI0DcJh0H0*!w~J2fq+c1S5$Uqqs{d{`Ui_&6dwe9 zQ9^gz%s&iijz;Xk4=0&;(ALDec!&zV6Y^ngk}3N@AC)kP>`^*uI8!xaZ@EM^zjR5F zuVu1j^025SPo^^ULMrdL?`T1e&2C;<6sCO^>{bdlmpkdJr?}b)-Ar){Elyfn_`+hBGb4CDQZWb?!wpV>Q?N)9`Uh*P~I>e3#$Oo9p#)+E;}4Q&<#_ zQ%$koMTd}J zWq1~oj3rlevseDBAg+i$p{ikPK<0*Ogb<~xq*OAz6^e9e zX25<#i%(A*(X;R2k}HVpd?5v6Vs2HKZ*bpeiG&;aTMXxgHgDvus@;d`Y|43}x6JiuX$azhYAtWuF%aFgl z>!*v0yDfr{w?S%{c6zdbbxh(?b01b#lp3S?^KQ_Sek}T+U>)r)3uIOx7UX?Ak4yQ{ zpExmSHzli`Y!v8yQ;2B3hoKt1WjIO9A6QU^Nip?rdvL%E^oruGSRLW95j2dY^;lh%V+$SxE3FvKt|nZ zd!8>6D$Ukt0De{LvmNH>hjkc6<~$3l%MTmUW!ZPUpsn5Z5uymMPT}&o`k5Tt)HR`H zzUX|M1Rc$8O#Ya5gXG}$F zr|^6x&>^}a2WddFh={0{>4dAmhAUK=?SQm`DgY_x^$ogjPW~HzmGRCH`q3Mbg^S+T z0%z)(gj-oFSKfA4)Ngc$C@mw4bMig(;ktF~xuVv#Mik}dRRhjc$yE754MzU^+hf%^ zSB#WcX^Y5Ymnmy0Dem(q!&Qp9xbTsXO;%|rju{})2o z-=|9jzW$i)Qi|9r=9)5$j1~P6e(mi0>|N?XD`iR!(PGUA!==|?$St zKQp*flo^9==p=>K&5^EMd_@Pzz99>0q~vF^xA#uF99WWgkIde(EU7ONO;w;F(`rpd znP0x|p~5T#8eY-wk+_lf(15ED?7SWW~DKA*flFV^mQ}5m_V~lF3BmP zT13t{a(6A{J&+;_)@8L{2e{#R^={)A0*N}SqVJ?rmZ)?*Wx z&vq1i@rrFGTRH{^(G6v~x?2V*&JmF7-*MhDaT*Q&^nj%7inq1K`C`@(5OzWMD$;LZ zjh8atlw+e%+G|2lK@QedY(`Z3SK#oL;4A9+-zgNO{E0~o`n72jS5vDd{|NowC>$Ig z^ITtD`Nwe~#d<4B?pSU!Z^CQTO-(r;L^Z76_{40x5Z;)P8xB>MFR?P|kcCqEo`(91 z#$lX|S4N$qeE=sME=dGdFO7=NC?&7`_Lz)+@5sq&NkR93)}M0?;c;uxhfhfVEj)vs z1|xMYbav&EoS6Ez7!3l*eL?or=R?y!zw5}yih0)OALWLm;Ix3g^~8|djTV{`+a#!< zT2uDteC4r^j>llzn$9JUxhjl)If-FhRgc3T{p;EjGR0ptHv06!HtBR;udKFOo&YO4I6Uc@qR8jX< z0wf{Yfc`m4E>@@2kyveNz1xt3t2Usi&=sx}dD9g03ZwWbbFKlk*>MV}B{!TqS$SVd zb!S!^*YWsIHa4s4uTKlkj{TAO^SJtIvmvYB)CmoGbrIMHjy> zt?1hjf}=Gxs5_c23$Ggoed2S2db+ts(Jx7yk@{7j4s(m#nl|)$i=+M}Dgb{w7Bj_) zUBdi1$;~^YT$5(3YqRoI5v1M)kR%R#KXn znBXVM`XsN^e~qhm6%yVme6AP=MaUd8V)pLWL9&;Igv~!<*%$C2&XoO^ScE}(M4Wk6 zLdUv1#0!9wn7%L|5)K^{$t}aBhJKy3K+3n|m2)Q(HAiW%#g`)#uCU9p)TKA2L;C8f zZjYW;mb~WV#pAEl9HAgy{5X&)!z{grTc$C@=+<=AI0H&Vaed zu%;-xp|~`OCQw6SO$;d~zS7tIYzdpkXKUo-Q!#H)PB~pRwYn zWwYHvN59M}+L9|D=Dep6IH$26S0Ibn{VI4#GHrljDqM#peL;2}0>(kr)@6EU2=mQ3 zhnLK}K03W(PNpKIF$0&EAuLg~tEQd5;hUakJrZib>yYOk=oMc@<>=LZZ^46LERhkI zQ-+`Ikbuo?!EG_BA)JoBMvu1Z&>-tS>d}R<%qVYFky`-nkigZHqigZM^r#0s+tj#D zVmte6$jecBLU9YGA-v$~n+y3p+Z{gu0Jxv40l(4y7K7^-?6lA!>7~5aiAZ2b6WA@e zYvhSHT;Pwu+i>>6w+HLRew0HTFqmk5j zSa26RCAZvgiy8tEXi`bvgoZ}{)~y68|5Ns5W~*kG%6jc*K~JF>o^192+ZXT30;AUi zD3E@3x#t6C;r1^(K@_Uir+_>0bnSN|N_B7DraIK!brTl;C_3Cs9Ugs=Fni6Q$sTl7 zU3T0ENf)c5OQBDHJ36y)E%ayb1^`ooNwg0ljqIAjt}Ler_$d6C0_N(+X3qY;u!;^saeA#~$Q6(EN9 z&(=8CrunA76ZKiGci%L$tqC@Ab&c!0tqk|v<|d_Cetw)H^nr33rBmCeKwMtRP*&;T zT?o8XSM9C5+$Yfmxp`e3UhTh`5?Wlnx=K}+_fq$^VFrm^;TlxfKu{7QWMHPj>|$?@ zqf8@rtpG1{nX-=_`LkR8LOC3s?(_{}QQjN;>MxHwCa&uih}^{Hyr~_UlT*!M5K)=u z<@f;o2u7w%m(YJ0mU_E!q?eW>$fvaCA!MI3?>ntNVtsS!gvjiM&iR*bR`=M)N0t6Q z!9(E6vxlK@6AlVrc_HJ)>JK(n25xW5R51(_z~m6=t425QCJAFFmYqt*_4HeaiNI| z1Q()FiQ+=z!Wh3g(P%=5V)%%pV%4SEyLe?Fsr9>DSF6#8@o`takYx=o-rno#bUuGnj=%I7ers;%1Se{`a3v7F7QZ?z}y zYTvy5+KX++Bk*41pU*7)E8zR?v);aaD&+jZZDUtC^`|Qpxz|Xmr^HD61(VX*VZvn> ziEY0?Nj4kbH$5#f`lpo>zls_f(cb8vjSgMAe`8@LBkzb+JKosUdh~RSnt+`P_)6cVhOLO2pZ`J{QHuq3x zTVS|>*3*Y4CUOmT-&qMBy4Ukr?M(ZtZyWh)zZFKgpo;~FK8 zY}Apvfbse}VesAu8NaEiJY`JwYTV;Y3sIdOy5jI+)PviKhbGJUl|5@q!S>C*ZyoI5 zPgY)d$;j{tiKaEW<2=JZGr)m6U9wE%iN~~bU8bUdxN}bs6uxZn8*{}YZ|usiN?EEy zo~|}VoaL2hzygbXHXd1EpLyQMZztmg1gM$EUX|X54Qyc(+i0MLCfYDmGyMaY9gIzZ zI7{dv8nD3dS=@k;EscvbHpWw0>wyhyVH4YEpoJ#dFu(#6Z2tgeyN#X1Z3-^V61s>6 zEHHc)H>elv>Co6l11&Vsh5?p2Y$8YiK`lXhS|rirCpv3fq==9=QSAEjt(nFkCLjJC;)Q8CmRNKbM<5 zM-y$5sm_it{QZx7E>uMqlVu22l4vOuSde-J`v@r_S=Z>WM7aUmX_|3eQ>?!jDt!6W0fSVasH*-jfQ`*bzgMYPLm?e z(Uye8CTz1l++Ro*of+V9C>Q}EPo+{A8jgJl<42FNKo%yfrE&P;i(+jUV1X%SiyJag zZ-B5y-+)qlXvE7=FfMIZin4~?Czp%>uZ<09>0bN6a~nJBcEorzNj*=FT1%x36KqLX zGdgZ$7)6tVz5%5;)h(k)4d(lEM597rfHzqJ2b1h9(CFmpj9~ zPkM6G4NAtxWhQ!PeeTVKYw72>hkLPst>p9bV9Jc@f002ovPDHLkV1h@h#H9cL literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/Square71x71Logo.png b/desktop/src-tauri/icons/Square71x71Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..06f74c1838bb957fd0c4be78dec98278028fbb78 GIT binary patch literal 3882 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 literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/Square89x89Logo.png b/desktop/src-tauri/icons/Square89x89Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..be700044425afd1d8bcf102894375c8fb42a533c GIT binary patch literal 5111 zcmYj#WmFVg)b$`G5~CsvrKIpsgLDrKQiC)M`OwlKNP~0@jWDF5455^Cm%z}%NH+}K zgLJ+4yzlzf_v76A=kB}j+UMMT?z+)$ph~2VXdVFo08-`G@>=(^;oo>ja6jr2N0kEr zgQ=5{?;Y6>Og_xGi{fNk1Y=s58#zg^ClhXoY?=^{&8s{=QX3{i>04#ofn#A zRo>mS+dx#AGrG)eCa)imb2fc<0?!jvn3S}eGa0BfHdltS*Zu}WLn&9m?5WBuS!8fK@ z%4jarujjhzUpgvEYJ20wMFWkk^5aiAY5}Gk)*C9plau3VZ(SMinWx8=_C zx9LTIZ~Efzg+TpP1U>^Fdk1Fg+Qv0T)w2@j@~t37Wn|^yZ>mJspIJOgu|ZEYKHwd4z^3uVuNqO>JW~4}J5FU44ZB&f2kg|zE7LN9F z#3Q7nOybKz;$p*8Yqt{2OkXOmecooZefZ3QXH-VsuEcew2eNhDQVeE!N>qU!N>m6=*DgRqL-VrzM z4aZ`!S1czpQ(uyWoaZkJj)C$%jd<=h6QwD5>2_$PgjUtb)AIChsu46NmB>d1_5yJ@ z?Vgh~7wvxV<|7s6sU_bQQuHjWDcnnzMuqeY!-bjY)ay_wdjpFbDjNI$-OrA3)c{)U-j$FEN%5!KCuF%x}*QZmbdbY0F>;J!rI4Np|_JCskobXSOLf#5KZ;wtT{>OfL(h-sQ~v-@ zA*4{g>OV6G#$bakJU-df%H!< zdI|ZbZ;FmVobhJD3fq+NH#NTW@2fJRBu}JMMNLQ-sxJ-~bqGH$6r6JDQf==LNS$@n z!5Y>~dS;CQEJE#X?#6i}MvA`)UK+3_T&HWpNi(~3)*)K&#-@k8ek>vxNcoYuJo%ta zn``8vO;U|}cw+>Yf2n}61Xu|4H0$QDF8dlShX`s;-89t}Ml_b)*GiI~*S^82ZQ+;E zb)CB21%ht`JJJxtEGh@~?5}#l5jcw{Y^)&Jam4-2#4hm@OSyT9^fJt=Sawk6m652*99|`THp|h@~-R{ z`Z$ng3Ha9Ln`qhTSVN}oV@~}j|I0FY@EE?W1mR%&hgchb!@Y&~tq08$7O`l3NlMBd zospqQac3dy6BC{cpZ56GZX?km;zQeg<+Wd&-=AlYoyZKxjg`>*37hu%-`MfD<;;~9 zpM^S|P-mq^W;-CoD)8Xfe@yfi5*=JciM)VAQ+N5O0N___m08&0YQD#?MbpK~fQVU8 z1L}DloBMS4^81Nc8_0fMiDJ-t?%)VuMZYICg-f@ze_MZ9N$G{HLCW;4pT^3Q9EflU z!kn9jH>&BN0&C?~wuW{43nd)2INBy28U0*h~J8*=-FAU0ZNAjF&-A`P$&l4zn z%0Jy1wd9V>r~6bPOGdRCR5{MR*yp*#NUT>w1_h_c0SN&iIdrt7*X9J#pbjRGlPlge zM*H7ji3O+NFNB@-RP?J>&2d>r%!CQdAS@#rmPr^JnfSr;!vOU!tIo7AoPdg6)ZI!A zEUV$jvgfg1y=CkPr>EPIx4jEskQ?kg?;9J-By58j|5gZ|@s>Yx8u8z?wBsdaG;Ja< z$!U)Mq=oT-WvWSt7?XPNbiA;5;+QtwS2=2~$&YMF=_IgZYSx%r3;r@o)!SE3E#-dL z1T35g%|^w}p$AJFV_Wa4yfSC?F19BpE>bVZ~Ao>Z?Bhd#Y9 zDNjDF)1k4Gz^YPw$8{n@pS7YXCLYOKuiRgNdfS>fJ#RiI%C{mP8Z3Tf-kBzkrqU50 zpW+sxIq#UlgcH<1%)HkO8}>=_g^P0N912M2-Hs1&ebl^8gwVDw|LMz`P7k9wz4;kB zJ-Xa}mErQVwtpAXU*NHWn-@*Hszip7DbosE328>buX_^+UqD(PBi_F ze zENrIpeQL$%h>BJusV6UE$yBVcWt>?~nYP8qLNJ(!|94Uj_bgn@pzUd*x2!2%@8+<0 z@5%^fu$ltlT9BtF`H?e*k303g-ziuoENSifZ0pB7-3GUJnFvG(ckQRey=4uDBT?8n39&CeZtpF7?I+>2#Eg1=M0KS8R7pu=$%g}b=k_C$)9f(=kRvN=k? zLFtFYgDhdJk=GU81D4h1wx6X2lOHx1BEw~qFw@^%;nrjWEt;rSjH+SFKa#Y zpR(sos~PK7ULr_M?y&N|%EQZaKjtC3x<@SJ^xiHBg=mb5hGC0R#&%@aLwxXLVMRW2iP6 zy5`x;cVv|>IS9Xw>d40HKkxL=c?@4b) z(K2lcro4u`U*k?<)NMJ|(_M#J6Hg9K@Dk6e9{7v_cVHIw9^3WJ)bRW#o==iE2eHJ` z3MYWiy(|mwkAA0%@BA_m&jF{<%3{~s35-CDVX~Ee^7SO#>(tS@pP9!UR3)E7>_5YR zjY&`0J1iEh&yQ}=dO{A7@=p=d!9P2Lo;`<*fs~QZgseP)FTlYMsy@C{Hd(Og{krsb+d7!-COKnkz?^40`AZGr=7z@Mg$)KYO`n^8khVZEQ7 zFNG1{1Q=v~>z!4J`a}fXg*XJElt!YD(1IB3z6M{;J`L7B0RA_MpekJ%1LBedmcd}~EoP$hCQk6H;eQP*>T!#HX-i*X% z;k(CeqmRNO=>Ehmy-Kq8Q|Yk~gwQ_Yds~#^;Ptlo{N0}GAxB7djl>!7uM=KBp6(7X0b6(!#JcY^w^;hVFAN)egI~J_6B_?D?4eY} zSsXa>LrFinD)J*A#`hx1mK9R4NU^7D;$L7p8nl~cGzVm$cUOEV8#uz~Si$#Ki4GkD z;lePvM(Bl<{m2XVmQ8Qj-4HdJ8R~O;f1;ZH)G@6s>i0oo%x?jxP-B$7Lv<4ggA|=V zmr}#MA_~qPA!-3ML^J{l`L;lAYrD=4NKW7r-p}Fq!M*S#{wZKTfz{s{5 zfa2#+^eYtLaAN-@ymG|$rA_tM>XUwt2m9%Xng=2y`HY034|(VFlDUu+1=TGTfF69H zPcyaJ>>AB|-(-|B^q*uODQtHzO_clWWwR-!pv~fY>g_bq9UMW&`|8=w>mprbsu!az zMYkg(MmpDke#Jp4nc?gx`cwB|uPs^{w^zPTboExek*?VoQJ_y0YM&>@46Y?_r{!b5ZFlkAyH zyiRuPa=j@TbT6D}x|f2E+{6(!Go{E-x9)f5Jv*^e#7-=U#21O^EX6e1`?>Jbvb9SWm=fzhx4Y2Re$etT|44FZ4 zQwgQMv#-o72)=Xv%->$)Qt7_%2=QHgJ=gM2R(TyHVHXjw$Ab0Hw0t^*yXw1fK;yJV zPPw&7+C9aaV+08bVzpfT+)!fUWG^?aKojrS`hFw* zTd9+U`;h8ZyUgpIytC@NWm7$sVy;nQxL+A~RhP1OOF#50{4qac9rOK%9za0qNbr}>yK2hBr7QXs3ee(R7_PgO`DqRZf16~J3rpN-p_mUX5UV`8`;h* zvI8$K`)1~z&w2NpbI<+038gD9t0N<#XV0o;uWsGy+~}w{5#u^-Q9A{`cdwckw>ljg zmFW7QR)2pHcTU$jwf(UnXQou$ zRHX4!nE6UDfX@y8|P8oaj#H+-7TK zKuxcz2Jv^Ci^SO(XN*kvi_faKKSfrKO=sC~&lFvm_$UE!bkHe|j6a-rZt4XO z@tA-A;E{(*=h|&_+!1DhGk5DlpPb%ggXpV9&4(k~Co?m%azn8eyLTV5xP;kRk9V|$?M)`-8$eo#%0*g*5_+}xR? zUKe@sipZ(cksJHHi_ZT;!v6k}f3sYTta;$b;o`U2ZNDN%NJNtPwtHQEpjvq}Unt%_ zK0Ym*ZnX9Hz035x^%nIZGzVR+iA-JyWzwo^28651B>TKnSiG1$lyi z;a%?y6u5}u=|}nZMUkgZIXQFA$;B7E6H`7f{9U(ASUwZ_*(&)OwsC{Xwjq^UcBs5& zWAYhaC}O9N{48=$KIIyv)uo=ORz7DVv->9x7cX7U8NFUOB~G}%I4!=~MwQzBkD8nh zrT8x9{9XO~Kb`#i*G^8Jc2e>1fiF_Ip5&};qca1M50Y9vITyWCH*Z&Y&pT9J|5}xr zpG{`hhngJvfvuUKm{V7I&PMtcoLMZ)bfLs1$q1*xYWbwo(oh&wYWIIC$Za1=LV@J< zp&-BdjT4{ivZ^<^t1goVFKe)wKNw~|-YCuSmbBF%xX9I*1}<1U6O_9dSO3oo82nW%}vcNv4R z7?ZKFfh}xe8wOYwV+|HqCnBm-p||+is}tq=J)a12JKwCaf#)xYeEC2m|9UP--o@_z z|ME(|%Zy(1WB>W2lO5ZP^!AcVzBmkO@Y~-K#lP{N73^`);za%Cbh97WR67kNdftr_rkJ{QE*jW9d>!^jFgf&?pt+pItQxvxmz7?m7r2(XO;u}8yd?5toL23TN%4MteA>@i-l zJ!Mtao$M!Q#pz;MH|U)xi>_^THad6i#E~7dwZ=3{G7PZ51RIR7X4%6e#*AZoTAQhC zW>ds|f&p1KXaMP*T5Y&Ls#TfqS%*~wDwQ@DOKigc%Z7E*WUC6hP?(c#v(*r_17(9f zHrrEnc5I4pByPq1)b@mPo1;~$MDF>xiTfkl;hZte1pnS6R<2!3W`hF;SZ-XeF&m7q z!tB2`i4S2a*&r0CDQF=-Yy10>eI5G=TJdy7I6^=0j&0gnPqafi3}XXLE02vd0vI0# zSdx8>dPZw!s=da!*|q-CU-2Pq4dm4hpF-4V1cG<~2DNP=#GkYg#B;-TOizl(4NWq3 zd(^@JOPoh0UhAB)_irjR%^X=7ua+a|PS#5{s2yo5PWTvo=>~@SPOfw#w7C22L&5+{ zx&?p{dCBiyrdp05VS5fYw$fyzVqOJ`s`pu~5JsoA~5zrG~!w9ozNto61PcIt;Mj z6mk;USUzVbU``|>pVx`*YL$A70*H8q?!=ea4K*Tc!MY4(8cf0(R2%Ff30T!5GgAvv&d+bOe?fYEtf-+hx zGA0Tj*U+7iY^d+c-Ns`R+c5Bg2{ssE&9XPqj6(oJ6-Q7;i$%tax47ONbSL6>x!ZVb zVjBinV1f-sSYb||t+ehj&nKFy`9TC_v{+G8^b$vF1q(+O-~3!B*HZ&+Z04MtcOR8e@y5?}Pv zKB_o^GFoiB<@KMucb}10tx00H8_uM15H_%ts*W(g0#nSEVSQOg@DT9}-3VzPRUAPX zEtUZXR*QW8z980}Iz2P#OfWV!u$Ah-Fu(#+Q_~9DWz$8q-w*CDKOW|ax7TJXH9vSu zGM$)AbSESm$|Etn)IyMcmz*G+maVKs70000< KMNUMnLSTX_Q?vj8 literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/icon.icns b/desktop/src-tauri/icons/icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..d0876646312d6507113e7df84fbbaa2d40bdceb7 GIT binary patch literal 152014 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üerOB;O2^$rS+m2h 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%0AoS{dSyOYd(mfame$n@ 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 literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/icon.ico b/desktop/src-tauri/icons/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b33e51e20f4ed2b03f917f266d28322415e6e750 GIT binary patch literal 32665 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 Y?mffUsgDHH-+mq1^K?c3-*!d+3-VRsI{*Lx literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/icons/icon.png b/desktop/src-tauri/icons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a7f7b1c2962b4dd77c7cc67703550573cc0a34ad GIT binary patch literal 4251 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 literal 0 HcmV?d00001 diff --git a/desktop/src-tauri/src/autostart.rs b/desktop/src-tauri/src/autostart.rs new file mode 100644 index 0000000..e711ee5 --- /dev/null +++ b/desktop/src-tauri/src/autostart.rs @@ -0,0 +1,25 @@ +//! Автозапуск приложения (docs/client-tauri.md §5). +//! +//! Запуск идёт с аргументом `--minimized`: приложение поднимается свёрнутым в +//! трей и не перебивает работу пользователя окном. + +use tauri::{AppHandle, Runtime}; +use tauri_plugin_autostart::ManagerExt; + +/// Аргумент командной строки для запуска свёрнутым в трей. +pub const MINIMIZED_ARG: &str = "--minimized"; + +/// Приводит системный автозапуск в соответствие с настройкой. +pub fn apply(app: &AppHandle, enabled: bool) -> Result<(), String> { + let manager = app.autolaunch(); + let current = manager.is_enabled().unwrap_or(false); + if current == enabled { + return Ok(()); + } + let result = if enabled { + manager.enable() + } else { + manager.disable() + }; + result.map_err(|error| format!("не удалось изменить автозапуск: {error}")) +} diff --git a/desktop/src-tauri/src/bridge.rs b/desktop/src-tauri/src/bridge.rs new file mode 100644 index 0000000..9bb80f0 --- /dev/null +++ b/desktop/src-tauri/src/bridge.rs @@ -0,0 +1,68 @@ +//! Мост «Rust → веб-клиент». +//! +//! Обратное направление (страница → обёртка) идёт через типизированные команды +//! (`commands.rs`), а события платформы передаются вызовом единственной функции +//! `window.__glchatDesktop.receive(...)` в самой странице. Отдельного канала +//! событий нет намеренно: сообщений мало, а типы у них общие с `web/src/lib/platform.ts`. + +use serde::Serialize; +use tauri::{AppHandle, Manager, Runtime}; + +use crate::settings::Settings; +use crate::state::AppState; + +/// Метка главного окна (единственное окно приложения). +pub const WEB_WINDOW: &str = "main"; + +/// Сообщение веб-клиенту: то, что платформа сообщает странице. +#[derive(Debug, Clone, Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum WebMessage { + /// Нажат или отпущен глобальный push-to-talk. + Ptt { active: bool }, + /// Переключить микрофон (глобальный шорткат). + ToggleMic, + /// Переключить «не слышу» (глобальный шорткат). + ToggleDeafen, + /// Открыть deep link: приглашение или сервер с комнатой. + DeepLink { url: String }, + /// Настройки обёртки изменились (обновлена страница настроек). + Settings { settings: Settings }, + /// Доступно обновление — клиент показывает уведомление в интерфейсе. + UpdateAvailable { version: String }, +} + +/// Отправляет сообщение в веб-клиент. +/// +/// Если клиент ещё не загрузился, deep link ставится в очередь и будет отдан +/// после `desktop_ready` (docs/client-tauri.md §5). Остальные сообщения в этот +/// момент терять не страшно: они относятся к активному взаимодействию. +pub fn send(app: &AppHandle, message: &WebMessage) -> bool { + let state = app.state::(); + if !state.web_ready() { + if let WebMessage::DeepLink { url } = message { + state.push_deep_link(url.clone()); + } + return false; + } + dispatch(app, message) +} + +/// Немедленная доставка без проверки готовности клиента. +pub fn dispatch(app: &AppHandle, message: &WebMessage) -> bool { + let Some(window) = app.get_webview_window(WEB_WINDOW) else { + return false; + }; + let Ok(payload) = serde_json::to_string(message) else { + log::warn!("не удалось сериализовать сообщение веб-клиенту"); + return false; + }; + let script = format!("window.__glchatDesktop && window.__glchatDesktop.receive({payload});"); + match window.eval(&script) { + Ok(()) => true, + Err(error) => { + log::debug!("веб-клиент не принял сообщение: {error}"); + false + } + } +} diff --git a/desktop/src-tauri/src/commands.rs b/desktop/src-tauri/src/commands.rs new file mode 100644 index 0000000..a6c79e4 --- /dev/null +++ b/desktop/src-tauri/src/commands.rs @@ -0,0 +1,128 @@ +//! Команды обёртки: типизированный мост «веб-клиент → Rust» (docs/client-tauri.md §2). +//! +//! Команд ровно столько, сколько нужно странице: прочитать и сохранить +//! настройки, сообщить о готовности, показать уведомление, обновить счётчик +//! непрочитанных, открыть настройки/клиент и проверить обновления. Никакой +//! бизнес-логики здесь нет — только платформенные действия. + +use tauri::{AppHandle, Manager, Runtime}; + +use crate::bridge::{self, WebMessage}; +use crate::settings::Settings; +use crate::state::AppState; +use crate::{autostart, instance, notifications, shortcuts, updates, window}; + +/// Текущие настройки обёртки. +#[tauri::command] +pub fn desktop_settings(app: AppHandle) -> Settings { + app.state::().settings() +} + +/// Версия приложения — показывается на странице настроек. +#[tauri::command] +pub fn desktop_version(app: AppHandle) -> String { + app.package_info().version.to_string() +} + +/// Сохраняет настройки и применяет их: автозапуск, шорткаты, адрес инстанса. +#[tauri::command] +pub fn desktop_save_settings( + app: AppHandle, + settings: Settings, +) -> Result { + // Адрес проверяем до применения, чтобы не оставить обёртку без клиента. + let url = instance::normalize(&settings.instance_url)?; + let mut next = settings; + next.instance_url = instance::display(&url); + + let previous = app.state::().settings(); + // Шорткаты применяем первыми: если комбинация занята, настройки не сохраняем. + if next.ptt_shortcut != previous.ptt_shortcut + || next.mute_shortcut != previous.mute_shortcut + || next.deafen_shortcut != previous.deafen_shortcut + { + if let Err(error) = shortcuts::apply(&app, &next) { + let _ = shortcuts::apply(&app, &previous); + return Err(error); + } + } + if let Err(error) = autostart::apply(&app, next.autostart) { + log::warn!("{error}"); + } + + app.state::().set_settings(next.clone()); + crate::settings::save(&app, &next)?; + crate::tray::refresh(&app); + announce_settings(&app, &next); + if next.instance_url != previous.instance_url { + window::open_instance_page(&app)?; + } + Ok(next) +} + +/// Веб-клиент загрузился: отдаём накопленные deep link. +#[tauri::command] +pub fn desktop_ready(app: AppHandle) { + let pending = app.state::().mark_web_ready(); + for url in pending { + bridge::dispatch(&app, &WebMessage::DeepLink { url }); + } +} + +/// Показывает системное уведомление. +#[tauri::command] +pub fn desktop_notify( + app: AppHandle, + payload: notifications::NotifyPayload, +) -> Result<(), String> { + notifications::show(&app, &payload) +} + +/// Обновляет счётчик непрочитанных в доке и трее. +#[tauri::command] +pub fn desktop_set_badge(app: AppHandle, count: u32) { + notifications::set_badge(&app, count); +} + +/// Открывает локальную страницу настроек обёртки. +#[tauri::command] +pub fn desktop_open_settings(app: AppHandle) -> Result<(), String> { + window::open_settings_page(&app) +} + +/// Возвращает окно к клиенту инстанса. +#[tauri::command] +pub fn desktop_open_instance(app: AppHandle) -> Result<(), String> { + window::open_instance_page(&app) +} + +/// Перезагружает клиент инстанса. +#[tauri::command] +pub fn desktop_reload(app: AppHandle) -> Result<(), String> { + window::reload_instance(&app) +} + +/// Проверяет обновления (кнопка на странице настроек). +#[tauri::command] +pub async fn desktop_check_updates(app: AppHandle) { + updates::check(app, true).await; +} + +/// Открывает ссылку в системном браузере. +#[tauri::command] +pub fn desktop_open_external(app: AppHandle, url: String) -> Result<(), String> { + let parsed = instance::normalize(&url)?; + tauri_plugin_opener::OpenerExt::opener(&app) + .open_url(parsed.as_str(), None::<&str>) + .map_err(|error| format!("не удалось открыть ссылку: {error}")) +} + +/// Сообщает веб-клиенту, что настройки обёртки изменились. +pub fn announce_settings(app: &AppHandle, settings: &Settings) { + bridge::send( + app, + &WebMessage::Settings { + settings: settings.clone(), + }, + ); +} diff --git a/desktop/src-tauri/src/deeplink.rs b/desktop/src-tauri/src/deeplink.rs new file mode 100644 index 0000000..8fe9b68 --- /dev/null +++ b/desktop/src-tauri/src/deeplink.rs @@ -0,0 +1,47 @@ +//! Deep links `glchat://…` (docs/client-tauri.md §5). +//! +//! Поддерживаются `glchat://invite/` и `glchat://guild//channel/`. +//! Ссылка приходит и при холодном старте (приложение ещё поднимается), и при +//! тёплом: в первом случае она ждёт в очереди до `desktop_ready` веб-клиента. + +use tauri::{AppHandle, Runtime}; +use tauri_plugin_deep_link::DeepLinkExt; + +use crate::bridge::{self, WebMessage}; + +/// Схема deep link, зарегистрированная в `tauri.conf.json`. +pub const SCHEME: &str = "glchat"; + +/// Подписывается на ссылки, пришедшие из системы. +pub fn install(app: &AppHandle) { + let handle = app.clone(); + app.deep_link().on_open_url(move |event| { + for url in event.urls() { + log::info!("deep link: {url}"); + bridge::send(&handle, &WebMessage::DeepLink { url: url.to_string() }); + } + }); + + // В разработке и в AppImage схема может быть не прописана в системе: + // регистрируем её на лету (в собранном .app/установщике это делает бандл). + if let Err(error) = app.deep_link().register_all() { + log::debug!("схема {SCHEME}:// не зарегистрирована автоматически: {error}"); + } + + // Ссылка могла быть передана аргументом командной строки (Windows/Linux). + if let Ok(Some(urls)) = app.deep_link().get_current() { + for url in urls { + bridge::send(app, &WebMessage::DeepLink { url: url.to_string() }); + } + } +} + +/// Достаёт deep link из аргументов повторного запуска приложения. +/// +/// Второй экземпляр не поднимается (single-instance): его аргументы приходят +/// первому, и ссылку нужно доставить в уже открытый клиент. +pub fn from_args(args: &[String]) -> Option { + args.iter() + .find(|arg| arg.starts_with(&format!("{SCHEME}://"))) + .cloned() +} diff --git a/desktop/src-tauri/src/instance.rs b/desktop/src-tauri/src/instance.rs new file mode 100644 index 0000000..9ebf54a --- /dev/null +++ b/desktop/src-tauri/src/instance.rs @@ -0,0 +1,59 @@ +//! Адрес инстанса и границы навигации. +//! +//! Desktop-обёртка загружает тот же клиент, что и браузер, но только с одного +//! адреса: переходы на сторонние сайты уходят в системный браузер +//! (docs/client-tauri.md §6). + +use url::Url; + +/// Приводит введённый пользователем адрес к абсолютному URL. +/// +/// Допускаются `http` и `https`; схема по умолчанию — `https`, чтобы в поле +/// настроек можно было написать просто `gl.mhspx.su`. +pub fn normalize(input: &str) -> Result { + let trimmed = input.trim(); + if trimmed.is_empty() { + return Err("адрес инстанса не заполнен".to_string()); + } + let candidate = if trimmed.contains("://") { + trimmed.to_string() + } else { + format!("https://{trimmed}") + }; + let url = Url::parse(&candidate).map_err(|error| format!("некорректный адрес: {error}"))?; + match url.scheme() { + "http" | "https" => {} + other => return Err(format!("поддерживаются только http и https, а не «{other}»")), + } + if url.host_str().unwrap_or_default().is_empty() { + return Err("в адресе нет имени хоста".to_string()); + } + Ok(url) +} + +/// Строка адреса для загрузки в окно: без завершающего слэша. +pub fn display(url: &Url) -> String { + url.as_str().trim_end_matches('/').to_string() +} + +/// Хост адреса — граница, внутри которой разрешена навигация webview. +pub fn host(url: &Url) -> String { + url.host_str().unwrap_or_default().to_ascii_lowercase() +} + +/// Разрешена ли навигация внутри окна. +/// +/// Свой инстанс и локальные страницы обёртки (`tauri://localhost`) — да, +/// всё остальное открывается в системном браузере. +pub fn navigation_allowed(target: &Url, instance_host: &str) -> bool { + match target.scheme() { + // Локальные ресурсы обёртки: страница настроек. + "tauri" | "asset" => true, + "http" | "https" => { + let host = target.host_str().unwrap_or_default().to_ascii_lowercase(); + // На Windows/Linux локальная страница отдаётся как http://tauri.localhost. + host == "tauri.localhost" || (!instance_host.is_empty() && host == instance_host) + } + _ => false, + } +} diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs new file mode 100644 index 0000000..1d8e9ca --- /dev/null +++ b/desktop/src-tauri/src/lib.rs @@ -0,0 +1,243 @@ +//! glchat desktop — обёртка Tauri 2 вокруг веб-клиента (docs/client-tauri.md). +//! +//! Принцип: тот же веб-код, что и в браузере, плюс системная интеграция — +//! трей, нативные уведомления, глобальный push-to-talk, автозапуск, +//! автообновление и deep links. Бизнес-логики в Rust нет: обёртка знает только +//! адрес инстанса, свои переключатели и границы навигации. + +mod autostart; +mod bridge; +mod commands; +mod deeplink; +mod instance; +mod notifications; +mod settings; +mod shortcuts; +mod state; +mod tray; +mod updates; +mod window; + +use std::time::Duration; + +use tauri::{Manager, WindowEvent}; +use tauri_plugin_autostart::MacosLauncher; +use tauri_plugin_dialog::{DialogExt, MessageDialogButtons}; + +use state::AppState; + +/// Задержка перед фоновой проверкой обновлений: окно должно успеть открыться. +const UPDATE_CHECK_DELAY: Duration = Duration::from_secs(30); + +/// Задержка перед вопросом об автозапуске при первом запуске. +const AUTOSTART_PROMPT_DELAY: Duration = Duration::from_secs(3); + +/// Аргументы командной строки обёртки. +#[derive(Debug, Default)] +struct Cli { + /// Переопределение адреса инстанса (`--instance https://…`). + instance: Option, + /// Запуск свёрнутым в трей (используется автозапуском). + minimized: bool, + /// Сразу открыть страницу настроек обёртки. + settings: bool, + /// Принудительно включить или выключить автозапуск (установка скриптом). + autostart: Option, +} + +impl Cli { + fn parse() -> Self { + let mut cli = Self::default(); + let mut args = std::env::args().skip(1); + while let Some(arg) = args.next() { + match arg.as_str() { + "--instance" => cli.instance = args.next(), + "--minimized" => cli.minimized = true, + "--settings" => cli.settings = true, + "--autostart" => cli.autostart = args.next().as_deref().and_then(parse_switch), + other => { + if let Some(value) = other.strip_prefix("--instance=") { + cli.instance = Some(value.to_string()); + } else if let Some(value) = other.strip_prefix("--autostart=") { + cli.autostart = parse_switch(value); + } + } + } + } + cli + } +} + +/// Разбирает `on/off` (а также `true/false`, `1/0`) из аргументов командной строки. +fn parse_switch(value: &str) -> Option { + match value.trim().to_ascii_lowercase().as_str() { + "on" | "true" | "1" | "yes" => Some(true), + "off" | "false" | "0" | "no" => Some(false), + _ => None, + } +} + +/// Точка входа приложения. +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + let cli = Cli::parse(); + + tauri::Builder::default() + // Single-instance регистрируется первым: повторный запуск передаёт + // аргументы (в том числе deep link) первому экземпляру и завершается. + .plugin(tauri_plugin_single_instance::init(|app, argv, _cwd| { + window::show_main(app); + if let Some(url) = deeplink::from_args(&argv) { + bridge::send(app, &bridge::WebMessage::DeepLink { url }); + } + })) + .plugin( + tauri_plugin_log::Builder::default() + .level(log::LevelFilter::Info) + .build(), + ) + .plugin(tauri_plugin_store::Builder::new().build()) + .plugin(tauri_plugin_notification::init()) + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_window_state::Builder::default().build()) + .plugin(tauri_plugin_updater::Builder::new().build()) + .plugin(tauri_plugin_deep_link::init()) + .plugin(tauri_plugin_autostart::init( + MacosLauncher::LaunchAgent, + Some(vec![autostart::MINIMIZED_ARG]), + )) + .plugin( + tauri_plugin_global_shortcut::Builder::new() + .with_handler(shortcuts::on_shortcut) + .build(), + ) + .invoke_handler(tauri::generate_handler![ + commands::desktop_settings, + commands::desktop_save_settings, + commands::desktop_version, + commands::desktop_ready, + commands::desktop_notify, + commands::desktop_set_badge, + commands::desktop_open_settings, + commands::desktop_open_instance, + commands::desktop_reload, + commands::desktop_check_updates, + commands::desktop_open_external, + ]) + .setup(move |app| { + setup(app.handle(), &cli); + Ok(()) + }) + .on_window_event(|window, event| { + // Закрытие окна: либо сворачиваемся в трей, либо выходим целиком + // (docs/client-tauri.md §2; открытый вопрос §9.2 решён настройкой). + if let WindowEvent::CloseRequested { api, .. } = event { + let app = window.app_handle(); + if app.state::().settings().close_to_tray { + api.prevent_close(); + if let Err(error) = window.hide() { + log::warn!("не удалось свернуть окно в трей: {error}"); + } + } else { + app.exit(0); + } + } + }) + .run(tauri::generate_context!()) + .expect("не удалось запустить glchat desktop"); +} + +/// Начальная настройка: настройки, трей, окно, шорткаты, deep links. +fn setup(app: &tauri::AppHandle, cli: &Cli) { + let mut current = settings::load(app); + if let Some(instance) = &cli.instance { + match instance::normalize(instance) { + Ok(url) => current.instance_url = instance::display(&url), + Err(error) => log::warn!("адрес из командной строки не принят: {error}"), + } + } + // Аргумент `--autostart` перекрывает сохранённое значение и снимает + // необходимость спрашивать пользователя при первом запуске. + if let Some(autostart) = cli.autostart { + current.autostart = autostart; + current.autostart_prompted = true; + } + app.manage(AppState::default()); + app.state::().set_settings(current.clone()); + if let Err(error) = settings::save(app, ¤t) { + log::warn!("не удалось сохранить настройки при старте: {error}"); + } + + if let Err(error) = autostart::apply(app, current.autostart) { + log::warn!("{error}"); + } + if let Err(error) = tray::build(app) { + log::error!("{error}"); + } + if let Err(error) = window::create_main(app, ¤t, cli.minimized) { + log::error!("{error}"); + } + if let Err(error) = shortcuts::apply(app, ¤t) { + log::warn!("{error}"); + } + + deeplink::install(app); + + log::info!( + "обёртка запущена: адрес={}, окно={}, автозапуск={}", + current.instance_url, + if cli.minimized { "свёрнуто" } else { "видимо" }, + current.autostart + ); + + if cli.settings { + if let Err(error) = window::open_settings_page(app) { + log::warn!("{error}"); + } + } + + spawn_update_check(app.clone()); + spawn_autostart_prompt(app.clone()); +} + +/// Фоновая проверка обновлений при старте (без диалогов). +fn spawn_update_check(app: tauri::AppHandle) { + std::thread::spawn(move || { + std::thread::sleep(UPDATE_CHECK_DELAY); + tauri::async_runtime::spawn(async move { + updates::check(app, false).await; + }); + }); +} + +/// Вопрос об автозапуске при первом запуске (docs/client-tauri.md §5). +fn spawn_autostart_prompt(app: tauri::AppHandle) { + std::thread::spawn(move || { + std::thread::sleep(AUTOSTART_PROMPT_DELAY); + if app.state::().settings().autostart_prompted { + return; + } + let handle = app.clone(); + app.dialog() + .message( + "Запускать glchat при входе в систему? Приложение будет стартовать свёрнутым в трей.", + ) + .title("Автозапуск glchat") + .buttons(MessageDialogButtons::YesNo) + .show(move |confirmed| { + log::info!("ответ на вопрос об автозапуске: {confirmed}"); + let mut next = handle.state::().settings(); + next.autostart = confirmed; + next.autostart_prompted = true; + handle.state::().set_settings(next.clone()); + if let Err(error) = autostart::apply(&handle, next.autostart) { + log::warn!("{error}"); + } + if let Err(error) = settings::save(&handle, &next) { + log::warn!("не удалось сохранить настройки: {error}"); + } + tray::refresh(&handle); + }); + }); +} diff --git a/desktop/src-tauri/src/main.rs b/desktop/src-tauri/src/main.rs new file mode 100644 index 0000000..785c32f --- /dev/null +++ b/desktop/src-tauri/src/main.rs @@ -0,0 +1,6 @@ +// Отключает лишнее консольное окно на Windows в релизной сборке. +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + glchat_desktop_lib::run(); +} diff --git a/desktop/src-tauri/src/notifications.rs b/desktop/src-tauri/src/notifications.rs new file mode 100644 index 0000000..fb52cb8 --- /dev/null +++ b/desktop/src-tauri/src/notifications.rs @@ -0,0 +1,68 @@ +//! Нативные уведомления и счётчик непрочитанных (docs/client-tauri.md §5). +//! +//! Решение о том, показывать ли уведомление, принимает веб-клиент (он знает про +//! упоминания, личные сообщения и настройки пользователя), а обёртка только +//! показывает системное уведомление и обновляет бейдж. + +use serde::Deserialize; +use tauri::{AppHandle, Manager, Runtime}; +use tauri_plugin_notification::NotificationExt; + +use crate::bridge::WEB_WINDOW; +use crate::state::AppState; + +/// Уведомление, пришедшее из веб-клиента. +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct NotifyPayload { + /// Заголовок: имя автора или название сервера. + pub title: String, + /// Текст: начало сообщения. + pub body: String, + /// Сервер и комната — нужны для перехода по клику (в текущем инкременте + /// только сохраняются в логе: клик по уведомлению обрабатывается системой). + #[serde(default)] + pub guild_id: Option, + #[serde(default)] + pub channel_id: Option, +} + +/// Показывает системное уведомление, если они включены в настройках обёртки. +pub fn show(app: &AppHandle, payload: &NotifyPayload) -> Result<(), String> { + if !app.state::().settings().notifications { + return Ok(()); + } + // В лог не попадают ни текст сообщения, ни имя автора (docs/client-tauri.md §6). + log::debug!( + "показываем уведомление (сервер {:?}, комната {:?})", + payload.guild_id, + payload.channel_id + ); + app.notification() + .builder() + .title(payload.title.clone()) + .body(payload.body.clone()) + .show() + .map_err(|error| format!("не удалось показать уведомление: {error}")) +} + +/// Обновляет число непрочитанных: значок приложения и подпись у иконки в трее. +pub fn set_badge(app: &AppHandle, count: u32) { + let count = app.state::().set_badge(count); + if let Some(window) = app.get_webview_window(WEB_WINDOW) { + // На части платформ бейдж не поддерживается — это не ошибка. + let _ = window.set_badge_count(if count == 0 { None } else { Some(i64::from(count)) }); + } + if let Some(tray) = app.tray_by_id(crate::tray::TRAY_ID) { + let _ = tray.set_title(if count == 0 { + None + } else { + Some(count.to_string()) + }); + let _ = tray.set_tooltip(Some(if count == 0 { + "glchat".to_string() + } else { + format!("glchat — непрочитанных: {count}") + })); + } +} diff --git a/desktop/src-tauri/src/settings.rs b/desktop/src-tauri/src/settings.rs new file mode 100644 index 0000000..fd5a42b --- /dev/null +++ b/desktop/src-tauri/src/settings.rs @@ -0,0 +1,94 @@ +//! Настройки desktop-обёртки. +//! +//! Лежат в `tauri-plugin-store` (`settings.json` в каталоге конфигурации +//! приложения). Обёртка хранит только то, что относится к платформе: адрес +//! инстанса и переключатели поведения. Сессия целиком живёт в cookie webview +//! (docs/client-tauri.md §2): токенов и паролей здесь нет. + +use serde::{Deserialize, Serialize}; +use tauri::{AppHandle, Runtime}; +use tauri_plugin_store::StoreExt; + +/// Файл хранилища в каталоге конфигурации приложения. +const STORE_FILE: &str = "settings.json"; +/// Ключ, под которым лежит объект настроек. +const STORE_KEY: &str = "settings"; + +/// Адрес стенда по умолчанию: тот же клиент, что открывается в браузере. +pub const DEFAULT_INSTANCE: &str = "https://gl.mhspx.su"; + +/// Комбинация push-to-talk по умолчанию. +/// +/// Голых клавиш (как `V` в браузерном PTT) в глобальном шорткате быть не может: +/// системный перехват занял бы клавишу у всех приложений, поэтому по умолчанию +/// комбинация с модификаторами, а пустая строка означает «выключено». +pub const DEFAULT_PTT_SHORTCUT: &str = "CommandOrControl+Shift+Space"; + +/// Комбинация «выключить/включить микрофон» по умолчанию. +pub const DEFAULT_MUTE_SHORTCUT: &str = "CommandOrControl+Shift+M"; + +/// Комбинация «не слышу» (deafen) по умолчанию. +pub const DEFAULT_DEAFEN_SHORTCUT: &str = "CommandOrControl+Shift+D"; + +/// Настройки обёртки. Поля в camelCase — их читает и пишет страница настроек. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default, rename_all = "camelCase")] +pub struct Settings { + /// Адрес инстанса, который загружается в главное окно. + pub instance_url: String, + /// Закрытие окна сворачивает приложение в трей. + pub close_to_tray: bool, + /// Запускать приложение при входе в систему (свёрнутым в трей). + pub autostart: bool, + /// Пользователю уже задавали вопрос про автозапуск при первом запуске. + pub autostart_prompted: bool, + /// Глобальный push-to-talk (пустая строка — выключен). + pub ptt_shortcut: String, + /// Глобальное переключение микрофона (пустая строка — выключено). + pub mute_shortcut: String, + /// Глобальное переключение «не слышу» (пустая строка — выключено). + pub deafen_shortcut: String, + /// Показывать нативные уведомления об упоминаниях и личных сообщениях. + pub notifications: bool, +} + +impl Default for Settings { + fn default() -> Self { + Self { + instance_url: DEFAULT_INSTANCE.to_string(), + close_to_tray: true, + autostart: false, + autostart_prompted: false, + ptt_shortcut: DEFAULT_PTT_SHORTCUT.to_string(), + mute_shortcut: DEFAULT_MUTE_SHORTCUT.to_string(), + deafen_shortcut: DEFAULT_DEAFEN_SHORTCUT.to_string(), + notifications: true, + } + } +} + +/// Читает настройки из хранилища; при отсутствии или порче — значения по умолчанию. +pub fn load(app: &AppHandle) -> Settings { + let Ok(store) = app.store(STORE_FILE) else { + log::warn!("не удалось открыть хранилище настроек, используются значения по умолчанию"); + return Settings::default(); + }; + let Some(value) = store.get(STORE_KEY) else { + return Settings::default(); + }; + match serde_json::from_value::(value) { + Ok(settings) => settings, + Err(error) => { + log::warn!("настройки в хранилище повреждены ({error}), берём значения по умолчанию"); + Settings::default() + } + } +} + +/// Сохраняет настройки в хранилище. +pub fn save(app: &AppHandle, settings: &Settings) -> Result<(), String> { + let store = app.store(STORE_FILE).map_err(|error| error.to_string())?; + let value = serde_json::to_value(settings).map_err(|error| error.to_string())?; + store.set(STORE_KEY, value); + store.save().map_err(|error| error.to_string()) +} diff --git a/desktop/src-tauri/src/shortcuts.rs b/desktop/src-tauri/src/shortcuts.rs new file mode 100644 index 0000000..fbd147d --- /dev/null +++ b/desktop/src-tauri/src/shortcuts.rs @@ -0,0 +1,67 @@ +//! Глобальные горячие клавиши (docs/client-tauri.md §5). +//! +//! Push-to-talk работает при неактивном окне: системный перехват ловит нажатие +//! и отпускание выбранной комбинации и передаёт состояние в веб-клиент, а тот +//! включает микрофон (в самом клиенте должен быть выбран режим «Push-to-talk»). +//! Дополнительно доступны переключение микрофона и «не слышу». + +use tauri::{AppHandle, Manager, Runtime}; +use tauri_plugin_global_shortcut::{GlobalShortcutExt, Shortcut, ShortcutState}; + +use crate::bridge::{self, WebMessage}; +use crate::settings::Settings; +use crate::state::AppState; + +/// Обработчик нажатий: плагин вызывает его для любой зарегистрированной комбинации. +pub fn on_shortcut(app: &AppHandle, shortcut: &Shortcut, event: tauri_plugin_global_shortcut::ShortcutEvent) { + let settings = app.state::().settings(); + let pressed = event.state == ShortcutState::Pressed; + + let ptt = parse(&settings.ptt_shortcut); + if ptt.as_ref() == Some(shortcut) { + bridge::send(app, &WebMessage::Ptt { active: pressed }); + return; + } + // Остальные шорткаты срабатывают по нажатию, чтобы не дублировать действие. + if !pressed { + return; + } + if parse(&settings.mute_shortcut).as_ref() == Some(shortcut) { + bridge::send(app, &WebMessage::ToggleMic); + return; + } + if parse(&settings.deafen_shortcut).as_ref() == Some(shortcut) { + bridge::send(app, &WebMessage::ToggleDeafen); + } +} + +/// Перерегистрирует комбинации после изменения настроек. +pub fn apply(app: &AppHandle, settings: &Settings) -> Result<(), String> { + let shortcuts = app.global_shortcut(); + shortcuts + .unregister_all() + .map_err(|error| format!("не удалось снять старые шорткаты: {error}"))?; + + for spec in [ + &settings.ptt_shortcut, + &settings.mute_shortcut, + &settings.deafen_shortcut, + ] { + if spec.trim().is_empty() { + continue; + } + shortcuts + .register(spec.as_str()) + .map_err(|error| format!("комбинация «{spec}» не зарегистрирована: {error}"))?; + } + Ok(()) +} + +/// Разбирает строку комбинации; пустая строка и мусор дают `None`. +fn parse(spec: &str) -> Option { + let trimmed = spec.trim(); + if trimmed.is_empty() { + return None; + } + trimmed.parse::().ok() +} diff --git a/desktop/src-tauri/src/state.rs b/desktop/src-tauri/src/state.rs new file mode 100644 index 0000000..348993f --- /dev/null +++ b/desktop/src-tauri/src/state.rs @@ -0,0 +1,68 @@ +//! Общее состояние процесса: настройки, готовность веб-клиента и очередь +//! сообщений, которые нужно передать в страницу. + +use std::sync::Mutex; + +use crate::settings::Settings; + +/// Состояние, доступное командам, трею и обработчикам событий. +#[derive(Default)] +pub struct AppState { + inner: Mutex, +} + +#[derive(Default)] +struct Inner { + settings: Settings, + /// Веб-клиент сообщил, что загрузился и готов принимать события. + web_ready: bool, + /// Ссылки, пришедшие до готовности клиента (холодный старт deep link). + pending_deep_links: Vec, + /// Последнее переданное в трей/док число непрочитанных. + badge: u32, +} + +impl AppState { + /// Текущие настройки (копия). + pub fn settings(&self) -> Settings { + self.lock().settings.clone() + } + + /// Заменяет настройки в памяти (запись в хранилище — отдельно). + pub fn set_settings(&self, settings: Settings) { + self.lock().settings = settings; + } + + /// Отмечает веб-клиент готовым и отдаёт накопленные deep link. + pub fn mark_web_ready(&self) -> Vec { + let mut inner = self.lock(); + inner.web_ready = true; + std::mem::take(&mut inner.pending_deep_links) + } + + /// Готов ли веб-клиент принимать сообщения. + pub fn web_ready(&self) -> bool { + self.lock().web_ready + } + + /// Ставит deep link в очередь (если клиент ещё не готов). + pub fn push_deep_link(&self, url: String) { + let mut inner = self.lock(); + if inner.pending_deep_links.len() < 16 { + inner.pending_deep_links.push(url); + } + } + + /// Запоминает число непрочитанных и возвращает его. + pub fn set_badge(&self, count: u32) -> u32 { + let mut inner = self.lock(); + inner.badge = count; + inner.badge + } + + fn lock(&self) -> std::sync::MutexGuard<'_, Inner> { + // Отравленный мьютекс не должен ронять приложение: состояние — + // это только настройки и очередь событий. + self.inner.lock().unwrap_or_else(|error| error.into_inner()) + } +} diff --git a/desktop/src-tauri/src/tray.rs b/desktop/src-tauri/src/tray.rs new file mode 100644 index 0000000..1fc91c8 --- /dev/null +++ b/desktop/src-tauri/src/tray.rs @@ -0,0 +1,157 @@ +//! Иконка в трее: индикатор непрочитанных и меню управления обёрткой +//! (docs/client-tauri.md §2 — «открыть, mute, статус, выйти»). + +use tauri::menu::{CheckMenuItem, Menu, MenuItem, PredefinedMenuItem}; +use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}; +use tauri::{AppHandle, Manager, Runtime}; + +use crate::state::AppState; +use crate::{autostart, commands, settings, shortcuts, updates, window}; + +/// Идентификатор иконки в трее. +pub const TRAY_ID: &str = "main"; + +/// Создаёт иконку в трее с меню по текущим настройкам. +pub fn build(app: &AppHandle) -> Result<(), String> { + let icon = app + .default_window_icon() + .cloned() + .ok_or_else(|| "в сборке нет иконки приложения".to_string())?; + TrayIconBuilder::with_id(TRAY_ID) + .icon(icon) + .icon_as_template(true) + .tooltip("glchat") + .menu(&menu(app)?) + .show_menu_on_left_click(false) + .on_menu_event(on_menu_event) + .on_tray_icon_event(|tray, event| { + // Левый клик по иконке — показать окно, меню остаётся на правом. + if let TrayIconEvent::Click { + button: MouseButton::Left, + button_state: MouseButtonState::Up, + .. + } = event + { + window::show_main(tray.app_handle()); + } + }) + .build(app) + .map_err(|error| format!("не удалось создать иконку в трее: {error}"))?; + Ok(()) +} + +/// Пересобирает меню: галочки должны совпадать с текущими настройками. +pub fn refresh(app: &AppHandle) { + let Some(tray) = app.tray_by_id(TRAY_ID) else { + return; + }; + match menu(app) { + Ok(menu) => { + if let Err(error) = tray.set_menu(Some(menu)) { + log::warn!("не удалось обновить меню трея: {error}"); + } + } + Err(error) => log::warn!("не удалось собрать меню трея: {error}"), + } +} + +/// Собирает меню трея по текущим настройкам. +fn menu(app: &AppHandle) -> Result, String> { + let current = app.state::().settings(); + let item = |id: &str, title: &str| -> Result, String> { + MenuItem::with_id(app, id, title, true, None::<&str>) + .map_err(|error| format!("пункт меню «{title}»: {error}")) + }; + let check = |id: &str, title: &str, checked: bool| -> Result, String> { + CheckMenuItem::with_id(app, id, title, true, checked, None::<&str>) + .map_err(|error| format!("пункт меню «{title}»: {error}")) + }; + + let open = item("open", "Открыть glchat")?; + let client = item("open-settings", "Настройки обёртки…")?; + let first_sep = PredefinedMenuItem::separator(app).map_err(|error| error.to_string())?; + let autostart_item = check("autostart", "Запускать при входе", current.autostart)?; + let close_to_tray = check("close-to-tray", "Закрывать в трей", current.close_to_tray)?; + let notifications = check("notifications", "Уведомления", current.notifications)?; + let update_item = item("updates", "Проверить обновления…")?; + let second_sep = PredefinedMenuItem::separator(app).map_err(|error| error.to_string())?; + let quit = item("quit", "Выход")?; + + Menu::with_items( + app, + &[ + &open, + &client, + &first_sep, + &autostart_item, + &close_to_tray, + ¬ifications, + &update_item, + &second_sep, + &quit, + ], + ) + .map_err(|error| format!("не удалось собрать меню трея: {error}")) +} + +/// Обработчик пунктов меню трея. +fn on_menu_event(app: &AppHandle, event: tauri::menu::MenuEvent) { + match event.id().as_ref() { + "open" => window::show_main(app), + "open-settings" => { + if let Err(error) = window::open_settings_page(app) { + log::warn!("{error}"); + } + } + "autostart" => { + let mut current = app.state::().settings(); + current.autostart = !current.autostart; + persist(app, current); + } + "close-to-tray" => { + let mut current = app.state::().settings(); + current.close_to_tray = !current.close_to_tray; + persist(app, current); + } + "notifications" => { + let mut current = app.state::().settings(); + current.notifications = !current.notifications; + persist(app, current); + } + "updates" => { + let handle = app.clone(); + tauri::async_runtime::spawn(async move { + updates::check(handle, true).await; + }); + } + "quit" => app.exit(0), + other => log::debug!("неизвестный пункт меню трея: {other}"), + } +} + +/// Применяет и сохраняет настройки, меняя только один переключатель. +fn persist(app: &AppHandle, next: settings::Settings) { + let previous = app.state::().settings(); + app.state::().set_settings(next.clone()); + if let Err(error) = autostart::apply(app, next.autostart) { + log::warn!("{error}"); + } + if next.ptt_shortcut != previous.ptt_shortcut + || next.mute_shortcut != previous.mute_shortcut + || next.deafen_shortcut != previous.deafen_shortcut + { + if let Err(error) = shortcuts::apply(app, &next) { + log::warn!("{error}"); + } + } + if let Err(error) = settings::save(app, &next) { + log::warn!("не удалось сохранить настройки: {error}"); + } + refresh(app); + commands::announce_settings(app, &next); + if next.instance_url != previous.instance_url { + if let Err(error) = window::open_instance_page(app) { + log::warn!("{error}"); + } + } +} diff --git a/desktop/src-tauri/src/updates.rs b/desktop/src-tauri/src/updates.rs new file mode 100644 index 0000000..ed04099 --- /dev/null +++ b/desktop/src-tauri/src/updates.rs @@ -0,0 +1,154 @@ +//! Автообновление (docs/client-tauri.md §4). +//! +//! Манифест обновлений отдаёт сам инстанс: `GET /updates/{target}/{arch}/{current_version}` +//! (статика через Caddy). Артефакты подписаны ключом ed25519, подпись +//! проверяется до установки — публичный ключ задаётся в `UPDATER_PUBKEY`. +//! +//! Пока ключ не заведён (сборка без релизного контура), проверка обновлений +//! честно сообщает, что канал не настроен, вместо «суррогатного» обновления. + +use tauri::{AppHandle, Manager, Runtime}; +use tauri_plugin_dialog::{DialogExt, MessageDialogButtons}; +use tauri_plugin_updater::UpdaterExt; + +use crate::bridge::{self, WebMessage}; +use crate::instance; +use crate::state::AppState; + +/// Публичный ключ подписи обновлений (ed25519, формат minisign). +/// +/// Приватный ключ в репозиторий не попадает: он живёт в CI-секретах +/// (`TAURI_SIGNING_PRIVATE_KEY`), а локально — в `build/desktop-keys/` +/// (каталог `build/` в .gitignore). Подпись обязательна: манифест без неё +/// плагин отклоняет, downgrade запрещён (docs/client-tauri.md §4, §6). +pub const UPDATER_PUBKEY: &str = "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDhCQkQ1NjkwN0EyQzZBOEEKUldTS2FpeDZrRmE5aXhqSThPWXA3am5YMnB5dmVWZWFEcVY4NGI3cG8yOTU1MjdtMW9sR09BNGIK"; + +/// Путь манифеста обновлений на инстансе. +const UPDATE_PATH: &str = "/updates/{{target}}/{{arch}}/{{current_version}}"; + +/// Проверяет обновления. `interactive` — вызов из меню трея или настроек, +/// тогда пользователь видит результат в диалоге; фоновая проверка молчит. +pub async fn check(app: AppHandle, interactive: bool) { + if UPDATER_PUBKEY.is_empty() { + log::info!("автообновление не настроено: в сборке нет публичного ключа подписи"); + if interactive { + app.dialog() + .message( + "В этой сборке нет публичного ключа подписи обновлений, поэтому проверка \ + недоступна. Ключ и манифест обновлений появятся вместе с релизным контуром \ + (docs/client-tauri.md §4).", + ) + .title("Обновления не настроены") + .buttons(MessageDialogButtons::Ok) + .show(|_| {}); + } + return; + } + + let settings = app.state::().settings(); + let endpoint = match instance::normalize(&settings.instance_url) { + Ok(url) => format!("{}{UPDATE_PATH}", instance::display(&url)), + Err(error) => { + log::warn!("не удалось определить адрес инстанса для обновлений: {error}"); + return; + } + }; + let Ok(endpoint) = url::Url::parse(&endpoint) else { + log::warn!("некорректный адрес манифеста обновлений: {endpoint}"); + return; + }; + + let updater = match app + .updater_builder() + .endpoints(vec![endpoint]) + .and_then(|builder| builder.pubkey(UPDATER_PUBKEY).build()) + { + Ok(updater) => updater, + Err(error) => { + log::warn!("не удалось собрать клиент обновлений: {error}"); + return; + } + }; + + match updater.check().await { + Ok(Some(update)) => { + let version = update.version.clone(); + log::info!("доступно обновление {version}"); + // Обновление показываем в интерфейсе, установку спрашиваем отдельно: + // во время звонка перезапуск приложения недопустим без согласия. + bridge::send(&app, &WebMessage::UpdateAvailable { version: version.clone() }); + prompt_install(app, update, version).await; + } + Ok(None) => { + log::info!("обновлений нет"); + if interactive { + app.dialog() + .message("Установлена последняя версия.") + .title("Обновления") + .buttons(MessageDialogButtons::Ok) + .show(|_| {}); + } + } + Err(error) => { + log::warn!("проверка обновлений не удалась: {error}"); + if interactive { + let text = format!("Не удалось проверить обновления: {error}"); + app.dialog() + .message(text) + .title("Обновления") + .buttons(MessageDialogButtons::Ok) + .show(|_| {}); + } + } + } +} + +/// Спрашивает согласие и устанавливает обновление. +async fn prompt_install( + app: AppHandle, + update: tauri_plugin_updater::Update, + version: String, +) { + let handle = app.clone(); + let question = format!( + "Доступна версия {version}. Скачать и установить сейчас? Приложение будет перезапущено, \ + активный голосовой звонок прервётся." + ); + let (tx, rx) = std::sync::mpsc::channel::(); + app.dialog() + .message(question) + .title("Обновление glchat") + .buttons(MessageDialogButtons::YesNo) + .show(move |confirmed| { + let _ = tx.send(confirmed); + }); + + // Диалог асинхронный: ждём ответ, не блокируя основной поток. + let confirmed = tauri::async_runtime::spawn_blocking(move || rx.recv().unwrap_or(false)) + .await + .unwrap_or(false); + if !confirmed { + return; + } + + match update + .download_and_install(|_chunk, _total| {}, || {}) + .await + { + Ok(()) => { + log::info!("обновление {version} установлено, перезапуск"); + handle.restart(); + } + Err(error) => { + log::error!("установка обновления не удалась: {error}"); + app.dialog() + .message(format!( + "Обновление не установлено: {error}. Скачать установщик вручную можно на \ + странице инстанса." + )) + .title("Обновление glchat") + .buttons(MessageDialogButtons::Ok) + .show(|_| {}); + } + } +} diff --git a/desktop/src-tauri/src/window.rs b/desktop/src-tauri/src/window.rs new file mode 100644 index 0000000..466177b --- /dev/null +++ b/desktop/src-tauri/src/window.rs @@ -0,0 +1,135 @@ +//! Главное окно приложения. +//! +//! Окно одно (docs/client-tauri.md §2): в нём либо веб-клиент инстанса, либо +//! локальная страница настроек обёртки. Вторых окон не заводим, повторный +//! запуск приложения фокусирует уже открытое окно. + +use tauri::webview::PageLoadEvent; +use tauri::{AppHandle, Manager, Runtime, WebviewUrl, WebviewWindow, WebviewWindowBuilder}; +use tauri_plugin_opener::OpenerExt; +use tauri_plugin_window_state::{StateFlags, WindowExt}; + +use crate::bridge::WEB_WINDOW; +use crate::instance; +use crate::settings::Settings; +use crate::state::AppState; + +/// Создаёт главное окно с клиентом инстанса. +pub fn create_main( + app: &AppHandle, + settings: &Settings, + minimized: bool, +) -> Result, String> { + let url = instance::normalize(&settings.instance_url)?; + let handle = app.clone(); + let window = WebviewWindowBuilder::new(app, WEB_WINDOW, WebviewUrl::External(url)) + .title("glchat") + .inner_size(1280.0, 800.0) + .min_inner_size(900.0, 600.0) + .visible(!minimized) + .on_navigation(move |target| navigation_guard(&handle, target)) + .on_page_load(|_window, payload| { + // В логе видно, что именно открыто в окне: это первое, что нужно + // при разборе «приложение открылось, но клиента нет». + if payload.event() == PageLoadEvent::Finished { + log::info!("загружена страница: {}", payload.url()); + } + }) + .build() + .map_err(|error| format!("не удалось создать окно: {error}"))?; + // Геометрия окна переживает перезапуск (tauri-plugin-window-state). + let _ = window.restore_state(StateFlags::all()); + Ok(window) +} + +/// Показывает и фокусирует главное окно (повторный запуск, клик по трею). +pub fn show_main(app: &AppHandle) { + if let Some(window) = app.get_webview_window(WEB_WINDOW) { + let _ = window.show(); + let _ = window.unminimize(); + let _ = window.set_focus(); + } +} + +/// Проверяет, загружен ли сейчас в окне клиент инстанса (а не страница настроек). +pub fn is_instance_page(app: &AppHandle) -> bool { + let Some(window) = app.get_webview_window(WEB_WINDOW) else { + return false; + }; + let Ok(current) = window.url() else { + return false; + }; + let settings = app.state::().settings(); + let Ok(instance_url) = instance::normalize(&settings.instance_url) else { + return false; + }; + instance::host(¤t) == instance::host(&instance_url) +} + +/// Открывает локальную страницу настроек обёртки. +pub fn open_settings_page(app: &AppHandle) -> Result<(), String> { + let window = app + .get_webview_window(WEB_WINDOW) + .ok_or_else(|| "окно не создано".to_string())?; + window + .navigate(local_page_url("index.html")) + .map_err(|error| format!("не удалось открыть настройки: {error}"))?; + show_main(app); + Ok(()) +} + +/// Возвращает окно к клиенту инстанса. +pub fn open_instance_page(app: &AppHandle) -> Result<(), String> { + let settings = app.state::().settings(); + let url = instance::normalize(&settings.instance_url)?; + let window = app + .get_webview_window(WEB_WINDOW) + .ok_or_else(|| "окно не создано".to_string())?; + window + .navigate(url) + .map_err(|error| format!("не удалось открыть клиент: {error}"))?; + show_main(app); + Ok(()) +} + +/// Адрес локальной страницы обёртки. +/// +/// `WebviewUrl::App` резолвится Tauri во внутренний источник (`tauri://localhost` +/// на macOS/Linux, `http://tauri.localhost` на Windows), а `navigate` принимает +/// уже готовый URL — собираем его тем же правилом, что и сам Tauri. +fn local_page_url(path: &str) -> url::Url { + let base = if cfg!(any(windows, target_os = "android")) { + url::Url::parse("http://tauri.localhost").expect("базовый адрес локальной страницы") + } else { + url::Url::parse("tauri://localhost").expect("базовый адрес локальной страницы") + }; + base.join(path).unwrap_or(base) +} + +/// Перезагружает клиент инстанса (после смены адреса или по запросу). +pub fn reload_instance(app: &AppHandle) -> Result<(), String> { + let window = app + .get_webview_window(WEB_WINDOW) + .ok_or_else(|| "окно не создано".to_string())?; + if is_instance_page(app) { + window + .eval("window.location.reload();") + .map_err(|error| error.to_string())?; + return Ok(()); + } + open_instance_page(app) +} + +/// Граница навигации: чужой адрес открывается в системном браузере. +fn navigation_guard(app: &AppHandle, target: &url::Url) -> bool { + let settings = app.state::().settings(); + let host = instance::normalize(&settings.instance_url) + .map(|url| instance::host(&url)) + .unwrap_or_default(); + if instance::navigation_allowed(target, &host) { + return true; + } + log::info!("внешняя ссылка уходит в системный браузер: {target}"); + let _ = app.opener().open_url(target.as_str(), None::<&str>); + false +} diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json new file mode 100644 index 0000000..18bfcb2 --- /dev/null +++ b/desktop/src-tauri/tauri.conf.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "productName": "glchat", + "version": "0.1.0", + "identifier": "su.mhspx.glchat", + "build": { + "frontendDist": "./ui" + }, + "app": { + "withGlobalTauri": false, + "windows": [], + "security": { + "csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' ipc: http://ipc.localhost; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" + } + }, + "bundle": { + "active": true, + "targets": [ + "app", + "dmg" + ], + "createUpdaterArtifacts": true, + "category": "SocialNetworking", + "shortDescription": "glchat — self-hosted платформа общения", + "longDescription": "Desktop-клиент glchat: тот же веб-клиент в обёртке Tauri с нативными уведомлениями, треем, глобальным push-to-talk и автообновлением.", + "copyright": "glchat, AGPL-3.0-or-later", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "macOS": { + "minimumSystemVersion": "10.15" + } + }, + "plugins": { + "updater": { + "endpoints": [ + "https://gl.mhspx.su/updates/{{target}}/{{arch}}/{{current_version}}" + ], + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDhCQkQ1NjkwN0EyQzZBOEEKUldTS2FpeDZrRmE5aXhqSThPWXA3am5YMnB5dmVWZWFEcVY4NGI3cG8yOTU1MjdtMW9sR09BNGIK", + "windows": { + "installMode": "passive" + } + }, + "deep-link": { + "desktop": { + "schemes": [ + "glchat" + ] + } + } + } +} diff --git a/desktop/src-tauri/ui/index.html b/desktop/src-tauri/ui/index.html new file mode 100644 index 0000000..dad44f9 --- /dev/null +++ b/desktop/src-tauri/ui/index.html @@ -0,0 +1,90 @@ + + + + + + + glchat — настройки приложения + + + +

+
+

Настройки приложения

+

+ Это настройки desktop-обёртки. Настройки аккаунта, серверов и голоса живут внутри самого + клиента. +

+
+ +
+

Инстанс

+ +

+ Тот же адрес, что открывается в браузере. Сторонние ссылки уходят в системный браузер, а + не открываются внутри окна. +

+
+ + +
+
+ +
+

Поведение

+ + + +
+ +
+

Глобальные горячие клавиши

+

+ Работают, когда окно неактивно. Push-to-talk включает микрофон, пока клавиша удерживается: + в клиенте должен быть выбран режим микрофона «Push-to-talk» (Настройки → Голос). +

+ + + +
+ +
+

Обновления

+

+ Обновления проверяются при запуске и вручную. Манифест отдаёт сам инстанс. +

+
+ + +
+
+ +
+ + +
+
+ + + diff --git a/desktop/src-tauri/ui/settings.css b/desktop/src-tauri/ui/settings.css new file mode 100644 index 0000000..0772d91 --- /dev/null +++ b/desktop/src-tauri/ui/settings.css @@ -0,0 +1,154 @@ +:root { + --bg: #1a1b1e; + --panel: #232428; + --border: #33353b; + --fg: #e6e7ea; + --muted: #9a9ca3; + --accent: #4c5bd4; + --accent-fg: #ffffff; +} + +@media (prefers-color-scheme: light) { + :root { + --bg: #f5f6f8; + --panel: #ffffff; + --border: #dcdee4; + --fg: #1c1d21; + --muted: #5f626b; + } +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + background: var(--bg); + color: var(--fg); + font: + 14px/1.5 -apple-system, + "Segoe UI", + Roboto, + sans-serif; +} + +.page { + max-width: 640px; + margin: 0 auto; + padding: 32px 24px 48px; + display: flex; + flex-direction: column; + gap: 20px; +} + +.head h1 { + margin: 0 0 6px; + font-size: 22px; +} + +.muted { + color: var(--muted); +} + +.hint { + margin: 8px 0 0; + color: var(--muted); + font-size: 12.5px; +} + +.card { + background: var(--panel); + border: 1px solid var(--border); + border-radius: 12px; + padding: 18px 20px; +} + +.card h2 { + margin: 0 0 12px; + font-size: 15px; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--muted); +} + +.field { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: 12px; +} + +.field > span { + font-weight: 500; +} + +.check { + display: flex; + gap: 10px; + align-items: flex-start; + margin-bottom: 10px; +} + +input[type='text'], +select { + background: var(--bg); + color: var(--fg); + border: 1px solid var(--border); + border-radius: 8px; + padding: 9px 11px; + font: inherit; +} + +input[type='text']:focus, +select:focus { + outline: 2px solid var(--accent); + outline-offset: 1px; +} + +.row { + display: flex; + gap: 10px; + align-items: center; + flex-wrap: wrap; + margin-top: 12px; +} + +button { + background: var(--panel); + color: var(--fg); + border: 1px solid var(--border); + border-radius: 8px; + padding: 9px 14px; + font: inherit; + cursor: pointer; +} + +button:hover { + border-color: var(--accent); +} + +button.primary { + background: var(--accent); + border-color: var(--accent); + color: var(--accent-fg); +} + +.foot { + display: flex; + align-items: center; + gap: 14px; + position: sticky; + bottom: 0; + padding: 14px 0 0; + background: linear-gradient(transparent, var(--bg) 40%); +} + +.status { + color: var(--muted); + font-size: 13px; +} + +.status.error { + color: #e06c75; +} diff --git a/desktop/src-tauri/ui/settings.js b/desktop/src-tauri/ui/settings.js new file mode 100644 index 0000000..a1474b2 --- /dev/null +++ b/desktop/src-tauri/ui/settings.js @@ -0,0 +1,165 @@ +// Страница настроек desktop-обёртки. +// +// Локальная страница (tauri://localhost) внутри главного окна: команды обёртки +// вызываются через встроенный IPC Tauri. Ничего, кроме настроек платформы, +// здесь нет — настройки клиента живут в самом клиенте. + +/** Вызов команды обёртки: тонкая обёртка над IPC Tauri v2. */ +const invoke = (command, args) => window.__TAURI_INTERNALS__.invoke(command, args); + +/** Варианты комбинаций: пустая строка — «выключено». */ +const OFF = { value: '', label: 'Выключено' }; + +const PTT_OPTIONS = [ + OFF, + { value: 'CommandOrControl+Shift+Space', label: 'Cmd/Ctrl + Shift + Пробел' }, + { value: 'CommandOrControl+Shift+M', label: 'Cmd/Ctrl + Shift + M' }, + { value: 'CommandOrControl+Shift+V', label: 'Cmd/Ctrl + Shift + V' }, + { value: 'CommandOrControl+Shift+B', label: 'Cmd/Ctrl + Shift + B' }, + { value: 'Control+Shift+Space', label: 'Ctrl + Shift + Пробел' }, +]; + +const MUTE_OPTIONS = [ + OFF, + { value: 'CommandOrControl+Shift+M', label: 'Cmd/Ctrl + Shift + M' }, + { value: 'CommandOrControl+Shift+U', label: 'Cmd/Ctrl + Shift + U' }, + { value: 'Control+Shift+M', label: 'Ctrl + Shift + M' }, +]; + +const DEAFEN_OPTIONS = [ + OFF, + { value: 'CommandOrControl+Shift+D', label: 'Cmd/Ctrl + Shift + D' }, + { value: 'CommandOrControl+Shift+F', label: 'Cmd/Ctrl + Shift + F' }, + { value: 'Control+Shift+D', label: 'Ctrl + Shift + D' }, +]; + +/** Поля формы и соответствующие настройки. */ +const fields = { + instanceUrl: document.getElementById('instance-url'), + autostart: document.getElementById('autostart'), + closeToTray: document.getElementById('close-to-tray'), + notifications: document.getElementById('notifications'), + pttShortcut: document.getElementById('ptt-shortcut'), + muteShortcut: document.getElementById('mute-shortcut'), + deafenShortcut: document.getElementById('deafen-shortcut'), +}; + +const status = document.getElementById('status'); +const version = document.getElementById('version'); +const updatesHint = document.getElementById('updates-hint'); + +/** Заполняет выпадающий список комбинаций. */ +function fillSelect(select, options, current) { + select.replaceChildren(); + for (const option of options) { + const node = document.createElement('option'); + node.value = option.value; + node.textContent = option.label; + select.append(node); + } + // Комбинация могла быть задана вручную (например, прежней версией) — не теряем её. + if (current && !options.some((option) => option.value === current)) { + const node = document.createElement('option'); + node.value = current; + node.textContent = current; + select.append(node); + } + select.value = current ?? ''; +} + +/** Показывает состояние сохранения. */ +function setStatus(text, isError = false) { + status.textContent = text; + status.classList.toggle('error', isError); +} + +/** Переносит настройки в форму. */ +function render(settings) { + fields.instanceUrl.value = settings.instanceUrl ?? ''; + fields.autostart.checked = Boolean(settings.autostart); + fields.closeToTray.checked = Boolean(settings.closeToTray); + fields.notifications.checked = Boolean(settings.notifications); + fillSelect(fields.pttShortcut, PTT_OPTIONS, settings.pttShortcut); + fillSelect(fields.muteShortcut, MUTE_OPTIONS, settings.muteShortcut); + fillSelect(fields.deafenShortcut, DEAFEN_OPTIONS, settings.deafenShortcut); +} + +/** Собирает настройки из формы. */ +function collect() { + return { + instanceUrl: fields.instanceUrl.value.trim(), + autostart: fields.autostart.checked, + closeToTray: fields.closeToTray.checked, + notifications: fields.notifications.checked, + pttShortcut: fields.pttShortcut.value, + muteShortcut: fields.muteShortcut.value, + deafenShortcut: fields.deafenShortcut.value, + }; +} + +/** Сохраняет настройки и, если нужно, открывает клиент. */ +async function save({ openClient = false } = {}) { + setStatus('Сохраняем…'); + try { + const saved = await invoke('desktop_save_settings', { settings: collect() }); + render(saved); + setStatus('Сохранено'); + if (openClient) { + await invoke('desktop_open_instance'); + } + } catch (error) { + setStatus(String(error), true); + } +} + +document.getElementById('save').addEventListener('click', () => { + void save(); +}); + +document.getElementById('open-client').addEventListener('click', () => { + void save({ openClient: true }); +}); + +document.getElementById('reload-client').addEventListener('click', async () => { + await save(); + try { + await invoke('desktop_reload'); + } catch (error) { + setStatus(String(error), true); + } +}); + +document.getElementById('check-updates').addEventListener('click', async () => { + updatesHint.textContent = 'Проверяем обновления…'; + try { + await invoke('desktop_check_updates'); + updatesHint.textContent = 'Проверка завершена: результат показан в системном диалоге.'; + } catch (error) { + updatesHint.textContent = String(error); + } +}); + +// Автосохранение переключателей и списков: отдельная кнопка нужна только для адреса. +for (const node of [ + fields.autostart, + fields.closeToTray, + fields.notifications, + fields.pttShortcut, + fields.muteShortcut, + fields.deafenShortcut, +]) { + node.addEventListener('change', () => { + void save(); + }); +} + +async function start() { + try { + render(await invoke('desktop_settings')); + version.textContent = `Версия обёртки: ${await invoke('desktop_version')}`; + } catch (error) { + setStatus(`Не удалось прочитать настройки: ${error}`, true); + } +} + +void start(); diff --git a/web/src/App.tsx b/web/src/App.tsx index cdc9ab8..cb19999 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,6 +1,7 @@ import { Suspense } from 'react'; import { RouterProvider } from 'react-router'; +import { DesktopBridge } from '@/components/DesktopBridge'; import { Card } from '@/components/ui/primitives'; import { SkeletonLines } from '@/components/ui/Skeleton'; import { router } from '@/router'; @@ -20,6 +21,8 @@ export function RouteFallback() { export function App() { return ( }> + {/* Мост desktop-обёртки: события платформы и счётчик непрочитанных. */} + ); diff --git a/web/src/components/DesktopBridge.tsx b/web/src/components/DesktopBridge.tsx new file mode 100644 index 0000000..8ea15cb --- /dev/null +++ b/web/src/components/DesktopBridge.tsx @@ -0,0 +1,79 @@ +import { useEffect } from 'react'; + +import { unreadCount, useMessagesStore } from '@/stores/messages'; +import { useVoiceConnectionStore } from '@/stores/voiceConnection'; +import { platform, routeFromDeepLink } from '@/lib/platform'; +import { router } from '@/router'; + +/** + * Мост desktop-обёртки (docs/client-tauri.md §2). + * + * Обёртка присылает события платформы (глобальный push-to-talk, mute/deafen, + * deep link, готовность обновления), а клиент отдаёт ей счётчик непрочитанных. + * В браузере компонент безвреден: реализация платформы там пустая. + */ +export function DesktopBridge() { + // События обёртки: глобальные шорткаты, deep links, обновления. + useEffect( + () => + platform.onMessage((message) => { + const voice = useVoiceConnectionStore.getState(); + switch (message.type) { + case 'ptt': + // Удержание клавиши: микрофон включается, пока она нажата. + voice.setPushToTalkActive(message.active); + break; + case 'toggleMic': + void voice.setMicEnabled(!voice.micEnabled); + break; + case 'toggleDeafen': + void voice.setDeafened(!voice.deafened); + break; + case 'deepLink': { + const route = routeFromDeepLink(message.url); + if (route === null) { + console.warn('[desktop] неизвестная ссылка', message.url); + break; + } + void router.navigate(route); + break; + } + case 'updateAvailable': + platform.notify({ + title: 'Доступно обновление glchat', + body: `Версия ${message.version}. Установить можно из настроек приложения.`, + }); + break; + case 'settings': + // Настройки обёртки клиенту не нужны: он читает только свои. + break; + } + }), + [], + ); + + // Обёртка отдаёт накопленные deep links после этого сигнала. + useEffect(() => { + platform.ready(); + }, []); + + // Счётчик непрочитанных для значка приложения и иконки в трее. + useEffect(() => { + let last = -1; + const sync = (): void => { + const channels = useMessagesStore.getState().channels; + let total = 0; + for (const record of Object.values(channels)) { + total += unreadCount(record); + } + if (total !== last) { + last = total; + platform.setBadge(total); + } + }; + sync(); + return useMessagesStore.subscribe(sync); + }, []); + + return null; +} diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index 96b8104..f21dbf1 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -1107,8 +1107,11 @@ "navLabel": "Settings sections", "notifications": { "title": "Notifications", - "description": "Sounds, mentions and web push.", - "stub": "Notification settings are coming later." + "description": "System notifications for mentions and direct messages.", + "desktop": "Desktop notifications", + "desktopHint": "Show system notifications when the window is inactive or the channel is not open. Native in the desktop app, permission-based in the browser.", + "desktopSettings": "Desktop app settings", + "unsupported": "This browser does not show system notifications: open the client in the desktop app." }, "voice": { "title": "Audio & video", diff --git a/web/src/i18n/locales/ru.json b/web/src/i18n/locales/ru.json index 477926c..8b2804f 100644 --- a/web/src/i18n/locales/ru.json +++ b/web/src/i18n/locales/ru.json @@ -1107,8 +1107,11 @@ "navLabel": "Пункты настроек", "notifications": { "title": "Уведомления", - "description": "Звуки, упоминания и веб-пуш.", - "stub": "Настройки уведомлений появятся позже." + "description": "Системные уведомления об упоминаниях и личных сообщениях.", + "desktop": "Уведомления рабочего стола", + "desktopHint": "Показывать системные уведомления, когда окно неактивно или комната не открыта. В desktop-приложении уведомления нативные, в браузере — при разрешённых уведомлениях.", + "desktopSettings": "Настройки desktop-приложения", + "unsupported": "Браузер не показывает системные уведомления: откройте клиент в desktop-приложении." }, "voice": { "title": "Аудио-видео", diff --git a/web/src/lib/desktopNotifications.ts b/web/src/lib/desktopNotifications.ts new file mode 100644 index 0000000..9476703 --- /dev/null +++ b/web/src/lib/desktopNotifications.ts @@ -0,0 +1,114 @@ +/** + * Нативные уведомления desktop-обёртки (docs/client-tauri.md §5). + * + * Решение «показывать или нет» принимает клиент: только упоминания и личные + * сообщения, только когда окно неактивно или комната не открыта, и только если + * пользователь не выключил уведомления в настройках. Текст уведомления готовит + * этот модуль, показывает — платформенный адаптер. + */ + +import type { Message } from '@/api/messages'; +import type { DesktopNotification } from '@/lib/platform'; + +/** Ключ предпочтения в localStorage (настройка устройства, не аккаунта). */ +const STORAGE_KEY = 'glchat.desktop-notifications'; + +/** Сколько символов сообщения показываем в уведомлении. */ +const PREVIEW_LIMIT = 140; + +/** Включены ли уведомления рабочего стола (по умолчанию — да). */ +export function notificationsEnabled(): boolean { + try { + return window.localStorage.getItem(STORAGE_KEY) !== 'off'; + } catch { + // Приватный режим браузера может запретить localStorage — считаем включёнными. + return true; + } +} + +/** Переключает уведомления рабочего стола. */ +export function setNotificationsEnabled(enabled: boolean): void { + try { + window.localStorage.setItem(STORAGE_KEY, enabled ? 'on' : 'off'); + } catch { + // Без localStorage предпочтение живёт до перезагрузки страницы. + } +} + +/** Данные, от которых зависит решение об уведомлении. */ +export interface NotificationInput { + message: Pick; + /** Мой идентификатор: свои сообщения не уведомляют. */ + meId: string | null; + /** Комната — личная беседа. */ + isDirect: boolean; + /** Имя комнаты для заголовка. */ + channelName: string | null; + /** Сервер комнаты (в личной беседе — null). */ + guildId: string | null; + /** Комната открыта в клиенте. */ + isChannelOpen: boolean; + /** Окно клиента в фокусе. */ + windowFocused: boolean; + /** Уведомления включены пользователем. */ + enabled: boolean; +} + +/** Убирает Markdown-разметку и лишние переводы строк из текста сообщения. */ +export function previewText(content: string): string { + const plain = content + .replace(/```[\s\S]*?```/g, ' [код] ') + .replace(/`([^`]*)`/g, '$1') + .replace(/!?\[([^\]]*)\]\([^)]*\)/g, '$1') + .replace(/[*_~>#]/g, '') + .replace(/\s+/g, ' ') + .trim(); + if (plain.length <= PREVIEW_LIMIT) { + return plain; + } + return `${plain.slice(0, PREVIEW_LIMIT - 1).trimEnd()}…`; +} + +/** + * Текст уведомления или `null`, если показывать не нужно. + * + * Чистая функция: её поведение проверяется тестами без DOM и без обёртки. + */ +export function notificationFor(input: NotificationInput): DesktopNotification | null { + if (!input.enabled) { + return null; + } + const { message } = input; + // Системные сообщения (входы, баны) уведомлений не требуют. + if (message.type === 'system') { + return null; + } + if (input.meId !== null && message.author_id === input.meId) { + return null; + } + const mentionsMe = input.meId !== null && message.mentions.includes(input.meId); + if (!mentionsMe && !input.isDirect) { + return null; + } + // Комната открыта и окно активно — пользователь и так видит сообщение. + if (input.isChannelOpen && input.windowFocused) { + return null; + } + const body = previewText(message.content); + if (body === '' && message.mentions.length === 0) { + return null; + } + const title = input.isDirect + ? input.channelName === null || input.channelName === '' + ? 'Личное сообщение' + : `Личное сообщение — ${input.channelName}` + : input.channelName === null || input.channelName === '' + ? 'Упоминание' + : `Упоминание в #${input.channelName}`; + return { + title, + body: body === '' ? 'Вложение' : body, + guildId: input.guildId, + channelId: message.channel_id, + }; +} diff --git a/web/src/lib/platform.ts b/web/src/lib/platform.ts new file mode 100644 index 0000000..0453aed --- /dev/null +++ b/web/src/lib/platform.ts @@ -0,0 +1,199 @@ +/** + * Платформенный адаптер клиента (docs/client-tauri.md §2). + * + * Один и тот же веб-код работает и в браузере, и внутри desktop-обёртки Tauri: + * реализация выбирается при старте по наличию моста Tauri, а вызовы платформы + * идут только через этот модуль. В браузере доступно не всё (нативные + * уведомления — по разрешению браузера, трея и бейджа нет), поэтому у каждой + * реализации свои возможности, а не заглушки «на будущее». + */ + +/** Настройки обёртки: поля совпадают с Rust-структурой `Settings`. */ +export interface DesktopSettings { + /** Адрес инстанса, загруженного в окно. */ + instanceUrl: string; + /** Закрытие окна сворачивает приложение в трей. */ + closeToTray: boolean; + /** Автозапуск при входе в систему. */ + autostart: boolean; + /** Вопрос об автозапуске уже задавали. */ + autostartPrompted: boolean; + pttShortcut: string; + muteShortcut: string; + deafenShortcut: string; + /** Нативные уведомления включены. */ + notifications: boolean; +} + +/** Сообщение из обёртки (см. `WebMessage` в desktop/src-tauri/src/bridge.rs). */ +export type DesktopMessage = + | { type: 'ptt'; active: boolean } + | { type: 'toggleMic' } + | { type: 'toggleDeafen' } + | { type: 'deepLink'; url: string } + | { type: 'settings'; settings: DesktopSettings } + | { type: 'updateAvailable'; version: string }; + +/** Уведомление для системы. Текст готовит клиент, показывает — платформа. */ +export interface DesktopNotification { + title: string; + body: string; + guildId?: string | null; + channelId?: string | null; +} + +export type PlatformKind = 'web' | 'tauri'; + +export interface Platform { + readonly kind: PlatformKind; + /** Показать системное уведомление (если платформа это умеет). */ + notify(notification: DesktopNotification): void; + /** Число непрочитанных для значка приложения и трея. */ + setBadge(count: number): void; + /** Сообщить обёртке, что клиент загрузился (deep links ждут этого). */ + ready(): void; + /** Открыть страницу настроек обёртки. */ + openSettings(): void; + /** Подписка на сообщения обёртки; возвращает функцию отписки. */ + onMessage(handler: (message: DesktopMessage) => void): () => void; +} + +/** Мост Tauri v2: этого объекта в браузере нет. */ +interface TauriInternals { + invoke(command: string, args?: Record): Promise; +} + +interface DesktopBridgeGlobal { + __TAURI_INTERNALS__?: TauriInternals; + __glchatDesktop?: { receive: (message: DesktopMessage) => void }; +} + +function tauri(): TauriInternals | null { + const bridge = window as unknown as DesktopBridgeGlobal; + const internals = bridge.__TAURI_INTERNALS__; + return internals !== undefined && typeof internals.invoke === 'function' ? internals : null; +} + +/** Открыт ли клиент внутри desktop-обёртки. */ +export function isTauri(): boolean { + return tauri() !== null; +} + +/** Реализация для браузера: системных возможностей почти нет. */ +const webPlatform: Platform = { + kind: 'web', + notify(notification) { + // В браузере показываем только при уже выданном разрешении: запрашивать + // его без действия пользователя нельзя, а веб-пуш — отдельная фаза. + if (!('Notification' in window) || Notification.permission !== 'granted') { + return; + } + try { + new Notification(notification.title, { body: notification.body }); + } catch { + // Браузер может запретить уведомление (например, в фоновой вкладке) — + // это не ошибка клиента. + } + }, + setBadge(count) { + // В браузере счётчик виден в заголовке вкладки: это делает сам клиент. + void count; + }, + ready() {}, + openSettings() {}, + onMessage() { + return () => {}; + }, +}; + +/** Реализация для desktop-обёртки: тонкие вызовы команд Rust. */ +function tauriPlatform(internals: TauriInternals): Platform { + const handlers = new Set<(message: DesktopMessage) => void>(); + const bridge = window as unknown as DesktopBridgeGlobal; + bridge.__glchatDesktop = { + receive(message) { + for (const handler of handlers) { + handler(message); + } + }, + }; + + /** Команды обёртки не должны ронять клиент: ошибку только логируем. */ + const call = (command: string, args?: Record): void => { + void internals.invoke(command, args).catch((error: unknown) => { + console.warn(`[desktop] команда ${command} не выполнена`, error); + }); + }; + + return { + kind: 'tauri', + notify(notification) { + call('desktop_notify', { + payload: { + title: notification.title, + body: notification.body, + guildId: notification.guildId ?? null, + channelId: notification.channelId ?? null, + }, + }); + }, + setBadge(count) { + call('desktop_set_badge', { count }); + }, + ready() { + call('desktop_ready'); + }, + openSettings() { + call('desktop_open_settings'); + }, + onMessage(handler) { + handlers.add(handler); + return () => { + handlers.delete(handler); + }; + }, + }; +} + +const internals = tauri(); + +/** Платформа текущего запуска: браузер или desktop-обёртка. */ +export const platform: Platform = internals === null ? webPlatform : tauriPlatform(internals); + +/** + * Маршрут клиента для deep link обёртки (docs/client-tauri.md §5). + * + * Поддерживаются `glchat://invite/` и + * `glchat://guild//channel/`; неизвестная ссылка даёт `null`. + */ +export function routeFromDeepLink(link: string): string | null { + let url: URL; + try { + url = new URL(link); + } catch { + return null; + } + if (url.protocol !== 'glchat:') { + return null; + } + const segments = url.pathname.split('/').filter((segment) => segment !== ''); + // В `glchat://invite/ABC` хост — это первый сегмент пути. + const [kind, ...rest] = [url.hostname, ...segments]; + if (kind === 'invite') { + const code = rest[0]; + return rest.length === 1 && code !== undefined ? `/invite/${encodeURIComponent(code)}` : null; + } + if (kind === 'guild') { + const [guildId, marker, channelId] = rest; + if ( + rest.length !== 3 || + marker !== 'channel' || + guildId === undefined || + channelId === undefined + ) { + return null; + } + return `/app/${encodeURIComponent(guildId)}/${encodeURIComponent(channelId)}`; + } + return null; +} diff --git a/web/src/pages/settings/NotificationsSettingsSection.tsx b/web/src/pages/settings/NotificationsSettingsSection.tsx index e976c4b..2221013 100644 --- a/web/src/pages/settings/NotificationsSettingsSection.tsx +++ b/web/src/pages/settings/NotificationsSettingsSection.tsx @@ -1,22 +1,61 @@ +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { notificationsEnabled, setNotificationsEnabled } from '@/lib/desktopNotifications'; +import { platform } from '@/lib/platform'; import { SettingsSection } from '@/pages/settings/SettingsSection'; /** - * «Уведомления»: пункт уже есть в списке настроек, но сами уведомления - * (веб-пуш и звуки) появятся в следующих фазах — показываем заглушку. + * «Уведомления»: системные уведомления об упоминаниях и личных сообщениях. + * + * Предпочтение хранится на устройстве (localStorage): в desktop-обёртке + * уведомления нативные, в браузере — только при выданном разрешении, а + * веб-пуш (Фаза 7) появится отдельным пунктом. */ export function NotificationsSettingsSection() { const { t } = useTranslation(); + const [enabled, setEnabled] = useState(notificationsEnabled); + // В обёртке уведомления всегда доступны, в браузере — по разрешению. + const supported = platform.kind === 'tauri' || 'Notification' in window; return ( -

- {t('settings.notifications.stub')} -

+ + + {supported ? null : ( +

+ {t('settings.notifications.unsupported')} +

+ )} + + {platform.kind === 'tauri' ? ( + + ) : null}
); } diff --git a/web/src/stores/gateway.ts b/web/src/stores/gateway.ts index ca4f984..05b0e65 100644 --- a/web/src/stores/gateway.ts +++ b/web/src/stores/gateway.ts @@ -31,7 +31,6 @@ import { parseUserUpdate, } from '@/api/gatewayEvents'; import { guildSoundsQueryKey } from '@/api/sounds'; -import { parseSystemMessage } from '@/lib/systemMessage'; import { useFriendsStore } from '@/stores/friends'; import { useMessagesStore } from '@/stores/messages'; import { useSessionStore, type SessionGuild } from '@/stores/session'; @@ -39,6 +38,9 @@ import { playEventSound, useSoundboardStore } from '@/stores/soundboard'; import { useVoiceConnectionStore } from '@/stores/voiceConnection'; import { parseVoiceStateEvent } from '@/api/voice'; import type { Message } from '@/api/messages'; +import { notificationFor, notificationsEnabled } from '@/lib/desktopNotifications'; +import { platform } from '@/lib/platform'; +import { parseSystemMessage } from '@/lib/systemMessage'; /** * Состояние соединения со шлюзом. Данные приходят в session-store, @@ -232,6 +234,7 @@ export function dispatchGatewayEvent(event: GatewayDispatch): void { // В личной беседе «последнее сообщение» — источник бейджа и порядка. session.touchDmChannel(message.channel_id, message.id, message.created_at); playMessageSound(message); + notifyAboutMessage(message); } return; } @@ -448,6 +451,37 @@ function playMessageSound(message: Message): void { playEventSound(guildId, me !== null && message.mentions.includes(me) ? 'mention' : 'message'); } +/** + * Системное уведомление об упоминании или личном сообщении + * (docs/client-tauri.md §5). Решение принимает `notificationFor`, + * а показывает его платформенный адаптер. + */ +function notifyAboutMessage(message: Message): void { + const session = useSessionStore.getState(); + const me = session.user?.id ?? null; + const dmChannel = session.dmChannels.find((channel) => channel.id === message.channel_id); + const guildId = guildIdOfChannel(session.guilds, message.channel_id); + const guildChannel = + guildId === null + ? undefined + : session.guilds + .find((guild) => guild.id === guildId) + ?.channels.find((channel) => channel.id === message.channel_id); + const notification = notificationFor({ + message, + meId: me, + isDirect: dmChannel !== undefined, + channelName: dmChannel?.name ?? guildChannel?.name ?? null, + guildId, + isChannelOpen: session.selectedChannelId === message.channel_id, + windowFocused: document.hasFocus(), + enabled: notificationsEnabled(), + }); + if (notification !== null) { + platform.notify(notification); + } +} + /** Сервер, которому принадлежит комната: в личной беседе его нет. */ function guildIdOfChannel(guilds: SessionGuild[], channelId: string): string | null { for (const guild of guilds) { @@ -466,6 +500,10 @@ async function addGuildFromRest(guildId: string): Promise { ]); const client = getQueryClient(); try { + // Список серверов мог быть прочитан раньше (кэш свеж 30 секунд), поэтому + // сначала помечаем его устаревшим: без этого возврат в сервер после кика + // не появлялся в рейке до перезагрузки (AGENT.md 11.6). + await client.invalidateQueries({ queryKey: users.myGuildsQueryKey }); const guilds = await client.fetchQuery({ queryKey: users.myGuildsQueryKey, queryFn: () => users.fetchMyGuilds(), @@ -475,8 +513,7 @@ async function addGuildFromRest(guildId: string): Promise { useSessionStore.getState().upsertGuild(guild); } } catch { - // Сеть подвела — просто помечаем данные устаревшими для следующего рендера. - await client.invalidateQueries({ queryKey: users.myGuildsQueryKey }); + // Сеть подвела — данные уже помечены устаревшими для следующего рендера. } } @@ -568,10 +605,11 @@ async function invalidateCurrentUser(): Promise { import('@/lib/queryClient'), import('@/api/users'), ]); + const client = getQueryClient(); // Именно refetch, а не removeQueries: AuthGuard узнаёт о мёртвой сессии по // 401 на запросе профиля и только тогда уводит на экран входа (AGENT.md 11.6). - getQueryClient().removeQueries({ queryKey: currentUserQueryKey }); - await getQueryClient().refetchQueries({ queryKey: currentUserQueryKey }); + client.removeQueries({ queryKey: currentUserQueryKey }); + await client.refetchQueries({ queryKey: currentUserQueryKey }); } async function refetchCurrentUser(): Promise { diff --git a/web/tests/desktopNotifications.test.ts b/web/tests/desktopNotifications.test.ts new file mode 100644 index 0000000..2ed0e72 --- /dev/null +++ b/web/tests/desktopNotifications.test.ts @@ -0,0 +1,126 @@ +import { describe, expect, it, vi } from 'vitest'; + +import { + notificationFor, + notificationsEnabled, + previewText, + setNotificationsEnabled, +} from '@/lib/desktopNotifications'; +import type { NotificationInput } from '@/lib/desktopNotifications'; + +/** Сообщение по умолчанию: обычное сообщение в канале сервера. */ +function input(overrides: Partial = {}): NotificationInput { + return { + message: { + type: 'default', + content: 'привет', + mentions: [], + channel_id: 'c1', + author_id: 'u2', + }, + meId: 'u1', + isDirect: false, + channelName: 'общий', + guildId: 'g1', + isChannelOpen: false, + windowFocused: false, + enabled: true, + ...overrides, + }; +} + +describe('notificationFor', () => { + it('уведомляет об упоминании в неактивной комнате', () => { + const result = notificationFor(input({ message: { ...input().message, mentions: ['u1'] } })); + expect(result).toMatchObject({ title: 'Упоминание в #общий', body: 'привет', channelId: 'c1' }); + }); + + it('уведомляет о личном сообщении', () => { + const result = notificationFor(input({ isDirect: true, channelName: 'Аня', guildId: null })); + expect(result).toMatchObject({ title: 'Личное сообщение — Аня', guildId: null }); + }); + + it('молчит об обычном сообщении в канале', () => { + expect(notificationFor(input())).toBeNull(); + }); + + it('молчит о собственных сообщениях', () => { + const result = notificationFor( + input({ + isDirect: true, + message: { ...input().message, author_id: 'u1' }, + }), + ); + expect(result).toBeNull(); + }); + + it('молчит, когда открытая комната в фокусе', () => { + const result = notificationFor( + input({ isDirect: true, isChannelOpen: true, windowFocused: true }), + ); + expect(result).toBeNull(); + }); + + it('уведомляет об открытой комнате, если окно не в фокусе', () => { + const result = notificationFor( + input({ isDirect: true, isChannelOpen: true, windowFocused: false }), + ); + expect(result).not.toBeNull(); + }); + + it('молчит при выключенных уведомлениях', () => { + expect(notificationFor(input({ isDirect: true, enabled: false }))).toBeNull(); + }); + + it('пропускает системные сообщения', () => { + const result = notificationFor( + input({ + isDirect: true, + message: { ...input().message, type: 'system' }, + }), + ); + expect(result).toBeNull(); + }); + + it('подставляет «Вложение» для сообщения без текста', () => { + const result = notificationFor( + input({ + isDirect: true, + message: { ...input().message, content: '', mentions: ['u1'] }, + }), + ); + expect(result?.body).toBe('Вложение'); + }); +}); + +describe('previewText', () => { + it('убирает разметку и лишние переводы строк', () => { + expect(previewText('**жирный**\n\n[ссылка](https://example.com) `код`')).toBe( + 'жирный ссылка код', + ); + }); + + it('обрезает длинный текст', () => { + const result = previewText('а'.repeat(400)); + expect(result.length).toBeLessThanOrEqual(140); + expect(result.endsWith('…')).toBe(true); + }); +}); + +describe('предпочтение уведомлений', () => { + it('включено по умолчанию и выключается переключателем', () => { + expect(notificationsEnabled()).toBe(true); + setNotificationsEnabled(false); + expect(notificationsEnabled()).toBe(false); + setNotificationsEnabled(true); + expect(notificationsEnabled()).toBe(true); + }); + + it('не падает, если localStorage недоступен', () => { + const stub = vi.spyOn(window, 'localStorage', 'get').mockImplementation(() => { + throw new Error('нет доступа'); + }); + expect(notificationsEnabled()).toBe(true); + stub.mockRestore(); + }); +}); diff --git a/web/tests/platform.test.ts b/web/tests/platform.test.ts new file mode 100644 index 0000000..185045b --- /dev/null +++ b/web/tests/platform.test.ts @@ -0,0 +1,86 @@ +import { describe, expect, it, vi } from 'vitest'; + +import { isTauri, platform, routeFromDeepLink, type DesktopMessage } from '@/lib/platform'; + +/** Ставит в window фальшивый мост Tauri v2 и возвращает список вызовов. */ +function stubTauri(): Array<{ command: string; args: unknown }> { + const calls: Array<{ command: string; args: unknown }> = []; + vi.stubGlobal('__TAURI_INTERNALS__', { + invoke: (command: string, args?: unknown) => { + calls.push({ command, args }); + return Promise.resolve(undefined); + }, + }); + return calls; +} + +describe('routeFromDeepLink', () => { + it('разбирает приглашение', () => { + expect(routeFromDeepLink('glchat://invite/AbC123')).toBe('/invite/AbC123'); + }); + + it('разбирает сервер и комнату', () => { + expect(routeFromDeepLink('glchat://guild/10/channel/20')).toBe('/app/10/20'); + }); + + it('игнорирует чужие схемы и неизвестные пути', () => { + expect(routeFromDeepLink('https://gl.mhspx.su/invite/abc')).toBeNull(); + expect(routeFromDeepLink('glchat://unknown/1')).toBeNull(); + expect(routeFromDeepLink('glchat://guild/10')).toBeNull(); + expect(routeFromDeepLink('не ссылка')).toBeNull(); + }); +}); + +describe('платформа в браузере', () => { + it('определяется как web и не падает на вызовах', () => { + expect(isTauri()).toBe(false); + expect(platform.kind).toBe('web'); + expect(() => { + platform.notify({ title: 'a', body: 'b' }); + platform.setBadge(3); + platform.ready(); + platform.openSettings(); + }).not.toThrow(); + expect(platform.onMessage(() => {})()).toBeUndefined(); + }); +}); + +describe('платформа в desktop-обёртке', () => { + it('вызывает команды обёртки и принимает её сообщения', async () => { + const calls = stubTauri(); + vi.resetModules(); + const desktop = await import('@/lib/platform'); + + expect(desktop.isTauri()).toBe(true); + expect(desktop.platform.kind).toBe('tauri'); + + desktop.platform.notify({ title: 'Упоминание', body: 'привет', channelId: 'c1' }); + desktop.platform.setBadge(2); + desktop.platform.ready(); + desktop.platform.openSettings(); + + expect(calls.map((call) => call.command)).toEqual([ + 'desktop_notify', + 'desktop_set_badge', + 'desktop_ready', + 'desktop_open_settings', + ]); + expect(calls[0]?.args).toEqual({ + payload: { title: 'Упоминание', body: 'привет', guildId: null, channelId: 'c1' }, + }); + expect(calls[1]?.args).toEqual({ count: 2 }); + + // Обёртка зовёт страницу через window.__glchatDesktop.receive. + const received: DesktopMessage[] = []; + const unsubscribe = desktop.platform.onMessage((message) => received.push(message)); + const bridge = window as unknown as { + __glchatDesktop?: { receive: (m: DesktopMessage) => void }; + }; + bridge.__glchatDesktop?.receive({ type: 'ptt', active: true }); + expect(received).toEqual([{ type: 'ptt', active: true }]); + + unsubscribe(); + bridge.__glchatDesktop?.receive({ type: 'toggleMic' }); + expect(received).toHaveLength(1); + }); +}); diff --git a/web/tests/settings.test.tsx b/web/tests/settings.test.tsx index e5f5620..1628103 100644 --- a/web/tests/settings.test.tsx +++ b/web/tests/settings.test.tsx @@ -222,14 +222,20 @@ describe('настройки: окно и навигация', () => { expect(within(dialog).queryByRole('button', { name: 'Инстанс' })).toBeNull(); }); - it('«Уведомления» пока заглушка', async () => { + it('«Уведомления» переключают уведомления рабочего стола', async () => { installFetch(appRoutes()); renderApp('/app/empty'); const dialog = await openSettings(); await goToSection(dialog, 'Уведомления'); - expect(within(dialog).getByText('Настройки уведомлений появятся позже.')).toBeVisible(); + const toggle = within(dialog).getByRole('checkbox', { name: /Уведомления рабочего стола/ }); + expect(toggle).toBeChecked(); + + await userEvent.click(toggle); + + expect(toggle).not.toBeChecked(); + expect(window.localStorage.getItem('glchat.desktop-notifications')).toBe('off'); }); it('«Аудио-видео» без mediaDevices честно сообщает о недоступности', async () => {