From 67820a02ca2d87922a4d697c89dbeaea7f6632c9 Mon Sep 17 00:00:00 2001 From: thewh1teagle <61390950+thewh1teagle@users.noreply.github.com> Date: Fri, 17 Jan 2025 05:37:43 +0200 Subject: [PATCH] Feat/keepawake (#481) * bump version to 3.0.1 in tauri configuration * feat: keep system awake * feat: add Vulkan runtime to resources and refactor wget calls for platform compatibility * feat: enhance wget command with progress bar and retry options * refactor: remove unused file associations from tauri configuration * feat: add function to clean updater files and integrate it into setup process * fix: update app info logging to use the correct utility function * style: update globals.css for print styling and remove header/footer margins * chore: update tauri-plugin-keepawake to version 0.1.1 * fix: improve error handling in download_audio by using map_while for stderr output * style: refine print styles in globals.css and improve button formatting in pdf * refactor: remove unnecessary console logs related to keep awake functionality * fix: don't use transparent effect on linux with settings * style: enhance print styles to prevent blank pages and support dark/light mode * fix: simplify default device checks using is_ok_and for better readability * style: improve print styles for dark/light mode and prevent blank pages --- Cargo.lock | 602 ++++++++++++++++++++--- desktop/bun.lockb | Bin 184259 -> 184719 bytes desktop/package.json | 5 +- desktop/src-tauri/Cargo.toml | 1 + desktop/src-tauri/capabilities/main.json | 116 ++--- desktop/src-tauri/src/cleaner.rs | 27 + desktop/src-tauri/src/cmd/audio.rs | 4 +- desktop/src-tauri/src/cmd/ytdlp.rs | 2 +- desktop/src-tauri/src/main.rs | 1 + desktop/src-tauri/src/setup.rs | 2 + desktop/src-tauri/tauri.conf.json | 30 +- desktop/src/components/SettingsModal.tsx | 4 +- desktop/src/globals.css | 60 ++- desktop/src/lib/utils.ts | 17 + desktop/src/pages/batch/viewModel.tsx | 7 +- desktop/src/pages/home/Page.tsx | 8 +- desktop/src/pages/home/viewModel.ts | 7 +- scripts/pre_build.js | 37 +- 18 files changed, 745 insertions(+), 185 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e1266ed..6d95a4ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,6 +133,43 @@ version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +[[package]] +name = "apple-bindgen" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f109ee76f68b4767848cb5dc93bfcc7c425deca849c4c81fa11cdce525e3d2" +dependencies = [ + "apple-sdk", + "bindgen 0.63.0", + "derive_more", + "regex", + "serde", + "thiserror 1.0.69", + "toml 0.6.0", +] + +[[package]] +name = "apple-sdk" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a04f192a700686ee70008ff4e4eb76fe7d11814ab93b7ee9d48c36b9a9f0bd2a" +dependencies = [ + "plist", + "serde", + "serde_json", +] + +[[package]] +name = "apple-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b3a1c3342678cd72676d0c1644fde496c1f65ea41f51465f54a89cad3bdf34" +dependencies = [ + "apple-bindgen", + "apple-sdk", + "objc", +] + [[package]] name = "arbitrary" version = "1.4.1" @@ -187,7 +224,17 @@ dependencies = [ "wayland-backend", "wayland-client", "wayland-protocols", - "zbus", + "zbus 4.0.1", +] + +[[package]] +name = "async-broadcast" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener 2.5.3", + "futures-core", ] [[package]] @@ -196,7 +243,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" dependencies = [ - "event-listener", + "event-listener 5.3.1", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -222,20 +269,52 @@ checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "fastrand 2.2.0", + "futures-lite 2.5.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-fs" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" dependencies = [ - "async-lock", + "async-lock 3.4.0", "blocking", - "futures-lite", + "futures-lite 2.5.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.28", + "slab", + "socket2 0.4.10", + "waker-fn", ] [[package]] @@ -244,30 +323,56 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ - "async-lock", + "async-lock 3.4.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite", + "futures-lite 2.5.0", "parking", - "polling", - "rustix", + "polling 3.7.4", + "rustix 0.38.40", "slab", "tracing", "windows-sys 0.59.0", ] +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + [[package]] name = "async-lock" version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener", + "event-listener 5.3.1", "event-listener-strategy", "pin-project-lite", ] +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.40", + "windows-sys 0.48.0", +] + [[package]] name = "async-process" version = "2.3.0" @@ -275,15 +380,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel", - "async-io", - "async-lock", + "async-io 2.4.0", + "async-lock 3.4.0", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener", - "futures-lite", - "rustix", + "event-listener 5.3.1", + "futures-lite 2.5.0", + "rustix 0.38.40", "tracing", ] @@ -304,13 +409,13 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io", - "async-lock", + "async-io 2.4.0", + "async-lock 3.4.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix", + "rustix 0.38.40", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -450,6 +555,28 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bindgen" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 1.0.109", + "which 4.4.2", +] + [[package]] name = "bindgen" version = "0.69.5" @@ -539,7 +666,7 @@ dependencies = [ "async-channel", "async-task", "futures-io", - "futures-lite", + "futures-lite 2.5.0", "piper", ] @@ -768,7 +895,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.1", ] [[package]] @@ -1157,14 +1284,38 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + [[package]] name = "darling" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.10", + "darling_macro 0.20.10", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", ] [[package]] @@ -1177,17 +1328,28 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.11.1", "syn 2.0.87", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core", + "darling_core 0.20.10", "quote", "syn 2.0.87", ] @@ -1236,6 +1398,37 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "derive_builder" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f59169f400d8087f238c5c0c7db6a28af18681717f3b623227d92f397e938c7" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ec317cc3e7ef0928b0ca6e4a634a4d6c001672ae210438cf114a83e56b018d" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870368c3fb35b8031abb378861d4460f573b92238ec2152c927a21f77e3e0127" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -1303,7 +1496,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.7.4", + "libloading 0.8.5", ] [[package]] @@ -1483,6 +1676,23 @@ version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "event-listener" version = "5.3.1" @@ -1500,7 +1710,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener", + "event-listener 5.3.1", "pin-project-lite", ] @@ -1524,6 +1734,15 @@ dependencies = [ "serde", ] +[[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.2.0" @@ -1692,13 +1911,28 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[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.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ - "fastrand", + "fastrand 2.2.0", "futures-core", "futures-io", "parking", @@ -1880,7 +2114,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" dependencies = [ - "rustix", + "rustix 0.38.40", "windows-targets 0.52.6", ] @@ -2276,7 +2510,7 @@ dependencies = [ "httpdate", "itoa 1.0.11", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -2348,7 +2582,7 @@ dependencies = [ "http-body 1.0.1", "hyper 1.5.0", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -2601,6 +2835,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipnet" version = "2.10.1" @@ -2753,6 +2998,21 @@ dependencies = [ "serde_json", ] +[[package]] +name = "keepawake" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a1e324a09aa048770b565b4ab2970bb9d1a7dac1038c68c2d243d8f7b6b1c90" +dependencies = [ + "apple-sys", + "cfg-if", + "core-foundation 0.9.4", + "derive_builder", + "thiserror 1.0.69", + "windows 0.52.0", + "zbus 3.15.1", +] + [[package]] name = "keyboard-types" version = "0.7.0" @@ -2881,6 +3141,12 @@ dependencies = [ "redox_syscall", ] +[[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.14" @@ -3210,6 +3476,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3831,6 +4106,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -3990,7 +4271,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand", + "fastrand 2.2.0", "futures-io", ] @@ -4026,6 +4307,22 @@ 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.7.4" @@ -4036,7 +4333,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix", + "rustix 0.38.40", "tracing", "windows-sys 0.59.0", ] @@ -4103,7 +4400,7 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" dependencies = [ - "toml_datetime", + "toml_datetime 0.6.3", "toml_edit 0.20.2", ] @@ -4205,7 +4502,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.0.0", "rustls", - "socket2", + "socket2 0.5.7", "thiserror 1.0.69", "tokio", "tracing", @@ -4237,7 +4534,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.5.7", "tracing", "windows-sys 0.59.0", ] @@ -4632,6 +4929,20 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.37.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.40" @@ -4641,7 +4952,7 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] @@ -4974,7 +5285,7 @@ version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ - "darling", + "darling 0.20.10", "proc-macro2", "quote", "syn 2.0.87", @@ -5132,6 +5443,16 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.5.7" @@ -5245,6 +5566,12 @@ dependencies = [ "quote", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.1" @@ -5674,6 +6001,19 @@ dependencies = [ "urlpattern", ] +[[package]] +name = "tauri-plugin-keepawake" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19695262819df92661139c607c5b5449b21ef5fa9429b8cb556e6c55bf34e5cb" +dependencies = [ + "keepawake", + "serde", + "tauri", + "tauri-plugin", + "thiserror 2.0.3", +] + [[package]] name = "tauri-plugin-os" version = "2.0.1" @@ -5735,7 +6075,7 @@ dependencies = [ "tauri", "thiserror 1.0.69", "windows-sys 0.59.0", - "zbus", + "zbus 4.0.1", ] [[package]] @@ -5898,9 +6238,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", - "fastrand", + "fastrand 2.2.0", "once_cell", - "rustix", + "rustix 0.38.40", "windows-sys 0.59.0", ] @@ -6059,7 +6399,7 @@ dependencies = [ "mio", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.7", "tokio-macros", "tracing", "windows-sys 0.52.0", @@ -6110,6 +6450,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb9d890e4dc9298b70f740f615f2e05b9db37dce531f6b24fb77ac993f9f217" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.5.1", + "toml_edit 0.18.1", +] + [[package]] name = "toml" version = "0.7.8" @@ -6118,7 +6470,7 @@ checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.3", "toml_edit 0.19.15", ] @@ -6130,10 +6482,19 @@ checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.3", "toml_edit 0.20.2", ] +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" +dependencies = [ + "serde", +] + [[package]] name = "toml_datetime" version = "0.6.3" @@ -6143,6 +6504,19 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap 1.9.3", + "nom8", + "serde", + "serde_spanned", + "toml_datetime 0.5.1", +] + [[package]] name = "toml_edit" version = "0.19.15" @@ -6152,7 +6526,7 @@ dependencies = [ "indexmap 2.6.0", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.3", "winnow", ] @@ -6165,7 +6539,7 @@ dependencies = [ "indexmap 2.6.0", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.3", "winnow", ] @@ -6611,6 +6985,7 @@ dependencies = [ "tauri-plugin-dialog", "tauri-plugin-fs", "tauri-plugin-http", + "tauri-plugin-keepawake", "tauri-plugin-os", "tauri-plugin-process", "tauri-plugin-shell", @@ -6676,6 +7051,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "walkdir" version = "2.5.0" @@ -6795,7 +7176,7 @@ checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" dependencies = [ "cc", "downcast-rs", - "rustix", + "rustix 0.38.40", "scoped-tls", "smallvec", "wayland-sys", @@ -6808,7 +7189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" dependencies = [ "bitflags 2.6.0", - "rustix", + "rustix 0.38.40", "wayland-backend", "wayland-scanner", ] @@ -6961,7 +7342,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.40", ] [[package]] @@ -6972,7 +7353,7 @@ checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" dependencies = [ "either", "home", - "rustix", + "rustix 0.38.40", "winsafe", ] @@ -7525,7 +7906,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "gethostname 0.4.3", - "rustix", + "rustix 0.38.40", "x11rb-protocol", ] @@ -7542,8 +7923,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", - "linux-raw-sys", - "rustix", + "linux-raw-sys 0.4.14", + "rustix 0.38.40", ] [[package]] @@ -7580,25 +7961,66 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "3.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5acecd3f8422f198b1a2f954bcc812fe89f3fa4281646f3da1da7925db80085d" +dependencies = [ + "async-broadcast 0.5.1", + "async-executor", + "async-fs 1.6.0", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process 1.8.1", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "byteorder", + "derivative", + "enumflags2", + "event-listener 2.5.3", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix 0.26.4", + "once_cell", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "xdg-home", + "zbus_macros 3.15.1", + "zbus_names 2.6.1", + "zvariant 3.15.1", +] + [[package]] name = "zbus" version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" dependencies = [ - "async-broadcast", + "async-broadcast 0.7.1", "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-process", + "async-fs 2.1.2", + "async-io 2.4.0", + "async-lock 3.4.0", + "async-process 2.3.0", "async-recursion", "async-task", "async-trait", "blocking", "derivative", "enumflags2", - "event-listener", + "event-listener 5.3.1", "futures-core", "futures-sink", "futures-util", @@ -7615,9 +8037,23 @@ dependencies = [ "uds_windows", "windows-sys 0.52.0", "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", + "zbus_macros 4.0.1", + "zbus_names 3.0.0", + "zvariant 4.0.0", +] + +[[package]] +name = "zbus_macros" +version = "3.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2207eb71efebda17221a579ca78b45c4c5f116f074eb745c3a172e688ccf89f5" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils", ] [[package]] @@ -7634,6 +8070,17 @@ dependencies = [ "zvariant_utils", ] +[[package]] +name = "zbus_names" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" +dependencies = [ + "serde", + "static_assertions", + "zvariant 3.15.1", +] + [[package]] name = "zbus_names" version = "3.0.0" @@ -7642,7 +8089,7 @@ checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" dependencies = [ "serde", "static_assertions", - "zvariant", + "zvariant 4.0.0", ] [[package]] @@ -7746,6 +8193,20 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "zvariant" +version = "3.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b4fcf3660d30fc33ae5cd97e2017b23a96e85afd7a1dd014534cd0bf34ba67" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive 3.15.1", +] + [[package]] name = "zvariant" version = "4.0.0" @@ -7757,7 +8218,20 @@ dependencies = [ "serde", "static_assertions", "url", - "zvariant_derive", + "zvariant_derive 4.0.0", +] + +[[package]] +name = "zvariant_derive" +version = "3.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0277758a8a0afc0e573e80ed5bfd9d9c2b48bd3108ffe09384f9f738c83f4a55" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils", ] [[package]] diff --git a/desktop/bun.lockb b/desktop/bun.lockb index e68b47f7e35b30dfdc29fb553f54d90423bd8e4a..25959f4e64224c319ca0087c57289e57188d19c5 100755 GIT binary patch delta 31771 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 NR@z$nkox)k{~zLfO&0(F delta 31458 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 diff --git a/desktop/package.json b/desktop/package.json index a12032c4..927e15b0 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -11,6 +11,8 @@ "lint": "eslint ." }, "dependencies": { + "@fontsource/roboto": "^5.1.0", + "@formatjs/intl-durationformat": "^0.6.3", "@tauri-apps/api": "~2.1.1", "@tauri-apps/plugin-clipboard-manager": "~2.0.0", "@tauri-apps/plugin-deep-link": "~2.0.0", @@ -23,8 +25,6 @@ "@tauri-apps/plugin-store": "~2.1.0", "@tauri-apps/plugin-updater": "~2.0.0", "@tauri-apps/plugin-window-state": "~2.0.0", - "@fontsource/roboto": "^5.1.0", - "@formatjs/intl-durationformat": "^0.6.3", "docx": "^9.0.3", "format-duration": "^3.0.2", "i18next": "^23.16.5", @@ -35,6 +35,7 @@ "react-hot-toast": "^2.4.1", "react-i18next": "^15.1.1", "react-router-dom": "^6.28.0", + "tauri-plugin-keepawake-api": "^0.1.0", "usehooks-ts": "^3.1.0", "vite-plugin-svgr": "^4.3.0" }, diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index 81283b00..e743017a 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -25,6 +25,7 @@ tauri-plugin-deep-link = "2" tauri-plugin-store = "2" tauri-plugin-single-instance = "2" tauri-plugin-clipboard-manager = "2" +tauri-plugin-keepawake = "0.1.1" # Unsafe headers required for Ollama (to set Origin) tauri-plugin-http = { version = "2", features = ["unsafe-headers"] } diff --git a/desktop/src-tauri/capabilities/main.json b/desktop/src-tauri/capabilities/main.json index ff7f52bf..2a4e1fa0 100644 --- a/desktop/src-tauri/capabilities/main.json +++ b/desktop/src-tauri/capabilities/main.json @@ -1,12 +1,68 @@ { "$schema": "../gen/schemas/desktop-schema.json", - "identifier": "migrated", - "description": "permissions that were migrated from v1", + "identifier": "default", + "description": "default permissions", "local": true, "windows": [ "main" ], "permissions": [ + "keepawake:allow-start", + "keepawake:allow-stop", + "http:default", + "http:allow-fetch", + "store:allow-set", + "store:allow-get", + "store:allow-has", + "store:allow-reset", + "store:allow-clear", + "store:allow-save", + "store:allow-load", + "store:allow-get-store", + "core:path:default", + "core:event:default", + "core:resources:default", + "core:menu:default", + "core:tray:default", + "fs:allow-remove", + "fs:allow-read-dir", + "fs:allow-read-text-file", + "fs:allow-app-write", + "os:allow-arch", + "os:allow-platform", + "os:allow-version", + "os:allow-os-type", + "os:allow-locale", + "core:window:default", + "core:window:allow-unminimize", + "core:window:allow-set-focus", + "core:window:allow-close", + "core:window:allow-destroy", + "core:window:allow-show", + "core:window:allow-is-visible", + "window-state:allow-restore-state", + "window-state:allow-save-window-state", + "core:webview:default", + "core:webview:allow-print", + "dialog:default", + "dialog:allow-open", + "dialog:allow-save", + "dialog:allow-ask", + "dialog:allow-message", + "process:allow-restart", + "core:app:default", + "core:app:allow-version", + "core:app:allow-name", + "updater:default", + "shell:allow-open", + "shell:allow-execute", + "shell:allow-kill", + "shell:allow-spawn", + "fs:default", + "fs:allow-exists", + "core:path:allow-basename", + "deep-link:allow-get-current", + "clipboard-manager:allow-write-text", { "identifier": "fs:scope", "allow": [ @@ -65,60 +121,6 @@ "url": "http{s}?://localhost:*/*" } ] - }, - "http:default", - "http:allow-fetch", - "store:allow-set", - "store:allow-get", - "store:allow-has", - "store:allow-reset", - "store:allow-clear", - "store:allow-save", - "store:allow-load", - "store:allow-get-store", - "core:path:default", - "core:event:default", - "core:resources:default", - "core:menu:default", - "core:tray:default", - "fs:allow-remove", - "fs:allow-read-dir", - "fs:allow-read-text-file", - "fs:allow-app-write", - "os:allow-arch", - "os:allow-platform", - "os:allow-version", - "os:allow-os-type", - "os:allow-locale", - "core:window:default", - "core:window:allow-unminimize", - "core:window:allow-set-focus", - "core:window:allow-close", - "core:window:allow-destroy", - "core:window:allow-show", - "core:window:allow-is-visible", - "window-state:allow-restore-state", - "window-state:allow-save-window-state", - "core:webview:default", - "core:webview:allow-print", - "dialog:default", - "dialog:allow-open", - "dialog:allow-save", - "dialog:allow-ask", - "dialog:allow-message", - "process:allow-restart", - "core:app:default", - "core:app:allow-version", - "core:app:allow-name", - "updater:default", - "shell:allow-open", - "shell:allow-execute", - "shell:allow-kill", - "shell:allow-spawn", - "fs:default", - "fs:allow-exists", - "core:path:allow-basename", - "deep-link:allow-get-current", - "clipboard-manager:allow-write-text" + } ] } \ No newline at end of file diff --git a/desktop/src-tauri/src/cleaner.rs b/desktop/src-tauri/src/cleaner.rs index 322d4c82..bdc212bd 100644 --- a/desktop/src-tauri/src/cleaner.rs +++ b/desktop/src-tauri/src/cleaner.rs @@ -55,3 +55,30 @@ pub fn clean_old_files() -> Result<()> { } Ok(()) } + +pub fn clean_updater_files() -> Result<()> { + let current_temp_dir = get_vibe_temp_folder(); + let temp_dir = std::env::temp_dir(); + let temp_dir = temp_dir.to_str().unwrap_or_default(); + // Remove suffix + let temp_dir = temp_dir.strip_suffix('/').unwrap_or(temp_dir); + let temp_dir = temp_dir.strip_suffix('\\').unwrap_or(temp_dir); + let pattern = format!("{}/vibe*-updater*", temp_dir); + tracing::debug!("searching old files in {}", pattern); + for path in glob::glob(&pattern)? { + let path = path?; + if path == current_temp_dir { + tracing::debug!("Skip deletion of {}", current_temp_dir.display()); + continue; + } + if path.is_dir() { + tracing::debug!("Clean old folder {}", path.display()); + std::fs::remove_dir_all(&path) + .map_err(|e| eyre!("failed to delete {}: {:?}", path.display(), e)) + .log_error(); + } else { + tracing::debug!("Skipping non-directory path {}", path.display()); + } + } + Ok(()) +} diff --git a/desktop/src-tauri/src/cmd/audio.rs b/desktop/src-tauri/src/cmd/audio.rs index 0e946c97..c54cebf8 100644 --- a/desktop/src-tauri/src/cmd/audio.rs +++ b/desktop/src-tauri/src/cmd/audio.rs @@ -40,11 +40,11 @@ pub fn get_audio_devices() -> Result<Vec<AudioDevice>> { tracing::debug!("Devices: "); for (device_index, device) in devices.enumerate() { let name = device.name()?; - let is_default_in = default_in.as_ref().map_or(false, |d| d == &name); + let is_default_in = default_in.as_ref().is_ok_and(|d| d == &name); let is_default_out = if cfg!(target_os = "macos") { false } else { - default_out.as_ref().map_or(false, |d| d == &name) + default_out.as_ref().is_ok_and(|d| d == &name) }; let is_input = device.default_input_config().is_ok(); diff --git a/desktop/src-tauri/src/cmd/ytdlp.rs b/desktop/src-tauri/src/cmd/ytdlp.rs index 060cd1ed..3ab0abe4 100644 --- a/desktop/src-tauri/src/cmd/ytdlp.rs +++ b/desktop/src-tauri/src/cmd/ytdlp.rs @@ -124,7 +124,7 @@ pub async fn download_audio(app_handle: AppHandle, url: String, out_path: String if let Some(stderr) = child.stderr.take() { stderr_output = BufReader::new(stderr) .lines() - .filter_map(|line| line.ok()) + .map_while(Result::ok) .collect::<Vec<_>>() .join("\n"); eprintln!("Error: {}", stderr_output); diff --git a/desktop/src-tauri/src/main.rs b/desktop/src-tauri/src/main.rs index ff9bf403..ae46120c 100644 --- a/desktop/src-tauri/src/main.rs +++ b/desktop/src-tauri/src/main.rs @@ -64,6 +64,7 @@ fn main() -> Result<()> { .plugin(tauri_plugin_updater::Builder::default().build()) .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_keepawake::init()) .invoke_handler(tauri::generate_handler![ cmd::download_file, cmd::get_cargo_features, diff --git a/desktop/src-tauri/src/setup.rs b/desktop/src-tauri/src/setup.rs index 8db90b71..3596e2f7 100644 --- a/desktop/src-tauri/src/setup.rs +++ b/desktop/src-tauri/src/setup.rs @@ -47,6 +47,7 @@ pub fn setup(app: &App) -> Result<(), Box<dyn std::error::Error>> { crate::logging::setup_logging(app.handle(), store).unwrap(); crate::cleaner::clean_old_logs(app.handle()).log_error(); crate::cleaner::clean_old_files().log_error(); + crate::cleaner::clean_updater_files().log_error(); tracing::debug!("Vibe App Running"); // Crash handler @@ -111,6 +112,7 @@ pub fn setup(app: &App) -> Result<(), Box<dyn std::error::Error>> { tracing::debug!("APP VERSION: {}", app.package_info().version.to_string()); tracing::debug!("COMMIT HASH: {}", env!("COMMIT_HASH")); + tracing::debug!("App Info: {}", crate::utils::get_app_info()); let app_handle = app.app_handle().clone(); if is_cli_detected() { diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index 460fafa2..04f4c57d 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "./gen/schemas/desktop-schema.json", "productName": "vibe", - "version": "3.0.0", + "version": "3.0.1", "identifier": "github.aaakk.us.kg.thewh1teagle.vibe", "app": { "windows": [], @@ -45,33 +45,7 @@ ], "resources": { "locales": "locales" - }, - "fileAssociations": [ - { - "description": "Video files", - "ext": [ - "mp4", - "mkv", - "avi", - "mov", - "wmv", - "webm" - ] - }, - { - "description": "Audio files", - "ext": [ - "mp3", - "wav", - "aac", - "flac", - "oga", - "ogg", - "opic", - "opus" - ] - } - ] + } }, "plugins": { "updater": { diff --git a/desktop/src/components/SettingsModal.tsx b/desktop/src/components/SettingsModal.tsx index 267bf566..dfea1686 100644 --- a/desktop/src/components/SettingsModal.tsx +++ b/desktop/src/components/SettingsModal.tsx @@ -1,5 +1,6 @@ import { ModifyState, cx } from '~/lib/utils' import SettingsPage from '~/pages/settings/Page' +import * as os from '@tauri-apps/plugin-os' interface SettingsModalProps { visible: boolean @@ -8,7 +9,8 @@ interface SettingsModalProps { export default function SettingsModal({ visible, setVisible }: SettingsModalProps) { if (visible) { return ( - <div className={cx('modal modal-open backdrop-blur-3xl !bg-base-100 dark:!bg-transparent overflow-y-auto')}> + // Don't use transparent background on Linux since the backdrop doesn't work! + <div className={cx('modal modal-open backdrop-blur-3xl !bg-base-100 overflow-y-auto', os.platform() != 'linux' && 'dark:!bg-transparent')}> <SettingsPage setVisible={setVisible} /> </div> ) diff --git a/desktop/src/globals.css b/desktop/src/globals.css index 8d2e932e..43661ec9 100644 --- a/desktop/src/globals.css +++ b/desktop/src/globals.css @@ -14,14 +14,12 @@ } @media print { + html, body * { visibility: hidden; } - .printable { - visibility: visible; - } - + .printable, .printable * { visibility: visible; } @@ -31,5 +29,59 @@ left: 0; top: 0; height: 100vh; + width: 100vw; + } + + /* remove header and footer */ + @page { + margin: 0; + padding: 0; + } + + .segment { + padding-left: 5px; + padding-right: 5px; + } + + /* keep exact HTML colors! */ + * { + print-color-adjust: exact; + } + + /* Prevent blank page */ + html, + body { + height: 100vh; + margin: 0 !important; + padding: 0 !important; + overflow: hidden; + } + + body:last-child { + page-break-after: auto; + } + + /* Dark mode */ + + [data-theme='dark'] * { + background: #181818 !important; + } + + [data-theme='dark'] .segment { + color: white !important; + } + + /* Light mode */ + [data-theme='light'] * { + background: white !important; + } + + [data-theme='light'] .segment { + color: black !important; + } + + #footer, + #header { + all: unset; } } diff --git a/desktop/src/lib/utils.ts b/desktop/src/lib/utils.ts index 57568849..cceee9ed 100644 --- a/desktop/src/lib/utils.ts +++ b/desktop/src/lib/utils.ts @@ -4,6 +4,7 @@ import * as fs from '@tauri-apps/plugin-fs' import * as config from './config' import { Dispatch, SetStateAction } from 'react' import { load } from '@tauri-apps/plugin-store' +import * as keepAwake from 'tauri-plugin-keepawake-api' export interface NamedPath { name: string @@ -84,3 +85,19 @@ export async function getModelsFolder() {} export function formatSpeaker(speaker?: string, prefix = 'Speaker') { return `${prefix} ${speaker ?? '?'}: ` } + +export async function startKeepAwake() { + try { + keepAwake.start({ display: true, idle: true, sleep: true }) + } catch (e) { + console.error(`Keep awake failed: ${e}`) + } +} + +export async function stopKeepAwake() { + try { + keepAwake.stop() + } catch (e) { + console.error(`Keep awake failed: ${e}`) + } +} diff --git a/desktop/src/pages/batch/viewModel.tsx b/desktop/src/pages/batch/viewModel.tsx index 86179f17..75bed13a 100644 --- a/desktop/src/pages/batch/viewModel.tsx +++ b/desktop/src/pages/batch/viewModel.tsx @@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import { TextFormat, formatExtensions } from '~/components/FormatSelect' import { Segment, Transcript, asJson, asSrt, asText, asVtt } from '~/lib/transcript' -import { NamedPath, pathToNamedPath } from '~/lib/utils' +import { NamedPath, pathToNamedPath, startKeepAwake, stopKeepAwake } from '~/lib/utils' import * as webview from '@tauri-apps/api/webviewWindow' import * as dialog from '@tauri-apps/plugin-dialog' import * as config from '~/lib/config' @@ -112,6 +112,9 @@ export function viewModel() { if (inProgress) { return } + + startKeepAwake() + setInProgress(true) let localIndex = 0 await invoke('load_model', { modelPath: preference.modelPath, gpuDevice: preference.gpuDevice }) @@ -176,6 +179,7 @@ export function viewModel() { await new Promise((resolve) => setTimeout(resolve, 100)) setCurrentIndex(localIndex) } catch (error) { + stopKeepAwake() if (isAbortingRef.current) { navigate('/') } else { @@ -185,6 +189,7 @@ export function viewModel() { setCurrentIndex(localIndex) } } + stopKeepAwake() setCurrentIndex(files.length + 1) setInProgress(false) setIsAborting(false) diff --git a/desktop/src/pages/home/Page.tsx b/desktop/src/pages/home/Page.tsx index b19c42fd..a7c81e9a 100644 --- a/desktop/src/pages/home/Page.tsx +++ b/desktop/src/pages/home/Page.tsx @@ -14,6 +14,7 @@ import { ReactComponent as MicrphoneIcon } from '~/icons/microphone.svg' import { ReactComponent as LinkIcon } from '~/icons/link.svg' import { useEffect } from 'react' import { webviewWindow } from '@tauri-apps/api' +import * as keepAwake from 'tauri-plugin-keepawake-api' export default function Home() { const { t } = useTranslation() @@ -76,7 +77,12 @@ export default function Home() { {vm.isRecording && ( <> - <button onMouseDown={vm.stopRecord} className="btn relative btn-success mt-3"> + <button + onMouseDown={() => { + keepAwake.stop() + vm.stopRecord() + }} + className="btn relative btn-success mt-3"> <span className="loading loading-spinner"></span> {t('common.stop-and-transcribe')} </button> diff --git a/desktop/src/pages/home/viewModel.ts b/desktop/src/pages/home/viewModel.ts index f6a1674a..2fba7747 100644 --- a/desktop/src/pages/home/viewModel.ts +++ b/desktop/src/pages/home/viewModel.ts @@ -13,7 +13,7 @@ import { TextFormat } from '~/components/FormatSelect' import { AudioDevice } from '~/lib/audio' import * as config from '~/lib/config' import * as transcript from '~/lib/transcript' -import { NamedPath, ls, openPath, pathToNamedPath } from '~/lib/utils' +import { NamedPath, ls, openPath, pathToNamedPath, startKeepAwake, stopKeepAwake } from '~/lib/utils' import { getX86Features } from '~/lib/x86Features' import { ErrorModalContext } from '~/providers/ErrorModal' import { useFilesContext } from '~/providers/FilesProvider' @@ -278,6 +278,7 @@ export function viewModel() { }, []) async function startRecord() { + startKeepAwake() setSegments(null) setSummarizeSegments(null) setTranscriptTab('transcript') @@ -298,6 +299,8 @@ export function viewModel() { } async function transcribe(path: string) { + startKeepAwake() + setSegments(null) setSummarizeSegments(null) setTranscriptTab('transcript') @@ -330,11 +333,13 @@ export function viewModel() { hotToast.success(t('common.transcribe-took', { total: String(total) }), { position: 'bottom-center' }) } catch (error) { if (!abortRef.current) { + stopKeepAwake() console.error('error: ', error) setErrorModal?.({ log: String(error), open: true }) setLoading(false) } } finally { + stopKeepAwake() setLoading(false) setIsAborting(false) setProgress(null) diff --git a/scripts/pre_build.js b/scripts/pre_build.js index 8a3d8fe1..a379f952 100755 --- a/scripts/pre_build.js +++ b/scripts/pre_build.js @@ -17,6 +17,14 @@ function hasFeature(name) { return process.argv.includes(`--${name}`) || process.argv.includes(name) } +async function wget(url, path) { + if (platform === 'windows') { + await $`C:\\msys64\\usr\\bin\\wget.exe --show-progress --progress=bar:force:noscroll --tries=10 -nc ${url} -O ${path}` + } else { + await $`wget --show-progress --progress=bar:force:noscroll --tries=10 -nc ${url} -O ${path}` + } +} + const config = { ffmpegRealname: 'ffmpeg', openblasRealname: 'openblas', @@ -58,13 +66,7 @@ const config = { macos: { ffmpegName: 'ffmpeg-6.1-macOS-default', ffmpegUrl: 'https://master.dl.sourceforge.net/project/avbuild/macOS/ffmpeg-6.1-macOS-default.tar.xz?viasf=1', - }, - diarization: { - embedModelUrl: 'https://github.com/thewh1teagle/vibe/releases/download/v0.0.1/wespeaker_en_voxceleb_CAM++.onnx', - embedModelFilename: 'wespeaker_en_voxceleb_CAM++.onnx', - segmentModelUrl: 'https://github.com/thewh1teagle/vibe/releases/download/v0.0.1/segmentation-3.0.onnx', - segmentModelFilename: 'segmentation-3.0.onnx', - }, + } } // Export for Github actions @@ -92,7 +94,7 @@ if (platform == 'linux') { if (platform == 'windows') { // Setup FFMPEG if (!(await fs.exists(config.ffmpegRealname))) { - await $`C:\\msys64\\usr\\bin\\wget.exe -nc --show-progress ${config.windows.ffmpegUrl} -O ${config.windows.ffmpegName}.7z` + await wget(config.windows.ffmpegUrl, `${config.windows.ffmpegName}.7z`) await $`'C:\\Program Files\\7-Zip\\7z.exe' x ${config.windows.ffmpegName}.7z` await $`mv ${config.windows.ffmpegName} ${config.ffmpegRealname}` await $`rm -rf ${config.windows.ffmpegName}.7z` @@ -101,7 +103,7 @@ if (platform == 'windows') { // Setup OpenBlas if (!(await fs.exists(config.openblasRealname)) && hasFeature('openblas')) { - await $`C:\\msys64\\usr\\bin\\wget.exe -nc --show-progress ${config.windows.openBlasUrl} -O ${config.windows.openBlasName}.zip` + await wget(config.windows.openBlasUrl, `${config.windows.openBlasName}.zip`) await $`"C:\\Program Files\\7-Zip\\7z.exe" x ${config.windows.openBlasName}.zip -o${config.openblasRealname}` await $`rm ${config.windows.openBlasName}.zip` fs.cp(path.join(config.openblasRealname, 'include'), path.join(config.openblasRealname, 'lib'), { recursive: true, force: true }) @@ -111,12 +113,12 @@ if (platform == 'windows') { // Setup Vulkan if (!(await fs.exists(config.vulkanSdkRealName)) && hasFeature('vulkan')) { - await $`C:\\msys64\\usr\\bin\\wget.exe -nc --show-progress ${config.windows.vulkanSdkUrl} -O ${config.windows.vulkanSdkName}.exe` + await wget(config.windows.vulkanSdkUrl, `${config.windows.vulkanSdkName}.exe`) let executable = path.join(cwd, `${config.windows.vulkanSdkName}.exe`) let vulkanSdkRoot = path.join(cwd, config.vulkanSdkRealName) await $`${executable} --root ${vulkanSdkRoot} --accept-licenses --default-answer --confirm-command install copy_only=1` // copy_only=1 to run without admin rights - await $`C:\\msys64\\usr\\bin\\wget.exe -nc --show-progress ${config.windows.vulkanRuntimeUrl} -O ${config.windows.vulkanRuntimeName}.zip` + await wget(config.windows.vulkanRuntimeUrl, `${config.windows.vulkanRuntimeName}.zip`) await $`"C:\\Program Files\\7-Zip\\7z.exe" x ${config.windows.vulkanRuntimeName}.zip` // 7z file inside await $`mv ${config.windows.vulkanRuntimeName} ${config.vulkanRuntimeRealName}` await $`rm ${config.windows.vulkanSdkName}.exe` @@ -133,7 +135,7 @@ if (platform == 'windows') { if (platform == 'macos') { // Setup FFMPEG if (!(await fs.exists(config.ffmpegRealname))) { - await $`wget -nc --show-progress ${config.macos.ffmpegUrl} -O ${config.macos.ffmpegName}.tar.xz` + await wget(config.macos.ffmpegUrl, `${config.macos.ffmpegName}.tar.xz`) await $`tar xf ${config.macos.ffmpegName}.tar.xz` await $`mv ${config.macos.ffmpegName} ${config.ffmpegRealname}` await $`rm ${config.macos.ffmpegName}.tar.xz` @@ -222,17 +224,6 @@ if (hasFeature('rocm')) { } } -// Diarization -if (!(await fs.exists(config.diarization.embedModelFilename))) { - if (platform == 'windows') { - await $`C:\\msys64\\usr\\bin\\wget.exe -nc --show-progress ${config.diarization.embedModelUrl} -O ${config.diarization.embedModelFilename}` - await $`C:\\msys64\\usr\\bin\\wget.exe -nc --show-progress ${config.diarization.segmentModelUrl} -O ${config.diarization.segmentModelFilename}` - } else { - await $`wget -nc --show-progress ${config.diarization.embedModelUrl} -O ${config.diarization.embedModelFilename}` - await $`wget -nc --show-progress ${config.diarization.segmentModelUrl} -O ${config.diarization.segmentModelFilename}` - } -} - // Development hints if (!process.env.GITHUB_ENV) { console.log('\nCommands to build 🔨:')