Feat: Switch DRPC Plugins

This commit is contained in:
Youwes09
2026-04-03 22:07:42 -05:00
parent db44afc4dc
commit 5cd96abc0c
10 changed files with 302 additions and 413 deletions
+1 -1
View File
@@ -181,7 +181,7 @@ modules:
path: . path: .
- type: file - type: file
path: packaging/frontend-dist.tar.gz path: packaging/frontend-dist.tar.gz
sha256: 43b7274bdab884aacbc3dad6f0f7c043d8e3d82b7bf7398e1df9f516ed553152 sha256: d3ebde4d39e3de61420b78a9506df1a5c77c14d705e42662a45a2179bc96030e
- packaging/cargo-sources.json - packaging/cargo-sources.json
- type: inline - type: inline
dest: src-tauri/.cargo dest: src-tauri/.cargo
+1 -1
View File
@@ -71,7 +71,7 @@
inherit version; inherit version;
src = frontendSrc; src = frontendSrc;
fetcherVersion = 1; fetcherVersion = 1;
hash = "sha256-ezlckHhfSIe/Hs30tbiN0a/EuvGxhO5L020aup23Ozg="; hash = "sha256-oJVMFL1wdAd1x4AQECTh/yPMhiirbjUduBelZ3bWQtI=";
}; };
buildPhase = "pnpm build"; buildPhase = "pnpm build";
+1
View File
@@ -16,6 +16,7 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"phosphor-svelte": "^3.1.0", "phosphor-svelte": "^3.1.0",
"svelte-spa-router": "^4.0.1", "svelte-spa-router": "^4.0.1",
"tauri-plugin-discord-rpc-api": "github:Youwes09/tauri-plugin-discord-rpc",
"tauri-plugin-drpc": "^1.0.3" "tauri-plugin-drpc": "^1.0.3"
}, },
"devDependencies": { "devDependencies": {
+115 -115
View File
@@ -2030,92 +2030,92 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_collections/icu_collections-2.1.1.crate", "url": "https://static.crates.io/crates/icu_collections/icu_collections-2.2.0.crate",
"sha256": "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43", "sha256": "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c",
"dest": "cargo/vendor/icu_collections-2.1.1" "dest": "cargo/vendor/icu_collections-2.2.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43\", \"files\": {}}", "contents": "{\"package\": \"2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c\", \"files\": {}}",
"dest": "cargo/vendor/icu_collections-2.1.1", "dest": "cargo/vendor/icu_collections-2.2.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_locale_core/icu_locale_core-2.1.1.crate", "url": "https://static.crates.io/crates/icu_locale_core/icu_locale_core-2.2.0.crate",
"sha256": "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6", "sha256": "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29",
"dest": "cargo/vendor/icu_locale_core-2.1.1" "dest": "cargo/vendor/icu_locale_core-2.2.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6\", \"files\": {}}", "contents": "{\"package\": \"92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29\", \"files\": {}}",
"dest": "cargo/vendor/icu_locale_core-2.1.1", "dest": "cargo/vendor/icu_locale_core-2.2.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_normalizer/icu_normalizer-2.1.1.crate", "url": "https://static.crates.io/crates/icu_normalizer/icu_normalizer-2.2.0.crate",
"sha256": "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599", "sha256": "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4",
"dest": "cargo/vendor/icu_normalizer-2.1.1" "dest": "cargo/vendor/icu_normalizer-2.2.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599\", \"files\": {}}", "contents": "{\"package\": \"c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4\", \"files\": {}}",
"dest": "cargo/vendor/icu_normalizer-2.1.1", "dest": "cargo/vendor/icu_normalizer-2.2.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_normalizer_data/icu_normalizer_data-2.1.1.crate", "url": "https://static.crates.io/crates/icu_normalizer_data/icu_normalizer_data-2.2.0.crate",
"sha256": "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a", "sha256": "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38",
"dest": "cargo/vendor/icu_normalizer_data-2.1.1" "dest": "cargo/vendor/icu_normalizer_data-2.2.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a\", \"files\": {}}", "contents": "{\"package\": \"da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38\", \"files\": {}}",
"dest": "cargo/vendor/icu_normalizer_data-2.1.1", "dest": "cargo/vendor/icu_normalizer_data-2.2.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_properties/icu_properties-2.1.2.crate", "url": "https://static.crates.io/crates/icu_properties/icu_properties-2.2.0.crate",
"sha256": "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec", "sha256": "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de",
"dest": "cargo/vendor/icu_properties-2.1.2" "dest": "cargo/vendor/icu_properties-2.2.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec\", \"files\": {}}", "contents": "{\"package\": \"bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de\", \"files\": {}}",
"dest": "cargo/vendor/icu_properties-2.1.2", "dest": "cargo/vendor/icu_properties-2.2.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_properties_data/icu_properties_data-2.1.2.crate", "url": "https://static.crates.io/crates/icu_properties_data/icu_properties_data-2.2.0.crate",
"sha256": "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af", "sha256": "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14",
"dest": "cargo/vendor/icu_properties_data-2.1.2" "dest": "cargo/vendor/icu_properties_data-2.2.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af\", \"files\": {}}", "contents": "{\"package\": \"8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14\", \"files\": {}}",
"dest": "cargo/vendor/icu_properties_data-2.1.2", "dest": "cargo/vendor/icu_properties_data-2.2.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_provider/icu_provider-2.1.1.crate", "url": "https://static.crates.io/crates/icu_provider/icu_provider-2.2.0.crate",
"sha256": "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614", "sha256": "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421",
"dest": "cargo/vendor/icu_provider-2.1.1" "dest": "cargo/vendor/icu_provider-2.2.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614\", \"files\": {}}", "contents": "{\"package\": \"139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421\", \"files\": {}}",
"dest": "cargo/vendor/icu_provider-2.1.1", "dest": "cargo/vendor/icu_provider-2.2.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -2186,14 +2186,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/indexmap/indexmap-2.13.0.crate", "url": "https://static.crates.io/crates/indexmap/indexmap-2.13.1.crate",
"sha256": "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017", "sha256": "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff",
"dest": "cargo/vendor/indexmap-2.13.0" "dest": "cargo/vendor/indexmap-2.13.1"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017\", \"files\": {}}", "contents": "{\"package\": \"45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff\", \"files\": {}}",
"dest": "cargo/vendor/indexmap-2.13.0", "dest": "cargo/vendor/indexmap-2.13.1",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -2459,14 +2459,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/libc/libc-0.2.183.crate", "url": "https://static.crates.io/crates/libc/libc-0.2.184.crate",
"sha256": "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d", "sha256": "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af",
"dest": "cargo/vendor/libc-0.2.183" "dest": "cargo/vendor/libc-0.2.184"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d\", \"files\": {}}", "contents": "{\"package\": \"48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af\", \"files\": {}}",
"dest": "cargo/vendor/libc-0.2.183", "dest": "cargo/vendor/libc-0.2.184",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -2511,14 +2511,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/litemap/litemap-0.8.1.crate", "url": "https://static.crates.io/crates/litemap/litemap-0.8.2.crate",
"sha256": "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77", "sha256": "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0",
"dest": "cargo/vendor/litemap-0.8.1" "dest": "cargo/vendor/litemap-0.8.2"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77\", \"files\": {}}", "contents": "{\"package\": \"92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0\", \"files\": {}}",
"dest": "cargo/vendor/litemap-0.8.1", "dest": "cargo/vendor/litemap-0.8.2",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -2719,14 +2719,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/muda/muda-0.17.1.crate", "url": "https://static.crates.io/crates/muda/muda-0.17.2.crate",
"sha256": "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a", "sha256": "7c9fec5a4e89860383d778d10563a605838f8f0b2f9303868937e5ff32e86177",
"dest": "cargo/vendor/muda-0.17.1" "dest": "cargo/vendor/muda-0.17.2"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a\", \"files\": {}}", "contents": "{\"package\": \"7c9fec5a4e89860383d778d10563a605838f8f0b2f9303868937e5ff32e86177\", \"files\": {}}",
"dest": "cargo/vendor/muda-0.17.1", "dest": "cargo/vendor/muda-0.17.2",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -3577,14 +3577,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/potential_utf/potential_utf-0.1.4.crate", "url": "https://static.crates.io/crates/potential_utf/potential_utf-0.1.5.crate",
"sha256": "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77", "sha256": "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564",
"dest": "cargo/vendor/potential_utf-0.1.4" "dest": "cargo/vendor/potential_utf-0.1.5"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77\", \"files\": {}}", "contents": "{\"package\": \"0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564\", \"files\": {}}",
"dest": "cargo/vendor/potential_utf-0.1.4", "dest": "cargo/vendor/potential_utf-0.1.5",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -5514,14 +5514,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/tinystr/tinystr-0.8.2.crate", "url": "https://static.crates.io/crates/tinystr/tinystr-0.8.3.crate",
"sha256": "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869", "sha256": "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d",
"dest": "cargo/vendor/tinystr-0.8.2" "dest": "cargo/vendor/tinystr-0.8.3"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869\", \"files\": {}}", "contents": "{\"package\": \"c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d\", \"files\": {}}",
"dest": "cargo/vendor/tinystr-0.8.2", "dest": "cargo/vendor/tinystr-0.8.3",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -5696,27 +5696,27 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/toml_edit/toml_edit-0.25.9+spec-1.1.0.crate", "url": "https://static.crates.io/crates/toml_edit/toml_edit-0.25.10+spec-1.1.0.crate",
"sha256": "da053d28fe57e2c9d21b48261e14e7b4c8b670b54d2c684847b91feaf4c7dac5", "sha256": "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b",
"dest": "cargo/vendor/toml_edit-0.25.9+spec-1.1.0" "dest": "cargo/vendor/toml_edit-0.25.10+spec-1.1.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"da053d28fe57e2c9d21b48261e14e7b4c8b670b54d2c684847b91feaf4c7dac5\", \"files\": {}}", "contents": "{\"package\": \"a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b\", \"files\": {}}",
"dest": "cargo/vendor/toml_edit-0.25.9+spec-1.1.0", "dest": "cargo/vendor/toml_edit-0.25.10+spec-1.1.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/toml_parser/toml_parser-1.1.1+spec-1.1.0.crate", "url": "https://static.crates.io/crates/toml_parser/toml_parser-1.1.2+spec-1.1.0.crate",
"sha256": "39ca317ebc49f06bd748bfba29533eac9485569dc9bf80b849024b025e814fb9", "sha256": "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526",
"dest": "cargo/vendor/toml_parser-1.1.1+spec-1.1.0" "dest": "cargo/vendor/toml_parser-1.1.2+spec-1.1.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"39ca317ebc49f06bd748bfba29533eac9485569dc9bf80b849024b025e814fb9\", \"files\": {}}", "contents": "{\"package\": \"a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526\", \"files\": {}}",
"dest": "cargo/vendor/toml_parser-1.1.1+spec-1.1.0", "dest": "cargo/vendor/toml_parser-1.1.2+spec-1.1.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -7438,14 +7438,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/writeable/writeable-0.6.2.crate", "url": "https://static.crates.io/crates/writeable/writeable-0.6.3.crate",
"sha256": "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9", "sha256": "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4",
"dest": "cargo/vendor/writeable-0.6.2" "dest": "cargo/vendor/writeable-0.6.3"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9\", \"files\": {}}", "contents": "{\"package\": \"1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4\", \"files\": {}}",
"dest": "cargo/vendor/writeable-0.6.2", "dest": "cargo/vendor/writeable-0.6.3",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -7503,27 +7503,27 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/yoke/yoke-0.8.1.crate", "url": "https://static.crates.io/crates/yoke/yoke-0.8.2.crate",
"sha256": "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954", "sha256": "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca",
"dest": "cargo/vendor/yoke-0.8.1" "dest": "cargo/vendor/yoke-0.8.2"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954\", \"files\": {}}", "contents": "{\"package\": \"abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca\", \"files\": {}}",
"dest": "cargo/vendor/yoke-0.8.1", "dest": "cargo/vendor/yoke-0.8.2",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/yoke-derive/yoke-derive-0.8.1.crate", "url": "https://static.crates.io/crates/yoke-derive/yoke-derive-0.8.2.crate",
"sha256": "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d", "sha256": "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e",
"dest": "cargo/vendor/yoke-derive-0.8.1" "dest": "cargo/vendor/yoke-derive-0.8.2"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d\", \"files\": {}}", "contents": "{\"package\": \"de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e\", \"files\": {}}",
"dest": "cargo/vendor/yoke-derive-0.8.1", "dest": "cargo/vendor/yoke-derive-0.8.2",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -7555,27 +7555,27 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/zerofrom/zerofrom-0.1.6.crate", "url": "https://static.crates.io/crates/zerofrom/zerofrom-0.1.7.crate",
"sha256": "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5", "sha256": "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df",
"dest": "cargo/vendor/zerofrom-0.1.6" "dest": "cargo/vendor/zerofrom-0.1.7"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5\", \"files\": {}}", "contents": "{\"package\": \"69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df\", \"files\": {}}",
"dest": "cargo/vendor/zerofrom-0.1.6", "dest": "cargo/vendor/zerofrom-0.1.7",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/zerofrom-derive/zerofrom-derive-0.1.6.crate", "url": "https://static.crates.io/crates/zerofrom-derive/zerofrom-derive-0.1.7.crate",
"sha256": "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502", "sha256": "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1",
"dest": "cargo/vendor/zerofrom-derive-0.1.6" "dest": "cargo/vendor/zerofrom-derive-0.1.7"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502\", \"files\": {}}", "contents": "{\"package\": \"11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1\", \"files\": {}}",
"dest": "cargo/vendor/zerofrom-derive-0.1.6", "dest": "cargo/vendor/zerofrom-derive-0.1.7",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@@ -7594,40 +7594,40 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/zerotrie/zerotrie-0.2.3.crate", "url": "https://static.crates.io/crates/zerotrie/zerotrie-0.2.4.crate",
"sha256": "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851", "sha256": "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf",
"dest": "cargo/vendor/zerotrie-0.2.3" "dest": "cargo/vendor/zerotrie-0.2.4"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851\", \"files\": {}}", "contents": "{\"package\": \"0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf\", \"files\": {}}",
"dest": "cargo/vendor/zerotrie-0.2.3", "dest": "cargo/vendor/zerotrie-0.2.4",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/zerovec/zerovec-0.11.5.crate", "url": "https://static.crates.io/crates/zerovec/zerovec-0.11.6.crate",
"sha256": "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002", "sha256": "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239",
"dest": "cargo/vendor/zerovec-0.11.5" "dest": "cargo/vendor/zerovec-0.11.6"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002\", \"files\": {}}", "contents": "{\"package\": \"90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239\", \"files\": {}}",
"dest": "cargo/vendor/zerovec-0.11.5", "dest": "cargo/vendor/zerovec-0.11.6",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/zerovec-derive/zerovec-derive-0.11.2.crate", "url": "https://static.crates.io/crates/zerovec-derive/zerovec-derive-0.11.3.crate",
"sha256": "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3", "sha256": "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555",
"dest": "cargo/vendor/zerovec-derive-0.11.2" "dest": "cargo/vendor/zerovec-derive-0.11.3"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3\", \"files\": {}}", "contents": "{\"package\": \"625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555\", \"files\": {}}",
"dest": "cargo/vendor/zerovec-derive-0.11.2", "dest": "cargo/vendor/zerovec-derive-0.11.3",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
+11
View File
@@ -26,6 +26,9 @@ importers:
svelte-spa-router: svelte-spa-router:
specifier: ^4.0.1 specifier: ^4.0.1
version: 4.0.2 version: 4.0.2
tauri-plugin-discord-rpc-api:
specifier: github:Youwes09/tauri-plugin-discord-rpc
version: https://codeload.github.com/Youwes09/tauri-plugin-discord-rpc/tar.gz/4b20388e4b65e0efcff2aa9a8622b5884554cd8a
tauri-plugin-drpc: tauri-plugin-drpc:
specifier: ^1.0.3 specifier: ^1.0.3
version: 1.0.3(typescript@5.9.3) version: 1.0.3(typescript@5.9.3)
@@ -747,6 +750,10 @@ packages:
resolution: {integrity: sha512-TTDxwYnHkova6Wsyj1PGt9TByuWqvMoeY1bQiuAf2DM/JeDSMw7FjRKzk8K/5mJ99vGOKhbCqTDpyAKwjp4igg==} resolution: {integrity: sha512-TTDxwYnHkova6Wsyj1PGt9TByuWqvMoeY1bQiuAf2DM/JeDSMw7FjRKzk8K/5mJ99vGOKhbCqTDpyAKwjp4igg==}
engines: {node: '>=18'} engines: {node: '>=18'}
tauri-plugin-discord-rpc-api@https://codeload.github.com/Youwes09/tauri-plugin-discord-rpc/tar.gz/4b20388e4b65e0efcff2aa9a8622b5884554cd8a:
resolution: {tarball: https://codeload.github.com/Youwes09/tauri-plugin-discord-rpc/tar.gz/4b20388e4b65e0efcff2aa9a8622b5884554cd8a}
version: 0.1.0
tauri-plugin-drpc@1.0.3: tauri-plugin-drpc@1.0.3:
resolution: {integrity: sha512-vl5dXhjKbl7+Nf9veW12usdmIUtZXwEf91SzxQPZlbRRJ/sjizbbQlnkUTtx6baJuGzz0KXXgP9xUhF39BdiXQ==} resolution: {integrity: sha512-vl5dXhjKbl7+Nf9veW12usdmIUtZXwEf91SzxQPZlbRRJ/sjizbbQlnkUTtx6baJuGzz0KXXgP9xUhF39BdiXQ==}
peerDependencies: peerDependencies:
@@ -1372,6 +1379,10 @@ snapshots:
magic-string: 0.30.21 magic-string: 0.30.21
zimmerframe: 1.1.4 zimmerframe: 1.1.4
tauri-plugin-discord-rpc-api@https://codeload.github.com/Youwes09/tauri-plugin-discord-rpc/tar.gz/4b20388e4b65e0efcff2aa9a8622b5884554cd8a:
dependencies:
'@tauri-apps/api': 2.10.1
tauri-plugin-drpc@1.0.3(typescript@5.9.3): tauri-plugin-drpc@1.0.3(typescript@5.9.3):
dependencies: dependencies:
typescript: 5.9.3 typescript: 5.9.3
+55 -28
View File
@@ -268,9 +268,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.58" version = "1.2.59"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"shlex", "shlex",
@@ -699,6 +699,21 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "discord-rich-presence"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90c55d69cab17c19677ce3a5f8face993a9e6eaf847fecac3547f3a3ff4a2494"
dependencies = [
"log",
"serde",
"serde_derive",
"serde_json",
"serde_repr",
"thiserror 2.0.18",
"uuid 0.8.2",
]
[[package]] [[package]]
name = "dispatch2" name = "dispatch2"
version = "0.3.1" version = "0.3.1"
@@ -2109,10 +2124,10 @@ dependencies = [
"dirs 5.0.1", "dirs 5.0.1",
"serde", "serde",
"serde_json", "serde_json",
"sysinfo", "sysinfo 0.32.1",
"tauri", "tauri",
"tauri-build", "tauri-build",
"tauri-plugin-drpc", "tauri-plugin-discord-rpc",
"tauri-plugin-http", "tauri-plugin-http",
"tauri-plugin-os", "tauri-plugin-os",
"tauri-plugin-process", "tauri-plugin-process",
@@ -2370,6 +2385,16 @@ dependencies = [
"objc2-core-foundation", "objc2-core-foundation",
] ]
[[package]]
name = "objc2-io-kit"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
dependencies = [
"libc",
"objc2-core-foundation",
]
[[package]] [[package]]
name = "objc2-io-surface" name = "objc2-io-surface"
version = "0.3.2" version = "0.3.2"
@@ -3341,19 +3366,6 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "rpcdiscord"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71aa9a2097dc0176805e24debcb5d3ea5a17b796cd1d28e76b29f78fb49d7d5d"
dependencies = [
"serde",
"serde_derive",
"serde_json",
"serde_repr",
"uuid 0.8.2",
]
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
version = "2.1.2" version = "2.1.2"
@@ -3605,9 +3617,9 @@ dependencies = [
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.27" version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
dependencies = [ dependencies = [
"serde", "serde",
"serde_core", "serde_core",
@@ -4082,6 +4094,20 @@ dependencies = [
"windows 0.57.0", "windows 0.57.0",
] ]
[[package]]
name = "sysinfo"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
dependencies = [
"libc",
"memchr",
"ntapi",
"objc2-core-foundation",
"objc2-io-kit",
"windows 0.61.3",
]
[[package]] [[package]]
name = "system-configuration" name = "system-configuration"
version = "0.7.0" version = "0.7.0"
@@ -4314,15 +4340,16 @@ dependencies = [
] ]
[[package]] [[package]]
name = "tauri-plugin-drpc" name = "tauri-plugin-discord-rpc"
version = "0.1.6" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/Youwes09/tauri-plugin-discord-rpc#d2fd312945d0573153e0e7e2d2dfb131acecc52c"
checksum = "7b291669b7dbc05471fba380eeecf31e3f733ae6013aaa5216a43ca376027e5a"
dependencies = [ dependencies = [
"discord-rich-presence",
"libc",
"log", "log",
"rpcdiscord",
"serde", "serde",
"serde_json", "serde_json",
"sysinfo 0.36.1",
"tauri", "tauri",
"tauri-plugin", "tauri-plugin",
"thiserror 2.0.18", "thiserror 2.0.18",
@@ -4689,9 +4716,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.50.0" version = "1.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd"
dependencies = [ dependencies = [
"bytes", "bytes",
"libc", "libc",
@@ -4704,9 +4731,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.6.1" version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
+2 -2
View File
@@ -20,13 +20,13 @@ tauri-plugin-shell = "2"
tauri-plugin-updater = "2" tauri-plugin-updater = "2"
tauri-plugin-process = "2" tauri-plugin-process = "2"
tauri-plugin-http = "2" tauri-plugin-http = "2"
tauri-plugin-os = "2.3.2"
tauri-plugin-discord-rpc = { git = "https://github.com/Youwes09/tauri-plugin-discord-rpc" }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
walkdir = "2" walkdir = "2"
sysinfo = "0.32" sysinfo = "0.32"
dirs = "5" dirs = "5"
tauri-plugin-os = "2.3.2"
tauri-plugin-drpc = "0.1.6"
[profile.release] [profile.release]
codegen-units = 1 codegen-units = 1
+6 -6
View File
@@ -33,11 +33,11 @@
"process:allow-restart", "process:allow-restart",
"http:default", "http:default",
"http:allow-fetch", "http:allow-fetch",
"drpc:default", "discord-rpc:default",
"drpc:allow-is-running", "discord-rpc:allow-connect",
"drpc:allow-spawn-thread", "discord-rpc:allow-disconnect",
"drpc:allow-destroy-thread", "discord-rpc:allow-set-activity",
"drpc:allow-set-activity", "discord-rpc:allow-clear-activity",
"drpc:allow-clear-activity" "discord-rpc:allow-is-running"
] ]
} }
+36 -186
View File
@@ -26,9 +26,6 @@ pub enum SpawnError {
SpawnFailed(String), SpawnFailed(String),
} }
// ── Update types ──────────────────────────────────────────────────────────────
/// A single GitHub release returned to the frontend.
#[derive(Serialize, Clone)] #[derive(Serialize, Clone)]
pub struct ReleaseInfo { pub struct ReleaseInfo {
pub tag_name: String, pub tag_name: String,
@@ -38,7 +35,6 @@ pub struct ReleaseInfo {
pub html_url: String, pub html_url: String,
} }
/// Progress event emitted during download — matches what the frontend listens for.
#[derive(Clone, serde::Serialize)] #[derive(Clone, serde::Serialize)]
#[cfg_attr(not(target_os = "windows"), allow(dead_code))] #[cfg_attr(not(target_os = "windows"), allow(dead_code))]
struct UpdateProgress { struct UpdateProgress {
@@ -46,8 +42,6 @@ struct UpdateProgress {
total: Option<u64>, total: Option<u64>,
} }
/// Strip the \\?\ extended-length path prefix that Windows adds to long paths.
/// Java and many other tools do not accept this prefix and will fail silently.
fn strip_unc(path: PathBuf) -> PathBuf { fn strip_unc(path: PathBuf) -> PathBuf {
let s = path.to_string_lossy(); let s = path.to_string_lossy();
if let Some(stripped) = s.strip_prefix(r"\\?\") { if let Some(stripped) = s.strip_prefix(r"\\?\") {
@@ -61,10 +55,6 @@ fn resolve_downloads_path(downloads_path: &str) -> PathBuf {
if !downloads_path.trim().is_empty() { if !downloads_path.trim().is_empty() {
return PathBuf::from(downloads_path); return PathBuf::from(downloads_path);
} }
// Mirror Suwayomi-Server's own default: <data_dir>/Tachidesk/downloads
// Windows: %LOCALAPPDATA%\Tachidesk\downloads
// macOS: ~/Library/Application Support/Tachidesk/downloads
// Linux: $XDG_DATA_HOME/Tachidesk/downloads (~/.local/share/Tachidesk/downloads)
let base = std::env::var("XDG_DATA_HOME") let base = std::env::var("XDG_DATA_HOME")
.map(PathBuf::from) .map(PathBuf::from)
.unwrap_or_else(|_| dirs::data_dir().unwrap_or_else(|| PathBuf::from("/"))); .unwrap_or_else(|_| dirs::data_dir().unwrap_or_else(|| PathBuf::from("/")));
@@ -108,34 +98,23 @@ fn get_storage_info(downloads_path: String) -> Result<StorageInfo, String> {
}) })
} }
/// Returns the resolved default downloads path for the current platform.
/// This mirrors resolve_downloads_path("") so the frontend can display it.
#[tauri::command] #[tauri::command]
fn get_default_downloads_path() -> String { fn get_default_downloads_path() -> String {
resolve_downloads_path("").to_string_lossy().into_owned() resolve_downloads_path("").to_string_lossy().into_owned()
} }
/// Returns true if the given path exists and is a directory.
#[tauri::command] #[tauri::command]
fn check_path_exists(path: String) -> bool { fn check_path_exists(path: String) -> bool {
std::path::Path::new(path.trim()).is_dir() std::path::Path::new(path.trim()).is_dir()
} }
/// Creates a directory and all missing parent directories.
#[tauri::command] #[tauri::command]
fn create_directory(path: String) -> Result<(), String> { fn create_directory(path: String) -> Result<(), String> {
std::fs::create_dir_all(path.trim()).map_err(|e| e.to_string()) std::fs::create_dir_all(path.trim()).map_err(|e| e.to_string())
} }
/// Moves all content from `src` into `dst`, then removes `src`.
/// Emits `migrate_progress` events: `{ done, total, current }`.
/// Only deletes the source tree after every file is confirmed copied.
#[tauri::command] #[tauri::command]
async fn migrate_downloads( async fn migrate_downloads(app: tauri::AppHandle, src: String, dst: String) -> Result<(), String> {
app: tauri::AppHandle,
src: String,
dst: String,
) -> Result<(), String> {
use tauri::Emitter; use tauri::Emitter;
use std::fs; use std::fs;
@@ -143,19 +122,16 @@ async fn migrate_downloads(
let dst_path = std::path::PathBuf::from(dst.trim()); let dst_path = std::path::PathBuf::from(dst.trim());
if !src_path.is_dir() { if !src_path.is_dir() {
return Ok(()); // nothing to migrate return Ok(());
} }
// Count files first so the frontend can show accurate progress
let total: u64 = WalkDir::new(&src_path) let total: u64 = WalkDir::new(&src_path)
.into_iter() .into_iter()
.filter_map(|e| e.ok()) .filter_map(|e| e.ok())
.filter(|e| e.file_type().is_file()) .filter(|e| e.file_type().is_file())
.count() as u64; .count() as u64;
let _ = app.emit("migrate_progress", serde_json::json!({ let _ = app.emit("migrate_progress", serde_json::json!({ "done": 0u64, "total": total, "current": "" }));
"done": 0u64, "total": total, "current": ""
}));
let mut done: u64 = 0; let mut done: u64 = 0;
@@ -172,23 +148,15 @@ async fn migrate_downloads(
fs::copy(entry.path(), &target).map_err(|e| e.to_string())?; fs::copy(entry.path(), &target).map_err(|e| e.to_string())?;
done += 1; done += 1;
let _ = app.emit("migrate_progress", serde_json::json!({ let _ = app.emit("migrate_progress", serde_json::json!({
"done": done, "done": done, "total": total, "current": rel.to_string_lossy()
"total": total,
"current": rel.to_string_lossy()
})); }));
} }
} }
// Only remove source after all files are confirmed copied
fs::remove_dir_all(&src_path).map_err(|e| e.to_string())?; fs::remove_dir_all(&src_path).map_err(|e| e.to_string())?;
Ok(()) Ok(())
} }
/// Returns the OS/monitor DPI scale factor for the window's current monitor.
/// This is the real hardware scale — 1.0 on standard displays, 2.0 on HiDPI/4K,
/// 1.251.5 on Windows displays with OS-level scaling applied.
/// The frontend multiplies this by the user's uiZoom preference to get the
/// final effective zoom applied to document.documentElement.
#[tauri::command] #[tauri::command]
fn get_platform_ui_scale(window: tauri::Window) -> f64 { fn get_platform_ui_scale(window: tauri::Window) -> f64 {
window.scale_factor().unwrap_or(1.0) window.scale_factor().unwrap_or(1.0)
@@ -210,8 +178,6 @@ fn kill_tachidesk(app: &tauri::AppHandle) {
.creation_flags(CREATE_NO_WINDOW) .creation_flags(CREATE_NO_WINDOW)
.status(); .status();
// Poll until no java.exe remains (up to ~3 s) so the installer can
// overwrite the JRE DLLs without hitting a sharing-violation error.
for _ in 0..30 { for _ in 0..30 {
let still_running = std::process::Command::new("tasklist") let still_running = std::process::Command::new("tasklist")
.args(["/FI", "IMAGENAME eq java.exe", "/NH"]) .args(["/FI", "IMAGENAME eq java.exe", "/NH"])
@@ -220,20 +186,15 @@ fn kill_tachidesk(app: &tauri::AppHandle) {
.map(|o| String::from_utf8_lossy(&o.stdout).contains("java.exe")) .map(|o| String::from_utf8_lossy(&o.stdout).contains("java.exe"))
.unwrap_or(false); .unwrap_or(false);
if !still_running { if !still_running { break; }
break;
}
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
} }
} }
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let _ = std::process::Command::new("pkill") let _ = std::process::Command::new("pkill").args(["-f", "tachidesk"]).status();
.args(["-f", "tachidesk"])
.status();
} }
const DEFAULT_SERVER_CONF: &str = r#"server.ip = "127.0.0.1" const DEFAULT_SERVER_CONF: &str = r#"server.ip = "127.0.0.1"
server.port = 4567 server.port = 4567
server.webUIEnabled = false server.webUIEnabled = false
@@ -328,23 +289,14 @@ struct ServerInvocation {
working_dir: Option<PathBuf>, working_dir: Option<PathBuf>,
} }
/// Locate the `java` / `java.exe` binary inside a bundled JRE directory.
///
/// Expected layout (Windows and Linux):
/// <bundle_dir>/jre/bin/java[.exe]
///
/// On Windows `strip_unc` is applied so Java doesn't choke on `\\?\` prefixes.
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
fn find_java_in_bundle(bundle_dir: &PathBuf, log: &mut Option<std::fs::File>) -> Option<PathBuf> { fn find_java_in_bundle(bundle_dir: &PathBuf, log: &mut Option<std::fs::File>) -> Option<PathBuf> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let java = strip_unc(bundle_dir.join("jre").join("bin").join("java.exe")); let java = strip_unc(bundle_dir.join("jre").join("bin").join("java.exe"));
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let java = bundle_dir.join("jre").join("bin").join("java"); let java = bundle_dir.join("jre").join("bin").join("java");
do_log(log, &format!("[find_java] checking path: {:?}", java)); do_log(log, &format!("[find_java] path: {:?} exists: {}", java, java.exists()));
do_log(log, &format!("[find_java] exists: {}", java.exists()));
if java.exists() { Some(java) } else { None } if java.exists() { Some(java) } else { None }
} }
@@ -360,12 +312,8 @@ fn resolve_server_binary(
app: &tauri::AppHandle, app: &tauri::AppHandle,
log: &mut Option<std::fs::File>, log: &mut Option<std::fs::File>,
) -> Result<ServerInvocation, SpawnError> { ) -> Result<ServerInvocation, SpawnError> {
do_log(log, &format!("[resolve] binary arg = {:?}", binary)); do_log(log, &format!("[resolve] binary = {:?}", binary));
// ── 1. User-specified binary path ─────────────────────────────────────────
// Primary: honour the path as-is (doc-2 behaviour — trust the user).
// Fallback: if the path doesn't exist after stripping UNC, log a warning
// and continue so the bundled detection still has a chance.
if !binary.trim().is_empty() { if !binary.trim().is_empty() {
let path = strip_unc(PathBuf::from(binary.trim())); let path = strip_unc(PathBuf::from(binary.trim()));
do_log(log, &format!("[resolve] user path: {:?} exists={}", path, path.exists())); do_log(log, &format!("[resolve] user path: {:?} exists={}", path, path.exists()));
@@ -376,62 +324,44 @@ fn resolve_server_binary(
working_dir: path.parent().map(|p| p.to_path_buf()), working_dir: path.parent().map(|p| p.to_path_buf()),
}); });
} }
// Fallback: path was set but file is missing — warn and keep trying. do_log(log, "[resolve] user path not found, falling through");
do_log(log, "[resolve] WARNING: user-supplied path not found, falling through to bundled detection");
} }
// Resolve and UNC-strip resource_dir once; used by all non-macOS branches.
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
let resource_dir = { let resource_dir = {
let raw = app.path().resource_dir().unwrap_or_default(); let raw = app.path().resource_dir().unwrap_or_default();
let stripped = strip_unc(raw); let stripped = strip_unc(raw);
do_log(log, &format!("[resolve] resource_dir (stripped) = {:?}", stripped)); do_log(log, &format!("[resolve] resource_dir = {:?}", stripped));
stripped stripped
}; };
// ── 2. Bundled JRE + JAR (Windows / Linux — specific layout) ─────────────
// Primary path from doc-2: binaries/suwayomi-bundle/bin/Suwayomi-Server.jar
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
{ {
let bundle_dir = resource_dir.join("binaries").join("suwayomi-bundle"); let bundle_dir = resource_dir.join("binaries").join("suwayomi-bundle");
let jar = bundle_dir.join("bin").join("Suwayomi-Server.jar"); let jar = bundle_dir.join("bin").join("Suwayomi-Server.jar");
do_log(log, &format!("[resolve] bundle_dir = {:?}", bundle_dir)); do_log(log, &format!("[resolve] bundle_dir={:?} exists={}", bundle_dir, bundle_dir.exists()));
do_log(log, &format!("[resolve] bundle_dir exists: {}", bundle_dir.exists())); do_log(log, &format!("[resolve] jar={:?} exists={}", jar, jar.exists()));
do_log(log, &format!("[resolve] jar = {:?}", jar));
do_log(log, &format!("[resolve] jar exists: {}", jar.exists()));
match find_java_in_bundle(&bundle_dir, log) { match find_java_in_bundle(&bundle_dir, log) {
Some(java) => { Some(java) if jar.exists() => {
do_log(log, &format!("[resolve] java found: {:?}", java)); do_log(log, "[resolve] using bundled JRE");
if jar.exists() {
do_log(log, "[resolve] both java and jar found — using bundled JRE");
return Ok(ServerInvocation { return Ok(ServerInvocation {
bin: java.to_string_lossy().into_owned(), bin: java.to_string_lossy().into_owned(),
args: vec!["-jar".to_string(), jar.to_string_lossy().into_owned()], args: vec!["-jar".to_string(), jar.to_string_lossy().into_owned()],
working_dir: Some(bundle_dir), working_dir: Some(bundle_dir),
}); });
} }
do_log(log, "[resolve] java found but jar MISSING — falling through"); _ => do_log(log, "[resolve] bundled JRE/jar not found, falling through"),
}
None => {
do_log(log, "[resolve] java NOT found in bundle — falling through");
}
} }
} }
// ── 2b. Bundled launcher scripts / native sidecars (Windows / Linux) ──────
// Fallback for older bundle layouts that ship a wrapper script instead of a
// bare JRE + JAR. Also scans for any *.jar in resource_dir as a last resort.
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
{ {
// Named launcher scripts. for name in &["suwayomi-launcher", "suwayomi-launcher.sh", "tachidesk-server"] {
let script_candidates = ["suwayomi-launcher", "suwayomi-launcher.sh", "tachidesk-server"];
for name in &script_candidates {
let p = resource_dir.join(name); let p = resource_dir.join(name);
do_log(log, &format!("[resolve] sidecar candidate: {:?} exists={}", p, p.exists())); do_log(log, &format!("[resolve] sidecar: {:?} exists={}", p, p.exists()));
if p.exists() { if p.exists() {
do_log(log, &format!("[resolve] using sidecar: {:?}", p));
return Ok(ServerInvocation { return Ok(ServerInvocation {
bin: p.to_string_lossy().into_owned(), bin: p.to_string_lossy().into_owned(),
args: vec![], args: vec![],
@@ -440,50 +370,31 @@ fn resolve_server_binary(
} }
} }
// Generic JRE at resource_dir root + any *.jar alongside it.
do_log(log, "[resolve] no named sidecar found, trying generic JRE + any jar in resource_dir");
if let Some(java) = find_java_in_bundle(&resource_dir, log) { if let Some(java) = find_java_in_bundle(&resource_dir, log) {
let jar = std::fs::read_dir(&resource_dir) let jar = std::fs::read_dir(&resource_dir)
.ok() .ok()
.and_then(|mut rd| { .and_then(|mut rd| {
rd.find(|e| { rd.find(|e| e.as_ref().map(|e| e.file_name().to_string_lossy().ends_with(".jar")).unwrap_or(false))
e.as_ref()
.map(|e| e.file_name().to_string_lossy().ends_with(".jar"))
.unwrap_or(false)
})
.and_then(|e| e.ok()) .and_then(|e| e.ok())
.map(|e| e.path()) .map(|e| e.path())
}); });
do_log(log, &format!("[resolve] generic jar candidate: {:?}", jar));
if let Some(jar_path) = jar { if let Some(jar_path) = jar {
do_log(log, &format!("[resolve] using generic JRE java={:?} jar={:?}", java, jar_path)); do_log(log, &format!("[resolve] generic JRE java={:?} jar={:?}", java, jar_path));
return Ok(ServerInvocation { return Ok(ServerInvocation {
bin: java.to_string_lossy().into_owned(), bin: java.to_string_lossy().into_owned(),
args: vec!["-jar".to_string(), jar_path.to_string_lossy().into_owned()], args: vec!["-jar".to_string(), jar_path.to_string_lossy().into_owned()],
working_dir: Some(resource_dir), working_dir: Some(resource_dir),
}); });
} }
do_log(log, "[resolve] generic JRE found but no .jar — falling through");
} }
} }
// ── 3. macOS app bundle — MacOS/ then Resources/ ──────────────────────────
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
let resource_dir = app.path().resource_dir().unwrap_or_default(); let resource_dir = app.path().resource_dir().unwrap_or_default();
let macos_dir = resource_dir let macos_dir = resource_dir.parent().map(|p| p.join("MacOS")).unwrap_or_default();
.parent()
.map(|p| p.join("MacOS"))
.unwrap_or_default();
do_log(log, &format!("[resolve] macOS macos_dir = {:?}", macos_dir));
// Tauri strips the target triple when installing externalBin sidecars into
// Contents/MacOS/, so the binary is "suwayomi-server" at runtime.
// Triple-suffixed names are kept as a belt-and-suspenders fallback for
// dev / flat layouts.
let candidates = [ let candidates = [
"suwayomi-server", "suwayomi-server",
"suwayomi-server-aarch64-apple-darwin", "suwayomi-server-aarch64-apple-darwin",
@@ -498,7 +409,6 @@ fn resolve_server_binary(
let p = search_dir.join(name); let p = search_dir.join(name);
do_log(log, &format!("[resolve] macOS candidate: {:?} exists={}", p, p.exists())); do_log(log, &format!("[resolve] macOS candidate: {:?} exists={}", p, p.exists()));
if p.exists() { if p.exists() {
do_log(log, &format!("[resolve] using macOS sidecar: {:?}", p));
return Ok(ServerInvocation { return Ok(ServerInvocation {
bin: p.to_string_lossy().into_owned(), bin: p.to_string_lossy().into_owned(),
args: vec![], args: vec![],
@@ -509,37 +419,17 @@ fn resolve_server_binary(
} }
} }
// ── 4. PATH fallback ──────────────────────────────────────────────────────
// Use `where` on Windows, `which` everywhere else.
do_log(log, "[resolve] trying PATH fallback");
for name in &["suwayomi-server", "tachidesk-server"] { for name in &["suwayomi-server", "tachidesk-server"] {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let found = std::process::Command::new("where") let found = std::process::Command::new("where").arg(name).output().map(|o| o.status.success()).unwrap_or(false);
.arg(name)
.output()
.map(|o| o.status.success())
.unwrap_or(false);
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let found = std::process::Command::new("which") let found = std::process::Command::new("which").arg(name).output().map(|o| o.status.success()).unwrap_or(false);
.arg(name)
.output()
.map(|o| o.status.success())
.unwrap_or(false);
do_log(log, &format!("[resolve] PATH check {:?}: found={}", name, found));
if found { if found {
do_log(log, &format!("[resolve] using PATH binary: {}", name)); return Ok(ServerInvocation { bin: name.to_string(), args: vec![], working_dir: None });
return Ok(ServerInvocation {
bin: name.to_string(),
args: vec![],
working_dir: None,
});
} }
} }
do_log(log, "[resolve] FAILED — no binary found anywhere");
Err(SpawnError::NotConfigured( Err(SpawnError::NotConfigured(
"Server binary not found. Install Suwayomi-Server or set the path in Settings.".to_string(), "Server binary not found. Install Suwayomi-Server or set the path in Settings.".to_string(),
)) ))
@@ -555,50 +445,28 @@ fn spawn_server(binary: String, app: tauri::AppHandle) -> Result<(), SpawnError>
} }
let data_dir = suwayomi_data_dir(); let data_dir = suwayomi_data_dir();
let log_path = data_dir.join("moku-spawn.log"); let log_path = data_dir.join("moku-spawn.log");
let _ = std::fs::create_dir_all(&data_dir); let _ = std::fs::create_dir_all(&data_dir);
let mut log = std::fs::OpenOptions::new() let mut log = std::fs::OpenOptions::new().create(true).append(true).open(&log_path).ok();
.create(true)
.append(true)
.open(&log_path)
.ok();
do_log(&mut log, ""); do_log(&mut log, &format!("[spawn_server] binary={:?} data_dir={:?}", binary, data_dir));
do_log(&mut log, "========================================");
do_log(&mut log, &format!("[spawn_server] called at {:?}", std::time::SystemTime::now()));
do_log(&mut log, &format!("[spawn_server] binary arg = {:?}", binary));
do_log(&mut log, &format!("[spawn_server] data_dir = {:?}", data_dir));
do_log(&mut log, &format!("[spawn_server] log file = {:?}", log_path));
do_log(&mut log, &format!("[spawn_server] APPDATA = {:?}", std::env::var("APPDATA")));
do_log(&mut log, &format!("[spawn_server] LOCALAPPDATA = {:?}", std::env::var("LOCALAPPDATA")));
do_log(&mut log, &format!("[spawn_server] current_dir = {:?}", std::env::current_dir()));
seed_server_conf(&data_dir); seed_server_conf(&data_dir);
do_log(&mut log, "[spawn_server] server.conf seeded");
let mut invocation = match resolve_server_binary(&binary, &app, &mut log) { let mut invocation = resolve_server_binary(&binary, &app, &mut log).map_err(|e| {
Ok(i) => i, do_log(&mut log, &format!("[spawn_server] resolve failed: {:?}", e));
Err(e) => { e
do_log(&mut log, &format!("[spawn_server] resolve FAILED: {:?}", e)); })?;
return Err(e);
}
};
let bin_display = invocation.bin.clone();
let rootdir_flag = format!( let rootdir_flag = format!(
"-Dsuwayomi.tachidesk.config.server.rootDir={}", "-Dsuwayomi.tachidesk.config.server.rootDir={}",
data_dir.to_string_lossy() data_dir.to_string_lossy()
); );
invocation.args.insert(0, rootdir_flag); invocation.args.insert(0, rootdir_flag);
let working_dir = invocation.working_dir let working_dir = invocation.working_dir.unwrap_or_else(|| std::env::current_dir().unwrap_or_default());
.unwrap_or_else(|| std::env::current_dir().unwrap_or_default());
do_log(&mut log, &format!("[spawn_server] bin = {:?}", bin_display)); do_log(&mut log, &format!("[spawn_server] bin={:?} args={:?} cwd={:?}", invocation.bin, invocation.args, working_dir));
do_log(&mut log, &format!("[spawn_server] args = {:?}", invocation.args));
do_log(&mut log, &format!("[spawn_server] working_dir = {:?}", working_dir));
let cmd = app.shell() let cmd = app.shell()
.command(&invocation.bin) .command(&invocation.bin)
@@ -606,17 +474,13 @@ fn spawn_server(binary: String, app: tauri::AppHandle) -> Result<(), SpawnError>
.args(&invocation.args) .args(&invocation.args)
.current_dir(&working_dir); .current_dir(&working_dir);
do_log(&mut log, "[spawn_server] calling cmd.spawn()...");
match cmd.spawn() { match cmd.spawn() {
Ok((_rx, child)) => { Ok((_rx, child)) => {
do_log(&mut log, &format!("[spawn_server] SUCCESS — spawned: {}", bin_display));
*app.state::<ServerState>().0.lock().unwrap() = Some(child); *app.state::<ServerState>().0.lock().unwrap() = Some(child);
Ok(()) Ok(())
} }
Err(e) => { Err(e) => {
do_log(&mut log, &format!("[spawn_server] SPAWN FAILED: {}", e)); do_log(&mut log, &format!("[spawn_server] spawn failed: {}", e));
do_log(&mut log, &format!("[spawn_server] error kind: {:?}", e));
Err(SpawnError::SpawnFailed(e.to_string())) Err(SpawnError::SpawnFailed(e.to_string()))
} }
} }
@@ -628,10 +492,6 @@ fn kill_server(app: tauri::AppHandle) -> Result<(), String> {
Ok(()) Ok(())
} }
// ── Update commands ───────────────────────────────────────────────────────────
/// Fetch the list of all GitHub releases so the frontend can show a version picker.
/// Uses tauri-plugin-http so it goes through Tauri's permission system.
#[tauri::command] #[tauri::command]
async fn list_releases() -> Result<Vec<ReleaseInfo>, String> { async fn list_releases() -> Result<Vec<ReleaseInfo>, String> {
use tauri_plugin_http::reqwest; use tauri_plugin_http::reqwest;
@@ -663,22 +523,15 @@ async fn list_releases() -> Result<Vec<ReleaseInfo>, String> {
let body = resp.text().await.map_err(|e| e.to_string())?; let body = resp.text().await.map_err(|e| e.to_string())?;
let releases: Vec<GhRelease> = serde_json::from_str(&body).map_err(|e| e.to_string())?; let releases: Vec<GhRelease> = serde_json::from_str(&body).map_err(|e| e.to_string())?;
Ok(releases Ok(releases.into_iter().map(|r| ReleaseInfo {
.into_iter()
.map(|r| ReleaseInfo {
tag_name: r.tag_name.clone(), tag_name: r.tag_name.clone(),
name: r.name.unwrap_or_else(|| r.tag_name.clone()), name: r.name.unwrap_or_else(|| r.tag_name.clone()),
body: r.body.unwrap_or_default(), body: r.body.unwrap_or_default(),
published_at: r.published_at.unwrap_or_default(), published_at: r.published_at.unwrap_or_default(),
html_url: r.html_url, html_url: r.html_url,
}) }).collect())
.collect())
} }
/// Download and install the latest update using tauri-plugin-updater.
/// Emits `update-progress` events with `{ downloaded, total }` while downloading.
/// On Windows the installer runs in passive (silent) mode; the frontend prompts restart.
/// On other platforms this command is a no-op — the frontend opens the GitHub page instead.
#[tauri::command] #[tauri::command]
#[allow(unused_variables)] #[allow(unused_variables)]
async fn download_and_install_update(app: tauri::AppHandle) -> Result<(), String> { async fn download_and_install_update(app: tauri::AppHandle) -> Result<(), String> {
@@ -693,7 +546,7 @@ async fn download_and_install_update(app: tauri::AppHandle) -> Result<(), String
let update = updater.check().await.map_err(|e| e.to_string())?; let update = updater.check().await.map_err(|e| e.to_string())?;
let Some(update) = update else { let Some(update) = update else {
return Err("No update available from the updater endpoint.".into()); return Err("No update available.".into());
}; };
let app_clone = app.clone(); let app_clone = app.clone();
@@ -711,18 +564,15 @@ async fn download_and_install_update(app: tauri::AppHandle) -> Result<(), String
} }
} }
/// Restart the app after a successful update install.
#[tauri::command] #[tauri::command]
fn restart_app(app: tauri::AppHandle) { fn restart_app(app: tauri::AppHandle) {
tauri::process::restart(&app.env()); tauri::process::restart(&app.env());
} }
// ── App entry point ───────────────────────────────────────────────────────────
#[cfg_attr(mobile, tauri::mobile_entry_point)] #[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() { pub fn run() {
tauri::Builder::default() tauri::Builder::default()
.plugin(tauri_plugin_drpc::init()) .plugin(tauri_plugin_discord_rpc::init())
.plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_http::init())
+48 -48
View File
@@ -1,79 +1,79 @@
import { start, stop, setActivity, clearActivity } from "tauri-plugin-drpc"; import { connect, disconnect, setActivity, clearActivity } from "tauri-plugin-discord-rpc-api";
import { Activity, Assets, Button, Timestamps } from "tauri-plugin-drpc/activity"; import { listen } from '@tauri-apps/api/event'
import type { Manga, Chapter } from "./types"; import type { Manga, Chapter } from './types'
const APP_ID = "1487894643613106298"; const APP_ID = '1487894643613106298'
const FALLBACK_IMAGE = "moku_logo"; const FALLBACK_IMAGE = 'moku_logo'
let sessionStart: number | null = null; let sessionStart: number | null = null
let unlisten: (() => void) | null = null
function isPublicUrl(url: string | null | undefined): boolean { function isPublicUrl(url: string | null | undefined): boolean {
return typeof url === "string" && url.startsWith("https://"); return typeof url === 'string' && url.startsWith('https://')
} }
function resolveCoverImage(manga: Manga): string { function resolveCoverImage(manga: Manga): string {
return isPublicUrl(manga.thumbnailUrl) ? manga.thumbnailUrl : FALLBACK_IMAGE; return isPublicUrl(manga.thumbnailUrl) ? manga.thumbnailUrl : FALLBACK_IMAGE
} }
function trunc(s: string, max = 128): string { function trunc(s: string, max = 128): string {
return s.length <= max ? s : `${s.slice(0, max - 1)}`; return s.length <= max ? s : `${s.slice(0, max - 1)}`
} }
function formatChapter(chapter: Chapter): string { function formatChapter(chapter: Chapter): string {
const n = chapter.chapterNumber; const n = chapter.chapterNumber
return `Chapter ${Number.isInteger(n) ? n : n.toFixed(1)}`; return `Chapter ${Number.isInteger(n) ? n : n.toFixed(1)}`
}
function getTimestamps(): Timestamps {
return new Timestamps(sessionStart ?? Date.now());
} }
const BUTTONS = [ const BUTTONS = [
new Button("GitHub", "https://github.com/Youwes09/Moku"), { label: 'GitHub', url: 'https://github.com/Youwes09/Moku' },
new Button("Discord", "https://discord.gg/Jq3pwuNqPp"), { label: 'Discord', url: 'https://discord.gg/Jq3pwuNqPp' },
]; ]
export async function initRpc(): Promise<void> { export async function initRpc(): Promise<void> {
sessionStart = Date.now(); sessionStart = Date.now()
await start(APP_ID).catch(() => {});
unlisten = await listen('discord-rpc://running', ({ payload }) => {
if (payload) setIdle().catch(() => {})
})
await connect(APP_ID).catch(() => {})
} }
export async function setReading(manga: Manga, chapter: Chapter): Promise<void> { export async function setReading(manga: Manga, chapter: Chapter): Promise<void> {
const assets = new Assets() await setActivity({
.setLargeImage(resolveCoverImage(manga)) details: trunc(manga.title),
.setLargeText(trunc(manga.title)) state: `${formatChapter(chapter)} · Reading`,
.setSmallImage(FALLBACK_IMAGE) timestamps: { start: sessionStart ?? Date.now() },
.setSmallText("Moku"); assets: {
largeImage: resolveCoverImage(manga),
const activity = new Activity() largeText: trunc(manga.title),
.setDetails(trunc(manga.title)) smallImage: FALLBACK_IMAGE,
.setState(`${formatChapter(chapter)} · Reading`) smallText: 'Moku',
.setAssets(assets) },
.setTimestamps(getTimestamps()); buttons: BUTTONS,
activity.setButton(BUTTONS); }).catch(() => {})
await setActivity(activity).catch(() => {});
} }
export async function setIdle(): Promise<void> { export async function setIdle(): Promise<void> {
const assets = new Assets() await setActivity({
.setLargeImage(FALLBACK_IMAGE) details: 'Browsing',
.setLargeText("Moku"); timestamps: { start: sessionStart ?? Date.now() },
assets: {
const activity = new Activity() largeImage: FALLBACK_IMAGE,
.setDetails("Browsing") largeText: 'Moku',
.setAssets(assets) },
.setTimestamps(getTimestamps()); buttons: BUTTONS,
activity.setButton(BUTTONS); }).catch(() => {})
await setActivity(activity).catch(() => {});
} }
export async function clearReading(): Promise<void> { export async function clearReading(): Promise<void> {
await clearActivity().catch(() => {}); await clearActivity().catch(() => {})
} }
export async function destroyRpc(): Promise<void> { export async function destroyRpc(): Promise<void> {
sessionStart = null; unlisten?.()
await stop().catch(() => {}); unlisten = null
sessionStart = null
await disconnect().catch(() => {})
} }