diff --git a/.github/prebuild.js b/.github/prebuild.js index dcddb625..55ec9a29 100644 --- a/.github/prebuild.js +++ b/.github/prebuild.js @@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url"; import { exec as execCb } from "node:child_process"; import { env } from "node:process"; import { promisify } from "node:util"; +import { createTauriPlatformConfigs } from "../apps/desktop/scripts/prepare"; const exec = promisify(execCb); const signId = env.APPLE_SIGNING_IDENTITY || "-"; @@ -63,40 +64,31 @@ rustflags = [ throw e; }); - await fs.writeFile( - `${srcTauri}/tauri.macos.conf.json`, - JSON.stringify( - { - bundle: { - macOS: { - frameworks: [path.join(nativeDeps, "Spacedrive.framework")], - }, - }, + createTauriPlatformConfigs("darwin", { + bundle: { + macOS: { + frameworks: [path.join(nativeDeps, "Spacedrive.framework")], }, - null, - 4 - ) - ); + }, + }); } else if (os === "windows") { - const binFiles = await fs.readdir(path.join(nativeDeps, "bin")); - - await fs.writeFile( - `${srcTauri}/tauri.windows.conf.json`, - JSON.stringify( - { - bundle: { - resources: binFiles.filter( - (f) => - f.endsWith(".dll") && (f.startsWith("av") || f.startsWith("sw")) - ), - }, - }, - null, - 4 - ) - ); - - console.log(); + // const binFiles = await fs.readdir(path.join(nativeDeps, "bin")); + + // await fs.writeFile( + // `${srcTauri}/tauri.windows.conf.json`, + // JSON.stringify( + // { + // bundle: { + // resources: binFiles.filter( + // (f) => + // f.endsWith(".dll") && (f.startsWith("av") || f.startsWith("sw")) + // ), + // }, + // }, + // null, + // 4 + // ) + // ); } } diff --git a/Cargo.lock b/Cargo.lock index 6fd981d7..1a904e0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,24 +151,6 @@ dependencies = [ "derive_arbitrary", ] -[[package]] -name = "arboard" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" -dependencies = [ - "clipboard-win", - "core-graphics 0.23.2", - "image 0.25.2", - "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "parking_lot", - "windows-sys 0.48.0", - "x11rb", -] - [[package]] name = "arg_enum_proc_macro" version = "0.3.4" @@ -177,7 +159,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -322,7 +304,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -357,7 +339,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -422,9 +404,9 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" dependencies = [ "arrayvec", ] @@ -555,7 +537,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex 1.3.0", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -573,7 +555,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex 1.3.0", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -705,7 +687,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -740,7 +722,7 @@ dependencies = [ "glib", "libc", "once_cell", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -790,10 +772,10 @@ dependencies = [ "cap-project", "cap-rendering", "cap-utils", - "image 0.25.2", + "image 0.25.5", "mp4", "tempfile", - "thiserror", + "thiserror 1.0.63", "tokio", ] @@ -850,7 +832,7 @@ dependencies = [ "serde", "specta", "tempfile", - "thiserror", + "thiserror 1.0.63", "tracing", "windows 0.58.0", "windows-capture", @@ -878,14 +860,15 @@ dependencies = [ "device_query", "either", "flume 0.11.0", - "image 0.25.2", + "image 0.25.5", "objc", "serde", "serde_json", "specta", - "thiserror", + "thiserror 1.0.63", "tokio", "tracing", + "windows 0.58.0", ] [[package]] @@ -901,11 +884,11 @@ dependencies = [ "ffmpeg-sys-next", "futures", "futures-intrusive", - "image 0.25.2", + "image 0.25.5", "nix 0.29.0", "serde", "specta", - "thiserror", + "thiserror 1.0.63", "tokio", "wgpu", ] @@ -940,7 +923,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -1094,6 +1077,20 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" +[[package]] +name = "clipboard-rs" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c525d1554fa31abe88c8aa853d3cf0170320f6553dbc322642d4fe0a5cb2cda1" +dependencies = [ + "clipboard-win", + "image 0.25.5", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "x11rb", +] + [[package]] name = "clipboard-win" version = "5.4.0" @@ -1101,6 +1098,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" dependencies = [ "error-code", + "windows-win", ] [[package]] @@ -1593,7 +1591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1603,7 +1601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1638,7 +1636,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1649,7 +1647,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1701,17 +1699,6 @@ dependencies = [ "serde", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "derive_arbitrary" version = "1.3.2" @@ -1720,7 +1707,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1733,7 +1720,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1753,6 +1740,7 @@ dependencies = [ "cap-rendering", "cap-utils", "chrono", + "clipboard-rs", "cocoa 0.26.0", "core-foundation 0.10.0", "core-graphics 0.24.0", @@ -1763,7 +1751,7 @@ dependencies = [ "futures", "futures-intrusive", "global-hotkey", - "image 0.25.2", + "image 0.25.5", "keyed_priority_queue", "mp4", "nix 0.29.0", @@ -1783,7 +1771,6 @@ dependencies = [ "tauri", "tauri-build", "tauri-nspanel", - "tauri-plugin-clipboard-manager", "tauri-plugin-dialog", "tauri-plugin-fs", "tauri-plugin-global-shortcut", @@ -1887,7 +1874,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1919,7 +1906,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -2050,7 +2037,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -2226,15 +2213,6 @@ dependencies = [ "miniz_oxide 0.8.0", ] -[[package]] -name = "fluent-uri" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "flume" version = "0.10.14" @@ -2293,7 +2271,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -2407,7 +2385,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -2634,7 +2612,7 @@ dependencies = [ "once_cell", "pin-project-lite", "smallvec", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -2681,7 +2659,7 @@ dependencies = [ "memchr", "once_cell", "smallvec", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -2691,11 +2669,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" dependencies = [ "heck 0.4.1", - "proc-macro-crate 2.0.2", + "proc-macro-crate 2.0.0", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -2726,7 +2704,7 @@ dependencies = [ "objc2-app-kit", "once_cell", "serde", - "thiserror", + "thiserror 1.0.63", "windows-sys 0.59.0", "x11-dl", ] @@ -2790,7 +2768,7 @@ checksum = "fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7" dependencies = [ "log", "presser", - "thiserror", + "thiserror 1.0.63", "winapi", "windows 0.52.0", ] @@ -2864,7 +2842,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -2922,7 +2900,7 @@ dependencies = [ "com", "libc", "libloading 0.8.5", - "thiserror", + "thiserror 1.0.63", "widestring", "winapi", ] @@ -3209,9 +3187,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.2" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" dependencies = [ "bytemuck", "byteorder-lite", @@ -3232,9 +3210,9 @@ dependencies = [ [[package]] name = "image-webp" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904" +checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f" dependencies = [ "byteorder-lite", "quick-error", @@ -3294,7 +3272,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -3377,7 +3355,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.63", "walkdir", "windows-sys 0.45.0", ] @@ -3412,39 +3390,16 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "json-patch" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1fb8864823fad91877e6caea0baca82e49e8db50f8e5c9f9a453e27d3330fc" -dependencies = [ - "jsonptr 0.4.7", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "json-patch" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" dependencies = [ - "jsonptr 0.6.3", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "jsonptr" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c6e529149475ca0b2820835d3dce8fcc41c6b943ca608d32f35b449255e4627" -dependencies = [ - "fluent-uri", + "jsonptr", "serde", "serde_json", + "thiserror 1.0.63", ] [[package]] @@ -3762,6 +3717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ "cfg-if 1.0.0", + "rayon", ] [[package]] @@ -3904,7 +3860,7 @@ dependencies = [ "num-rational", "serde", "serde_json", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -3923,7 +3879,7 @@ dependencies = [ "once_cell", "png", "serde", - "thiserror", + "thiserror 1.0.63", "windows-sys 0.59.0", ] @@ -3944,7 +3900,7 @@ dependencies = [ "rustc-hash 1.1.0", "spirv", "termcolor", - "thiserror", + "thiserror 1.0.63", "unicode-xid", ] @@ -3994,7 +3950,7 @@ dependencies = [ "log", "ndk-sys 0.5.0+25.2.9519653", "num_enum", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -4009,7 +3965,7 @@ dependencies = [ "ndk-sys 0.6.0+11769913", "num_enum", "raw-window-handle", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -4051,7 +4007,6 @@ dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", "libc", - "memoffset", ] [[package]] @@ -4064,6 +4019,7 @@ dependencies = [ "cfg-if 1.0.0", "cfg_aliases 0.2.1", "libc", + "memoffset", ] [[package]] @@ -4085,7 +4041,7 @@ dependencies = [ "nokhwa-core", "paste", "serde", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -4132,7 +4088,7 @@ dependencies = [ "image 0.24.9", "mozjpeg", "serde", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -4207,7 +4163,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -4265,10 +4221,10 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 2.0.2", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -4610,7 +4566,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -4850,7 +4806,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -4897,7 +4853,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -4937,7 +4893,7 @@ dependencies = [ "nix 0.27.1", "once_cell", "pipewire-sys", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -5043,14 +4999,22 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_datetime", "toml_edit 0.20.2", ] +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -5083,9 +5047,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -5106,7 +5070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -5180,7 +5144,7 @@ dependencies = [ "rustc-hash 2.0.0", "rustls", "socket2", - "thiserror", + "thiserror 1.0.63", "tokio", "tracing", ] @@ -5197,7 +5161,7 @@ dependencies = [ "rustc-hash 2.0.0", "rustls", "slab", - "thiserror", + "thiserror 1.0.63", "tinyvec", "tracing", ] @@ -5341,22 +5305,23 @@ dependencies = [ "rand_chacha 0.3.1", "simd_helpers", "system-deps", - "thiserror", + "thiserror 1.0.63", "v_frame", "wasm-bindgen", ] [[package]] name = "ravif" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f0bfd976333248de2078d350bfdf182ff96e168a24d23d2436cef320dd4bdd" +checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" dependencies = [ "avif-serialize", "imgref", "loop9", "quick-error", "rav1e", + "rayon", "rgb", ] @@ -5415,7 +5380,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", "libredox", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -5532,9 +5497,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f86ae463694029097b846d8f99fd5536740602ae00022c0c50c5600720b2f71" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -5575,7 +5540,7 @@ dependencies = [ "hound", "lewton", "symphonia", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -5732,7 +5697,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -5936,7 +5901,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "thiserror", + "thiserror 1.0.63", "time", "url", "uuid", @@ -5970,7 +5935,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -5981,7 +5946,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -6014,7 +5979,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -6065,7 +6030,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -6265,7 +6230,7 @@ checksum = "4ccbb212565d2dc177bc15ecb7b039d66c4490da892436a4eee5b394d620c9bc" dependencies = [ "paste", "specta-macros", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -6277,7 +6242,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -6287,7 +6252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12260cbb21abb2e83a0375b1521867910e3aed8a7afa782206150ce552cd2e5a" dependencies = [ "specta", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -6298,7 +6263,7 @@ checksum = "b1e4472229365ceb6395487e3a60d921ad8e21f9ad06eaecc396f098902c9adc" dependencies = [ "specta", "specta-serde", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -6448,9 +6413,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -6532,9 +6497,9 @@ dependencies = [ [[package]] name = "tao" -version = "0.30.5" +version = "0.30.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f1f6b2017cc33d7f6fc9c6186a2c0f5dfc985899a7b4fe9e64985c17533db3" +checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da" dependencies = [ "bitflags 2.6.0", "cocoa 0.26.0", @@ -6589,7 +6554,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -6611,9 +6576,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.0.6" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3889b392db6d32a105d3757230ea0220090b8f94c90d3e60b6c5eb91178ab1b" +checksum = "e545de0a2dfe296fa67db208266cd397c5a55ae782da77973ef4c4fac90e9f2c" dependencies = [ "anyhow", "bytes", @@ -6627,7 +6592,7 @@ dependencies = [ "heck 0.5.0", "http", "http-range", - "image 0.25.2", + "image 0.25.5", "jni", "libc", "log", @@ -6651,11 +6616,11 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror", + "thiserror 2.0.6", "tokio", "tray-icon", "url", - "urlpattern 0.3.0", + "urlpattern", "webkit2gtk", "webview2-com", "window-vibrancy", @@ -6664,16 +6629,16 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f96827ccfb1aa40d55d0ded79562d18ba18566657a553f992a982d755148376" +checksum = "7bd2a4bcfaf5fb9f4be72520eefcb61ae565038f8ccba2a497d8c28f463b8c01" dependencies = [ "anyhow", "cargo_toml", "dirs", "glob", "heck 0.5.0", - "json-patch 3.0.1", + "json-patch", "schemars", "semver", "serde", @@ -6686,14 +6651,14 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947f16f47becd9e9cd39b74ee337fd1981574d78819be18e4384d85e5a0b82f" +checksum = "bf79faeecf301d3e969b1fae977039edb77a4c1f25cc0a961be298b54bff97cf" dependencies = [ "base64 0.22.1", "brotli", "ico", - "json-patch 2.0.0", + "json-patch", "plist", "png", "proc-macro2", @@ -6702,9 +6667,9 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.85", + "syn 2.0.90", "tauri-utils", - "thiserror", + "thiserror 2.0.6", "time", "url", "uuid", @@ -6713,14 +6678,14 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd1c8d4a66799d3438747c3a79705cd665a95d6f24cb5f315413ff7a981fe2a" +checksum = "c52027c8c5afb83166dacddc092ee8fff50772f9646d461d8c33ee887e447a03" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", "tauri-codegen", "tauri-utils", ] @@ -6758,21 +6723,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "tauri-plugin-clipboard-manager" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a66feaa0fb7fce8e5073323d11ca381c9da7ac06f458e42b9ff77364b76a360" -dependencies = [ - "arboard", - "log", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "thiserror", -] - [[package]] name = "tauri-plugin-dialog" version = "2.0.3" @@ -6787,15 +6737,15 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror", + "thiserror 1.0.63", "url", ] [[package]] name = "tauri-plugin-fs" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba7d46e86db8c830d143ef90ab5a453328365b0cc834c24edea4267b16aba0" +checksum = "0cdaf6701ee5efc83161cf41004aa5aec4d255c9fb2d2b11fe518fe506acc588" dependencies = [ "anyhow", "dunce", @@ -6807,7 +6757,9 @@ dependencies = [ "serde_repr", "tauri", "tauri-plugin", - "thiserror", + "tauri-utils", + "thiserror 2.0.6", + "toml 0.8.2", "url", "uuid", ] @@ -6824,14 +6776,14 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "thiserror", + "thiserror 1.0.63", ] [[package]] name = "tauri-plugin-http" -version = "2.0.0-rc.0" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eef17218eaa8bd0fc6cafb7831c63d82ef83b3950d59dc817d92d5320c4f20c" +checksum = "fd6f26c4e715b50f06e3fde65cda1d805dae23f04869a01380c4cf8708dbb296" dependencies = [ "data-url", "http", @@ -6843,10 +6795,10 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror", + "thiserror 2.0.6", "tokio", "url", - "urlpattern 0.2.0", + "urlpattern", ] [[package]] @@ -6863,7 +6815,7 @@ dependencies = [ "serde_repr", "tauri", "tauri-plugin", - "thiserror", + "thiserror 1.0.63", "time", "url", ] @@ -6878,7 +6830,7 @@ dependencies = [ "serde", "tauri", "tauri-plugin", - "thiserror", + "thiserror 1.0.63", "url", ] @@ -6897,7 +6849,7 @@ dependencies = [ "sys-locale", "tauri", "tauri-plugin", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -6927,7 +6879,7 @@ dependencies = [ "shared_child", "tauri", "tauri-plugin", - "thiserror", + "thiserror 1.0.63", "tokio", ] @@ -6941,7 +6893,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "thiserror", + "thiserror 1.0.63", "windows-sys 0.59.0", "zbus", ] @@ -6958,15 +6910,15 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "thiserror", + "thiserror 1.0.63", "tokio", ] [[package]] name = "tauri-plugin-updater" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd3d2fe0f02bf52eebb5a9d23b987fffac6684646ab6fd683d706dafb18da87" +checksum = "50ba9adaede60b0df5e0764692c6ac176eb133aade95d326bddeb968ad793320" dependencies = [ "base64 0.22.1", "dirs", @@ -6984,7 +6936,7 @@ dependencies = [ "tauri", "tauri-plugin", "tempfile", - "thiserror", + "thiserror 2.0.6", "time", "tokio", "url", @@ -7004,14 +6956,14 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "thiserror", + "thiserror 1.0.63", ] [[package]] name = "tauri-runtime" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ef7363e7229ac8d04e8a5d405670dbd43dde8fc4bc3bc56105c35452d03784" +checksum = "cce18d43f80d4aba3aa8a0c953bbe835f3d0f2370aca75e8dbb14bd4bab27958" dependencies = [ "dpi", "gtk", @@ -7021,16 +6973,16 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "thiserror", + "thiserror 2.0.6", "url", "windows 0.58.0", ] [[package]] name = "tauri-runtime-wry" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fa2068e8498ad007b54d5773d03d57c3ff6dd96f8c8ce58beff44d0d5e0d30" +checksum = "9f442a38863e10129ffe2cec7bd09c2dcf8a098a3a27801a476a304d5bb991d2" dependencies = [ "gtk", "http", @@ -7065,7 +7017,7 @@ dependencies = [ "specta-typescript", "tauri", "tauri-specta-macros", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -7077,14 +7029,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] name = "tauri-utils" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc65d6f5c54e56b66258948a6d9e47a82ea41f4b5a7612bfbdd1634c2913ed0" +checksum = "9271a88f99b4adea0dc71d0baca4505475a0bbd139fb135f62958721aaa8fe54" dependencies = [ "brotli", "cargo_metadata", @@ -7092,8 +7044,9 @@ dependencies = [ "dunce", "glob", "html5ever", + "http", "infer", - "json-patch 2.0.0", + "json-patch", "kuchikiki", "log", "memchr", @@ -7108,10 +7061,10 @@ dependencies = [ "serde_json", "serde_with", "swift-rs", - "thiserror", + "thiserror 2.0.6", "toml 0.8.2", "url", - "urlpattern 0.3.0", + "urlpattern", "uuid", "walkdir", ] @@ -7191,7 +7144,16 @@ version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.63", +] + +[[package]] +name = "thiserror" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" +dependencies = [ + "thiserror-impl 2.0.6", ] [[package]] @@ -7202,7 +7164,18 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", ] [[package]] @@ -7288,7 +7261,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -7363,9 +7336,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -7380,7 +7353,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] @@ -7393,7 +7366,18 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.5.0", + "toml_datetime", + "winnow 0.6.20", ] [[package]] @@ -7459,7 +7443,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -7498,7 +7482,7 @@ dependencies = [ "once_cell", "png", "serde", - "thiserror", + "thiserror 1.0.63", "windows-sys 0.59.0", ] @@ -7522,7 +7506,7 @@ dependencies = [ "log", "rand 0.8.5", "sha1", - "thiserror", + "thiserror 1.0.63", "utf-8", ] @@ -7678,19 +7662,6 @@ 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 = "urlpattern" version = "0.3.0" @@ -7853,7 +7824,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", "wasm-bindgen-shared", ] @@ -7887,7 +7858,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -8056,7 +8027,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -8065,7 +8036,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886" dependencies = [ - "thiserror", + "thiserror 1.0.63", "windows 0.58.0", "windows-core 0.58.0", ] @@ -8121,7 +8092,7 @@ dependencies = [ "raw-window-handle", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.63", "wgpu-hal", "wgpu-types", ] @@ -8164,7 +8135,7 @@ dependencies = [ "renderdoc-sys", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.63", "wasm-bindgen", "web-sys", "wgpu-types", @@ -8313,7 +8284,7 @@ checksum = "5cc0a71a6b97b2fb0643c0655e19b8fa4a78c768bf5b2acfdaf453873e53ad4e" dependencies = [ "parking_lot", "rayon", - "thiserror", + "thiserror 1.0.63", "windows 0.58.0", ] @@ -8369,7 +8340,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -8380,7 +8351,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -8391,7 +8362,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -8402,7 +8373,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -8535,6 +8506,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-win" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e23e33622b3b52f948049acbec9bcc34bf6e26d74176b88941f213c75cf2dc" +dependencies = [ + "error-code", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -8676,6 +8656,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.52.0" @@ -8688,12 +8677,13 @@ dependencies = [ [[package]] name = "wry" -version = "0.46.3" +version = "0.47.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd5cdf57c66813d97601181349c63b96994b3074fc3d7a31a8cce96e968e3bbd" +checksum = "61ce51277d65170f6379d8cda935c80e3c2d1f0ff712a123c8bddb11b31a4b73" dependencies = [ "base64 0.22.1", "block2", + "cookie", "crossbeam-channel", "dpi", "dunce", @@ -8717,7 +8707,8 @@ dependencies = [ "sha2", "soup3", "tao-macros", - "thiserror", + "thiserror 1.0.63", + "url", "webkit2gtk", "webkit2gtk-sys", "webview2-com", @@ -8803,9 +8794,9 @@ dependencies = [ [[package]] name = "zbus" -version = "4.0.1" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" dependencies = [ "async-broadcast", "async-executor", @@ -8817,14 +8808,13 @@ dependencies = [ "async-task", "async-trait", "blocking", - "derivative", "enumflags2", "event-listener", "futures-core", "futures-sink", "futures-util", "hex", - "nix 0.27.1", + "nix 0.29.0", "ordered-stream", "rand 0.8.5", "serde", @@ -8843,15 +8833,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.0.1" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3e850ff1e7217a3b7a07eba90d37fe9bb9e89a310f718afcde5885ca9b6d7" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "regex", - "syn 1.0.109", + "syn 2.0.90", "zvariant_utils", ] @@ -8884,7 +8873,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -8905,7 +8894,7 @@ dependencies = [ "displaydoc", "indexmap 2.5.0", "memchr", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -8934,9 +8923,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.0.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e09e8be97d44eeab994d752f341e67b3b0d80512a8b315a0671d47232ef1b65" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" dependencies = [ "endi", "enumflags2", @@ -8948,24 +8937,24 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "4.0.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a5857e2856435331636a9fbb415b09243df4521a267c5bedcd5289b4d5799e" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "1.1.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] diff --git a/Cargo.toml b/Cargo.toml index 5ec6ad85..d20ee260 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ tokio = { version = "1.39.3", features = [ "rt-multi-thread", "time", ] } -tauri = { version = "2.0.0" } +tauri = { version = "2.1.1" } specta = { version = "=2.0.0-rc.20" } scap = { git = "https://github.com/CapSoftware/scap", rev = "58d4410bf52f" } nokhwa = { git = "https://github.com/CapSoftware/nokhwa", rev = "0d3d1f30a78b", features = [ diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 67168006..64eb6e6c 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -2,7 +2,9 @@ "name": "@cap/desktop", "type": "module", "scripts": { - "dev": "dotenv -e ../../.env -- tauri dev", + "dev": "dotenv -e ../../.env -- pnpm run preparescript && tauri dev", + "build:tauri": "dotenv -e ../../.env -- pnpm run preparescript && tauri build", + "preparescript": "node scripts/prepare.js", "localdev": "dotenv -e ../../.env -- vinxi dev --port 3001", "build": "vinxi build", "tauri": "tauri" @@ -32,16 +34,15 @@ "@solidjs/start": "^1.0.6", "@tanstack/solid-query": "^5.51.21", "@tauri-apps/api": "^2.1.1", - "@tauri-apps/plugin-clipboard-manager": "^2.0.0", - "@tauri-apps/plugin-dialog": "2.0.0-rc.1", - "@tauri-apps/plugin-fs": "2.0.0-rc.0", + "@tauri-apps/plugin-dialog": "2.0.1", + "@tauri-apps/plugin-fs": "2.0.3", "@tauri-apps/plugin-http": "^2.0.1", - "@tauri-apps/plugin-notification": "2.0.0-rc.0", - "@tauri-apps/plugin-os": "2.0.0-rc.1", - "@tauri-apps/plugin-process": "2.0.0-rc.0", - "@tauri-apps/plugin-shell": ">=2.0.0-rc.0", + "@tauri-apps/plugin-notification": "2.0.0", + "@tauri-apps/plugin-os": "2.0.0", + "@tauri-apps/plugin-process": "2.0.0", + "@tauri-apps/plugin-shell": ">=2.0.1", "@tauri-apps/plugin-store": "2.1.0", - "@tauri-apps/plugin-updater": "2.0.0-rc.0", + "@tauri-apps/plugin-updater": "2.0.0", "@ts-rest/core": "^3.51.0", "@types/react-tooltip": "^4.2.4", "cva": "npm:class-variance-authority@^0.7.0", @@ -60,7 +61,7 @@ "devDependencies": { "@fontsource/geist-sans": "^5.0.3", "@iconify/json": "^2.2.239", - "@tauri-apps/cli": ">=2.0.0-rc.0", + "@tauri-apps/cli": ">=2.1.0", "@total-typescript/ts-reset": "^0.6.1", "@types/dom-webcodecs": "^0.1.11", "typescript": "^5.7.2", diff --git a/apps/desktop/scripts/prepare.js b/apps/desktop/scripts/prepare.js new file mode 100644 index 00000000..5d6f447b --- /dev/null +++ b/apps/desktop/scripts/prepare.js @@ -0,0 +1,248 @@ +// @ts-check + +import * as fs from "node:fs/promises"; +import * as path from "node:path"; +import { fileURLToPath } from "node:url"; +import { exec as execCb, execSync } from "node:child_process"; +import { promisify } from "node:util"; + +const exec = promisify(execCb); + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const binariesDir = path.join(__dirname, "../../../target/binaries"); +const ffmpegUnzippedPath = path.join(binariesDir, "ffmpeg-unzipped"); + +const isWindows = process.platform === "win32"; +const fileExtension = isWindows ? ".exe" : ""; +const rustInfo = execSync("rustc -vV"); +const rsTargetTriple = /host: (\S+)/.exec(rustInfo.toString())?.[1]; + +const FFMPEG_BINARIES = { + "aarch64-apple-darwin": { + url: "https://cap-ffmpeg.s3.amazonaws.com/ffmpegarm.zip", + path: "./ffmpeg", + }, + "x86_64-apple-darwin": { + url: "https://cap-ffmpeg.s3.amazonaws.com/ffmpeg-7.0.1.zip", + path: "./ffmpeg", + }, + "x86_64-pc-windows-msvc": { + // TODO: Select a stable version, use Cap's own ffmpeg build to also support aarch64. + url: "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl-shared.zip", + path: "bin/ffmpeg.exe", + }, +}; + +/** + * @param {string} filePath + * @returns {Promise} + */ +async function exists(filePath) { + return fs + .access(filePath) + .then(() => true) + .catch(() => false); +} + +/** + * @param {string} targetPath + * @param {string} outputPath + */ +async function unzip(targetPath, outputPath) { + console.log(`unzipping \"${targetPath}\" --> \"${outputPath}\"`); + if (isWindows) { + await exec(`tar -xf ${targetPath} -C ${outputPath}`); + } else { + await exec(`unzip -o ${targetPath} -d ${outputPath}`); + } +} + +async function prepareFfmpegSidecar() { + const binaries = FFMPEG_BINARIES[rsTargetTriple]; + const ffmpegDownloadPath = path.join(binariesDir, "ffmpeg-download.zip"); + + // Skip downloading if the archive already exists + if (!(await exists(ffmpegDownloadPath))) { + if (await exists(ffmpegUnzippedPath)) return; + console.log(`Couldn't locate "ffmpeg-download.zip" in "${ffmpegDownloadPath}"`); + console.log(`Downloading from: ${binaries.url}`); + await fs.mkdir(binariesDir, { recursive: true }); + + const response = await fetch(binaries.url); + if (!response.ok || !response.body) throw new Error(`Failed to download: ${response.statusText}`); + + const contentLength = response.headers.get("content-length"); + if (!contentLength) throw new Error("Unable to determine file size for progress reporting."); + + const totalBytes = parseInt(contentLength, 10); + let downloadedBytes = 0; + + const archiveBuffer = []; + const reader = response.body.getReader(); + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + downloadedBytes += value.length; + archiveBuffer.push(value); + + const progress = ((downloadedBytes / totalBytes) * 100).toFixed(2); + process.stdout.write(`\rDownloading: ${progress}%`); + } + console.log("\nDownload complete."); + const archive = Buffer.concat(archiveBuffer); + await fs.writeFile(ffmpegDownloadPath, archive); + } + + // Skip unzipping if the directory already exists + if (!(await exists(ffmpegUnzippedPath))) { + console.log("Extracting ffmpeg archive..."); + await fs.mkdir(ffmpegUnzippedPath, { recursive: true }); + await unzip(ffmpegDownloadPath, ffmpegUnzippedPath); + } + + // Check if there's a single nested folder and move its contents to the root + const unzippedContents = await fs.readdir(ffmpegUnzippedPath); + if (unzippedContents.length === 1) { + const nestedPath = path.join(ffmpegUnzippedPath, unzippedContents[0]); + const stat = await fs.stat(nestedPath); + + if (stat.isDirectory()) { + console.log(`Detected nested folder '${unzippedContents[0]}'. Moving contents to root.`); + const nestedContents = await fs.readdir(nestedPath); + + for (const entry of nestedContents) { + const srcPath = path.join(nestedPath, entry); + const destPath = path.join(ffmpegUnzippedPath, entry); + await fs.rename(srcPath, destPath); + } + + // Remove the now-empty nested folder + await fs.rmdir(nestedPath); + } + } + + const ffmpegBinaryPath = path.join(ffmpegUnzippedPath, binaries.path); + const ffmpegSidecarName = `ffmpeg-${rsTargetTriple}${fileExtension}`; + const finalDestinationPath = path.join(binariesDir, ffmpegSidecarName); + if (await exists(finalDestinationPath)) { + console.log(`Using ffmpeg sidecar: ${ffmpegSidecarName}`); + return; + }; + + console.log(`Copying ffmpeg binary to '${ffmpegSidecarName}'...`); + + await fs.copyFile( + ffmpegBinaryPath, + path.join(binariesDir, ffmpegSidecarName) + ); +} + +/** + * Creates a Microsoft Windows Installer (TM) compatible version from the provided crate's semver version. + * `major.minor.patch.build` + * + * @see {@link https://tauri.app/reference/config/#version-1} + * @param {string} cargoFilePath + * @returns {Promise} + */ +async function semverToWIXCompatibleVersion(cargoFilePath) { + const config = await fs.readFile(cargoFilePath, "utf-8"); + const match = /version\s*=\s*"([\w.-]+)"/.exec(config); + if (!match) throw new Error( + "Failed to extract version from \"Cargo.toml\". Have you removed the main crate version by accident?" + ); + + const ver = match[1]; + const [core, buildOrPrerelease] = ver.includes('+') ? ver.split('+') : ver.split('-'); + const [major, minor, patch] = core.split("."); + let build = 0; + if (buildOrPrerelease) { + const numMatch = buildOrPrerelease.match(/\d+$/); + build = numMatch ? parseInt(numMatch[0]) : 0; + } + const wixVersion = `${major}.${minor}.${patch}${build === 0 ? "" : `.${build}`}`; + if (wixVersion !== ver) console.log(`Using wix-compatible version ${ver} --> ${wixVersion}`); + return wixVersion; +} +/** + * Deeply merges two objects + * + * @param {Object} target + * @param {Object} source + * @returns {Object} + */ +function deepMerge(target, source) { + for (const key of Object.keys(source)) { + if (source[key] instanceof Object && key in target && target[key] instanceof Object) { + Object.assign(source[key], deepMerge(target[key], source[key])); + } + } + return { ...target, ...source }; +} + +/** + * Writes platform-specific tauri configs + * + * @param {NodeJS.Platform} platform + * @param {{} | undefined} configOptions + */ +export async function createTauriPlatformConfigs(platform, configOptions = undefined) { + const srcTauri = path.join(__dirname, "../src-tauri/"); + let baseConfig = {}; + let configFileName = ""; + + console.log(`Updating Platform (${platform}) Tauri config...`); + if (platform === "win32") { + configFileName = "tauri.windows.conf.json"; + baseConfig = { + ...baseConfig, + bundle: { + resources: { + "../../../target/binaries/ffmpeg-unzipped/bin/*.dll": "" + }, + windows: { + wix: { + version: await semverToWIXCompatibleVersion(path.join(srcTauri, "Cargo.toml")) + } + }, + }, + }; + } else if (platform === "darwin") { + configFileName = "tauri.macos.conf.json"; + baseConfig = { + ...baseConfig, + bundle: { + icon: ["icons/macos/icon.icns"], + }, + }; + } else { + throw new Error("Unsupported platform!"); + } + const mergedConfig = configOptions ? deepMerge(baseConfig, configOptions) : baseConfig; + await fs.writeFile(`${srcTauri}/${configFileName}`, JSON.stringify(mergedConfig, null, 2)); +} + +async function main() { + console.log("--- Preparing sidecars and configs..."); + const targetTripleEnv = process.env.TARGET_TRIPLE || rsTargetTriple; + const binaries = FFMPEG_BINARIES[targetTripleEnv]; + if (!binaries) { + console.error(`Unsupported target: ${targetTripleEnv}`); + return; + } + console.log(`Target is ${targetTripleEnv}`); + + await prepareFfmpegSidecar(); + await createTauriPlatformConfigs(process.platform); + console.log("--- Preparation finished"); +} + +main().catch((err) => { + console.error("--- Preparation Failed"); + console.error(err); + console.error("---"); + process.exit(1); +}); \ No newline at end of file diff --git a/apps/desktop/scripts/prepareSidecars.js b/apps/desktop/scripts/prepareSidecars.js deleted file mode 100644 index b2245ffd..00000000 --- a/apps/desktop/scripts/prepareSidecars.js +++ /dev/null @@ -1,72 +0,0 @@ -import * as fs from "node:fs/promises"; -import * as path from "node:path"; -import { fileURLToPath } from "node:url"; -import { exec as execCb } from "node:child_process"; -import { promisify } from "node:util"; - -const exec = promisify(execCb); - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -const binariesDir = path.join(__dirname, "../../../target/binaries"); - -const FFMPEG_BINARIES = { - "aarch64-apple-darwin": { - url: "https://cap-ffmpeg.s3.amazonaws.com/ffmpegarm.zip", - path: "./ffmpeg", - }, - "x86_64-apple-darwin": { - url: "https://cap-ffmpeg.s3.amazonaws.com/ffmpeg-7.0.1.zip", - path: "./ffmpeg", - }, -}; - -async function getRustupTarget() { - const { stdout } = await exec("rustup show"); - const line = stdout - .split("\n") - .find((line) => line.includes("Default host:")); - - return line.split(":")[1].trim(); -} - -async function exists(path) { - return await fs - .access(path) - .then(() => true) - .catch(() => false); -} - -async function main() { - const targetTriple = process.env.TARGET_TRIPLE ?? (await getRustupTarget()); - const binaries = FFMPEG_BINARIES[targetTriple]; - if (!binaries) return; - - const ffmpegDownloadPath = path.join(binariesDir, "ffmpeg-download"); - if (!(await exists(ffmpegDownloadPath))) { - await fs.mkdir(binariesDir, { recursive: true }); - console.log("downloading ffmpeg archive"); - const archive = await fetch(binaries.url) - .then((r) => r.blob()) - .then((b) => b.arrayBuffer()) - .then((a) => Buffer.from(a)); - - await fs.writeFile(ffmpegDownloadPath, archive); - } - - const ffmpegUnzippedPath = path.join(binariesDir, "ffmpeg-unzipped"); - if (!(await exists(ffmpegUnzippedPath))) { - console.log("extracting ffmpeg archive"); - await exec(`unzip ${ffmpegDownloadPath} -d ${ffmpegUnzippedPath}`); - } - - const ffmpegSidecarName = `ffmpeg-${targetTriple}`; - console.log(`copying ffmpeg binary '${ffmpegSidecarName}`); - await fs.copyFile( - path.join(ffmpegUnzippedPath, binaries.path), - path.join(binariesDir, ffmpegSidecarName) - ); -} - -main(); diff --git a/apps/desktop/scripts/stripDebugSymbols.js b/apps/desktop/scripts/stripDebugSymbols.js index 0eab21b8..a0078242 100644 --- a/apps/desktop/scripts/stripDebugSymbols.js +++ b/apps/desktop/scripts/stripDebugSymbols.js @@ -34,10 +34,16 @@ async function main() { const binaryPath = path.join(releaseDir, releaseFile); - await exec( - `dsymutil "${binaryPath}" -o "${path.join(targetDir, releaseFile)}.dSYM"` - ); - await exec(`strip "${binaryPath}"`); + if (process.platform === "darwin") { + await exec( + `dsymutil "${binaryPath}" -o "${path.join(targetDir, releaseFile)}.dSYM"` + ); + await exec(`strip "${binaryPath}"`); + } else if (process.platform === "win32") { + // TODO + } else { + throw new Error("Unsupported platform!"); + } } main(); diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index cafd5c59..4f25947c 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -12,7 +12,7 @@ name = "desktop_solid_lib" crate-type = ["lib", "cdylib", "staticlib"] [build-dependencies] -tauri-build = { version = "2.0.0-rc", features = [] } +tauri-build = { version = "2.0.3", features = [] } [target.'cfg(target_os = "macos")'.build-dependencies] swift-rs = { version = "1.0.6", features = ["build"] } @@ -24,18 +24,20 @@ tauri = { workspace = true, features = [ "tray-icon", "image-png", ] } +tauri-specta = { version = "=2.0.0-rc.20", features = ["derive", "typescript"] } +tauri-plugin-dialog = "2.0.0" +tauri-plugin-fs = "2.0.0-rc.0" +tauri-plugin-global-shortcut = "2.0.1" +tauri-plugin-http = "2.0.4" +tauri-plugin-notification = "2.0.1" +tauri-plugin-os = "2.0.0" +tauri-plugin-process = "2.0.1" tauri-plugin-shell = "2.0.0" +tauri-plugin-single-instance = "2.0.1" tauri-plugin-store = "2.0.0" -tauri-plugin-os = "2.0.0" -tauri-plugin-process = "2.0.0" -tauri-plugin-dialog = "2.0.0" -tauri-plugin-updater = "2.0.0" -tauri-plugin-notification = "2.0.0-rc" +tauri-plugin-updater = "2.1.0" tauri-plugin-oauth = { git = "https://github.com/FabianLars/tauri-plugin-oauth", branch = "v2" } -tauri-plugin-global-shortcut = "2.0.0" -tauri-plugin-single-instance = "2.0.1" -tauri-plugin-http = "2.0.0-rc.0" -tauri-specta = { version = "=2.0.0-rc.20", features = ["derive", "typescript"] } +tauri-plugin-window-state = "2.0.2" serde = { version = "1", features = ["derive"] } serde_json = "1" @@ -46,7 +48,6 @@ uuid = { version = "1.10.0", features = ["v4"] } scap.workspace = true image = "0.25.2" mp4 = "0.14.0" -tauri-plugin-fs = "2.0.0-rc.0" futures-intrusive = "0.5.0" anyhow.workspace = true futures = "0.3" @@ -65,7 +66,8 @@ global-hotkey = "0.6.3" rand = "0.8.5" cpal.workspace = true keyed_priority_queue = "0.4.2" -sentry = { workspace = true } +sentry.workspace = true +clipboard-rs = "0.2.2" cap-utils = { path = "../../../crates/utils" } cap-project = { path = "../../../crates/project" } @@ -76,8 +78,6 @@ cap-media = { path = "../../../crates/media" } cap-flags = { path = "../../../crates/flags" } cap-recording = { path = "../../../crates/recording" } cap-export = { path = "../../../crates/export" } -tauri-plugin-window-state = "2.0.2" -tauri-plugin-clipboard-manager = "2.0.2" [target.'cfg(target_os = "macos")'.dependencies] core-graphics = "0.24.0" diff --git a/apps/desktop/src-tauri/assets/nsis-sidebar.bmp b/apps/desktop/src-tauri/assets/nsis-sidebar.bmp index 8933c03c..07460e15 100644 Binary files a/apps/desktop/src-tauri/assets/nsis-sidebar.bmp and b/apps/desktop/src-tauri/assets/nsis-sidebar.bmp differ diff --git a/apps/desktop/src-tauri/assets/wix-banner.bmp b/apps/desktop/src-tauri/assets/wix-banner.bmp index 94369ead..3fcc7467 100644 Binary files a/apps/desktop/src-tauri/assets/wix-banner.bmp and b/apps/desktop/src-tauri/assets/wix-banner.bmp differ diff --git a/apps/desktop/src-tauri/assets/wix-dialog.bmp b/apps/desktop/src-tauri/assets/wix-dialog.bmp new file mode 100644 index 00000000..36625dc9 Binary files /dev/null and b/apps/desktop/src-tauri/assets/wix-dialog.bmp differ diff --git a/apps/desktop/src-tauri/capabilities/default.json b/apps/desktop/src-tauri/capabilities/default.json index 9374964e..fc8192f1 100644 --- a/apps/desktop/src-tauri/capabilities/default.json +++ b/apps/desktop/src-tauri/capabilities/default.json @@ -18,6 +18,8 @@ "core:window:allow-set-focus", "core:window:allow-start-dragging", "core:window:allow-set-position", + "core:window:allow-set-theme", + "core:window:allow-set-progress-bar", "core:webview:default", "core:webview:allow-create-webview-window", "core:app:allow-version", @@ -32,7 +34,6 @@ { "identifier": "http:default", "allow": [{ "url": "https://cap.so" }] - }, - "clipboard-manager:allow-write-text" + } ] } diff --git a/apps/desktop/src-tauri/icons/macos/icon.icns b/apps/desktop/src-tauri/icons/macos/icon.icns new file mode 100644 index 00000000..5ff9d031 Binary files /dev/null and b/apps/desktop/src-tauri/icons/macos/icon.icns differ diff --git a/apps/desktop/src-tauri/icons/macos/icon.png b/apps/desktop/src-tauri/icons/macos/icon.png new file mode 100644 index 00000000..15fca4af Binary files /dev/null and b/apps/desktop/src-tauri/icons/macos/icon.png differ diff --git a/apps/desktop/src-tauri/src/fake_window.rs b/apps/desktop/src-tauri/src/fake_window.rs index 909eb2f6..4eaf3bc5 100644 --- a/apps/desktop/src-tauri/src/fake_window.rs +++ b/apps/desktop/src-tauri/src/fake_window.rs @@ -57,9 +57,14 @@ pub fn spawn_fake_window_listener(app: AppHandle, window: WebviewWindow) { continue; }; - let window_position = window.outer_position().unwrap(); - let mouse_position = window.cursor_position().unwrap(); - let scale_factor = window.scale_factor().unwrap(); + let (Ok(window_position), Ok(mouse_position), Ok(scale_factor)) = ( + window.outer_position(), + window.cursor_position(), + window.scale_factor(), + ) else { + let _ = window.set_ignore_cursor_events(true); + continue; + }; let mut ignore = true; diff --git a/apps/desktop/src-tauri/src/general_settings.rs b/apps/desktop/src-tauri/src/general_settings.rs index 09fe123d..88c11db1 100644 --- a/apps/desktop/src-tauri/src/general_settings.rs +++ b/apps/desktop/src-tauri/src/general_settings.rs @@ -24,7 +24,16 @@ pub struct GeneralSettingsStore { #[serde(default = "true_b")] pub has_completed_startup: bool, #[serde(default)] - pub dark_mode: bool, + pub theme: AppTheme, +} + +#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, Type)] +#[serde(rename_all = "camelCase")] +pub enum AppTheme { + #[default] + System, + Light, + Dark, } fn true_b() -> bool { diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 28fc6e22..93edf8f3 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -30,6 +30,8 @@ use cap_media::{ use cap_project::{Content, ProjectConfiguration, RecordingMeta, SharingMeta}; use cap_recording::RecordingOptions; use cap_rendering::ProjectRecordings; +use clipboard_rs::common::RustImage; +use clipboard_rs::{Clipboard, ClipboardContext}; // use display::{list_capture_windows, Bounds, CaptureTarget, FPS}; use cap_export::is_valid_mp4; use general_settings::GeneralSettingsStore; @@ -750,73 +752,15 @@ async fn copy_file_to_path(app: AppHandle, src: String, dst: String) -> Result<( #[tauri::command] #[specta::specta] -async fn copy_screenshot_to_clipboard(app: AppHandle, path: PathBuf) -> Result<(), String> { +async fn copy_screenshot_to_clipboard( + clipboard: MutableState<'_, ClipboardContext>, + path: String, +) -> Result<(), String> { println!("Copying screenshot to clipboard: {:?}", path); - let image_data = match tokio::fs::read(&path).await { - Ok(data) => data, - Err(e) => { - println!("Failed to read screenshot file: {}", e); - notifications::send_notification( - &app, - notifications::NotificationType::ScreenshotCopyFailed, - ); - return Err(format!("Failed to read screenshot file: {}", e)); - } - }; - - #[cfg(target_os = "macos")] - { - use cocoa::appkit::{NSImage, NSPasteboard}; - use cocoa::base::{id, nil}; - use cocoa::foundation::{NSArray, NSData}; - use objc::rc::autoreleasepool; - - let result = unsafe { - autoreleasepool(|| { - let pasteboard: id = NSPasteboard::generalPasteboard(nil); - NSPasteboard::clearContents(pasteboard); - - let ns_data = NSData::dataWithBytes_length_( - nil, - image_data.as_ptr() as *const std::os::raw::c_void, - image_data.len() as u64, - ); - - let image = NSImage::initWithData_(NSImage::alloc(nil), ns_data); - if image != nil { - NSPasteboard::writeObjects(pasteboard, NSArray::arrayWithObject(nil, image)); - Ok(()) - } else { - Err("Failed to create NSImage from data".to_string()) - } - }) - }; - - if let Err(e) = result { - notifications::send_notification( - &app, - notifications::NotificationType::ScreenshotCopyFailed, - ); - return Err(e); - } - - notifications::send_notification( - &app, - notifications::NotificationType::ScreenshotCopiedToClipboard, - ); - } - - // TODO(Ilya) (Windows) Add support - #[cfg(not(target_os = "macos"))] - { - notifications::send_notification( - &app, - notifications::NotificationType::ScreenshotCopyFailed, - ); - return Err("Clipboard operations are only supported on macOS".to_string()); - } - + let img_data = clipboard_rs::RustImageData::from_path(&path) + .map_err(|e| format!("Failed to copy screenshot to clipboard: {}", e))?; + clipboard.write().await.set_image(img_data); Ok(()) } @@ -937,68 +881,18 @@ async fn create_editor_instance( #[tauri::command] #[specta::specta] -async fn copy_video_to_clipboard(app: AppHandle, path: String) -> Result<(), String> { +async fn copy_video_to_clipboard( + app: AppHandle, + clipboard: MutableState<'_, ClipboardContext>, + path: String, +) -> Result<(), String> { println!("copying"); - - #[cfg(target_os = "macos")] - { - use cocoa::appkit::NSPasteboard; - use cocoa::base::{id, nil}; - use cocoa::foundation::{NSArray, NSString, NSURL}; - use objc::rc::autoreleasepool; - - let result: Result<(), String> = unsafe { - autoreleasepool(|| { - let pasteboard: id = NSPasteboard::generalPasteboard(nil); - NSPasteboard::clearContents(pasteboard); - - let url_str = NSString::alloc(nil).init_str(&path); - let url = NSURL::fileURLWithPath_(nil, url_str); - - if url == nil { - return Err("Failed to create NSURL".to_string()); - } - - let objects = NSArray::arrayWithObject(nil, url); - if objects == nil { - return Err("Failed to create NSArray".to_string()); - } - - #[cfg(target_arch = "x86_64")] - { - let write_result: i8 = NSPasteboard::writeObjects(pasteboard, objects); - if write_result == 0 { - return Err("Failed to write to pasteboard".to_string()); - } - } - - #[cfg(target_arch = "aarch64")] - { - let write_result: bool = NSPasteboard::writeObjects(pasteboard, objects); - if !write_result { - return Err("Failed to write to pasteboard".to_string()); - } - } - - Ok(()) - }) - }; - - if let Err(e) = result { - println!("Failed to copy to clipboard: {}", e); - notifications::send_notification( - &app, - notifications::NotificationType::VideoCopyFailed, - ); - return Err(e); - } - } + let _ = clipboard.write().await.set_files(vec![path]); notifications::send_notification( &app, notifications::NotificationType::VideoCopiedToClipboard, ); - Ok(()) } @@ -1294,12 +1188,13 @@ async fn upload_exported_video( meta.save_for_project().ok(); RecordingMetaChanged { id: video_id }.emit(&app).ok(); - // Copy link to clipboard - #[cfg(target_os = "macos")] - platform::macos::write_string_to_pasteboard(&uploaded_video.link); + let _ = app + .state::>() + .write() + .await + .set_text(uploaded_video.link.clone()); NotificationType::ShareableLinkCopied.send(&app); - Ok(UploadResult::Success(uploaded_video.link)) } Err(e) => { @@ -1313,6 +1208,7 @@ async fn upload_exported_video( #[specta::specta] async fn upload_screenshot( app: AppHandle, + clipboard: MutableState<'_, ClipboardContext>, screenshot_path: PathBuf, ) -> Result { let Ok(Some(mut auth)) = AuthStore::get(&app) else { @@ -1384,8 +1280,7 @@ async fn upload_screenshot( println!("Copying to clipboard: {:?}", share_link); // Copy link to clipboard - #[cfg(target_os = "macos")] - platform::write_string_to_pasteboard(&share_link); + let _ = clipboard.write().await.set_text(share_link.clone()); // Send notification after successful upload and clipboard copy notifications::send_notification(&app, notifications::NotificationType::ShareableLinkCopied); @@ -1839,7 +1734,8 @@ async fn seek_to(app: AppHandle, video_id: String, frame_number: u32) { .await; } -#[tauri::command] +// keep this async otherwise opening windows may hang on windows +#[tauri::command(async)] #[specta::specta] fn show_window(app: AppHandle, window: ShowCapWindow) { window.show(&app).ok(); @@ -1879,18 +1775,6 @@ async fn check_notification_permissions(app: AppHandle) { } } -#[tauri::command] -#[specta::specta] -fn set_window_theme(window: tauri::Window, dark: bool) { - window - .set_theme(Some(if dark { - tauri::Theme::Dark - } else { - tauri::Theme::Light - })) - .ok(); -} - #[cfg_attr(mobile, tauri::mobile_entry_point)] pub async fn run() { let specta_builder = tauri_specta::Builder::new() @@ -1943,9 +1827,10 @@ pub async fn run() { seek_to, send_feedback_request, windows::position_traffic_lights, + windows::set_theme, global_message_dialog, show_window, - set_window_theme, + write_clipboard_string, ]) .events(tauri_specta::collect_events![ RecordingOptionsChanged, @@ -2010,7 +1895,6 @@ pub async fn run() { .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_notification::init()) - .plugin(tauri_plugin_clipboard_manager::init()) .plugin( tauri_plugin_window_state::Builder::new() .with_state_flags({ @@ -2105,6 +1989,10 @@ pub async fn run() { pre_created_video: None, }))); + app.manage(Arc::new(RwLock::new( + ClipboardContext::new().expect("Failed to create clipboard context"), + ))); + tray::create_tray(&app).unwrap(); RequestStartRecording::listen_any_spawn(&app, |_, app| async move { @@ -2390,6 +2278,20 @@ fn global_message_dialog(app: AppHandle, message: String) { app.dialog().message(message).show(|_| {}); } +#[tauri::command] +#[specta::specta] +async fn write_clipboard_string( + clipboard: MutableState<'_, ClipboardContext>, + text: String, +) -> Result<(), String> { + let writer = clipboard + .try_write() + .map_err(|e| format!("Failed to acquire lock on clipboard state: {e}"))?; + writer + .set_text(text) + .map_err(|e| format!("Failed to write text to clipboard: {e}")) +} + trait EventExt: tauri_specta::Event { fn listen_any_spawn( app: &AppHandle, diff --git a/apps/desktop/src-tauri/src/platform/macos/mod.rs b/apps/desktop/src-tauri/src/platform/macos/mod.rs index efe75b2d..28d368c3 100644 --- a/apps/desktop/src-tauri/src/platform/macos/mod.rs +++ b/apps/desktop/src-tauri/src/platform/macos/mod.rs @@ -52,22 +52,6 @@ extern "C" { rect: *mut CGRect, ) -> boolean_t; } -pub fn write_string_to_pasteboard(string: &str) { - use cocoa::appkit::NSPasteboard; - use cocoa::base::{id, nil}; - use cocoa::foundation::{NSArray, NSString}; - use objc::rc::autoreleasepool; - - unsafe { - autoreleasepool(|| { - let pasteboard: id = NSPasteboard::generalPasteboard(nil); - NSPasteboard::clearContents(pasteboard); - let ns_string = NSString::alloc(nil).init_str(string); - let objects: id = NSArray::arrayWithObject(nil, ns_string); - NSPasteboard::writeObjects(pasteboard, objects); - }); - } -} /// Makes the background of the WKWebView layer transparent. /// This differs from Tauri's implementation as it does not change the window background which causes performance performance issues and artifacts when shadows are enabled on the window. diff --git a/apps/desktop/src-tauri/src/recording.rs b/apps/desktop/src-tauri/src/recording.rs index 290a1e53..da093dfa 100644 --- a/apps/desktop/src-tauri/src/recording.rs +++ b/apps/desktop/src-tauri/src/recording.rs @@ -21,6 +21,7 @@ use cap_project::{ }; use cap_recording::CompletedRecording; use cap_rendering::{ProjectRecordings, ZOOM_DURATION}; +use clipboard_rs::{Clipboard, ClipboardContext}; use tauri::{AppHandle, Manager}; use tauri_specta::Event; @@ -217,8 +218,11 @@ pub async fn stop_recording(app: AppHandle, state: MutableState<'_, App>) -> Res if auth.is_upgraded() && settings.auto_create_shareable_link { if let Some(pre_created_video) = state.pre_created_video.take() { // Copy link to clipboard - #[cfg(target_os = "macos")] - platform::write_string_to_pasteboard(&pre_created_video.link); + let _ = app + .state::>() + .write() + .await + .set_text(pre_created_video.link.clone()); // Send notification for shareable link notifications::send_notification( diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index b2d6f716..e6d15e8f 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -1,6 +1,6 @@ #![allow(unused_mut)] -use crate::fake_window; +use crate::{fake_window, general_settings::AppTheme}; use cap_flags::FLAGS; use serde::Deserialize; use specta::Type; @@ -136,7 +136,6 @@ impl ShowCapWindow { .center() .focused(true) .maximizable(false) - // .theme(Some(tauri::Theme::Light)) .shadow(true) .build()?, Self::Main => self @@ -145,8 +144,6 @@ impl ShowCapWindow { .resizable(false) .maximized(false) .maximizable(false) - .maximized(false) - // .theme(Some(tauri::Theme::Light)) .build()?, Self::Settings { page } => self .window_builder( @@ -156,13 +153,11 @@ impl ShowCapWindow { .min_inner_size(600.0, 450.0) .resizable(true) .maximized(false) - // .theme(Some(tauri::Theme::Light)) .build()?, Self::Editor { project_id } => self .window_builder(app, format!("/editor?id={project_id}")) .inner_size(1150.0, 800.0) .maximizable(true) - // .theme(Some(tauri::Theme::Dark)) .build()?, Self::Upgrade => self .window_builder(app, "/upgrade") @@ -259,7 +254,6 @@ impl ShowCapWindow { ((monitor.size().width as f64) / monitor.scale_factor() - width) / 2.0, (monitor.size().height as f64) / monitor.scale_factor() - height - 120.0, ) - // .theme(Some(tauri::Theme::Dark)) .skip_taskbar(true) .build()? } @@ -339,8 +333,7 @@ impl ShowCapWindow { .title(id.title()) .visible(false) .accept_first_mouse(true) - .shadow(true) - .theme(Some(tauri::Theme::Light)); + .shadow(true); #[cfg(target_os = "macos")] { @@ -404,11 +397,35 @@ fn add_traffic_lights(window: &WebviewWindow, controls_inset: Option None, + AppTheme::Light => Some(tauri::Theme::Light), + AppTheme::Dark => Some(tauri::Theme::Dark), + }); + + #[cfg(target_os = "macos")] + match CapWindowId::from_str(window.label()) { + Ok(win) if win.traffic_lights_position().is_some() => position_traffic_lights(window, None), + Ok(_) | Err(_) => {} + } +} + #[tauri::command] #[specta::specta] pub fn position_traffic_lights(window: tauri::Window, controls_inset: Option<(f64, f64)>) { #[cfg(target_os = "macos")] - position_traffic_lights_impl(&window, controls_inset.map(LogicalPosition::from)); + position_traffic_lights_impl( + &window, + controls_inset.map(LogicalPosition::from).or_else(|| { + // Attempt to get the default inset from the window's traffic lights position + CapWindowId::from_str(window.label()) + .ok() + .and_then(|id| id.traffic_lights_position().flatten()) + }), + ); } #[cfg(target_os = "macos")] diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 6aeeea1f..0542db77 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -1,12 +1,12 @@ { - "$schema": "../node_modules/@tauri-apps/cli/schema.json", + "$schema": "https://schema.tauri.app/config/2", "productName": "Cap - Development", "identifier": "so.cap.desktop.dev", "mainBinaryName": "Cap - Development", "build": { - "beforeDevCommand": "node scripts/prepareSidecars.js && pnpm localdev", + "beforeDevCommand": "pnpm localdev", "devUrl": "http://localhost:3001", - "beforeBuildCommand": "node scripts/prepareSidecars.js && pnpm turbo build --filter @cap/desktop", + "beforeBuildCommand": "pnpm turbo build --filter @cap/desktop", "beforeBundleCommand": "node scripts/stripDebugSymbols.js", "frontendDist": "../.output/public" }, @@ -38,7 +38,7 @@ "icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", - "icons/icon.icns", + "icons/macos/icon.icns", "icons/icon.ico" ], "externalBin": ["../../../target/binaries/ffmpeg"], @@ -62,7 +62,9 @@ "installerIcon": "icons/icon.ico" }, "wix": { - "bannerPath": "assets/wix-banner.bmp" + "upgradeCode": "79f4309d-ca23-54df-b6f9-826a1d783676", + "bannerPath": "assets/wix-banner.bmp", + "dialogImagePath": "assets/wix-dialog.bmp" } } } diff --git a/apps/desktop/src-tauri/tauri.conf.prod.json b/apps/desktop/src-tauri/tauri.conf.prod.json index 1af7ed9c..93b35f2e 100644 --- a/apps/desktop/src-tauri/tauri.conf.prod.json +++ b/apps/desktop/src-tauri/tauri.conf.prod.json @@ -1,5 +1,5 @@ { - "$schema": "../node_modules/@tauri-apps/cli/schema.json", + "$schema": "https://schema.tauri.app/config/2", "productName": "Cap", "mainBinaryName": "Cap", "identifier": "so.cap.desktop", @@ -14,6 +14,11 @@ "bundle": { "macOS": { "entitlements": "Entitlements.plist" + }, + "windows": { + "wix": { + "upgradeCode": "a765d9de-0ecc-55d0-b8a0-61e9d3276664" + } } } } diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index c03e7546..93a43800 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -1,22 +1,25 @@ import { Router, useCurrentMatches } from "@solidjs/router"; import { FileRoutes } from "@solidjs/start/router"; import { - createEffect, createResource, ErrorBoundary, + onCleanup, onMount, Suspense, } from "solid-js"; import { QueryClient, QueryClientProvider } from "@tanstack/solid-query"; -import { getCurrentWindow } from "@tauri-apps/api/window"; import { message } from "@tauri-apps/plugin-dialog"; import "@cap/ui-solid/main.css"; import "unfonts.css"; import "./styles/theme.css"; import { generalSettingsStore } from "./store"; -import { getCurrentWebview } from "@tauri-apps/api/webview"; -import { commands } from "./utils/tauri"; +import { commands, type AppTheme } from "./utils/tauri"; +import type { UnlistenFn } from "@tauri-apps/api/event"; +import { + getCurrentWebviewWindow, + WebviewWindow, +} from "@tauri-apps/api/webviewWindow"; const queryClient = new QueryClient({ defaultOptions: { @@ -37,7 +40,8 @@ export default function App() { } function Inner() { - createThemeListener(); + const currentWindow = getCurrentWebviewWindow(); + createThemeListener(currentWindow); return ( {props.children}; @@ -74,30 +78,39 @@ function Inner() { ); } -function createThemeListener() { - const [theme, themeActions] = createResource(() => - generalSettingsStore.get().then((s) => s?.darkMode ?? null) +function createThemeListener(currentWindow: WebviewWindow) { + const [theme, themeActions] = createResource(() => + generalSettingsStore.get().then((s) => { + const t = s?.theme ?? null; + update(t); + return t; + }) ); - generalSettingsStore.listen((s) => { - themeActions.mutate(s?.darkMode); + themeActions.mutate(s?.theme ?? null); + update(theme()); + }); + + let unlisten: UnlistenFn | undefined; + onMount(async () => { + unlisten = await currentWindow.onThemeChanged((_) => update(theme())); }); + onCleanup(() => unlisten?.()); - createEffect(() => { - let t = theme(); + function update(appTheme: AppTheme | null | undefined) { + if (appTheme === undefined || appTheme === null) return; if ( location.pathname === "/camera" || location.pathname === "/prev-recordings" ) - t = false; - if (t === undefined) return; - - commands.setWindowTheme(!!t); + return; - if (t) { - document.documentElement.classList.add("dark"); - } else { - document.documentElement.classList.remove("dark"); - } - }); + commands.setTheme(appTheme).then(() => { + document.documentElement.classList.toggle( + "dark", + appTheme === "dark" || + window.matchMedia("(prefers-color-scheme: dark)").matches + ); + }); + } } diff --git a/apps/desktop/src/assets/theme-previews/auto.jpg b/apps/desktop/src/assets/theme-previews/auto.jpg new file mode 100644 index 00000000..6ba498fc Binary files /dev/null and b/apps/desktop/src/assets/theme-previews/auto.jpg differ diff --git a/apps/desktop/src/assets/theme-previews/dark.jpg b/apps/desktop/src/assets/theme-previews/dark.jpg new file mode 100644 index 00000000..0f391636 Binary files /dev/null and b/apps/desktop/src/assets/theme-previews/dark.jpg differ diff --git a/apps/desktop/src/assets/theme-previews/light.jpg b/apps/desktop/src/assets/theme-previews/light.jpg new file mode 100644 index 00000000..f52be40b Binary files /dev/null and b/apps/desktop/src/assets/theme-previews/light.jpg differ diff --git a/apps/desktop/src/components/titlebar/Titlebar.tsx b/apps/desktop/src/components/titlebar/Titlebar.tsx index 1f4353e0..16019842 100644 --- a/apps/desktop/src/components/titlebar/Titlebar.tsx +++ b/apps/desktop/src/components/titlebar/Titlebar.tsx @@ -1,5 +1,5 @@ // Credits: tauri-controls -import { ComponentProps, Match, splitProps, Switch } from "solid-js"; +import { type ComponentProps, Match, splitProps, Switch } from "solid-js"; import { type } from "@tauri-apps/plugin-os"; import CaptionControlsWindows11 from "./controls/CaptionControlsWindows11"; import titlebarState from "~/utils/titlebar-state"; @@ -51,7 +51,7 @@ function WindowControls(props: ComponentProps<"div">) { /> -
+
); diff --git a/apps/desktop/src/components/titlebar/controls/CaptionControlsWindows11.tsx b/apps/desktop/src/components/titlebar/controls/CaptionControlsWindows11.tsx index b5f8651b..bff87474 100644 --- a/apps/desktop/src/components/titlebar/controls/CaptionControlsWindows11.tsx +++ b/apps/desktop/src/components/titlebar/controls/CaptionControlsWindows11.tsx @@ -1,4 +1,4 @@ -import { ComponentProps, JSX, Show, splitProps } from "solid-js"; +import { type ComponentProps, createSignal, type JSX, onCleanup, onMount, Show, splitProps } from "solid-js"; import { WindowControlButton as ControlButton } from "./WindowControlButton"; import { getCurrentWindow } from "@tauri-apps/api/window"; import titlebarState from "~/utils/titlebar-state"; @@ -6,44 +6,52 @@ import { cx } from "cva"; export default function (props: ComponentProps<"div">) { const [local, otherProps] = splitProps(props, ["class"]); - const window = getCurrentWindow(); + const currentWindow = getCurrentWindow(); + const [focused, setFocus] = createSignal(true); + + let unlisten: () => void | undefined; + onMount(async () => { + unlisten = await currentWindow.onFocusChanged(({ payload: focused }) => setFocus(focused)); + }); + onCleanup(() => unlisten?.()); return (
*]:opacity-30" + "hover:bg-[#0000000D] dark:hover:bg-[#FFFFFF0D] active:bg-[#00000008] dark:active:bg-[#e9e9e908]", + "disabled:hover:bg-transparent dark:disabled:hover:bg-transparent disabled:text-black-transparent-40", )} > *]:opacity-30" + "hover:bg-[#0000000D] dark:hover:bg-[#FFFFFF0D] active:bg-[#00000008] dark:active:bg-[#e9e9e908]", + "disabled:hover:bg-transparent dark:disabled:hover:bg-transparent disabled:text-black-transparent-40", )} > {titlebarState.maximized ? ( @@ -54,15 +62,12 @@ export default function (props: ComponentProps<"div">) { *]:opacity-30" + "max-h-20 w-[46px] rounded-none bg-transparent hover:text-gray-50", + "hover:bg-[#c42b1c] dark:hover:bg-[#c42b1c active:bg-[#c42b1c]/90 dark:active:bg-[#c42b1c]/90", + "disabled:hover:bg-transparent dark:disabled:hover:bg-transparent disabled:text-black-transparent-40", )} > diff --git a/apps/desktop/src/entry-client.tsx b/apps/desktop/src/entry-client.tsx index 0ca4e3c3..c4f2cfe0 100644 --- a/apps/desktop/src/entry-client.tsx +++ b/apps/desktop/src/entry-client.tsx @@ -1,4 +1,6 @@ // @refresh reload import { mount, StartClient } from "@solidjs/start/client"; +import { type } from "@tauri-apps/plugin-os"; +document.documentElement.classList.add(`platform-${type()}`); mount(() => , document.getElementById("app")!); diff --git a/apps/desktop/src/routes/(window-chrome)/(main).tsx b/apps/desktop/src/routes/(window-chrome)/(main).tsx index f74525f9..668d39fe 100644 --- a/apps/desktop/src/routes/(window-chrome)/(main).tsx +++ b/apps/desktop/src/routes/(window-chrome)/(main).tsx @@ -84,7 +84,7 @@ export default function () { }, })); - const [isUpgraded] = createResource(() => commands.checkUpgradedAndUpdate()); + const [isUpgraded] = createResource(checkIsUpgradedAndUpdate); createAsync(() => getAuth()); @@ -127,8 +127,10 @@ export default function () {
-