diff --git a/package.json b/package.json index 170a296..2348626 100644 --- a/package.json +++ b/package.json @@ -8,5 +8,9 @@ }, "devDependencies": { "@tauri-apps/cli": "^2" + }, + "dependencies": { + "@tauri-apps/plugin-dialog": "~2", + "@tauri-apps/plugin-fs": "~2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0587e78..9af2e76 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,13 @@ settings: importers: .: + dependencies: + '@tauri-apps/plugin-dialog': + specifier: ~2 + version: 2.0.1 + '@tauri-apps/plugin-fs': + specifier: ~2 + version: 2.0.2 devDependencies: '@tauri-apps/cli': specifier: ^2 @@ -14,6 +21,9 @@ importers: packages: + '@tauri-apps/api@2.1.1': + resolution: {integrity: sha512-fzUfFFKo4lknXGJq8qrCidkUcKcH2UHhfaaCNt4GzgzGaW2iS26uFOg4tS3H4P8D6ZEeUxtiD5z0nwFF0UN30A==} + '@tauri-apps/cli-darwin-arm64@2.0.4': resolution: {integrity: sha512-siH7rOHobb16rPbc11k64p1mxIpiRCkWmzs2qmL5IX21Gx9K5onI3Tk67Oqpf2uNupbYzItrOttaDT4NHFC7tw==} engines: {node: '>= 10'} @@ -79,8 +89,16 @@ packages: engines: {node: '>= 10'} hasBin: true + '@tauri-apps/plugin-dialog@2.0.1': + resolution: {integrity: sha512-fnUrNr6EfvTqdls/ufusU7h6UbNFzLKvHk/zTuOiBq01R3dTODqwctZlzakdbfSp/7pNwTKvgKTAgl/NAP/Z0Q==} + + '@tauri-apps/plugin-fs@2.0.2': + resolution: {integrity: sha512-4YZaX2j7ta81M5/DL8aN10kTnpUkEpkPo1FTYPT8Dd0ImHe3azM8i8MrtjrDGoyBYLPO3zFv7df/mSCYF8oA0Q==} + snapshots: + '@tauri-apps/api@2.1.1': {} + '@tauri-apps/cli-darwin-arm64@2.0.4': optional: true @@ -123,3 +141,11 @@ snapshots: '@tauri-apps/cli-win32-arm64-msvc': 2.0.4 '@tauri-apps/cli-win32-ia32-msvc': 2.0.4 '@tauri-apps/cli-win32-x64-msvc': 2.0.4 + + '@tauri-apps/plugin-dialog@2.0.1': + dependencies: + '@tauri-apps/api': 2.1.1 + + '@tauri-apps/plugin-fs@2.0.2': + dependencies: + '@tauri-apps/api': 2.1.1 diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0c418de..a828459 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -62,6 +62,61 @@ version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +[[package]] +name = "ashpd" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c39d707614dbcc6bed00015539f488d8e3fe3e66ed60961efc0c90f4b380b3" +dependencies = [ + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.8.5", + "raw-window-handle", + "serde", + "serde_repr", + "tokio", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "atk" version = "0.18.0" @@ -373,6 +428,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -605,6 +669,15 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + [[package]] name = "dlopen2" version = "0.7.0" @@ -628,6 +701,12 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dpi" version = "0.1.1" @@ -693,6 +772,33 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -709,6 +815,43 @@ dependencies = [ "typeid", ] +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" + [[package]] name = "fdeflate" version = "0.3.6" @@ -1079,7 +1222,7 @@ 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", @@ -1735,9 +1878,17 @@ dependencies = [ "serde_json", "tauri", "tauri-build", + "tauri-plugin-dialog", + "tauri-plugin-fs", "tauri-plugin-shell", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "litemap" version = "0.7.3" @@ -1894,6 +2045,19 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -1930,7 +2094,7 @@ 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 1.3.1", "proc-macro2", "quote", "syn 2.0.87", @@ -2054,6 +2218,7 @@ checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.6.0", "block2", + "dispatch", "libc", "objc2", ] @@ -2195,6 +2360,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "os_pipe" version = "1.2.1" @@ -2230,6 +2405,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -2425,7 +2606,7 @@ checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64 0.22.1", "indexmap 2.6.0", - "quick-xml", + "quick-xml 0.32.0", "serde", "time", ] @@ -2476,14 +2657,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" @@ -2532,6 +2721,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.37" @@ -2714,6 +2912,29 @@ dependencies = [ "windows-registry", ] +[[package]] +name = "rfd" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f6f80a9b882647d9014673ca9925d30ffc9750f2eed2b4490e189eaebd01e8" +dependencies = [ + "ashpd", + "block2", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.48.0", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2729,6 +2950,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "ryu" version = "1.0.18" @@ -2771,6 +3005,12 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -2981,6 +3221,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -3072,6 +3321,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.7" @@ -3356,6 +3611,45 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-dialog" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4307310e1d2c09ab110235834722e7c2b85099b683e1eb7342ab351b0be5ada3" +dependencies = [ + "log", + "raw-window-handle", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror", + "url", +] + +[[package]] +name = "tauri-plugin-fs" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ba7d46e86db8c830d143ef90ab5a453328365b0cc834c24edea4267b16aba0" +dependencies = [ + "anyhow", + "dunce", + "glob", + "percent-encoding", + "schemars", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "thiserror", + "url", + "uuid", +] + [[package]] name = "tauri-plugin-shell" version = "2.0.2" @@ -3468,6 +3762,19 @@ dependencies = [ "toml 0.7.8", ] +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "tendril" version = "0.4.3" @@ -3557,7 +3864,9 @@ dependencies = [ "libc", "mio", "pin-project-lite", + "signal-hook-registry", "socket2", + "tracing", "windows-sys 0.52.0", ] @@ -3600,9 +3909,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", ] @@ -3617,7 +3926,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] @@ -3630,7 +3939,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.6.0", + "toml_datetime", + "winnow 0.6.20", ] [[package]] @@ -3646,9 +3966,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -3697,6 +4029,17 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + [[package]] name = "unic-char-property" version = "0.9.0" @@ -3945,6 +4288,66 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wayland-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" +dependencies = [ + "bitflags 2.6.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml 0.36.2", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.72" @@ -4396,6 +4799,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" @@ -4480,6 +4892,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "yoke" version = "0.7.4" @@ -4504,6 +4926,63 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1162094dc63b1629fcc44150bcceeaa80798cd28bcbe7fa987b65a034c258608" +dependencies = [ + "async-broadcast", + "async-recursion", + "async-trait", + "enumflags2", + "event-listener", + "futures-core", + "futures-util", + "hex", + "nix", + "ordered-stream", + "serde", + "serde_repr", + "static_assertions", + "tokio", + "tracing", + "uds_windows", + "windows-sys 0.59.0", + "winnow 0.6.20", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd2dcdce3e2727f7d74b7e33b5a89539b3cc31049562137faf7ae4eb86cd16d" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.87", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856b7a38811f71846fd47856ceee8bccaec8399ff53fb370247e66081ace647b" +dependencies = [ + "serde", + "static_assertions", + "winnow 0.6.20", + "zvariant", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -4567,3 +5046,46 @@ dependencies = [ "quote", "syn 2.0.87", ] + +[[package]] +name = "zvariant" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1200ee6ac32f1e5a312e455a949a4794855515d34f9909f4a3e082d14e1a56f" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "url", + "winnow 0.6.20", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687e3b97fae6c9104fbbd36c73d27d149abf04fb874e2efbd84838763daa8916" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.87", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20d1d011a38f12360e5fcccceeff5e2c42a8eb7f27f0dcba97a0862ede05c9c6" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "static_assertions", + "syn 2.0.87", + "winnow 0.6.20", +] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 2cbf491..e7d269e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -22,4 +22,6 @@ tauri = { version = "2", features = [] } tauri-plugin-shell = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" +tauri-plugin-fs = "2" +tauri-plugin-dialog = "2" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 3bb4cc4..f2367cf 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -2,9 +2,29 @@ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "Capability for the main window", - "windows": ["main"], + "windows": [ + "main" + ], "permissions": [ "core:default", - "shell:allow-open" + "shell:allow-open", + "fs:default", + { + "identifier": "fs:allow-exists", + "allow": [ + { + "path": "$DOCUMENT/*" + } + ] + }, + { + "identifier": "fs:allow-app-write-recursive", + "allow": [ + { + "path": "$DOCUMENT/*" + } + ] + }, + "dialog:default" ] -} +} \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index f91b35e..60d6479 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -7,6 +7,8 @@ fn greet(name: &str) -> String { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_shell::init()) .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!()) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8d0291d..0cd2754 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -6,13 +6,14 @@ "build": { "frontendDist": "../src" }, + "app": { "withGlobalTauri": true, "windows": [ { "title": "lightningbeam", - "width": 800, - "height": 600 + "width": 1500, + "height": 1024 } ], "security": { diff --git a/src/main.js b/src/main.js index 9c258b6..9c2df09 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,10 @@ const { invoke } = window.__TAURI__.core; import * as fitCurve from '/fit-curve.js'; import { Bezier } from "/bezier.js"; -import earcut from './earcut.js'; - +import { Quadtree } from './quadtree.js'; +const { writeTextFile, BaseDirectory }= window.__TAURI__.fs; +const { save } = window.__TAURI__.dialog; +const { documentDir, join } = window.__TAURI__.path; let simplifyPolyline = simplify @@ -22,6 +24,7 @@ let redoStack = []; let layoutElements = [] + let tools = { select: { icon: "/assets/select.svg", @@ -94,6 +97,7 @@ let config = { // undo: "+z" undo: "z", redo: "Z", + save: "s", } } @@ -191,6 +195,26 @@ let actions = { shape.update() } }, + colorRegion: { + create: (region, color) => { + redoStack.length = 0; // Clear redo stack + let action = { + region: region.idx, + oldColor: region.fillStyle, + newColor: color + } + undoStack.push({name: "colorRegion", action: action}) + actions.colorRegion.execute(action) + }, + execute: (action) => { + let region = pointerList[action.region] + region.fillStyle = action.newColor + }, + rollback: (action) => { + let region = pointerList[action.region] + region.fillStyle = action.oldColor + } + }, addImageObject: { create: (x, y, img, parent) => { redoStack.length = 0; // Clear redo stack @@ -543,19 +567,6 @@ function redo() { } -class Curve { - constructor(startx, starty, cp1x, cp1y, cp2x, cp2y, x, y) { - this.startx = startx - this.starty = starty - this.cp1x = cp1x; - this.cp1y = cp1y; - this.cp2x = cp2x; - this.cp2y = cp2y; - this.x = x; - this.y = y; - } -} - class Frame { constructor(uuid) { this.keys = {} @@ -603,6 +614,7 @@ class Shape { x: {min: startx, max: starty}, y: {min: starty, max: starty} } + this.quadtree = new Quadtree({x: {min: 0, max: 500}, y: {min: 0, max: 500}}, 4) if (!uuid) { this.idx = uuidv4() } else { @@ -612,6 +624,7 @@ class Shape { } addCurve(curve) { this.curves.push(curve) + this.quadtree.insert(curve, this.curves.length - 1) growBoundingBox(this.boundingBox, curve.bbox()) } addLine(x, y) { @@ -638,6 +651,7 @@ class Shape { } } simplify(mode="corners") { + this.quadtree.clear() // Mode can be corners, smooth or auto if (mode=="corners") { let points = [{x: this.startx, y: this.starty}] @@ -656,6 +670,7 @@ class Shape { midpoint.x,midpoint.y, point.x,point.y) this.curves.push(bezier) + this.quadtree.insert(bezier, this.curves.length - 1) lastpoint = point } } else if (mode=="smooth") { @@ -672,6 +687,7 @@ class Shape { curve[2][0], curve[2][1], curve[3][0], curve[3][1]) this.curves.push(bezier) + this.quadtree.insert(bezier, this.curves.length - 1) } } @@ -679,7 +695,10 @@ class Shape { let newCurves = [] let intersectMap = {} for (let i=0; i start) { - this.regions.push({ + let newRegion = { + idx: uuidv4(), // TODO: generate this deterministically so that undo/redo works curves: region.curves.splice(start, end - start), fillStyle: region.fillStyle, filled: true - }) + } + pointerList[newRegion.idx] = newRegion + this.regions.push(newRegion) } } else { // not sure how to handle vertices with more than 4 curves @@ -840,120 +860,6 @@ class Shape { } } }) - // Generate enclosed regions - let graph = {} - let edges = [] - this.vertices.forEach((vertex, i) => { - this.vertices.forEach((otherVertex, j) => { - for (let curve in vertex.startCurves) { - if (curve in otherVertex.endCurves) { - edges.push([i, j]) - if (graph[i]) { - graph[i].push(j) - } else { - graph[i] = [j] - } - } - } - for (let curve in vertex.endCurves) { - if (curve in otherVertex.startCurves) { - edges.push([i, j]) - if (graph[i]) { - graph[i].push(j) - } else { - graph[i] = [j] - } - } - } - }) - }) - // for (let vertex in graph) { - // let node = vertex - // let seenNodes = [] - // for (let i=0; i 1) { - for (let otherPolygon of polygons) { - if (polygon.every((val, idx) => val === otherPolygon[idx])) { - return; - } - } - polygons.push(polygon); - } - return; - } - - visited.add(node); - for (const edge of edges) { - if (edge[0] === node) { - dfs(edge[1], [...path, node]); - } else if (edge[1] === node) { - dfs(edge[0], [...path, node]); - } - } - } - - for (const edge of edges) { - dfs(edge[0], []); - } - - return polygons; - } - - /* - const polygons = findEnclosedPolygons(edges); - this.regions = [] - - for (let polygon of polygons) { - let region = [] - let firstVertex = undefined - let lastVertex = undefined - for (let vertex of polygon) { - firstVertex ||= vertex - if (lastVertex) { - for (let i in this.vertices[vertex].startCurves) { - let curve = this.vertices[vertex].startCurves[i] - if (i in this.vertices[lastVertex].endCurves) { - region.push(curve) - } - } - for (let i in this.vertices[vertex].endCurves) { - let curve = this.vertices[vertex].endCurves[i] - if (i in this.vertices[lastVertex].startCurves) { - region.push(new Bezier(curve.points.toReversed())) - } - } - } - lastVertex = vertex - } - for (let i in this.vertices[firstVertex].startCurves) { - let curve = this.vertices[firstVertex].startCurves[i] - if (i in this.vertices[lastVertex].endCurves) { - region.push(curve) - } - } - for (let i in this.vertices[firstVertex].endCurves) { - let curve = this.vertices[firstVertex].endCurves[i] - if (i in this.vertices[lastVertex].startCurves) { - region.push(new Bezier(curve.points.toReversed())) - } - } - if (region.length > 1) { - // Filter out single curves - this.regions.push(region) - } - }*/ } draw(context) { let ctx = context.ctx; @@ -993,6 +899,8 @@ class Shape { // ctx.arc(curve.points[3].x,curve.points[3].y, 3, 0, 2*Math.PI) // ctx.fill() } + // Debug, show quadtree + // this.quadtree.draw(ctx) } } @@ -1216,9 +1124,46 @@ window.addEventListener("keypress", (e) => { undo() } else if (e.key == config.shortcuts.redo && e.ctrlKey == true) { redo() + } else if (e.key == config.shortcuts.save && e.ctrlKey == true) { + saveFile() } }) +async function saveTextFile() { + console.log(await documentDir()) + const path = await save({ + filters: [ + { + name: 'Lightningbeam files (.beam)', + extensions: ['beam'], + }, + ], + defaultPath: await join(await documentDir(), "untitled.beam") + }); + console.log(path) + // console.log("saving") + // console.log(BaseDirectory) + try { + const fileData = { + version: "1.0", + actions: undoStack + } + const contents = JSON.stringify(fileData ); + await writeTextFile(path, contents)//, { + // baseDir: BaseDirectory.Document, + // }); + + // console.log("Text file saved successfully!"); + } catch (error) { + console.error("Error saving text file:", error); + } +} + +function saveFile() { + console.log("gonna save") + saveTextFile() +} + function stage() { let stage = document.createElement("canvas") let scroller = document.createElement("div") @@ -1339,7 +1284,6 @@ function stage() { let line = {p1: mouse, p2: {x: mouse.x + 3000, y: mouse.y}} for (let shape of context.activeObject.currentFrame.shapes) { for (let region of shape.regions) { - let intersect_count = 0; for (let curve of region.curves) { intersect_count += curve.intersects(line).length @@ -1347,7 +1291,8 @@ function stage() { console.log(region) console.log(intersect_count) if (intersect_count%2==1) { - region.fillStyle = context.fillStyle + // region.fillStyle = context.fillStyle + actions.colorRegion.create(region, context.fillStyle) } } }