From 60808ee83e44014f8421394418babeccce1eafb0 Mon Sep 17 00:00:00 2001 From: inkfarer Date: Thu, 4 Apr 2024 07:31:33 +0300 Subject: [PATCH 01/28] Fix the system color theme not being respected when the application is first launched --- src/main.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main.ts b/src/main.ts index 39dc6ea..d2ad46d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,14 +4,19 @@ import App from './App.vue' import { createPinia } from 'pinia' import { setUpErrorHandler } from '@/store/errorHandlerStore' +function setColorTheme(useLightMode: boolean) { + if (useLightMode) { + document.documentElement.classList.add('light') + } else { + document.documentElement.classList.remove('light') + } +} + (async () => { const lightModePreference = window.matchMedia('(prefers-color-scheme: light)') + setColorTheme(lightModePreference.matches) lightModePreference.addEventListener('change', e => { - if (e.matches) { - document.documentElement.classList.add('light') - } else { - document.documentElement.classList.remove('light') - } + setColorTheme(e.matches) }) const app = createApp(App) From d185e050d22e75259bc352e69ef5ee03a99463d3 Mon Sep 17 00:00:00 2001 From: inkfarer Date: Thu, 4 Apr 2024 07:32:14 +0300 Subject: [PATCH 02/28] Bump version number --- package.json | 2 +- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 13ba48c..f2adbf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ncgmgr", - "version": "0.6.0", + "version": "0.7.0", "private": true, "scripts": { "dev": "vite", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 4704c9c..99d079d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2272,7 +2272,7 @@ dependencies = [ [[package]] name = "ncgmgr" -version = "0.6.0" +version = "0.7.0" dependencies = [ "fix-path-env", "flate2", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4df3c17..faf5e43 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ncgmgr" -version = "0.6.0" +version = "0.7.0" description = "Helps manage NodeCG installations." authors = [ "inkfarer" ] license = "" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e3a7d23..a90274c 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "NCGMGR", - "version": "0.6.0" + "version": "0.7.0" }, "build": { "distDir": "../dist", From 74dedf05209bd993cd5248b718152014eadfb7dc Mon Sep 17 00:00:00 2001 From: inkfarer Date: Thu, 4 Apr 2024 08:23:50 +0300 Subject: [PATCH 03/28] Edit the short description of the application to make it appear less strange in the windows task manager --- src-tauri/tauri.conf.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a90274c..be9205f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -26,8 +26,8 @@ "externalBin": [], "copyright": "© inkfarer (inkfarer@inkfarer.com)", "category": "Utility", - "shortDescription": "Helps manage NodeCG installations.", - "longDescription": "", + "shortDescription": "NCGMGR", + "longDescription": "Helps manage NodeCG installations.", "deb": { "depends": [] }, From 5163e7b9a5f1301f33920e0d5240e4a62a95fadb Mon Sep 17 00:00:00 2001 From: inkfarer Date: Thu, 4 Apr 2024 13:11:08 +0300 Subject: [PATCH 04/28] Update to Tauri 2.0 --- jest.config.js | 2 +- package.json | 8 +- src-tauri/.gitignore | 1 + src-tauri/Cargo.lock | 2105 +++++++++-------- src-tauri/Cargo.toml | 13 +- src-tauri/capabilities/main.json | 33 + src-tauri/src/bundles.rs | 11 +- src-tauri/src/dependencies.rs | 19 +- src-tauri/src/error.rs | 29 +- src-tauri/src/log.rs | 18 +- src-tauri/src/main.rs | 57 +- src-tauri/src/nodecg.rs | 106 +- src-tauri/src/npm.rs | 17 +- src-tauri/tauri.conf.json | 92 +- src/__mocks__/setup.ts | 3 + src/__mocks__/tauri.ts | 14 +- src/components/BundleInstaller.vue | 2 +- src/components/InstallManager.vue | 4 +- src/components/bundleList/BundleConfig.vue | 8 +- .../bundleList/__tests__/BundleConfig.test.ts | 4 +- src/service/__tests__/nodecgService.test.ts | 57 +- src/service/dependencyService.ts | 2 +- src/service/nodecgService.ts | 45 +- src/util/fs.ts | 2 +- yarn.lock | 147 +- 25 files changed, 1491 insertions(+), 1308 deletions(-) create mode 100644 src-tauri/capabilities/main.json create mode 100644 src/__mocks__/setup.ts diff --git a/jest.config.js b/jest.config.js index 5be021e..3b87f8d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -13,6 +13,6 @@ module.exports = { '@/(.*)$': '/src/$1' }, resetMocks: true, - setupFilesAfterEnv: ['./src/__mocks__/tauri.ts'], + setupFilesAfterEnv: ['./src/__mocks__/tauri.ts', './src/__mocks__/setup.ts'], reporters: [['github-actions', { silent: false }], 'summary'] } diff --git a/package.json b/package.json index f2adbf5..76e61cb 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,12 @@ "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/vue-fontawesome": "^3.0.0-5", "@iplsplatoon/vue-components": "3.2.0", - "@tauri-apps/api": "^1.5.3", - "@tauri-apps/cli": "^1.5.11", + "@tauri-apps/api": "2.0.0-beta.7", + "@tauri-apps/cli": "2.0.0-beta.12", + "@tauri-apps/plugin-dialog": "2.0.0-beta.2", + "@tauri-apps/plugin-fs": "2.0.0-beta.2", + "@tauri-apps/plugin-os": "2.0.0-beta.2", + "@tauri-apps/plugin-shell": "2.0.0-beta.2", "anser": "^2.1.0", "lodash": "^4.17.21", "node-gyp": "^10.1.0", diff --git a/src-tauri/.gitignore b/src-tauri/.gitignore index c123704..4b93dd6 100644 --- a/src-tauri/.gitignore +++ b/src-tauri/.gitignore @@ -2,3 +2,4 @@ # will have compiled files and executables /target/ WixTools +/gen/schemas diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 99d079d..4486bf7 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -63,33 +63,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] -name = "arboard" -version = "3.3.2" +name = "ashpd" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2041f1943049c7978768d84e6d0fd95de98b76d6c4727b09e78ec253d29fa58" +checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" dependencies = [ - "clipboard-win", - "core-graphics 0.23.1", - "image", - "log", - "objc", - "objc-foundation", - "objc_id", - "parking_lot", - "thiserror", - "windows-sys 0.48.0", - "wl-clipboard-rs", - "x11rb", + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.8.5", + "serde", + "serde_repr", + "tokio", + "url", + "zbus", ] [[package]] name = "async-broadcast" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +checksum = "258b52a1aa741b9f09783b2d86cf0aeeb617bbf847f6933340a39644227acbdb" dependencies = [ - "event-listener 2.5.3", + "event-listener 5.2.0", + "event-listener-strategy 0.5.0", "futures-core", + "pin-project-lite", ] [[package]] @@ -105,52 +104,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-executor" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" -dependencies = [ - "async-lock 3.3.0", - "async-task", - "concurrent-queue", - "fastrand 2.0.2", - "futures-lite 2.3.0", - "slab", -] - -[[package]] -name = "async-fs" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "blocking", - "futures-lite 1.13.0", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - [[package]] name = "async-io" version = "2.3.2" @@ -161,10 +114,10 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.3.0", + "futures-lite", "parking", - "polling 3.6.0", - "rustix 0.38.32", + "polling", + "rustix", "slab", "tracing", "windows-sys 0.52.0", @@ -192,19 +145,22 @@ dependencies = [ [[package]] name = "async-process" -version = "1.8.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +checksum = "d999d925640d51b662b7b4e404224dd81de70f4aa4a199383c2c5e5b86885fa3" dependencies = [ - "async-io 1.13.0", - "async-lock 2.8.0", + "async-channel", + "async-io", + "async-lock 3.3.0", "async-signal", + "async-task", "blocking", "cfg-if", - "event-listener 3.1.0", - "futures-lite 1.13.0", - "rustix 0.38.32", - "windows-sys 0.48.0", + "event-listener 5.2.0", + "futures-lite", + "rustix", + "tracing", + "windows-sys 0.52.0", ] [[package]] @@ -224,13 +180,13 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io 2.3.2", + "async-io", "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.32", + "rustix", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -255,26 +211,25 @@ dependencies = [ [[package]] name = "atk" -version = "0.15.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" +checksum = "b4af014b17dd80e8af9fa689b2d4a211ddba6eb583c1622f35d0cb543f6b17e4" dependencies = [ "atk-sys", - "bitflags 1.3.2", - "glib", + "glib 0.18.5", "libc", ] [[package]] name = "atk-sys" -version = "0.15.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" +checksum = "251e0b7d90e33e0ba930891a505a9a35ece37b2dd37a14f3ffc306c13b980009" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", - "system-deps 6.2.2", + "system-deps", ] [[package]] @@ -306,15 +261,15 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.21.7" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" [[package]] name = "bitflags" @@ -327,6 +282,9 @@ name = "bitflags" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] [[package]] name = "block" @@ -352,9 +310,9 @@ dependencies = [ "async-channel", "async-lock 3.3.0", "async-task", - "fastrand 2.0.2", + "fastrand", "futures-io", - "futures-lite 2.3.0", + "futures-lite", "piper", "tracing", ] @@ -380,16 +338,6 @@ dependencies = [ "alloc-stdlib", ] -[[package]] -name = "bstr" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "bumpalo" version = "3.15.4" @@ -419,36 +367,69 @@ dependencies = [ [[package]] name = "cairo-rs" -version = "0.15.12" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c76ee391b03d35510d9fa917357c7f1855bd9a6659c95a1b392e33f49b3369bc" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "cairo-sys-rs", - "glib", + "glib 0.18.5", "libc", + "once_cell", "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.15.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" dependencies = [ - "glib-sys", + "glib-sys 0.18.1", "libc", - "system-deps 6.2.2", + "system-deps", +] + +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", ] [[package]] name = "cargo_toml" -version = "0.15.3" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "599aa35200ffff8f04c1925aa1acc92fa2e08874379ef42e210a80e527e60838" +checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719" dependencies = [ "serde", - "toml 0.7.8", + "toml 0.8.12", ] [[package]] @@ -478,15 +459,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "cfg-expr" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7" -dependencies = [ - "smallvec", -] - [[package]] name = "cfg-expr" version = "0.15.7" @@ -509,6 +481,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f" + [[package]] name = "chrono" version = "0.4.37" @@ -522,27 +500,18 @@ dependencies = [ "windows-targets 0.52.4", ] -[[package]] -name = "clipboard-win" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d517d4b86184dbb111d3556a10f1c8a04da7428d2987bf1081602bf11c3aa9ee" -dependencies = [ - "error-code", -] - [[package]] name = "cocoa" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", "core-foundation", - "core-graphics 0.22.3", - "foreign-types 0.3.2", + "core-graphics", + "foreign-types 0.5.0", "libc", "objc", ] @@ -561,12 +530,6 @@ dependencies = [ "objc", ] -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "combine" version = "4.6.6" @@ -608,19 +571,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types 0.3.2", - "libc", -] - [[package]] name = "core-graphics" version = "0.23.1" @@ -779,6 +729,12 @@ dependencies = [ "syn 2.0.55", ] +[[package]] +name = "data-url" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" + [[package]] name = "deranged" version = "0.3.11" @@ -800,17 +756,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive-new" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.55", -] - [[package]] name = "derive_more" version = "0.99.17" @@ -867,14 +812,40 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading", + "libloading 0.8.3", ] [[package]] -name = "downcast-rs" -version = "1.2.0" +name = "dlopen2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "dpi" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +dependencies = [ + "serde", +] [[package]] name = "dtoa" @@ -897,6 +868,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "either" version = "1.10.0" @@ -932,6 +909,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + [[package]] name = "enumflags2" version = "0.7.9" @@ -969,29 +952,12 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "error-code" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" - [[package]] name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" -[[package]] -name = "event-listener" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - [[package]] name = "event-listener" version = "4.0.3" @@ -1034,15 +1000,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.0.2" @@ -1064,7 +1021,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ - "memoffset 0.9.1", + "memoffset", "rustc_version", ] @@ -1089,12 +1046,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - [[package]] name = "flate2" version = "1.0.28" @@ -1204,28 +1155,13 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-lite" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.2", + "fastrand", "futures-core", "futures-io", "parking", @@ -1283,87 +1219,100 @@ dependencies = [ [[package]] name = "gdk" -version = "0.15.4" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" +checksum = "f5ba081bdef3b75ebcdbfc953699ed2d7417d6bd853347a42a37d76406a33646" dependencies = [ - "bitflags 1.3.2", "cairo-rs", "gdk-pixbuf", "gdk-sys", "gio", - "glib", + "glib 0.18.5", "libc", "pango", ] [[package]] name = "gdk-pixbuf" -version = "0.15.11" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" dependencies = [ - "bitflags 1.3.2", "gdk-pixbuf-sys", "gio", - "glib", + "glib 0.18.5", "libc", + "once_cell", ] [[package]] name = "gdk-pixbuf-sys" -version = "0.15.10" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", + "gio-sys 0.18.1", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", - "system-deps 6.2.2", + "system-deps", ] [[package]] name = "gdk-sys" -version = "0.15.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" +checksum = "31ff856cb3386dae1703a920f803abafcc580e9b5f711ca62ed1620c25b51ff2" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", + "gio-sys 0.18.1", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", "pango-sys", "pkg-config", - "system-deps 6.2.2", + "system-deps", ] [[package]] name = "gdkwayland-sys" -version = "0.15.3" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca49a59ad8cfdf36ef7330fe7bdfbe1d34323220cc16a0de2679ee773aee2c2" +checksum = "a90fbf5c033c65d93792192a49a8efb5bb1e640c419682a58bb96f5ae77f3d4a" dependencies = [ "gdk-sys", - "glib-sys", - "gobject-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", "pkg-config", - "system-deps 6.2.2", + "system-deps", +] + +[[package]] +name = "gdkx11" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2ea8a4909d530f79921290389cbd7c34cb9d623bfe970eaae65ca5f9cd9cce" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib 0.18.5", + "libc", + "x11", ] [[package]] name = "gdkx11-sys" -version = "0.15.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b7f8c7a84b407aa9b143877e267e848ff34106578b64d1e0a24bf550716178" +checksum = "fee8f00f4ee46cad2939b8990f5c70c94ff882c3028f3cc5abf950fa4ab53043" dependencies = [ "gdk-sys", - "glib-sys", + "glib-sys 0.18.1", "libc", - "system-deps 6.2.2", + "system-deps", "x11", ] @@ -1430,31 +1379,46 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "gio" -version = "0.15.12" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68fdbc90312d462781a395f7a16d96a2b379bb6ef8cd6310a2df272771c4283b" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" dependencies = [ - "bitflags 1.3.2", "futures-channel", "futures-core", "futures-io", - "gio-sys", - "glib", + "futures-util", + "gio-sys 0.18.1", + "glib 0.18.5", "libc", "once_cell", + "pin-project-lite", + "smallvec", "thiserror", ] [[package]] name = "gio-sys" -version = "0.15.10" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9b693b8e39d042a95547fc258a7b07349b1f0b48f4b2fa3108ba3c51c0b5229" +dependencies = [ + "glib-sys 0.16.3", + "gobject-sys 0.16.3", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", - "system-deps 6.2.2", + "system-deps", "winapi", ] @@ -1475,47 +1439,96 @@ dependencies = [ [[package]] name = "glib" -version = "0.15.12" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" +checksum = "16aa2475c9debed5a32832cb5ff2af5a3f9e1ab9e69df58eaadc1ab2004d6eba" dependencies = [ "bitflags 1.3.2", "futures-channel", "futures-core", "futures-executor", "futures-task", - "glib-macros", - "glib-sys", - "gobject-sys", + "futures-util", + "gio-sys 0.16.3", + "glib-macros 0.16.8", + "glib-sys 0.16.3", + "gobject-sys 0.16.3", "libc", "once_cell", "smallvec", "thiserror", ] +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.5.0", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys 0.18.1", + "glib-macros 0.18.5", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror", +] + [[package]] name = "glib-macros" -version = "0.15.13" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c6ae9f6fa26f4fb2ac16b528d138d971ead56141de489f8111e259b9df3c4a" +checksum = "fb1a9325847aa46f1e96ffea37611b9d51fc4827e67f79e7de502a297560a67b" dependencies = [ "anyhow", "heck 0.4.1", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", ] +[[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.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "glib-sys" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61a4f46316d06bfa33a7ac22df6f0524c8be58e3db2d9ca99ccb1f357b62a65" +dependencies = [ + "libc", + "system-deps", +] + [[package]] name = "glib-sys" -version = "0.15.10" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" dependencies = [ "libc", - "system-deps 6.2.2", + "system-deps", ] [[package]] @@ -1525,96 +1538,91 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] -name = "globset" -version = "0.4.14" +name = "gobject-sys" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "3520bb9c07ae2a12c7f2fbb24d4efc11231c8146a86956413fb1a79bb760a0f1" dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "glib-sys 0.16.3", + "libc", + "system-deps", ] [[package]] name = "gobject-sys" -version = "0.15.10" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" dependencies = [ - "glib-sys", + "glib-sys 0.18.1", "libc", - "system-deps 6.2.2", + "system-deps", ] [[package]] name = "gtk" -version = "0.15.5" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0" +checksum = "93c4f5e0e20b60e10631a5f06da7fe3dda744b05ad0ea71fee2f47adf865890c" dependencies = [ "atk", - "bitflags 1.3.2", "cairo-rs", "field-offset", "futures-channel", "gdk", "gdk-pixbuf", "gio", - "glib", + "glib 0.18.5", "gtk-sys", "gtk3-macros", "libc", - "once_cell", "pango", "pkg-config", ] [[package]] name = "gtk-sys" -version = "0.15.3" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" +checksum = "771437bf1de2c1c0b496c11505bdf748e26066bbe942dfc8f614c9460f6d7722" dependencies = [ "atk-sys", "cairo-sys-rs", "gdk-pixbuf-sys", "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", + "gio-sys 0.18.1", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", "pango-sys", - "system-deps 6.2.2", + "system-deps", ] [[package]] name = "gtk3-macros" -version = "0.15.6" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684c0456c086e8e7e9af73ec5b84e35938df394712054550e81558d21c44ab0d" +checksum = "c6063efb63db582968fb7df72e1ae68aa6360dcfb0a75143f34fc7d616bad75e" dependencies = [ - "anyhow", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.55", ] [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap 2.2.6", "slab", "tokio", @@ -1634,15 +1642,6 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.1" @@ -1667,15 +1666,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "html5ever" version = "0.26.0" @@ -1701,6 +1691,17 @@ dependencies = [ "itoa 1.0.11", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.11", +] + [[package]] name = "http-body" version = "0.4.6" @@ -1708,15 +1709,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", "pin-project-lite", ] [[package]] -name = "http-range" -version = "0.1.5" +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite", +] [[package]] name = "httparse" @@ -1741,19 +1759,38 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa 1.0.11", "pin-project-lite", - "socket2 0.5.6", + "socket2", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "itoa 1.0.11", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -1761,12 +1798,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", "native-tls", "tokio", "tokio-native-tls", ] +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.2.0", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1816,36 +1873,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "ignore" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" -dependencies = [ - "crossbeam-deque", - "globset", - "log", - "memchr", - "regex-automata 0.4.6", - "same-file", - "walkdir", - "winapi-util", -] - -[[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "num-traits", - "png", - "tiff", -] - [[package]] name = "indexmap" version = "1.9.3" @@ -1870,9 +1897,9 @@ dependencies = [ [[package]] name = "infer" -version = "0.13.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f551f8c3a39f68f986517db0d1759de85881894fdc7db798bd2a9df9cb04b7fc" +checksum = "cb33622da908807a06f9513c19b3c1ad50fab3e4137d82a78107d502075aa199" dependencies = [ "cfb", ] @@ -1887,21 +1914,29 @@ dependencies = [ ] [[package]] -name = "io-lifetimes" -version = "1.0.11" +name = "ipnet" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", + "once_cell", ] [[package]] -name = "ipnet" -version = "2.9.0" +name = "is-wsl" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] [[package]] name = "itertools" @@ -1926,39 +1961,41 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "javascriptcore-rs" -version = "0.16.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf053e7843f2812ff03ef5afe34bb9c06ffee120385caad4f6b9967fcd37d41c" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" dependencies = [ "bitflags 1.3.2", - "glib", + "glib 0.18.5", "javascriptcore-rs-sys", ] [[package]] name = "javascriptcore-rs-sys" -version = "0.4.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "905fbb87419c5cde6e3269537e4ea7d46431f3008c5d057e915ef3f115e7793c" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", - "system-deps 5.0.0", + "system-deps", ] [[package]] name = "jni" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ "cesu8", + "cfg-if", "combine", "jni-sys", "log", "thiserror", "walkdir", + "windows-sys 0.45.0", ] [[package]] @@ -1976,12 +2013,6 @@ dependencies = [ "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" - [[package]] name = "js-sys" version = "0.3.69" @@ -2003,6 +2034,17 @@ dependencies = [ "treediff", ] +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.5.0", + "serde", + "unicode-segmentation", +] + [[package]] name = "kuchikiki" version = "0.8.2" @@ -2022,6 +2064,30 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" +dependencies = [ + "glib 0.18.5", + "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 0.7.4", + "once_cell", +] + [[package]] name = "libc" version = "0.2.153" @@ -2042,6 +2108,16 @@ 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 = "libloading" version = "0.8.3" @@ -2095,12 +2171,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -2144,19 +2214,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -[[package]] -name = "mac-notification-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51fca4d74ff9dbaac16a01b924bc3693fa2bba0862c2c633abc73f9a8ea21f64" -dependencies = [ - "cc", - "dirs-next", - "objc-foundation", - "objc_id", - "time", -] - [[package]] name = "malloc_buf" version = "0.0.6" @@ -2201,15 +2258,6 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.9.1" @@ -2225,12 +2273,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.2" @@ -2252,6 +2294,25 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "muda" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f428b4e9db3d17e2f809dfb1ff9ddfbbf16c71790d1656d10aee320877e1392f" +dependencies = [ + "cocoa", + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "objc", + "once_cell", + "png", + "serde", + "thiserror", + "windows-sys 0.52.0", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -2280,6 +2341,7 @@ dependencies = [ "git2", "itertools", "openssl", + "reqwest 0.11.27", "rm_rf", "semver-parser", "serde", @@ -2288,19 +2350,26 @@ dependencies = [ "tar", "tauri", "tauri-build", + "tauri-plugin-dialog", + "tauri-plugin-fs", + "tauri-plugin-http", + "tauri-plugin-os", + "tauri-plugin-shell", + "thiserror", "unwrap_or", ] [[package]] name = "ndk" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" dependencies = [ "bitflags 1.3.2", "jni-sys", "ndk-sys", "num_enum", + "raw-window-handle 0.5.2", "thiserror", ] @@ -2312,9 +2381,9 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "ndk-sys" -version = "0.3.0" +version = "0.4.1+23.1.7779620" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" dependencies = [ "jni-sys", ] @@ -2325,18 +2394,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.7.1", -] - [[package]] name = "nix" version = "0.28.0" @@ -2345,8 +2402,9 @@ checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.5.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", "libc", + "memoffset", ] [[package]] @@ -2355,29 +2413,6 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "notify-rust" -version = "4.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "827c5edfa80235ded4ab3fe8e9dc619b4f866ef16fe9b1c6b8a7f8692c0f2226" -dependencies = [ - "log", - "mac-notification-sys", - "serde", - "tauri-winrt-notification", - "zbus", -] - [[package]] name = "ntapi" version = "0.4.1" @@ -2437,7 +2472,7 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -2499,12 +2534,13 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "open" -version = "3.2.0" +version = "5.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" +checksum = "449f0ff855d85ddbf1edd5b646d65249ead3f5e422aaa86b7d2d0b049b103e32" dependencies = [ + "is-wsl", + "libc", "pathdiff", - "windows-sys 0.42.0", ] [[package]] @@ -2600,12 +2636,12 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pango" -version = "0.15.10" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" dependencies = [ - "bitflags 1.3.2", - "glib", + "gio", + "glib 0.18.5", "libc", "once_cell", "pango-sys", @@ -2613,14 +2649,14 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.15.10" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", - "system-deps 6.2.2", + "system-deps", ] [[package]] @@ -2675,16 +2711,6 @@ dependencies = [ "ucd-trie", ] -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap 2.2.6", -] - [[package]] name = "phf" version = "0.8.0" @@ -2819,6 +2845,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -2838,7 +2884,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" dependencies = [ "atomic-waker", - "fastrand 2.0.2", + "fastrand", "futures-io", ] @@ -2857,7 +2903,7 @@ dependencies = [ "base64 0.21.7", "indexmap 2.2.6", "line-wrap", - "quick-xml 0.31.0", + "quick-xml", "serde", "time", ] @@ -2875,22 +2921,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - [[package]] name = "polling" version = "3.6.0" @@ -2901,7 +2931,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 0.38.32", + "rustix", "tracing", "windows-sys 0.52.0", ] @@ -2934,6 +2964,24 @@ dependencies = [ "toml_edit 0.19.15", ] +[[package]] +name = "proc-macro-crate" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +dependencies = [ + "toml_edit 0.20.7", +] + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2982,15 +3030,6 @@ dependencies = [ "cc", ] -[[package]] -name = "quick-xml" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" -dependencies = [ - "memchr", -] - [[package]] name = "quick-xml" version = "0.31.0" @@ -3096,6 +3135,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "raw-window-handle" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" + [[package]] name = "rayon" version = "1.10.0" @@ -3192,9 +3237,9 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-tls", "ipnet", "js-sys", @@ -3212,6 +3257,41 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.50.0", +] + +[[package]] +name = "reqwest" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338" +dependencies = [ + "base64 0.21.7", + "bytes", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.2.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", "tokio-util", "tower-service", "url", @@ -3224,26 +3304,26 @@ dependencies = [ [[package]] name = "rfd" -version = "0.10.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea" +checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" dependencies = [ + "ashpd", "block", "dispatch", - "glib-sys", - "gobject-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "gtk-sys", "js-sys", - "lazy_static", "log", "objc", "objc-foundation", "objc_id", - "raw-window-handle", + "raw-window-handle 0.6.0", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows 0.37.0", + "windows-sys 0.48.0", ] [[package]] @@ -3270,20 +3350,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.37.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - [[package]] name = "rustix" version = "0.38.32" @@ -3293,7 +3359,7 @@ dependencies = [ "bitflags 2.5.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys", "windows-sys 0.52.0", ] @@ -3336,6 +3402,32 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -3350,9 +3442,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -3363,9 +3455,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -3429,13 +3521,23 @@ dependencies = [ "syn 2.0.55", ] +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_json" version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ - "indexmap 2.2.6", "itoa 1.0.11", "ryu", "serde", @@ -3614,50 +3716,60 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.10" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] -name = "socket2" -version = "0.5.6" +name = "softbuffer" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "071916a85d1db274b4ed57af3a14afb66bd836ae7f82ebb6f1fd3455107830d9" dependencies = [ - "libc", + "bytemuck", + "cfg_aliases 0.2.0", + "cocoa", + "core-graphics", + "foreign-types 0.5.0", + "js-sys", + "log", + "objc", + "raw-window-handle 0.6.0", + "redox_syscall", + "wasm-bindgen", + "wayland-sys", + "web-sys", "windows-sys 0.52.0", ] [[package]] -name = "soup2" -version = "0.2.1" +name = "soup3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b4d76501d8ba387cf0fefbe055c3e0a59891d09f0f995ae4e4b16f6b60f3c0" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" dependencies = [ - "bitflags 1.3.2", + "futures-channel", "gio", - "glib", + "glib 0.18.5", "libc", - "once_cell", - "soup2-sys", + "soup3-sys", ] [[package]] -name = "soup2-sys" -version = "0.2.0" +name = "soup3-sys" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "009ef427103fcb17f802871647a7fa6c60cbb654b4c4e4c0ac60a31c5f6dc9cf" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" dependencies = [ - "bitflags 1.3.2", - "gio-sys", - "glib-sys", - "gobject-sys", + "gio-sys 0.18.1", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "libc", - "system-deps 5.0.0", + "system-deps", ] [[package]] @@ -3681,9 +3793,9 @@ dependencies = [ [[package]] name = "state" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" dependencies = [ "loom", ] @@ -3735,6 +3847,17 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "swift-rs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bbdb58577b6301f8d17ae2561f32002a5bae056d444e0f69e611e504a276204" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + [[package]] name = "syn" version = "1.0.109" @@ -3765,15 +3888,11 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sys-locale" -version = "0.2.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee" +checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" dependencies = [ - "js-sys", "libc", - "wasm-bindgen", - "web-sys", - "windows-sys 0.45.0", ] [[package]] @@ -3812,56 +3931,36 @@ dependencies = [ "libc", ] -[[package]] -name = "system-deps" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e" -dependencies = [ - "cfg-expr 0.9.1", - "heck 0.3.3", - "pkg-config", - "toml 0.5.11", - "version-compare 0.0.11", -] - [[package]] name = "system-deps" version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ - "cfg-expr 0.15.7", + "cfg-expr", "heck 0.5.0", "pkg-config", "toml 0.8.12", - "version-compare 0.2.0", + "version-compare", ] [[package]] name = "tao" -version = "0.16.8" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a794e476ce829420b58059f4ac23c2b991dab2ee552be740f931aea95ae9c8" +checksum = "bd5b6ec2c43abd15155f040c765001098f50f425414b679225d471a1cd782753" dependencies = [ "bitflags 1.3.2", - "cairo-rs", - "cc", "cocoa", "core-foundation", - "core-graphics 0.22.3", + "core-graphics", "crossbeam-channel", "dispatch", - "gdk", - "gdk-pixbuf", - "gdk-sys", + "dlopen2", + "dpi", "gdkwayland-sys", "gdkx11-sys", - "gio", - "glib", - "glib-sys", "gtk", - "image", "instant", "jni", "lazy_static", @@ -3873,15 +3972,13 @@ dependencies = [ "objc", "once_cell", "parking_lot", - "png", - "raw-window-handle", + "raw-window-handle 0.6.0", "scopeguard", - "serde", "tao-macros", "unicode-segmentation", - "uuid", - "windows 0.39.0", - "windows-implement", + "url", + "windows 0.54.0", + "windows-version", "x11-dl", ] @@ -3915,88 +4012,81 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.6.1" +version = "2.0.0-beta.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f078117725e36d55d29fafcbb4b1e909073807ca328ae8deb8c0b3843aac0fed" +checksum = "a50fb0bdb687486415224f8be47c78993e9f3ea575ee0d5177c90d0c71842f4a" dependencies = [ "anyhow", "bytes", "cocoa", "dirs-next", - "dunce", "embed_plist", - "encoding_rs", - "flate2", "futures-util", - "glib", + "getrandom 0.2.12", "glob", "gtk", "heck 0.4.1", - "http", - "ignore", - "indexmap 1.9.3", - "nix 0.26.4", - "notify-rust", + "http 1.1.0", + "jni", + "libc", + "log", + "mime", + "muda", "objc", - "once_cell", - "open", - "os_info", - "os_pipe", "percent-encoding", - "rand 0.8.5", - "raw-window-handle", - "regex", - "reqwest", - "rfd", - "semver", + "raw-window-handle 0.6.0", + "reqwest 0.12.2", "serde", "serde_json", "serde_repr", "serialize-to-javascript", - "shared_child", "state", - "sys-locale", - "tar", + "swift-rs", + "tauri-build", "tauri-macros", "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "tempfile", "thiserror", "tokio", + "tray-icon", "url", - "uuid", + "urlpattern", "webkit2gtk", "webview2-com", - "windows 0.39.0", + "window-vibrancy", + "windows 0.54.0", ] [[package]] name = "tauri-build" -version = "1.5.1" +version = "2.0.0-beta.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9914a4715e0b75d9f387a285c7e26b5bbfeb1249ad9f842675a82481565c532" +checksum = "82a46303cc4bce0b17ad95965cbd8326e3511b9d2cb6fb13a4a4c98a11b0dcaf" dependencies = [ "anyhow", "cargo_toml", "dirs-next", + "glob", "heck 0.4.1", "json-patch", + "schemars", "semver", "serde", "serde_json", "tauri-utils", "tauri-winres", + "toml 0.8.12", "walkdir", ] [[package]] name = "tauri-codegen" -version = "1.4.2" +version = "2.0.0-beta.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1554c5857f65dbc377cefb6b97c8ac77b1cb2a90d30d3448114d5d6b48a77fc" +checksum = "f1665f6a986842061a67cb9dcbe2fa27076c1a616f6525fc06de9d6d52838d63" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "brotli", "ico", "json-patch", @@ -4004,81 +4094,197 @@ dependencies = [ "png", "proc-macro2", "quote", - "regex", "semver", "serde", "serde_json", "sha2", + "syn 2.0.55", "tauri-utils", "thiserror", "time", + "url", "uuid", "walkdir", ] [[package]] name = "tauri-macros" -version = "1.4.3" +version = "2.0.0-beta.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "277abf361a3a6993ec16bcbb179de0d6518009b851090a01adfea12ac89fa875" +checksum = "b0c1558fc42cc2a1735cfd5edb2954c735d4516f8ba31c58b7180ba8a2bc18de" dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.55", "tauri-codegen", "tauri-utils", ] +[[package]] +name = "tauri-plugin" +version = "2.0.0-beta.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ab1ac6122bf2ca5fc4ebb8aadff619f3b172477d2baf8134cf1d7f0e249a12" +dependencies = [ + "anyhow", + "glob", + "plist", + "schemars", + "serde", + "serde_json", + "tauri-utils", + "toml 0.8.12", + "walkdir", +] + +[[package]] +name = "tauri-plugin-dialog" +version = "2.0.0-beta.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e734642af7b5b2d107212a3c087480990d9d995290a67e4fdfd4815abf603969" +dependencies = [ + "glib 0.16.9", + "log", + "raw-window-handle 0.6.0", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror", +] + +[[package]] +name = "tauri-plugin-fs" +version = "2.0.0-beta.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7718012d8e2ec7070aab9dbf1747c1575dca1ec00fb4fc6fb59e8d70eee5b3b3" +dependencies = [ + "anyhow", + "glob", + "schemars", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "thiserror", + "url", + "uuid", +] + +[[package]] +name = "tauri-plugin-http" +version = "2.0.0-beta.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f7f516a45d008e21ead191fa24f50ec38e9719caa7ab7758dcada1ad08aa887" +dependencies = [ + "data-url", + "http 0.2.12", + "regex", + "reqwest 0.11.27", + "schemars", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror", + "url", + "urlpattern", +] + +[[package]] +name = "tauri-plugin-os" +version = "2.0.0-beta.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dc0a2037ef113d9d9db85edceab6f95f83ae111e4d989d6bc1df79c8ab4cf" +dependencies = [ + "gethostname", + "log", + "os_info", + "serde", + "serde_json", + "serialize-to-javascript", + "sys-locale", + "tauri", + "tauri-plugin", + "thiserror", +] + +[[package]] +name = "tauri-plugin-shell" +version = "2.0.0-beta.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5624537650f627707f3bd9c6562efe2116c7fb043fcfc2e3d10f802d7870a1cd" +dependencies = [ + "encoding_rs", + "log", + "open", + "os_pipe", + "regex", + "schemars", + "serde", + "serde_json", + "shared_child", + "tauri", + "tauri-plugin", + "thiserror", +] + [[package]] name = "tauri-runtime" -version = "0.14.2" +version = "2.0.0-beta.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2d0652aa2891ff3e9caa2401405257ea29ab8372cce01f186a5825f1bd0e76" +checksum = "612e05de1382575b32b5220b546861256f630f37ac64c29cab252592861b9bd4" dependencies = [ + "dpi", "gtk", - "http", - "http-range", - "rand 0.8.5", - "raw-window-handle", + "http 1.1.0", + "jni", + "raw-window-handle 0.6.0", "serde", "serde_json", "tauri-utils", "thiserror", "url", - "uuid", - "webview2-com", - "windows 0.39.0", + "windows 0.54.0", ] [[package]] name = "tauri-runtime-wry" -version = "0.14.5" +version = "2.0.0-beta.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "067c56fc153b3caf406d7cd6de4486c80d1d66c0f414f39e94cb2f5543f6445f" +checksum = "2f73672897b5396cb05c2f21b12b66ecfd4b51fae619dd35387467660d6c00fb" dependencies = [ - "arboard", "cocoa", "gtk", + "http 1.1.0", + "jni", + "log", "percent-encoding", - "rand 0.8.5", - "raw-window-handle", + "raw-window-handle 0.6.0", + "softbuffer", + "tao", "tauri-runtime", "tauri-utils", - "uuid", + "url", "webkit2gtk", "webview2-com", - "windows 0.39.0", + "windows 0.54.0", "wry", ] [[package]] name = "tauri-utils" -version = "1.5.3" +version = "2.0.0-beta.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ad0bbb31fccd1f4c56275d0a5c3abdf1f59999f72cb4ef8b79b4ed42082a21" +checksum = "0a148adf8077e1891c8b7d1c2be90c1c8eb8c7a071c35bb8edbdfe7cd9d8e23c" dependencies = [ "brotli", + "cargo_metadata", "ctor", "dunce", "glob", @@ -4092,14 +4298,18 @@ dependencies = [ "phf 0.11.2", "proc-macro2", "quote", + "regex", + "schemars", "semver", "serde", "serde_json", "serde_with", + "swift-rs", "thiserror", + "toml 0.8.12", "url", + "urlpattern", "walkdir", - "windows-version", ] [[package]] @@ -4112,16 +4322,6 @@ dependencies = [ "toml 0.7.8", ] -[[package]] -name = "tauri-winrt-notification" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006851c9ccefa3c38a7646b8cec804bb429def3da10497bfa977179869c3e8e2" -dependencies = [ - "quick-xml 0.30.0", - "windows 0.51.1", -] - [[package]] name = "tempfile" version = "3.10.1" @@ -4129,8 +4329,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.2", - "rustix 0.38.32", + "fastrand", + "rustix", "windows-sys 0.52.0", ] @@ -4181,17 +4381,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - [[package]] name = "time" version = "0.3.34" @@ -4250,7 +4439,9 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.6", + "signal-hook-registry", + "socket2", + "tracing", "windows-sys 0.48.0", ] @@ -4278,15 +4469,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.7.8" @@ -4333,6 +4515,28 @@ dependencies = [ "winnow 0.5.40", ] +[[package]] +name = "toml_edit" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.22.9" @@ -4346,6 +4550,28 @@ dependencies = [ "winnow 0.6.5", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -4358,6 +4584,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4414,17 +4641,23 @@ dependencies = [ ] [[package]] -name = "tree_magic_mini" -version = "3.1.4" +name = "tray-icon" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ee137597cdb361b55a4746983e4ac1b35ab6024396a419944ad473bb915265" +checksum = "da36482ee1dbcedfddb038b3a0f6d27f04d9470dc99dabfa90b8d7cdc8b5f3d6" dependencies = [ - "fnv", - "home", - "memchr", - "nom", + "cocoa", + "core-graphics", + "crossbeam-channel", + "dirs-next", + "libappindicator", + "muda", + "objc", "once_cell", - "petgraph", + "png", + "serde", + "thiserror", + "windows-sys 0.52.0", ] [[package]] @@ -4460,11 +4693,52 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ - "memoffset 0.9.1", + "memoffset", "tempfile", "winapi", ] +[[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-bidi" version = "0.3.15" @@ -4510,6 +4784,19 @@ dependencies = [ "serde", ] +[[package]] +name = "urlpattern" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9bd5ff03aea02fa45b13a7980151fe45009af1980ba69f651ec367121a31609" +dependencies = [ + "derive_more", + "regex", + "serde", + "unic-ucd-ident", + "url", +] + [[package]] name = "utf-8" version = "0.7.6" @@ -4543,12 +4830,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "version-compare" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" - [[package]] name = "version-compare" version = "0.2.0" @@ -4601,12 +4882,6 @@ dependencies = [ "quote", ] -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - [[package]] name = "walkdir" version = "2.5.0" @@ -4717,68 +4992,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wayland-backend" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" -dependencies = [ - "cc", - "downcast-rs", - "rustix 0.38.32", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" -dependencies = [ - "bitflags 2.5.0", - "rustix 0.38.32", - "wayland-backend", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" -dependencies = [ - "bitflags 2.5.0", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" -dependencies = [ - "bitflags 2.5.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" -dependencies = [ - "proc-macro2", - "quick-xml 0.31.0", - "quote", -] - [[package]] name = "wayland-sys" version = "0.31.1" @@ -4802,95 +5015,84 @@ dependencies = [ [[package]] name = "webkit2gtk" -version = "0.18.2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8f859735e4a452aeb28c6c56a852967a8a76c8eb1cc32dbf931ad28a13d6370" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" dependencies = [ "bitflags 1.3.2", "cairo-rs", "gdk", "gdk-sys", "gio", - "gio-sys", - "glib", - "glib-sys", - "gobject-sys", + "gio-sys 0.18.1", + "glib 0.18.5", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "gtk", "gtk-sys", "javascriptcore-rs", "libc", "once_cell", - "soup2", + "soup3", "webkit2gtk-sys", ] [[package]] name = "webkit2gtk-sys" -version = "0.18.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d76ca6ecc47aeba01ec61e480139dda143796abcae6f83bcddf50d6b5b1dcf3" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" dependencies = [ - "atk-sys", "bitflags 1.3.2", "cairo-sys-rs", - "gdk-pixbuf-sys", "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", + "gio-sys 0.18.1", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", "gtk-sys", "javascriptcore-rs-sys", "libc", - "pango-sys", "pkg-config", - "soup2-sys", - "system-deps 6.2.2", + "soup3-sys", + "system-deps", ] [[package]] name = "webview2-com" -version = "0.19.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a769c9f1a64a8734bde70caafac2b96cada12cd4aefa49196b3a386b8b4178" +checksum = "38d5949fc3f537e90240c3e4f78dda2fa0431b671d50845a2f582173ef8a1201" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows 0.39.0", + "windows 0.54.0", + "windows-core 0.54.0", "windows-implement", + "windows-interface", ] [[package]] name = "webview2-com-macros" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac" +checksum = "ac1345798ecd8122468840bcdf1b95e5dc6d2206c5e4b0eafa078d061f59c9bc" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.55", ] [[package]] name = "webview2-com-sys" -version = "0.19.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac48ef20ddf657755fdcda8dfed2a7b4fc7e4581acce6fe9b88c3d64f29dee7" +checksum = "cd1eaa1be63d6fdcadf893c40d7d53c889a6342b3a94930d34e6964d5bb7e8db" dependencies = [ - "regex", - "serde", - "serde_json", "thiserror", - "windows 0.39.0", - "windows-bindgen", - "windows-metadata", + "windows 0.54.0", + "windows-core 0.54.0", ] -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - [[package]] name = "winapi" version = "0.3.9" @@ -4923,30 +5125,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" -dependencies = [ - "windows_aarch64_msvc 0.37.0", - "windows_i686_gnu 0.37.0", - "windows_i686_msvc 0.37.0", - "windows_x86_64_gnu 0.37.0", - "windows_x86_64_msvc 0.37.0", -] - -[[package]] -name = "windows" -version = "0.39.0" +name = "window-vibrancy" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +checksum = "33082acd404763b315866e14a0d5193f3422c81086657583937a750cdd3ec340" dependencies = [ - "windows-implement", - "windows_aarch64_msvc 0.39.0", - "windows_i686_gnu 0.39.0", - "windows_i686_msvc 0.39.0", - "windows_x86_64_gnu 0.39.0", - "windows_x86_64_msvc 0.39.0", + "cocoa", + "objc", + "raw-window-handle 0.6.0", + "windows-sys 0.52.0", + "windows-version", ] [[package]] @@ -4958,16 +5146,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" -dependencies = [ - "windows-core 0.51.1", - "windows-targets 0.48.5", -] - [[package]] name = "windows" version = "0.52.0" @@ -4979,62 +5157,65 @@ dependencies = [ ] [[package]] -name = "windows-bindgen" -version = "0.39.0" +name = "windows" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68003dbd0e38abc0fb85b939240f4bce37c43a5981d3df37ccbaaa981b47cb41" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ - "windows-metadata", - "windows-tokens", + "windows-core 0.54.0", + "windows-implement", + "windows-interface", + "windows-targets 0.52.4", ] [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.4", ] [[package]] name = "windows-core" -version = "0.52.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ + "windows-result", "windows-targets 0.52.4", ] [[package]] name = "windows-implement" -version = "0.39.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7" +checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd" dependencies = [ - "syn 1.0.109", - "windows-tokens", + "proc-macro2", + "quote", + "syn 2.0.55", ] [[package]] -name = "windows-metadata" -version = "0.39.0" +name = "windows-interface" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" +checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] [[package]] -name = "windows-sys" -version = "0.42.0" +name = "windows-result" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "cd19df78e5168dfb0aedc343d1d1b8d422ab2db6756d2dc3fef75035402a3f64" 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", + "windows-targets 0.52.4", ] [[package]] @@ -5109,12 +5290,6 @@ dependencies = [ "windows_x86_64_msvc 0.52.4", ] -[[package]] -name = "windows-tokens" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" - [[package]] name = "windows-version" version = "0.1.0" @@ -5142,18 +5317,6 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" -[[package]] -name = "windows_aarch64_msvc" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -5172,18 +5335,6 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" -[[package]] -name = "windows_i686_gnu" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" - -[[package]] -name = "windows_i686_gnu" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -5202,18 +5353,6 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" -[[package]] -name = "windows_i686_msvc" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" - -[[package]] -name = "windows_i686_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -5232,18 +5371,6 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" -[[package]] -name = "windows_x86_64_gnu" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -5280,18 +5407,6 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" -[[package]] -name = "windows_x86_64_msvc" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -5348,62 +5463,46 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "wl-clipboard-rs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" -dependencies = [ - "derive-new", - "libc", - "log", - "nix 0.28.0", - "os_pipe", - "tempfile", - "thiserror", - "tree_magic_mini", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-protocols-wlr", -] - [[package]] name = "wry" -version = "0.24.7" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ad85d0e067359e409fcb88903c3eac817c392e5d638258abfb3da5ad8ba6fc4" +checksum = "4eca9d50437c04fc67e82c196ddd31d8e35794150713ae2d647f3a58c7f45d1a" dependencies = [ - "base64 0.13.1", + "base64 0.21.7", "block", + "cfg_aliases 0.1.1", "cocoa", - "core-graphics 0.22.3", + "core-graphics", "crossbeam-channel", + "dpi", "dunce", - "gdk", - "gio", - "glib", + "gdkx11", "gtk", "html5ever", - "http", + "http 1.1.0", + "javascriptcore-rs", + "jni", "kuchikiki", "libc", - "log", + "ndk", + "ndk-context", + "ndk-sys", "objc", "objc_id", "once_cell", - "serde", - "serde_json", + "percent-encoding", + "raw-window-handle 0.6.0", "sha2", - "soup2", - "tao", + "soup3", + "tao-macros", "thiserror", - "url", "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows 0.39.0", - "windows-implement", + "windows 0.54.0", + "windows-version", + "x11-dl", ] [[package]] @@ -5427,23 +5526,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11rb" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" -dependencies = [ - "gethostname", - "rustix 0.38.32", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" - [[package]] name = "xattr" version = "1.3.1" @@ -5451,8 +5533,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", - "linux-raw-sys 0.4.13", - "rustix 0.38.32", + "linux-raw-sys", + "rustix", ] [[package]] @@ -5467,39 +5549,32 @@ dependencies = [ [[package]] name = "zbus" -version = "3.15.2" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6" +checksum = "c9ff46f2a25abd690ed072054733e0bc3157e3d4c45f41bd183dce09c2ff8ab9" dependencies = [ "async-broadcast", - "async-executor", - "async-fs", - "async-io 1.13.0", - "async-lock 2.8.0", "async-process", "async-recursion", - "async-task", "async-trait", - "blocking", - "byteorder", "derivative", "enumflags2", - "event-listener 2.5.3", + "event-listener 5.2.0", "futures-core", "futures-sink", "futures-util", "hex", - "nix 0.26.4", - "once_cell", + "nix", "ordered-stream", "rand 0.8.5", "serde", "serde_repr", "sha1", "static_assertions", + "tokio", "tracing", "uds_windows", - "winapi", + "windows-sys 0.52.0", "xdg-home", "zbus_macros", "zbus_names", @@ -5508,11 +5583,11 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "3.15.2" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" +checksum = "4e0e3852c93dcdb49c9462afe67a2a468f7bd464150d866e861eaf06208633e0" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "regex", @@ -5522,9 +5597,9 @@ dependencies = [ [[package]] name = "zbus_names" -version = "2.6.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" dependencies = [ "serde", "static_assertions", @@ -5533,25 +5608,25 @@ dependencies = [ [[package]] name = "zvariant" -version = "3.15.2" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" +checksum = "2c1b3ca6db667bfada0f1ebfc94b2b1759ba25472ee5373d4551bb892616389a" dependencies = [ - "byteorder", + "endi", "enumflags2", - "libc", "serde", "static_assertions", + "url", "zvariant_derive", ] [[package]] name = "zvariant_derive" -version = "3.15.2" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" +checksum = "b7a4b236063316163b69039f77ce3117accb41a09567fd24c168e43491e521bc" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -5560,9 +5635,9 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" dependencies = [ "proc-macro2", "quote", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index faf5e43..c68034c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" build = "src/build.rs" [build-dependencies] -tauri-build = { version = "1.5.1", features = [] } +tauri-build = { version = "2.0.0-beta.11", features = [] } [dependencies] serde_json = "1.0.80" @@ -26,10 +26,17 @@ flate2 = "1.0.28" tar = "0.4.40" openssl = { version = "0.10", features = ["vendored"] } fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } +thiserror = "1.0.58" +reqwest = { version = "^0.11", features = ["json"] } +tauri-plugin-dialog = "2.0.0-beta.4" +tauri-plugin-fs = "2.0.0-beta.4" +tauri-plugin-os = "2.0.0-beta.3" +tauri-plugin-shell = "2.0.0-beta.3" +tauri-plugin-http = "2.0.0-beta.4" [dependencies.tauri] -version = "1.6.1" -features = ["api-all", "macos-private-api", "process-command-api", "http-api"] +version = "2.0.0-beta" +features = [ "macos-private-api"] [features] default = [ "custom-protocol" ] diff --git a/src-tauri/capabilities/main.json b/src-tauri/capabilities/main.json new file mode 100644 index 0000000..320c844 --- /dev/null +++ b/src-tauri/capabilities/main.json @@ -0,0 +1,33 @@ +{ + "identifier": "main-capability", + "local": true, + "windows": [ + "main" + ], + "permissions": [ + "path:default", + "event:default", + "window:default", + "app:default", + "resources:default", + "menu:default", + "tray:default", + "fs:default", + "fs:allow-home-read-recursive", + "fs:allow-home-write-recursive", + "os:allow-os-type", + "dialog:allow-open", + "shell:allow-open", + { + "identifier": "shell:allow-execute", + "allow": [ + { + "name": "node-version", + "cmd": "node", + "args": ["-v"], + "sidecar": false + } + ] + } + ] +} diff --git a/src-tauri/src/bundles.rs b/src-tauri/src/bundles.rs index a78bedd..ab13b29 100644 --- a/src-tauri/src/bundles.rs +++ b/src-tauri/src/bundles.rs @@ -1,6 +1,7 @@ use std::path::Path; use std::{fs}; use git2::{AutotagOption, FetchOptions, Repository}; +use tauri_plugin_shell::ShellExt; use unwrap_or::unwrap_ok_or; use crate::git; @@ -36,7 +37,7 @@ fn parse_bundle_url(url: String) -> Result { #[tauri::command(async)] pub fn install_bundle(handle: tauri::AppHandle, bundle_url: String, nodecg_path: String) -> Result<(), String> { - let logger = LogEmitter::with_progress(handle, "install-bundle", 5); + let logger = LogEmitter::with_progress(&handle, "install-bundle", 5); let parsed_url = match parse_bundle_url(bundle_url) { Ok(url) => url, Err(e) => { @@ -73,7 +74,8 @@ pub fn install_bundle(handle: tauri::AppHandle, bundle_url: String, nodecg_path: } logger.emit_progress(4); - match npm::install_npm_dependencies(&bundle_path).and_then(|child| { + let shell = handle.shell(); + match npm::install_npm_dependencies(shell, &bundle_path).and_then(|child| { log_npm_install(logger, child); Ok(()) }) { @@ -108,7 +110,7 @@ pub fn fetch_bundle_versions(bundle_name: String, nodecg_path: String) -> Result #[tauri::command(async)] pub fn set_bundle_version(handle: tauri::AppHandle, bundle_name: String, version: String, nodecg_path: String) -> Result<(), String> { - let logger = LogEmitter::with_progress(handle, "change-bundle-version", 4); + let logger = LogEmitter::with_progress(&handle, "change-bundle-version", 4); let bundle_dir = format!("{}/bundles/{}", nodecg_path, bundle_name); let path = Path::new(&bundle_dir); @@ -129,7 +131,8 @@ pub fn set_bundle_version(handle: tauri::AppHandle, bundle_name: String, version Err(e) => return format_error(&format!("Failed to open git repository for bundle '{}'", bundle_name), e) } - match npm::install_npm_dependencies(&bundle_dir).and_then(|child| { + let shell = handle.shell(); + match npm::install_npm_dependencies(shell, &bundle_dir).and_then(|child| { log_npm_install(logger, child); Ok(()) }) { diff --git a/src-tauri/src/dependencies.rs b/src-tauri/src/dependencies.rs index 5aba4e3..2362229 100644 --- a/src-tauri/src/dependencies.rs +++ b/src-tauri/src/dependencies.rs @@ -1,11 +1,20 @@ -use tauri::api::process::Command; +use tauri_plugin_shell::ShellExt; -#[tauri::command(async)] -pub fn get_nodejs_version() -> Option { - let output = Command::new("node").args(["-v"]).output(); +#[tauri::command] +pub async fn get_nodejs_version(app: tauri::AppHandle) -> Option { + let shell = app.shell(); + let output = shell + .command("node") + .args(["-v"]) + .output() + .await; return match output { - Ok(output) => Some(output.stdout.trim().to_string()), + Ok(output) => Some( + String::from_utf8(output.stdout) + .unwrap_or_else(|e| format!("Failed to decode command output: {}", e.to_string())) + .trim() + .to_string()), Err(_) => None } } diff --git a/src-tauri/src/error.rs b/src-tauri/src/error.rs index 667c0aa..a26f41e 100644 --- a/src-tauri/src/error.rs +++ b/src-tauri/src/error.rs @@ -1,9 +1,28 @@ -use std::error::Error; -use std::fmt; +use std::{fmt, io}; +use serde::Serializer; +use tauri_plugin_http::reqwest; pub trait MgrErrorCause: fmt::Display + fmt::Debug {} impl MgrErrorCause for T {} +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error(transparent)] + Request(#[from] reqwest::Error), + #[error(transparent)] + Io(#[from] io::Error), + #[error("Error installing NodeCG: {0}")] + NodeCGInstall(String), + #[error("Error installing npm dependencies: {0}")] + NPMInstall(String), +} + +impl serde::Serialize for Error { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(self.to_string().as_ref()) + } +} + #[derive(Debug)] pub struct MgrError { pub description: String, @@ -15,10 +34,6 @@ impl MgrError { MgrError { description: msg.to_string(), cause: None } } - pub fn with_cause(msg: &str, cause: T) -> MgrError { - MgrError { description: msg.to_string(), cause: Some(Box::new(cause)) } - } - pub fn boxed(self) -> Box { Box::new(self) } @@ -34,6 +49,6 @@ impl fmt::Display for MgrError { } } -impl Error for MgrError { +impl std::error::Error for MgrError { } diff --git a/src-tauri/src/log.rs b/src-tauri/src/log.rs index 44b84b8..9f30921 100644 --- a/src-tauri/src/log.rs +++ b/src-tauri/src/log.rs @@ -1,7 +1,7 @@ use std::{fmt}; -use tauri::api::process::{CommandEvent, TerminatedPayload}; +use tauri_plugin_shell::process::{CommandEvent, TerminatedPayload}; use tauri::async_runtime::{JoinHandle, Receiver, spawn}; -use tauri::{Manager}; +use tauri::Manager; #[derive(Clone)] pub struct LogEmitter { @@ -11,7 +11,7 @@ pub struct LogEmitter { } impl LogEmitter { - pub fn new(handle: tauri::AppHandle, key: &str) -> LogEmitter { + pub fn new(handle: &tauri::AppHandle, key: &str) -> LogEmitter { LogEmitter { handle: handle.clone(), key: key.to_string(), @@ -19,7 +19,7 @@ impl LogEmitter { } } - pub fn with_progress(handle: tauri::AppHandle, key: &str, max_progress_step: u32) -> LogEmitter { + pub fn with_progress(handle: &tauri::AppHandle, key: &str, max_progress_step: u32) -> LogEmitter { let mut emitter = LogEmitter::new(handle, key); emitter.max_progress_step = Some(max_progress_step); emitter.emit_progress(0); @@ -27,7 +27,7 @@ impl LogEmitter { } pub fn emit(&self, msg: &str) -> () { - self.handle.emit_all( + self.handle.emit( &format!("log:{}", self.key), LogPayload { message: msg.to_string() } ).expect("Failed to emit log message"); @@ -35,7 +35,7 @@ impl LogEmitter { pub fn emit_progress(&self, step: u32) -> () { if self.max_progress_step.is_some() { - self.handle.emit_all( + self.handle.emit( &format!("progress:{}", self.key), ProgressPayload { step, max_step: self.max_progress_step.unwrap() } ).expect("Failed to emit log message"); @@ -43,7 +43,7 @@ impl LogEmitter { } pub fn emit_process_closure(&self, payload: &TerminatedPayload) -> () { - self.handle.emit_all( + self.handle.emit( &format!("process-exit:{}", self.key), ProcessClosurePayload { code: payload.code, success: is_process_termination_successful(payload) } ).expect("Failed to emit log message for process closure"); @@ -77,8 +77,8 @@ pub fn emit_tauri_process_output(logger: LogEmitter, mut receiver: Receiver = None; while let Some(item) = receiver.recv().await { logger.emit(&*match item { - CommandEvent::Stderr(msg) => msg, - CommandEvent::Stdout(msg) => msg, + CommandEvent::Stderr(msg) => String::from_utf8(msg).unwrap_or_else(|e| format!("Failed to decode output: {}", e.to_string())), + CommandEvent::Stdout(msg) => String::from_utf8(msg).unwrap_or_else(|e| format!("Failed to decode output: {}", e.to_string())), CommandEvent::Error(msg) => msg, CommandEvent::Terminated(payload) => { logger.emit_process_closure(&payload); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index a7d6f3c..9bde510 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,10 +3,8 @@ all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] -extern crate core; - -use tauri::{AboutMetadata, Manager, Menu, MenuItem, RunEvent, Submenu}; -use tauri::api::process::{CommandEvent}; +use tauri::{Manager, RunEvent}; +use tauri_plugin_shell::process::CommandEvent; use tauri::async_runtime::{JoinHandle, Receiver}; use crate::log::{err_to_string, format_error, LogEmitter}; @@ -53,7 +51,17 @@ fn open_path_in_terminal(path: String) -> Result<(), String> { fn main() { let _ = fix_path_env::fix(); - let mut builder = tauri::Builder::default() + let builder = tauri::Builder::default() + .plugin(tauri_plugin_http::init()) + .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_fs::init()) + .plugin(tauri_plugin_os::init()) + .plugin(tauri_plugin_dialog::init()) + .setup(|app| { + app.manage(ManagedNodecg::new(app.handle().clone())); + + Ok(()) + }) .invoke_handler(tauri::generate_handler![ nodecg::install_nodecg, nodecg::start_nodecg, @@ -65,26 +73,25 @@ fn main() { bundles::uninstall_bundle, bundles::get_bundle_git_tag, dependencies::get_nodejs_version - ]) - .manage(ManagedNodecg::new()); - - if cfg!(target_os = "macos") { - let menu_app = Menu::new() - .add_native_item(MenuItem::About("NCGMGR".to_string(), AboutMetadata::new())) - .add_native_item(MenuItem::Quit); + ]); - let menu_edit = Menu::new() - .add_native_item(MenuItem::Cut) - .add_native_item(MenuItem::Copy) - .add_native_item(MenuItem::Paste) - .add_native_item(MenuItem::SelectAll) - .add_native_item(MenuItem::Undo) - .add_native_item(MenuItem::Redo); - - builder = builder.menu(Menu::new() - .add_submenu(Submenu::new("NCGMGR", menu_app)) - .add_submenu(Submenu::new("Edit", menu_edit))); - } + // if cfg!(target_os = "macos") { + // let menu_app = Menu::new() + // .add_native_item(MenuItem::About("NCGMGR".to_string(), AboutMetadata::new())) + // .add_native_item(MenuItem::Quit); + // + // let menu_edit = Menu::new() + // .add_native_item(MenuItem::Cut) + // .add_native_item(MenuItem::Copy) + // .add_native_item(MenuItem::Paste) + // .add_native_item(MenuItem::SelectAll) + // .add_native_item(MenuItem::Undo) + // .add_native_item(MenuItem::Redo); + // + // builder = builder.menu(Menu::new() + // .add_submenu(Submenu::new("NCGMGR", menu_app)) + // .add_submenu(Submenu::new("Edit", menu_edit))); + // } let app = builder .build(tauri::generate_context!()) @@ -96,7 +103,7 @@ fn main() { match managed_nodecg.stop() { Ok(_) => {} Err(e) => { - let logger = LogEmitter::new(handle.clone(), "run-nodecg"); + let logger = LogEmitter::new(&handle, "run-nodecg"); logger.emit(&err_to_string("Failed to shut down NodeCG", e)); api.prevent_exit(); } diff --git a/src-tauri/src/nodecg.rs b/src-tauri/src/nodecg.rs index 549434d..1c4a711 100644 --- a/src-tauri/src/nodecg.rs +++ b/src-tauri/src/nodecg.rs @@ -1,28 +1,31 @@ use std::fs; use std::sync::Mutex; -use tauri::api::process::{Command, CommandChild, CommandEvent}; +use tauri_plugin_shell::process::{CommandChild, CommandEvent}; use tauri::async_runtime::Receiver; use unwrap_or::unwrap_ok_or; use std::path::{Path, PathBuf}; use flate2::read::GzDecoder; use sysinfo::{Pid, ProcessRefreshKind, RefreshKind, System}; -use tauri::api::http::{ClientBuilder, HttpRequestBuilder, ResponseType}; -use futures_util::TryFutureExt; +use tauri_plugin_http::reqwest; use tar::Archive; +use tauri::AppHandle; +use tauri_plugin_shell::ShellExt; use crate::log::{format_error, emit_tauri_process_output, LogEmitter}; use crate::{err_to_string, log_npm_install, npm}; -use crate::error::MgrError; +use crate::error::{MgrError, Error}; use crate::npm::NPMPackageMetadata; pub struct ManagedNodecg { - process: Mutex> + process: Mutex>, + app_handle: AppHandle, } impl ManagedNodecg { - pub fn new() -> ManagedNodecg { + pub fn new(app_handle: AppHandle) -> Self { ManagedNodecg { - process: Mutex::new(None) + process: Mutex::new(None), + app_handle } } @@ -35,12 +38,12 @@ impl ManagedNodecg { return Err(MgrError::new("NodeCG is already running.").boxed()) } - let child = unwrap_ok_or!( - Command::new("node") - .args([format!("{}/index.js", nodecg_path)]) - .current_dir(PathBuf::from(nodecg_path)) - .spawn(), e, - { return Err(MgrError::with_cause("Failed to start NodeCG", e).boxed()) }); + let shell = self.app_handle.shell(); + let child = shell + .command("node") + .args([format!("{}/index.js", nodecg_path)]) + .current_dir(PathBuf::from(nodecg_path)) + .spawn()?; *lock = Some(child.1); @@ -62,56 +65,37 @@ impl ManagedNodecg { } #[tauri::command(async)] -pub async fn install_nodecg(handle: tauri::AppHandle, path: String) -> Result<(), String> { - let logger = LogEmitter::with_progress(handle, "install-nodecg", 4); +pub async fn install_nodecg(handle: AppHandle, path: String) -> Result<(), Error> { + let logger = LogEmitter::with_progress(&handle, "install-nodecg", 4); logger.emit("Starting NodeCG install..."); logger.emit("Loading version list..."); - let client = match ClientBuilder::new().build() { - Ok(client) => client, - Err(e) => return format_error("Failed to create HTTP client", e) - }; - let package_info_request = HttpRequestBuilder::new("GET", "https://registry.npmjs.org/nodecg/") - .unwrap() - .response_type(ResponseType::Json); - let tarball_url_and_version = match client.send(package_info_request).and_then(|response| async move { - response.read().await.and_then(|data| { - Ok(serde_json::from_value::(data.data)?) - }) - }).await { - Ok(response) => { - // According to npm, this shouldn't happen... - // https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#full-metadata-format - if !response.dist_tags.contains_key("latest") { - return Err("Couldn't find latest version of NodeCG".to_string()) - } + let client = reqwest::Client::builder().build()?; + let npm_metadata = client.get("https://registry.npmjs.org/nodecg/").send().await?.json::().await?; - let latest_version = response.dist_tags.get("latest").unwrap(); - if !response.versions.contains_key(latest_version) { - return Err(format!("Latest NodeCG version ({}) was not found in npm metadata", latest_version)) - } - let latest_version_metadata = response.versions.get(latest_version).unwrap(); - (latest_version_metadata.dist.tarball.clone(), latest_version.clone()) - }, - Err(e) => return format_error("Failed to get NodeCG version list", e) + let latest_version = match npm_metadata.dist_tags.get("latest") { + Some(version) => version, + None => { + // https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#full-metadata-format + return Err(Error::NodeCGInstall("Couldn't find latest version of NodeCG (This should never happen!)".to_string())); + } }; + let tarball_url = match npm_metadata.versions.get(latest_version) { + Some(metadata) => metadata.dist.tarball.clone(), + None => { + return Err(Error::NodeCGInstall(format!("Latest NodeCG version ({}) was not found in npm metadata", latest_version))); + } + }; + logger.emit_progress(1); - logger.emit(&format!("Downloading NodeCG {}...", tarball_url_and_version.1)); - let tarball_request = HttpRequestBuilder::new("GET", tarball_url_and_version.0) - .unwrap() - .response_type(ResponseType::Binary); - let tarball_response = match client.send(tarball_request).and_then(|response| async move { - response.bytes().await - }).await { - Ok(response) => response, - Err(e) => return format_error("Failed to download NodeCG", e) - }; + logger.emit(&format!("Downloading NodeCG {}...", latest_version)); + let tarball = client.get(tarball_url).send().await?.bytes().await?; logger.emit_progress(2); logger.emit("Extracting archive..."); - let gz = GzDecoder::new(tarball_response.data.as_slice()); + let gz = GzDecoder::new(tarball.iter().as_slice()); let mut archive = Archive::new(gz); let base_unpack_path = Path::new(&path); match archive.entries().map(|entries| { @@ -141,25 +125,23 @@ pub async fn install_nodecg(handle: tauri::AppHandle, path: String) -> Result<() } }); if has_err { - return Err("Received one or more errors unpacking NodeCG archive".to_string()) + return Err(Error::NodeCGInstall("Received one or more errors unpacking NodeCG archive".to_string())) } }, - Err(e) => return format_error("Failed to unpack archive", e) + Err(e) => return Err(Error::Io(e)) } logger.emit_progress(3); - match npm::install_npm_dependencies(&path).and_then(|child| { + let shell = handle.shell(); + npm::install_npm_dependencies(shell, &path).and_then(|child| { log_npm_install(logger, child); Ok(()) - }) { - Err(e) => format_error("Failed to install NodeCG dependencies", e), - Ok(_) => Ok(()) - } + }) } #[tauri::command(async)] -pub fn start_nodecg(handle: tauri::AppHandle, nodecg: tauri::State<'_, ManagedNodecg>, path: String) -> Result { - let logger = LogEmitter::new(handle, "run-nodecg"); +pub fn start_nodecg(handle: AppHandle, nodecg: tauri::State<'_, ManagedNodecg>, path: String) -> Result { + let logger = LogEmitter::new(&handle, "run-nodecg"); let output = unwrap_ok_or!(nodecg.start(&path), e, { return format_error("Failed to start NodeCG", e) }); emit_tauri_process_output(logger, output); @@ -168,7 +150,7 @@ pub fn start_nodecg(handle: tauri::AppHandle, nodecg: tauri::State<'_, ManagedNo #[tauri::command(async)] pub fn stop_nodecg(handle: tauri::AppHandle, nodecg: tauri::State) -> Result<(), String> { - let logger = LogEmitter::new(handle, "run-nodecg"); + let logger = LogEmitter::new(&handle, "run-nodecg"); match nodecg.stop() { Ok(_) => { diff --git a/src-tauri/src/npm.rs b/src-tauri/src/npm.rs index 5ad43ca..ab0bafb 100644 --- a/src-tauri/src/npm.rs +++ b/src-tauri/src/npm.rs @@ -1,7 +1,10 @@ use std::collections::HashMap; use std::path::PathBuf; -use tauri::api::process::{Command, CommandEvent}; +use tauri_plugin_shell::process::CommandEvent; use tauri::async_runtime::Receiver; +use tauri::Wry; +use tauri_plugin_shell::Shell; +use crate::error::Error; #[derive(serde::Deserialize)] pub struct NPMPackageMetadata { @@ -21,25 +24,25 @@ pub struct NPMPackageVersionDist { } #[cfg(target_os = "windows")] -pub fn install_npm_dependencies(path: &str) -> Result, String> { - let command = Command::new("cmd") +pub fn install_npm_dependencies(shell: &Shell, path: &str) -> Result, Error> { + let command = shell.command("cmd") .args(["/c", "npm", "i", "--omit=dev", "--no-progress"]) .current_dir(PathBuf::from(path)) .spawn(); match command { Ok(cmd) => Ok(cmd.0), - Err(e) => Err(format!("Failed to spawn npm process: {}", e.to_string())) + Err(e) => Err(Error::NPMInstall(e.to_string())) } } #[cfg(not(target_os = "windows"))] -pub fn install_npm_dependencies(path: &str) -> Result, String> { - let command = Command::new("npm") +pub fn install_npm_dependencies(shell: &Shell, path: &str) -> Result, Error> { + let command = shell.command("npm") .args(["i", "--omit=dev", "--no-progress"]) .current_dir(PathBuf::from(path)) .spawn(); match command { Ok(cmd) => Ok(cmd.0), - Err(e) => Err(format!("Failed to spawn npm process: {}", e.to_string())) + Err(e) => Err(Error::NPMInstall(e.to_string())) } } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index be9205f..87ca593 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,55 +1,48 @@ { - "package": { - "productName": "NCGMGR", - "version": "0.7.0" + "bundle": { + "active": true, + "targets": "all", + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": "sha256", + "timestampUrl": "" + }, + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "resources": [], + "externalBin": [], + "copyright": "© inkfarer (inkfarer@inkfarer.com)", + "category": "Utility", + "shortDescription": "NCGMGR", + "longDescription": "Helps manage NodeCG installations.", + "macOS": { + "frameworks": [] + }, + "linux": { + "deb": { + "depends": [] + } + } }, "build": { - "distDir": "../dist", - "devPath": "http://localhost:5173", + "beforeBuildCommand": "yarn build", + "frontendDist": "../dist", "beforeDevCommand": "yarn dev", - "beforeBuildCommand": "yarn build" + "devUrl": "http://localhost:5173" }, - "tauri": { + "productName": "NCGMGR", + "version": "0.7.0", + "identifier": "com.inkfarer.ncgmgr", + "plugins": {}, + "app": { "macOSPrivateApi": true, - "bundle": { - "active": true, - "targets": "all", - "identifier": "com.inkfarer.ncgmgr", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "resources": [], - "externalBin": [], - "copyright": "© inkfarer (inkfarer@inkfarer.com)", - "category": "Utility", - "shortDescription": "NCGMGR", - "longDescription": "Helps manage NodeCG installations.", - "deb": { - "depends": [] - }, - "macOS": { - "frameworks": [] - }, - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "" - } - }, - "updater": { - "active": false - }, - "allowlist": { - "all": true, - "fs": { - "scope": [ - "$HOME/**/*" - ] - } + "security": { + "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'; connect-src ipc: http://ipc.localhost" }, "windows": [ { @@ -61,9 +54,6 @@ "fullscreen": false, "titleBarStyle": "Transparent" } - ], - "security": { - "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'" - } + ] } -} +} \ No newline at end of file diff --git a/src/__mocks__/setup.ts b/src/__mocks__/setup.ts new file mode 100644 index 0000000..db3cb49 --- /dev/null +++ b/src/__mocks__/setup.ts @@ -0,0 +1,3 @@ +import { TextEncoder, TextDecoder } from 'util' + +Object.assign(global, { TextDecoder, TextEncoder }) diff --git a/src/__mocks__/tauri.ts b/src/__mocks__/tauri.ts index dc76ba5..d2db324 100644 --- a/src/__mocks__/tauri.ts +++ b/src/__mocks__/tauri.ts @@ -8,33 +8,33 @@ export const mockTauri = { invoke: jest.fn() } -jest.mock('@tauri-apps/api/tauri', () => mockTauri) +jest.mock('@tauri-apps/api/core', () => mockTauri) export const mockTauriDialog = { open: jest.fn() } -jest.mock('@tauri-apps/api/dialog', () => mockTauriDialog) +jest.mock('@tauri-apps/plugin-dialog', () => mockTauriDialog) export const mockTauriFs = { readDir: jest.fn(), readTextFile: jest.fn(), removeDir: jest.fn(), - removeFile: jest.fn(), - createDir: jest.fn(), + remove: jest.fn(), + mkdir: jest.fn(), writeFile: jest.fn() } -jest.mock('@tauri-apps/api/fs', () => mockTauriFs) +jest.mock('@tauri-apps/plugin-fs', () => mockTauriFs) export const mockTauriOs = { type: jest.fn() } -jest.mock('@tauri-apps/api/os', () => mockTauriOs) +jest.mock('@tauri-apps/plugin-os', () => mockTauriOs) export const mockTauriShell = { open: jest.fn() } -jest.mock('@tauri-apps/api/shell', () => mockTauriShell) +jest.mock('@tauri-apps/plugin-shell', () => mockTauriShell) diff --git a/src/components/BundleInstaller.vue b/src/components/BundleInstaller.vue index 64f34c3..5ed8949 100644 --- a/src/components/BundleInstaller.vue +++ b/src/components/BundleInstaller.vue @@ -25,7 +25,7 @@ diff --git a/src/components/InstallManager.vue b/src/components/InstallManager.vue index b0958a0..5522b24 100644 --- a/src/components/InstallManager.vue +++ b/src/components/InstallManager.vue @@ -3,22 +3,10 @@ class="layout vertical" color="secondary" > -
Installation folder: {{ installFolder }}
- - {{ nodecgStatusMessage }} - -
- +
@@ -72,14 +60,11 @@ diff --git a/src/components/InstallManager.vue b/src/components/InstallManager.vue index 5522b24..7c623d7 100644 --- a/src/components/InstallManager.vue +++ b/src/components/InstallManager.vue @@ -80,7 +80,7 @@ export default defineComponent({ const nodecgStore = useNodecgStore() const showLog = ref(false) - const installFolder = computed(() => config.userConfig.nodecgInstallPath) + const installFolder = computed(() => config.userConfig.nodecgInstallDir) const nodecgStatus = computed(() => nodecgStore.status.installStatus) onMounted(() => { diff --git a/src/components/bundleList/BundleConfig.vue b/src/components/bundleList/BundleConfig.vue index ff54dc6..e00d2f2 100644 --- a/src/components/bundleList/BundleConfig.vue +++ b/src/components/bundleList/BundleConfig.vue @@ -118,7 +118,7 @@ export default defineComponent({ async function checkConfigFile (bundleName: string): Promise { configFileLoading.value = true hasConfigFile.value = false - configFileExists(bundleName, configStore.userConfig.nodecgInstallPath).then(result => { + configFileExists(bundleName, configStore.userConfig.nodecgInstallDir).then(result => { hasConfigFile.value = result }).catch(e => { hasConfigFile.value = false @@ -129,7 +129,7 @@ export default defineComponent({ } function getBundlePath () { - return `${configStore.userConfig.nodecgInstallPath}/bundles/${props.bundle.name}` + return `${configStore.userConfig.nodecgInstallDir}/bundles/${props.bundle.name}` } return { @@ -168,11 +168,11 @@ export default defineComponent({ }, async openOrCreateConfigFile () { if (!hasConfigFile.value) { - await createConfigFile(props.bundle.name, configStore.userConfig.nodecgInstallPath) + await createConfigFile(props.bundle.name, configStore.userConfig.nodecgInstallDir) checkConfigFile(props.bundle.name) } - await openConfigFile(props.bundle.name, configStore.userConfig.nodecgInstallPath) + await openConfigFile(props.bundle.name, configStore.userConfig.nodecgInstallDir) }, async openBundleInTerminal () { await invoke('open_path_in_terminal', { path: getBundlePath() }) diff --git a/src/components/bundleList/BundleList.vue b/src/components/bundleList/BundleList.vue index 6d9b359..da9c924 100644 --- a/src/components/bundleList/BundleList.vue +++ b/src/components/bundleList/BundleList.vue @@ -117,7 +117,7 @@ export default defineComponent({ }, doUninstall: async () => { try { - await removeBundle(uninstallOverlayProps.bundleName, configStore.userConfig.nodecgInstallPath) + await removeBundle(uninstallOverlayProps.bundleName, configStore.userConfig.nodecgInstallDir) uninstallOverlayProps.visible = false } finally { nodecgStore.getBundleList() diff --git a/src/store/configStore.ts b/src/store/configStore.ts index 799ecd9..deaa98e 100644 --- a/src/store/configStore.ts +++ b/src/store/configStore.ts @@ -4,17 +4,16 @@ import { Store } from '@tauri-apps/plugin-store' import { readonly, ref } from 'vue' import { invoke } from '@tauri-apps/api/core' -export const LOCAL_STORAGE_CONFIG_KEY = 'config' const STORE_CONFIG_KEY = 'config' export interface Configuration { - nodecgInstallPath: string | null + nodecgInstallDir: string | null enableErrorLog: boolean } export const useConfigStore = defineStore('config', () => { const userConfig = ref({ - nodecgInstallPath: null, + nodecgInstallDir: null, enableErrorLog: false }) let store: Store diff --git a/src/store/nodecgStore.ts b/src/store/nodecgStore.ts index c18c302..89fbe9a 100644 --- a/src/store/nodecgStore.ts +++ b/src/store/nodecgStore.ts @@ -43,7 +43,7 @@ export const useNodecgStore = defineStore('nodecg', { this.status.message = 'Checking status...' try { - const { status, message } = await getNodecgStatus(configStore.userConfig.nodecgInstallPath) + const { status, message } = await getNodecgStatus(configStore.userConfig.nodecgInstallDir) this.status.message = message this.status.installStatus = status if (status === InstallStatus.INSTALLED) { @@ -61,7 +61,7 @@ export const useNodecgStore = defineStore('nodecg', { const configStore = useConfigStore() this.status.bundlesLoading = true try { - this.bundles = await getBundles(configStore.userConfig.nodecgInstallPath) + this.bundles = await getBundles(configStore.userConfig.nodecgInstallDir) } finally { this.status.bundlesLoading = false } From 1165fc67a26bb25380c6b042ed57399d761deeb6 Mon Sep 17 00:00:00 2001 From: inkfarer Date: Sun, 7 Apr 2024 10:28:04 +0300 Subject: [PATCH 16/28] Make the logic for determining if a path can be opened in a terminal reusable --- src/components/bundleList/BundleConfig.vue | 10 ++-------- src/store/configStore.ts | 7 +++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/bundleList/BundleConfig.vue b/src/components/bundleList/BundleConfig.vue index e00d2f2..d6593d1 100644 --- a/src/components/bundleList/BundleConfig.vue +++ b/src/components/bundleList/BundleConfig.vue @@ -36,7 +36,7 @@ /> @@ -62,7 +62,6 @@ import { useLogStore } from '@/store/logStore' import { invoke } from '@tauri-apps/api/core' import { useNodecgStore } from '@/store/nodecgStore' import { open } from '@tauri-apps/plugin-shell' -import { type } from '@tauri-apps/plugin-os' export default defineComponent({ name: 'BundleConfig', @@ -88,11 +87,6 @@ export default defineComponent({ const showInstallLog = ref(false) const hasConfigFile = ref(false) const configFileLoading = ref(true) - const enableOpenTerminal = ref(false) - - type().then(type => { - enableOpenTerminal.value = type === 'macos' || type === 'windows' - }) watch(showInstallLog, newValue => { if (!newValue) { @@ -133,7 +127,7 @@ export default defineComponent({ } return { - enableOpenTerminal, + configStore, hasConfigFile, configFileLoading, showInstallLog, diff --git a/src/store/configStore.ts b/src/store/configStore.ts index deaa98e..d516e3e 100644 --- a/src/store/configStore.ts +++ b/src/store/configStore.ts @@ -3,6 +3,7 @@ import { appConfigDir } from '@tauri-apps/api/path' import { Store } from '@tauri-apps/plugin-store' import { readonly, ref } from 'vue' import { invoke } from '@tauri-apps/api/core' +import { type } from '@tauri-apps/plugin-os' const STORE_CONFIG_KEY = 'config' @@ -16,6 +17,7 @@ export const useConfigStore = defineStore('config', () => { nodecgInstallDir: null, enableErrorLog: false }) + const allowOpenInTerminal = ref(false) let store: Store async function init() { @@ -32,6 +34,10 @@ export const useConfigStore = defineStore('config', () => { userConfig.value = newValue } }) + + await type().then(type => { + allowOpenInTerminal.value = type === 'macos' || type === 'windows' + }) } async function patch(values: Partial) { @@ -45,6 +51,7 @@ export const useConfigStore = defineStore('config', () => { return { userConfig: readonly(userConfig), + allowOpenInTerminal: readonly(allowOpenInTerminal), init, patch } From 8e3e45890e272bfa26c52e69112b400bfea24608 Mon Sep 17 00:00:00 2001 From: inkfarer Date: Sun, 7 Apr 2024 10:29:14 +0300 Subject: [PATCH 17/28] Minor layout tweak --- src/components/log/LogOverlay.vue | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/log/LogOverlay.vue b/src/components/log/LogOverlay.vue index e554d00..831461a 100644 --- a/src/components/log/LogOverlay.vue +++ b/src/components/log/LogOverlay.vue @@ -25,10 +25,7 @@ class="m-t-8 max-width" color="secondary" > - +
From 322692dd205e632c1e348fae4e7b06d49b50e0e5 Mon Sep 17 00:00:00 2001 From: inkfarer Date: Sun, 7 Apr 2024 10:34:44 +0300 Subject: [PATCH 18/28] Redo the app's setup process; Allow installing NodeCG to an automatically defined application data directory --- src-tauri/src/config.rs | 6 + src-tauri/src/error.rs | 4 + src-tauri/src/nodecg.rs | 23 +- src/App.vue | 36 ++- src/components/ConfigWindow.vue | 8 +- .../InitialInstallDirectorySetup.vue | 239 ++++++++++++++++++ src/components/InstallDirectoryConfig.vue | 38 +++ .../{InstallManager.vue => NodecgStarter.vue} | 40 +-- ...stallFolderConfig.vue => NodecgStatus.vue} | 73 +++--- src/components/mgr/MgrOverlay.vue | 4 + src/components/statusBar/StatusBar.vue | 6 +- src/main.ts | 3 + src/service/nodecgService.ts | 19 +- src/store/nodecgStore.ts | 6 +- src/styles/window.scss | 1 + 15 files changed, 405 insertions(+), 101 deletions(-) create mode 100644 src/components/InitialInstallDirectorySetup.vue create mode 100644 src/components/InstallDirectoryConfig.vue rename src/components/{InstallManager.vue => NodecgStarter.vue} (69%) rename src/components/{InstallFolderConfig.vue => NodecgStatus.vue} (57%) diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index f8c568f..37ebeef 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -62,6 +62,12 @@ pub fn with_config tauri_plugin_store::R }) } +pub fn update_install_dir(app: AppHandle, install_dir: String) -> Result<(), Error> { + let mut config = with_config(app.clone(), |c| Ok(c))?; + config.nodecg_install_dir = Some(install_dir); + update_config(app, config) +} + #[tauri::command] pub fn update_config(app: AppHandle, config: UserConfig) -> Result<(), Error> { with_config_store(app, |store| { diff --git a/src-tauri/src/error.rs b/src-tauri/src/error.rs index d060498..e9821cf 100644 --- a/src-tauri/src/error.rs +++ b/src-tauri/src/error.rs @@ -16,6 +16,8 @@ pub enum Error { TauriShell(#[from] tauri_plugin_shell::Error), #[error(transparent)] Git(#[from] git2::Error), + #[error(transparent)] + RmRf(#[from] rm_rf::Error), #[error("Error installing NodeCG: {0}")] NodeCGInstall(String), @@ -23,6 +25,8 @@ pub enum Error { NodeCGLaunch(String), #[error("NodeCG install directory is not configured")] MissingInstallDir, + #[error("Could not determine default install directory for NodeCG. Please select one manually.")] + CannotCreateDefaultInstallDir, #[error("Bundle {0} is not installed.")] MissingBundle(String), #[error("Failed to uninstall bundle {0}: {1}")] diff --git a/src-tauri/src/nodecg.rs b/src-tauri/src/nodecg.rs index 15a794d..f208228 100644 --- a/src-tauri/src/nodecg.rs +++ b/src-tauri/src/nodecg.rs @@ -5,7 +5,7 @@ use std::sync::Mutex; use sysinfo::{Pid, ProcessRefreshKind, RefreshKind, System}; use tar::Archive; use tauri::async_runtime::Receiver; -use tauri::AppHandle; +use tauri::{AppHandle, Manager}; use tauri_plugin_http::reqwest; use tauri_plugin_shell::process::{CommandChild, CommandEvent}; use tauri_plugin_shell::ShellExt; @@ -75,10 +75,27 @@ impl ManagedNodecg { } #[tauri::command(async)] -pub async fn install_nodecg(handle: AppHandle) -> Result<(), Error> { +pub async fn install_nodecg(handle: AppHandle, use_default_directory: bool) -> Result<(), Error> { let logger = LogEmitter::with_progress(&handle, "install-nodecg", 4); + let install_dir = if use_default_directory { + handle.path().app_local_data_dir() + .map_err(|_| Error::CannotCreateDefaultInstallDir)? + .join("nodecg") + .to_str() + .ok_or(Error::CannotCreateDefaultInstallDir)? + .to_string() + } else { + config::with_config(handle.clone(), |c| Ok(c.nodecg_install_dir))?.ok_or(Error::MissingInstallDir)? + }; + logger.emit("Starting NodeCG install..."); + if use_default_directory { + let install_dir_path = Path::new(&install_dir); + rm_rf::ensure_removed(install_dir_path)?; + fs::create_dir_all(install_dir_path)?; + config::update_install_dir(handle.clone(), install_dir.clone())?; + } logger.emit("Loading version list..."); let client = reqwest::Client::builder().build()?; @@ -117,8 +134,6 @@ pub async fn install_nodecg(handle: AppHandle) -> Result<(), Error> { logger.emit("Extracting archive..."); let gz = GzDecoder::new(tarball.iter().as_slice()); let mut archive = Archive::new(gz); - let install_dir = config::with_config(handle.clone(), |c| Ok(c.nodecg_install_dir))? - .ok_or(Error::MissingInstallDir)?; match archive.entries().map(|entries| { entries .filter_map(|e| e.ok()) diff --git a/src/App.vue b/src/App.vue index fe9cb26..13dabc5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -6,34 +6,52 @@ > Please install Node.js to continue. - - + + + + diff --git a/src/components/InstallDirectoryConfig.vue b/src/components/InstallDirectoryConfig.vue new file mode 100644 index 0000000..35a8e3e --- /dev/null +++ b/src/components/InstallDirectoryConfig.vue @@ -0,0 +1,38 @@ + + + diff --git a/src/components/InstallManager.vue b/src/components/NodecgStarter.vue similarity index 69% rename from src/components/InstallManager.vue rename to src/components/NodecgStarter.vue index 7c623d7..32ce62b 100644 --- a/src/components/InstallManager.vue +++ b/src/components/NodecgStarter.vue @@ -5,19 +5,10 @@ >
- - diff --git a/src/components/mgr/MgrOverlay.vue b/src/components/mgr/MgrOverlay.vue index ca284b6..84cc648 100644 --- a/src/components/mgr/MgrOverlay.vue +++ b/src/components/mgr/MgrOverlay.vue @@ -79,6 +79,10 @@ export default defineComponent({ background-color: rgba(0, 0, 0, 0.5); + &.fixed-width .mgr-overlay__content { + max-width: 400px; + } + .mgr-overlay__content { max-width: 90%; max-height: 80%; diff --git a/src/components/statusBar/StatusBar.vue b/src/components/statusBar/StatusBar.vue index b2678fe..e82cae6 100644 --- a/src/components/statusBar/StatusBar.vue +++ b/src/components/statusBar/StatusBar.vue @@ -22,6 +22,7 @@
- +
diff --git a/src/main.ts b/src/main.ts index 8636dd8..cb5a1a1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,7 @@ import { createPinia } from 'pinia' import { setUpErrorHandler } from '@/store/errorHandlerStore' import { useConfigStore } from '@/store/configStore' import { useDependencyStore } from '@/store/dependencyStore' +import { useNodecgStore } from '@/store/nodecgStore' function setColorTheme(useLightMode: boolean) { if (useLightMode) { @@ -28,6 +29,8 @@ function setColorTheme(useLightMode: boolean) { await configStore.init() const dependencyStore = useDependencyStore() await dependencyStore.checkVersions() + const nodecgStore = useNodecgStore() + await nodecgStore.checkNodecgStatus() setUpErrorHandler(app) diff --git a/src/service/nodecgService.ts b/src/service/nodecgService.ts index 1479dfc..3b67a99 100644 --- a/src/service/nodecgService.ts +++ b/src/service/nodecgService.ts @@ -6,11 +6,16 @@ import { invoke } from '@tauri-apps/api/core' import { fileExists, folderExists } from '@/util/fs' import { open } from '@tauri-apps/plugin-shell' import { NodecgConfiguration } from '@/types/nodecg' +import { appLocalDataDir } from '@tauri-apps/api/path' + +export async function getDefaultInstallDir (): Promise { + return `${await appLocalDataDir()}/nodecg` +} export async function getNodecgStatus (directory: string | null): Promise<{ status: InstallStatus, message: string }> { if (directory == null || isEmpty(directory?.trim())) { return { - status: InstallStatus.UNABLE_TO_INSTALL, + status: InstallStatus.MISSING_INSTALL_DIRECTORY, message: 'Please select an installation directory.' } } @@ -32,14 +37,14 @@ export async function getNodecgStatus (directory: string | null): Promise<{ stat } } else { return { - status: InstallStatus.UNABLE_TO_INSTALL, + status: InstallStatus.BAD_INSTALL_DIRECTORY, message: `Found unknown package "${packageJson.name}".` } } } else { return { - status: InstallStatus.UNABLE_TO_INSTALL, - message: 'Could not find package.json.' + status: InstallStatus.BAD_INSTALL_DIRECTORY, + message: 'Selected install directory is not empty, but NodeCG is not installed here.' } } } @@ -65,7 +70,7 @@ export async function getBundles (directory: string | null): Promise { return { name: packageJson.name, version: packageJson.version == null || packageJson.version.trim() === '0.0.0' - ? await getBundleGitTag(packageJson.name, directory) + ? await getBundleGitTag(packageJson.name) : packageJson.version } } catch (e) { @@ -132,6 +137,6 @@ export async function openDashboard (nodecgPath: string): Promise { return open(`http://localhost:${config?.port ?? '9090'}/dashboard`) } -export async function getBundleGitTag (bundleName: string, nodecgPath: string): Promise { - return invoke('get_bundle_git_tag', { bundleName, nodecgPath }) +export async function getBundleGitTag (bundleName: string): Promise { + return invoke('get_bundle_git_tag', { bundleName }) } diff --git a/src/store/nodecgStore.ts b/src/store/nodecgStore.ts index 89fbe9a..d839d47 100644 --- a/src/store/nodecgStore.ts +++ b/src/store/nodecgStore.ts @@ -7,7 +7,9 @@ export enum InstallStatus { UNKNOWN, READY_TO_INSTALL, INSTALLED, - UNABLE_TO_INSTALL + UNABLE_TO_INSTALL, + MISSING_INSTALL_DIRECTORY, + BAD_INSTALL_DIRECTORY } export enum RunStatus { @@ -39,8 +41,6 @@ export const useNodecgStore = defineStore('nodecg', { actions: { async checkNodecgStatus () { const configStore = useConfigStore() - this.status.installStatus = InstallStatus.UNKNOWN - this.status.message = 'Checking status...' try { const { status, message } = await getNodecgStatus(configStore.userConfig.nodecgInstallDir) diff --git a/src/styles/window.scss b/src/styles/window.scss index 0919285..ea9cf10 100644 --- a/src/styles/window.scss +++ b/src/styles/window.scss @@ -10,6 +10,7 @@ body { font-family: 'Roboto', sans-serif; color: var(--ipl-body-text-color); padding: 12px 8px; + margin: 0; background-color: var(--ipl-bg-primary); overflow-y: scroll; } From 06896758ecaf3f09e03e0aeb5eb523941143d0a0 Mon Sep 17 00:00:00 2001 From: inkfarer Date: Sun, 7 Apr 2024 11:34:48 +0300 Subject: [PATCH 19/28] Remove the app name from git release tags --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4df91a7..eeb65fb 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tagName: ncgmgr-v__VERSION__ + tagName: v__VERSION__ releaseName: "NCGMGR v__VERSION__" releaseDraft: true prerelease: false From 648d3784ad1a2095fabe62f1b8e67d7502a45b12 Mon Sep 17 00:00:00 2001 From: inkfarer Date: Sun, 7 Apr 2024 11:50:24 +0300 Subject: [PATCH 20/28] Edit the user's guide to reflect changes to first-time setup --- docs/img/bundle-management.jpg | Bin 72822 -> 0 bytes docs/img/first-install.png | Bin 0 -> 137926 bytes docs/img/main-view.png | Bin 0 -> 170820 bytes docs/img/missing-nodejs-warning.png | Bin 56355 -> 31718 bytes docs/img/select-install-directory.png | Bin 59182 -> 0 bytes docs/img/settings.png | Bin 0 -> 149772 bytes docs/users-guide.md | 49 ++++++++++++++++---------- src/components/NodecgStatus.vue | 2 +- 8 files changed, 31 insertions(+), 20 deletions(-) delete mode 100644 docs/img/bundle-management.jpg create mode 100644 docs/img/first-install.png create mode 100644 docs/img/main-view.png delete mode 100644 docs/img/select-install-directory.png create mode 100644 docs/img/settings.png diff --git a/docs/img/bundle-management.jpg b/docs/img/bundle-management.jpg deleted file mode 100644 index ce5aff54bae26c4c1ab601c880d8d4ebc9b4b950..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72822 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