diff --git a/Cargo.lock b/Cargo.lock index f3cd77db..e8883b65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" @@ -42,9 +42,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -111,37 +111,37 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.8" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -152,9 +152,9 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -169,15 +169,15 @@ checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -185,7 +185,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -196,9 +196,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" @@ -217,15 +217,15 @@ checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytemuck" -version = "1.23.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" @@ -244,9 +244,9 @@ dependencies = [ [[package]] name = "cap-fs-ext" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e41cc18551193fe8fa6f15c1e3c799bc5ec9e2cfbfaa8ed46f37013e3e6c173c" +checksum = "d5528f85b1e134ae811704e41ef80930f56e795923f866813255bc342cc20654" dependencies = [ "cap-primitives", "cap-std", @@ -256,9 +256,9 @@ dependencies = [ [[package]] name = "cap-primitives" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e394ed14f39f8bc26f59d4c0c010dbe7f0a1b9bafff451b1f98b67c8af62a" +checksum = "b6cf3aea8a5081171859ef57bc1606b1df6999df4f1110f8eef68b30098d1d3a" dependencies = [ "ambient-authority", "fs-set-times", @@ -266,7 +266,7 @@ dependencies = [ "io-lifetimes", "ipnet", "maybe-owned", - "rustix 1.0.7", + "rustix 1.1.3", "rustix-linux-procfs", "windows-sys 0.59.0", "winx", @@ -274,9 +274,9 @@ dependencies = [ [[package]] name = "cap-rand" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0acb89ccf798a28683f00089d0630dfaceec087234eae0d308c05ddeaa941b40" +checksum = "d8144c22e24bbcf26ade86cb6501a0916c46b7e4787abdb0045a467eb1645a1d" dependencies = [ "ambient-authority", "rand", @@ -284,36 +284,37 @@ dependencies = [ [[package]] name = "cap-std" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c0355ca583dd58f176c3c12489d684163861ede3c9efa6fd8bba314c984189" +checksum = "b6dc3090992a735d23219de5c204927163d922f42f575a0189b005c62d37549a" dependencies = [ "cap-primitives", "io-extras", "io-lifetimes", - "rustix 1.0.7", + "rustix 1.1.3", ] [[package]] name = "cap-time-ext" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "491af520b8770085daa0466978c75db90368c71896523f2464214e38359b1a5b" +checksum = "def102506ce40c11710a9b16e614af0cde8e76ae51b1f48c04b8d79f4b671a80" dependencies = [ "ambient-authority", "cap-primitives", "iana-time-zone", "once_cell", - "rustix 1.0.7", + "rustix 1.1.3", "winx", ] [[package]] name = "cc" -version = "1.2.23" +version = "1.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" +checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -321,9 +322,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" @@ -336,7 +337,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -385,15 +386,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "console_error_panic_hook" @@ -452,9 +453,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -536,12 +537,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -573,7 +574,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -595,9 +596,9 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "env_filter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ "log", "regex", @@ -621,12 +622,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -648,19 +649,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 1.0.7", + "rustix 1.1.3", "windows-sys 0.59.0", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" + [[package]] name = "flate2" -version = "1.1.1" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" dependencies = [ "crc32fast", - "libz-rs-sys", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -750,7 +757,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a" dependencies = [ "io-lifetimes", - "rustix 1.0.7", + "rustix 1.1.3", "windows-sys 0.59.0", ] @@ -855,9 +862,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", @@ -880,9 +887,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "git2" @@ -915,9 +922,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash", ] @@ -945,9 +952,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -966,9 +973,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -990,9 +997,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1003,9 +1010,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1016,11 +1023,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1031,42 +1037,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1166,21 +1168,21 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ "getrandom 0.3.4", "libc", @@ -1188,9 +1190,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ "once_cell", "wasm-bindgen", @@ -1222,9 +1224,9 @@ checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libgit2-sys" @@ -1242,15 +1244,15 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags", "libc", @@ -1281,20 +1283,11 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "libz-rs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a" -dependencies = [ - "zlib-rs", -] - [[package]] name = "libz-sys" -version = "1.1.22" +version = "1.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" dependencies = [ "cc", "libc", @@ -1310,23 +1303,22 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] @@ -1364,24 +1356,25 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-traits" @@ -1394,9 +1387,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -1404,9 +1397,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -1419,9 +1412,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl" @@ -1451,9 +1444,9 @@ dependencies = [ [[package]] name = "openssl-src" -version = "300.5.0+3.5.0" +version = "300.5.4+3.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f" +checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" dependencies = [ "cc", ] @@ -1490,15 +1483,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -1537,15 +1530,15 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -1558,9 +1551,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppmd-rust" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d558c559f0450f16f2a27a1f017ef38468c1090c9ce63c8e51366232d53717b4" +checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24" [[package]] name = "ppv-lite86" @@ -1573,27 +1566,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" @@ -1622,25 +1615,25 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 2.0.18", ] @@ -1667,9 +1660,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -1679,9 +1672,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -1690,9 +1683,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "ring" @@ -1702,7 +1695,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -1725,9 +1718,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustix" @@ -1744,15 +1737,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] @@ -1762,14 +1755,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" dependencies = [ "once_cell", - "rustix 1.0.7", + "rustix 1.1.3", ] [[package]] name = "rustls" -version = "0.23.27" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", @@ -1782,18 +1775,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ "ring", "rustls-pki-types", @@ -1802,9 +1795,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "schemars" @@ -1949,24 +1942,21 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "spin" @@ -1976,9 +1966,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stride_backend" @@ -2090,8 +2080,8 @@ dependencies = [ "serde_json", "stride_backend", "stride_backend_git", + "stride_backend_taskchampion", "stride_core", - "stride_crypto", "stride_database", "stride_logging", "stride_plugin_manager", @@ -2137,7 +2127,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23de088478b31c349c9ba67816fa55d9355232d63c3afea8bf513e31f0f1d2c0" dependencies = [ - "hashbrown 0.15.3", + "hashbrown 0.15.5", "serde", ] @@ -2149,20 +2139,19 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" [[package]] name = "strum_macros" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ "heck", "proc-macro2", "quote", - "rustversion", "syn", ] @@ -2174,9 +2163,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -2284,30 +2273,31 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5" dependencies = [ "deranged", "itoa", + "js-sys", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "78cc610bac2dcee56805c99642447d4c5dbde4d01f752ffea0199aee1f601dc4" dependencies = [ "num-conv", "time-core", @@ -2315,9 +2305,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -2325,11 +2315,10 @@ dependencies = [ [[package]] name = "tokio" -version = "1.45.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "backtrace", "pin-project-lite", ] @@ -2374,9 +2363,9 @@ checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -2385,9 +2374,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -2396,30 +2385,36 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] +[[package]] +name = "typed-path" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e43ffa54726cdc9ea78392023ffe9fe9cf9ac779e1c6fcb0d23f9862e3879d20" + [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "untrusted" @@ -2494,9 +2489,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi-common" @@ -2514,7 +2509,7 @@ dependencies = [ "io-extras", "io-lifetimes", "log", - "rustix 1.0.7", + "rustix 1.1.3", "system-interface", "thiserror 2.0.18", "tracing", @@ -2533,37 +2528,25 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -2572,9 +2555,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2582,34 +2565,34 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-encoder" -version = "0.230.0" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4349d0943718e6e434b51b9639e876293093dca4b96384fb136ab5bd5ce6660" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" dependencies = [ "leb128fmt", - "wasmparser 0.230.0", + "wasmparser 0.244.0", ] [[package]] @@ -2676,9 +2659,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.230.0" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808198a69b5a0535583370a51d459baa14261dfab04800c4864ee9e1a14346ed" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "indexmap 2.13.0", @@ -2695,9 +2678,9 @@ dependencies = [ [[package]] name = "wast" -version = "230.0.0" +version = "244.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8edac03c5fa691551531533928443faf3dc61a44f814a235c7ec5d17b7b34f1" +checksum = "b2e7b9f9e23311275920e3d6b56d64137c160cf8af4f84a7283b36cfecbf4acb" dependencies = [ "bumpalo", "leb128fmt", @@ -2708,18 +2691,18 @@ dependencies = [ [[package]] name = "wat" -version = "1.230.0" +version = "1.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d77d62229e38db83eac32bacb5f61ebb952366ab0dae90cf2b3c07a65eea894" +checksum = "bbf35b87ed352f9ab6cd0732abde5a67dd6153dfd02c493e61459218b19456fa" dependencies = [ - "wast 230.0.0", + "wast 244.0.0", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -2731,14 +2714,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.0", + "webpki-roots 1.0.5", ] [[package]] name = "webpki-roots" -version = "1.0.0" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" dependencies = [ "rustls-pki-types", ] @@ -2785,22 +2768,22 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.1.1", + "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", @@ -2809,21 +2792,15 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "windows-link" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" - [[package]] name = "windows-link" version = "0.2.1" @@ -2832,20 +2809,20 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.1.1", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.1.1", + "windows-link", ] [[package]] @@ -2875,6 +2852,15 @@ dependencies = [ "windows-targets 0.53.5", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -2897,7 +2883,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.2.1", + "windows-link", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -3040,17 +3026,16 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -3058,9 +3043,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -3070,18 +3055,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", @@ -3120,9 +3105,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", @@ -3131,9 +3116,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -3142,9 +3127,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -3153,9 +3138,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", @@ -3164,9 +3149,9 @@ dependencies = [ [[package]] name = "zip" -version = "7.1.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9013f1222db8a6d680f13a7ccdc60a781199cd09c2fa4eff58e728bb181757fc" +checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" dependencies = [ "aes", "bzip2", @@ -3184,6 +3169,7 @@ dependencies = [ "ppmd-rust", "sha1", "time", + "typed-path", "zeroize", "zopfli", "zstd", @@ -3191,21 +3177,21 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8" +checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" [[package]] name = "zmij" -version = "1.0.10" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e0d8dffbae3d840f64bda38e28391faef673a7b5a6017840f2a106c8145868" +checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65" [[package]] name = "zopfli" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" dependencies = [ "bumpalo", "crc32fast", @@ -3233,9 +3219,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", diff --git a/app/lib/blocs/dialog_bloc.dart b/app/lib/blocs/dialog_bloc.dart index f4654046..db1469c0 100644 --- a/app/lib/blocs/dialog_bloc.dart +++ b/app/lib/blocs/dialog_bloc.dart @@ -34,12 +34,12 @@ class DialogState { class DialogBloc extends Bloc { DialogBloc() - : super( - DialogState( - title: (context) => const Placeholder(), - onConfirm: (context) async => false, - ), - ) { + : super( + DialogState( + title: (context) => const Placeholder(), + onConfirm: (context) async => false, + ), + ) { on((event, emit) async { emit( DialogState( diff --git a/app/lib/blocs/tasks_bloc.dart b/app/lib/blocs/tasks_bloc.dart index 6dcb5c1a..23847e0e 100644 --- a/app/lib/blocs/tasks_bloc.dart +++ b/app/lib/blocs/tasks_bloc.dart @@ -12,7 +12,6 @@ import 'package:stride/bridge/api/repository.dart'; import 'package:stride/bridge/third_party/stride_backend_git/known_hosts.dart'; import 'package:stride/bridge/third_party/stride_core/event.dart'; import 'package:stride/bridge/third_party/stride_core/task.dart'; -import 'package:stride/routes/encryption_key_route.dart'; import 'package:uuid/uuid.dart'; @immutable @@ -30,13 +29,9 @@ final class TaskRemoveEvent extends TaskEvent { TaskRemoveEvent({required this.task}); } -final class TaskRemoveAllEvent extends TaskEvent { - final bool all; - TaskRemoveAllEvent({this.all = false}); -} - -final class TaskForcePushEvent extends TaskEvent { - TaskForcePushEvent(); +final class TaskRemoveRepositoryEvent extends TaskEvent { + final UuidValue uuid; + TaskRemoveRepositoryEvent({required this.uuid}); } final class TaskChangeStatusEvent extends TaskEvent { @@ -60,10 +55,6 @@ final class TaskFilterEvent extends TaskEvent { TaskFilterEvent({this.filter}); } -final class TaskCheckoutBranchEvent extends TaskEvent { - TaskCheckoutBranchEvent(); -} - class TaskState { final List tasks; final bool syncing; @@ -156,20 +147,8 @@ class TaskBloc extends Bloc { emit(TaskState(tasks: await _tasks())); }); - on((event, emit) async { - if (event.all) { - throw UnimplementedError(); - } else { - // await repository()?.deleteDatabase(); - // throw UnimplementedError(); - } - // emit(TaskState(tasks: await _tasks())); - }); - - on((event, emit) async { - // await repository()?.push(force: true); - throw UnimplementedError(); - // emit(TaskState(tasks: await _tasks())); + on((event, emit) async { + await Repository.remove(uuid: event.uuid); }); on((event, emit) async { @@ -201,12 +180,6 @@ class TaskBloc extends Bloc { filter = event.filter; emit(TaskState(tasks: await _tasks())); }); - - on((event, emit) async { - // await repository()?.checkout(); - throw UnimplementedError(); - // emit(TaskState(tasks: await _tasks())); - }); } Future> _tasks() async { @@ -261,13 +234,7 @@ class TaskBloc extends Bloc { content: 'Are you sure the encryption key is correct?', onConfirm: (context) async { Navigator.pop(context); - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => EncryptionKeyRoute( - repository: settingsBloc.settings.repositories.first, - ), - ), - ); + // TODO: Send user to encryption key. return true; }, ), diff --git a/app/lib/bridge/api/error.dart b/app/lib/bridge/api/error.dart index cac7d3c7..c8e62925 100644 --- a/app/lib/bridge/api/error.dart +++ b/app/lib/bridge/api/error.dart @@ -14,7 +14,7 @@ import 'package:stride/bridge/frb_generated.dart'; import 'package:stride/bridge/third_party/stride_backend_git/known_hosts.dart'; // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `ErrorKind`, `ExportError`, `ImportError`, `SettingsError` -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `source` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `source` // Rust type: RustOpaqueMoi> abstract class RustError implements RustOpaqueInterface { diff --git a/app/lib/bridge/api/repository.dart b/app/lib/bridge/api/repository.dart index d78be800..17eed962 100644 --- a/app/lib/bridge/api/repository.dart +++ b/app/lib/bridge/api/repository.dart @@ -19,13 +19,23 @@ import 'package:stride/bridge/third_party/stride_core/task/annotation.dart'; import 'package:stride/bridge/third_party/stride_core/task/uda.dart'; import 'package:uuid/uuid.dart'; -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt`, `fmt` // These functions are ignored (category: IgnoreBecauseExplicitAttribute): `database_mut`, `database`, `root_path` // Rust type: RustOpaqueMoi> abstract class Repository implements RustOpaqueInterface { + Future addBackend({required String name}); + Future> allTasks({required Filter filter}); + Future backend({required UuidValue id}); + + Future> backendNames(); + + Future> backends(); + + Future deleteBackend({required UuidValue id}); + Future insertTask({required Task task}); static Repository open({required UuidValue uuid}) => @@ -33,6 +43,9 @@ abstract class Repository implements RustOpaqueInterface { Future purgeTaskById({required UuidValue id}); + static Future remove({required UuidValue uuid}) => + RustLib.instance.api.crateApiRepositoryRepositoryRemove(uuid: uuid); + Future sync_(); Future taskById({required UuidValue id}); @@ -41,7 +54,46 @@ abstract class Repository implements RustOpaqueInterface { Future> tasksByStatus({required Set status}); + Future toggleBackend({required UuidValue id}); + Future undo(); + Future updateBackend({required BackendRecord backend}); + Future updateTask({required Task task}); } + +class BackendRecord { + final UuidValue id; + final String name; + final bool enabled; + final String schema; + final String config; + + const BackendRecord({ + required this.id, + required this.name, + required this.enabled, + required this.schema, + required this.config, + }); + + @override + int get hashCode => + id.hashCode ^ + name.hashCode ^ + enabled.hashCode ^ + schema.hashCode ^ + config.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is BackendRecord && + runtimeType == other.runtimeType && + id == other.id && + name == other.name && + enabled == other.enabled && + schema == other.schema && + config == other.config; +} diff --git a/app/lib/bridge/api/settings.dart b/app/lib/bridge/api/settings.dart index fb811144..9b7cd857 100644 --- a/app/lib/bridge/api/settings.dart +++ b/app/lib/bridge/api/settings.dart @@ -14,13 +14,12 @@ import 'package:freezed_annotation/freezed_annotation.dart' hide protected; import 'package:stride/bridge/api/error.dart'; import 'package:stride/bridge/api/filter.dart'; import 'package:stride/bridge/frb_generated.dart'; -import 'package:stride/bridge/third_party/stride_backend_git/encryption_key.dart'; import 'package:stride/bridge/third_party/stride_core/task.dart'; import 'package:uuid/uuid.dart'; part 'settings.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `application_cache_path`, `application_document_path`, `application_log_path`, `application_support_path`, `default_author`, `default_branch_name`, `default_email`, `default_repository_name`, `default_theme_mode`, `ssh_key_path` +// These functions are ignored because they are not marked as `pub`: `application_cache_path`, `application_document_path`, `application_log_path`, `application_support_path`, `default_repository_name`, `default_theme_mode`, `ssh_key_path` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `State` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt` // These functions are ignored (category: IgnoreBecauseOwnerTyShouldIgnore): `default` @@ -98,12 +97,6 @@ sealed class RepositorySpecification with _$RepositorySpecification { const factory RepositorySpecification({ required UuidValue uuid, required String name, - required String origin, - required String author, - required String email, - required String branch, - UuidValue? sshKeyUuid, - EncryptionKey? encryption, }) = _RepositorySpecification; const RepositorySpecification._(); static Future default_() => diff --git a/app/lib/bridge/api/settings.freezed.dart b/app/lib/bridge/api/settings.freezed.dart index 63074eee..ed597e33 100644 --- a/app/lib/bridge/api/settings.freezed.dart +++ b/app/lib/bridge/api/settings.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$RepositorySpecification { - UuidValue get uuid; String get name; String get origin; String get author; String get email; String get branch; UuidValue? get sshKeyUuid; EncryptionKey? get encryption; + UuidValue get uuid; String get name; /// Create a copy of RepositorySpecification /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $RepositorySpecificationCopyWith get copyWith => _$Repo @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is RepositorySpecification&&(identical(other.uuid, uuid) || other.uuid == uuid)&&(identical(other.name, name) || other.name == name)&&(identical(other.origin, origin) || other.origin == origin)&&(identical(other.author, author) || other.author == author)&&(identical(other.email, email) || other.email == email)&&(identical(other.branch, branch) || other.branch == branch)&&(identical(other.sshKeyUuid, sshKeyUuid) || other.sshKeyUuid == sshKeyUuid)&&(identical(other.encryption, encryption) || other.encryption == encryption)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is RepositorySpecification&&(identical(other.uuid, uuid) || other.uuid == uuid)&&(identical(other.name, name) || other.name == name)); } @override -int get hashCode => Object.hash(runtimeType,uuid,name,origin,author,email,branch,sshKeyUuid,encryption); +int get hashCode => Object.hash(runtimeType,uuid,name); @override String toString() { - return 'RepositorySpecification(uuid: $uuid, name: $name, origin: $origin, author: $author, email: $email, branch: $branch, sshKeyUuid: $sshKeyUuid, encryption: $encryption)'; + return 'RepositorySpecification(uuid: $uuid, name: $name)'; } @@ -45,7 +45,7 @@ abstract mixin class $RepositorySpecificationCopyWith<$Res> { factory $RepositorySpecificationCopyWith(RepositorySpecification value, $Res Function(RepositorySpecification) _then) = _$RepositorySpecificationCopyWithImpl; @useResult $Res call({ - UuidValue uuid, String name, String origin, String author, String email, String branch, UuidValue? sshKeyUuid, EncryptionKey? encryption + UuidValue uuid, String name }); @@ -62,17 +62,11 @@ class _$RepositorySpecificationCopyWithImpl<$Res> /// Create a copy of RepositorySpecification /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? uuid = null,Object? name = null,Object? origin = null,Object? author = null,Object? email = null,Object? branch = null,Object? sshKeyUuid = freezed,Object? encryption = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? uuid = null,Object? name = null,}) { return _then(_self.copyWith( uuid: null == uuid ? _self.uuid : uuid // ignore: cast_nullable_to_non_nullable as UuidValue,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable -as String,origin: null == origin ? _self.origin : origin // ignore: cast_nullable_to_non_nullable -as String,author: null == author ? _self.author : author // ignore: cast_nullable_to_non_nullable -as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String,branch: null == branch ? _self.branch : branch // ignore: cast_nullable_to_non_nullable -as String,sshKeyUuid: freezed == sshKeyUuid ? _self.sshKeyUuid : sshKeyUuid // ignore: cast_nullable_to_non_nullable -as UuidValue?,encryption: freezed == encryption ? _self.encryption : encryption // ignore: cast_nullable_to_non_nullable -as EncryptionKey?, +as String, )); } @@ -154,10 +148,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( UuidValue uuid, String name, String origin, String author, String email, String branch, UuidValue? sshKeyUuid, EncryptionKey? encryption)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( UuidValue uuid, String name)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _RepositorySpecification() when $default != null: -return $default(_that.uuid,_that.name,_that.origin,_that.author,_that.email,_that.branch,_that.sshKeyUuid,_that.encryption);case _: +return $default(_that.uuid,_that.name);case _: return orElse(); } @@ -175,10 +169,10 @@ return $default(_that.uuid,_that.name,_that.origin,_that.author,_that.email,_tha /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( UuidValue uuid, String name, String origin, String author, String email, String branch, UuidValue? sshKeyUuid, EncryptionKey? encryption) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( UuidValue uuid, String name) $default,) {final _that = this; switch (_that) { case _RepositorySpecification(): -return $default(_that.uuid,_that.name,_that.origin,_that.author,_that.email,_that.branch,_that.sshKeyUuid,_that.encryption);} +return $default(_that.uuid,_that.name);} } /// A variant of `when` that fallback to returning `null` /// @@ -192,10 +186,10 @@ return $default(_that.uuid,_that.name,_that.origin,_that.author,_that.email,_tha /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( UuidValue uuid, String name, String origin, String author, String email, String branch, UuidValue? sshKeyUuid, EncryptionKey? encryption)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( UuidValue uuid, String name)? $default,) {final _that = this; switch (_that) { case _RepositorySpecification() when $default != null: -return $default(_that.uuid,_that.name,_that.origin,_that.author,_that.email,_that.branch,_that.sshKeyUuid,_that.encryption);case _: +return $default(_that.uuid,_that.name);case _: return null; } @@ -207,17 +201,11 @@ return $default(_that.uuid,_that.name,_that.origin,_that.author,_that.email,_tha class _RepositorySpecification extends RepositorySpecification { - const _RepositorySpecification({required this.uuid, required this.name, required this.origin, required this.author, required this.email, required this.branch, this.sshKeyUuid, this.encryption}): super._(); + const _RepositorySpecification({required this.uuid, required this.name}): super._(); @override final UuidValue uuid; @override final String name; -@override final String origin; -@override final String author; -@override final String email; -@override final String branch; -@override final UuidValue? sshKeyUuid; -@override final EncryptionKey? encryption; /// Create a copy of RepositorySpecification /// with the given fields replaced by the non-null parameter values. @@ -229,16 +217,16 @@ _$RepositorySpecificationCopyWith<_RepositorySpecification> get copyWith => __$R @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _RepositorySpecification&&(identical(other.uuid, uuid) || other.uuid == uuid)&&(identical(other.name, name) || other.name == name)&&(identical(other.origin, origin) || other.origin == origin)&&(identical(other.author, author) || other.author == author)&&(identical(other.email, email) || other.email == email)&&(identical(other.branch, branch) || other.branch == branch)&&(identical(other.sshKeyUuid, sshKeyUuid) || other.sshKeyUuid == sshKeyUuid)&&(identical(other.encryption, encryption) || other.encryption == encryption)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _RepositorySpecification&&(identical(other.uuid, uuid) || other.uuid == uuid)&&(identical(other.name, name) || other.name == name)); } @override -int get hashCode => Object.hash(runtimeType,uuid,name,origin,author,email,branch,sshKeyUuid,encryption); +int get hashCode => Object.hash(runtimeType,uuid,name); @override String toString() { - return 'RepositorySpecification(uuid: $uuid, name: $name, origin: $origin, author: $author, email: $email, branch: $branch, sshKeyUuid: $sshKeyUuid, encryption: $encryption)'; + return 'RepositorySpecification(uuid: $uuid, name: $name)'; } @@ -249,7 +237,7 @@ abstract mixin class _$RepositorySpecificationCopyWith<$Res> implements $Reposit factory _$RepositorySpecificationCopyWith(_RepositorySpecification value, $Res Function(_RepositorySpecification) _then) = __$RepositorySpecificationCopyWithImpl; @override @useResult $Res call({ - UuidValue uuid, String name, String origin, String author, String email, String branch, UuidValue? sshKeyUuid, EncryptionKey? encryption + UuidValue uuid, String name }); @@ -266,17 +254,11 @@ class __$RepositorySpecificationCopyWithImpl<$Res> /// Create a copy of RepositorySpecification /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? uuid = null,Object? name = null,Object? origin = null,Object? author = null,Object? email = null,Object? branch = null,Object? sshKeyUuid = freezed,Object? encryption = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? uuid = null,Object? name = null,}) { return _then(_RepositorySpecification( uuid: null == uuid ? _self.uuid : uuid // ignore: cast_nullable_to_non_nullable as UuidValue,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable -as String,origin: null == origin ? _self.origin : origin // ignore: cast_nullable_to_non_nullable -as String,author: null == author ? _self.author : author // ignore: cast_nullable_to_non_nullable -as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String,branch: null == branch ? _self.branch : branch // ignore: cast_nullable_to_non_nullable -as String,sshKeyUuid: freezed == sshKeyUuid ? _self.sshKeyUuid : sshKeyUuid // ignore: cast_nullable_to_non_nullable -as UuidValue?,encryption: freezed == encryption ? _self.encryption : encryption // ignore: cast_nullable_to_non_nullable -as EncryptionKey?, +as String, )); } diff --git a/app/lib/bridge/frb_generated.dart b/app/lib/bridge/frb_generated.dart index 05d8d0c7..90d412c1 100644 --- a/app/lib/bridge/frb_generated.dart +++ b/app/lib/bridge/frb_generated.dart @@ -24,7 +24,6 @@ import 'package:stride/bridge/api/settings.dart'; import 'package:stride/bridge/frb_generated.dart'; import 'package:stride/bridge/frb_generated.io.dart' if (dart.library.js_interop) 'frb_generated.web.dart'; -import 'package:stride/bridge/third_party/stride_backend_git/encryption_key.dart'; import 'package:stride/bridge/third_party/stride_backend_git/known_hosts.dart'; import 'package:stride/bridge/third_party/stride_core/event.dart'; import 'package:stride/bridge/third_party/stride_core/task.dart'; @@ -86,7 +85,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.11.1'; @override - int get rustContentHash => -97564000; + int get rustContentHash => 1297363159; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -112,11 +111,34 @@ abstract class RustLibApi extends BaseApi { HostEvent strideCoreEventHostEventTimer({required int interval}); + Future crateApiRepositoryRepositoryAddBackend({ + required Repository that, + required String name, + }); + Future> crateApiRepositoryRepositoryAllTasks({ required Repository that, required Filter filter, }); + Future crateApiRepositoryRepositoryBackend({ + required Repository that, + required UuidValue id, + }); + + Future> crateApiRepositoryRepositoryBackendNames({ + required Repository that, + }); + + Future> crateApiRepositoryRepositoryBackends({ + required Repository that, + }); + + Future crateApiRepositoryRepositoryDeleteBackend({ + required Repository that, + required UuidValue id, + }); + Future crateApiRepositoryRepositoryInsertTask({ required Repository that, required Task task, @@ -129,6 +151,8 @@ abstract class RustLibApi extends BaseApi { required UuidValue id, }); + Future crateApiRepositoryRepositoryRemove({required UuidValue uuid}); + Future crateApiRepositoryRepositorySync({required Repository that}); Future crateApiRepositoryRepositoryTaskById({ @@ -146,8 +170,18 @@ abstract class RustLibApi extends BaseApi { required Set status, }); + Future crateApiRepositoryRepositoryToggleBackend({ + required Repository that, + required UuidValue id, + }); + Future crateApiRepositoryRepositoryUndo({required Repository that}); + Future crateApiRepositoryRepositoryUpdateBackend({ + required Repository that, + required BackendRecord backend, + }); + Future crateApiRepositoryRepositoryUpdateTask({ required Repository that, required Task task, @@ -204,12 +238,6 @@ abstract class RustLibApi extends BaseApi { Future crateApiPluginManagerEmitBroadcast({required HostEvent event}); - Future strideBackendGitEncryptionKeyEncryptionKeyGenerate(); - - String? strideBackendGitEncryptionKeyEncryptionKeyValidate({ - required String key, - }); - Future crateApiLoggingError({required String message}); Future crateApiFilterFilterDefault(); @@ -542,6 +570,45 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kStrideCoreEventHostEventTimerConstMeta => const TaskConstMeta(debugName: 'HostEvent_timer', argNames: ['interval']); + @override + Future crateApiRepositoryRepositoryAddBackend({ + required Repository that, + required String name, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRepository( + that, + serializer, + ); + sse_encode_String(name, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 7, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRustError, + ), + constMeta: kCrateApiRepositoryRepositoryAddBackendConstMeta, + argValues: [that, name], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiRepositoryRepositoryAddBackendConstMeta => + const TaskConstMeta( + debugName: 'Repository_add_backend', + argNames: ['that', 'name'], + ); + @override Future> crateApiRepositoryRepositoryAllTasks({ required Repository that, @@ -559,7 +626,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 7, + funcId: 8, port: port_, ); }, @@ -581,6 +648,154 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ['that', 'filter'], ); + @override + Future crateApiRepositoryRepositoryBackend({ + required Repository that, + required UuidValue id, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRepository( + that, + serializer, + ); + sse_encode_Uuid(id, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 9, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_backend_record, + decodeErrorData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRustError, + ), + constMeta: kCrateApiRepositoryRepositoryBackendConstMeta, + argValues: [that, id], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiRepositoryRepositoryBackendConstMeta => + const TaskConstMeta( + debugName: 'Repository_backend', + argNames: ['that', 'id'], + ); + + @override + Future> crateApiRepositoryRepositoryBackendNames({ + required Repository that, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRepository( + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 10, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_String, + decodeErrorData: null, + ), + constMeta: kCrateApiRepositoryRepositoryBackendNamesConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiRepositoryRepositoryBackendNamesConstMeta => + const TaskConstMeta( + debugName: 'Repository_backend_names', + argNames: ['that'], + ); + + @override + Future> crateApiRepositoryRepositoryBackends({ + required Repository that, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRepository( + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 11, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_backend_record, + decodeErrorData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRustError, + ), + constMeta: kCrateApiRepositoryRepositoryBackendsConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiRepositoryRepositoryBackendsConstMeta => + const TaskConstMeta(debugName: 'Repository_backends', argNames: ['that']); + + @override + Future crateApiRepositoryRepositoryDeleteBackend({ + required Repository that, + required UuidValue id, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRepository( + that, + serializer, + ); + sse_encode_Uuid(id, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 12, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRustError, + ), + constMeta: kCrateApiRepositoryRepositoryDeleteBackendConstMeta, + argValues: [that, id], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiRepositoryRepositoryDeleteBackendConstMeta => + const TaskConstMeta( + debugName: 'Repository_delete_backend', + argNames: ['that', 'id'], + ); + @override Future crateApiRepositoryRepositoryInsertTask({ required Repository that, @@ -598,7 +813,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 8, + funcId: 13, port: port_, ); }, @@ -627,7 +842,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Uuid(uuid, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14)!; }, codec: SseCodec( decodeSuccessData: @@ -662,7 +877,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 10, + funcId: 15, port: port_, ); }, @@ -684,6 +899,35 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ['that', 'id'], ); + @override + Future crateApiRepositoryRepositoryRemove({required UuidValue uuid}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Uuid(uuid, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 16, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRustError, + ), + constMeta: kCrateApiRepositoryRepositoryRemoveConstMeta, + argValues: [uuid], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiRepositoryRepositoryRemoveConstMeta => + const TaskConstMeta(debugName: 'Repository_remove', argNames: ['uuid']); + @override Future crateApiRepositoryRepositorySync({required Repository that}) { return handler.executeNormal( @@ -697,7 +941,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 11, + funcId: 17, port: port_, ); }, @@ -733,7 +977,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 12, + funcId: 18, port: port_, ); }, @@ -772,7 +1016,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 13, + funcId: 19, port: port_, ); }, @@ -811,7 +1055,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 14, + funcId: 20, port: port_, ); }, @@ -833,6 +1077,45 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ['that', 'status'], ); + @override + Future crateApiRepositoryRepositoryToggleBackend({ + required Repository that, + required UuidValue id, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRepository( + that, + serializer, + ); + sse_encode_Uuid(id, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 21, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRustError, + ), + constMeta: kCrateApiRepositoryRepositoryToggleBackendConstMeta, + argValues: [that, id], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiRepositoryRepositoryToggleBackendConstMeta => + const TaskConstMeta( + debugName: 'Repository_toggle_backend', + argNames: ['that', 'id'], + ); + @override Future crateApiRepositoryRepositoryUndo({required Repository that}) { return handler.executeNormal( @@ -846,7 +1129,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 15, + funcId: 22, port: port_, ); }, @@ -865,6 +1148,45 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiRepositoryRepositoryUndoConstMeta => const TaskConstMeta(debugName: 'Repository_undo', argNames: ['that']); + @override + Future crateApiRepositoryRepositoryUpdateBackend({ + required Repository that, + required BackendRecord backend, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRepository( + that, + serializer, + ); + sse_encode_box_autoadd_backend_record(backend, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 23, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRustError, + ), + constMeta: kCrateApiRepositoryRepositoryUpdateBackendConstMeta, + argValues: [that, backend], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiRepositoryRepositoryUpdateBackendConstMeta => + const TaskConstMeta( + debugName: 'Repository_update_backend', + argNames: ['that', 'backend'], + ); + @override Future crateApiRepositoryRepositoryUpdateTask({ required Repository that, @@ -882,7 +1204,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 16, + funcId: 24, port: port_, ); }, @@ -914,7 +1236,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_host, @@ -943,7 +1265,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -972,7 +1294,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -1001,7 +1323,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -1030,7 +1352,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1058,7 +1380,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 22, + funcId: 30, port: port_, ); }, @@ -1088,7 +1410,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1114,7 +1436,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 24, + funcId: 32, port: port_, ); }, @@ -1147,7 +1469,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 25, + funcId: 33, port: port_, ); }, @@ -1185,7 +1507,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 26, + funcId: 34, port: port_, ); }, @@ -1218,7 +1540,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35)!; }, codec: SseCodec( decodeSuccessData: sse_decode_Uuid, @@ -1246,7 +1568,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 28, + funcId: 36, port: port_, ); }, @@ -1276,7 +1598,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 29, + funcId: 37, port: port_, ); }, @@ -1306,7 +1628,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 30, + funcId: 38, port: port_, ); }, @@ -1336,7 +1658,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 31, + funcId: 39, port: port_, ); }, @@ -1368,7 +1690,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 32, + funcId: 40, port: port_, ); }, @@ -1407,7 +1729,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 33, + funcId: 41, port: port_, ); }, @@ -1439,7 +1761,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 34, + funcId: 42, port: port_, ); }, @@ -1458,63 +1780,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiPluginManagerEmitBroadcastConstMeta => const TaskConstMeta(debugName: 'emit_broadcast', argNames: ['event']); - @override - Future strideBackendGitEncryptionKeyEncryptionKeyGenerate() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 35, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_encryption_key, - decodeErrorData: null, - ), - constMeta: kStrideBackendGitEncryptionKeyEncryptionKeyGenerateConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta - get kStrideBackendGitEncryptionKeyEncryptionKeyGenerateConstMeta => - const TaskConstMeta(debugName: 'encryption_key_generate', argNames: []); - - @override - String? strideBackendGitEncryptionKeyEncryptionKeyValidate({ - required String key, - }) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_String, - decodeErrorData: null, - ), - constMeta: kStrideBackendGitEncryptionKeyEncryptionKeyValidateConstMeta, - argValues: [key], - apiImpl: this, - ), - ); - } - - TaskConstMeta - get kStrideBackendGitEncryptionKeyEncryptionKeyValidateConstMeta => - const TaskConstMeta( - debugName: 'encryption_key_validate', - argNames: ['key'], - ); - @override Future crateApiLoggingError({required String message}) { return handler.executeNormal( @@ -1525,7 +1790,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 37, + funcId: 43, port: port_, ); }, @@ -1552,7 +1817,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 38, + funcId: 44, port: port_, ); }, @@ -1579,7 +1844,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 39, + funcId: 45, port: port_, ); }, @@ -1604,7 +1869,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_host_key_type(keyType, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1632,7 +1897,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 41, + funcId: 47, port: port_, ); }, @@ -1661,7 +1926,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 42, + funcId: 48, port: port_, ); }, @@ -1688,7 +1953,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 43, + funcId: 49, port: port_, ); }, @@ -1715,7 +1980,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 44, + funcId: 50, port: port_, ); }, @@ -1745,7 +2010,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 45, + funcId: 51, port: port_, ); }, @@ -1773,7 +2038,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 46, + funcId: 52, port: port_, ); }, @@ -1801,7 +2066,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 47, + funcId: 53, port: port_, ); }, @@ -1829,7 +2094,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 48, + funcId: 54, port: port_, ); }, @@ -1862,7 +2127,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 49, + funcId: 55, port: port_, ); }, @@ -1895,7 +2160,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 50, + funcId: 56, port: port_, ); }, @@ -1928,7 +2193,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 51, + funcId: 57, port: port_, ); }, @@ -1961,7 +2226,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 52, + funcId: 58, port: port_, ); }, @@ -1994,7 +2259,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 53, + funcId: 59, port: port_, ); }, @@ -2029,7 +2294,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 54, + funcId: 60, port: port_, ); }, @@ -2061,7 +2326,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { manifest, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 55)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 61)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2093,7 +2358,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { manifest, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 56)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 62)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2124,7 +2389,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { manifest, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 57)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 63)!; }, codec: SseCodec( decodeSuccessData: sse_decode_manifest_event, @@ -2155,7 +2420,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { manifest, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 58)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 64)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2186,7 +2451,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { manifest, serializer, ); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 59)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 65)!; }, codec: SseCodec( decodeSuccessData: sse_decode_manifest_permission, @@ -2215,7 +2480,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 60, + funcId: 66, port: port_, ); }, @@ -2244,7 +2509,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 61, + funcId: 67, port: port_, ); }, @@ -2272,7 +2537,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 62, + funcId: 68, port: port_, ); }, @@ -2301,7 +2566,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 63, + funcId: 69, port: port_, ); }, @@ -2330,7 +2595,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 64, + funcId: 70, port: port_, ); }, @@ -2363,7 +2628,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 65, + funcId: 71, port: port_, ); }, @@ -2395,7 +2660,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 66, + funcId: 72, port: port_, ); }, @@ -2422,7 +2687,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 67, + funcId: 73, port: port_, ); }, @@ -2452,7 +2717,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 68, + funcId: 74, port: port_, ); }, @@ -2477,7 +2742,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 69)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 75)!; }, codec: SseCodec( decodeSuccessData: sse_decode_settings, @@ -2503,7 +2768,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 70, + funcId: 76, port: port_, ); }, @@ -2531,7 +2796,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 71, + funcId: 77, port: port_, ); }, @@ -2560,7 +2825,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 72, + funcId: 78, port: port_, ); }, @@ -2585,7 +2850,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(title, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 73)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 79)!; }, codec: SseCodec( decodeSuccessData: sse_decode_task, @@ -2611,7 +2876,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 74, + funcId: 80, port: port_, ); }, @@ -2641,7 +2906,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 75, + funcId: 81, port: port_, ); }, @@ -2668,7 +2933,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 76, + funcId: 82, port: port_, ); }, @@ -2696,7 +2961,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 77, + funcId: 83, port: port_, ); }, @@ -2724,7 +2989,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_task(that, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 78)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 84)!; }, codec: SseCodec( decodeSuccessData: sse_decode_f_32, @@ -2754,7 +3019,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 79, + funcId: 85, port: port_, ); }, @@ -2784,7 +3049,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 80, + funcId: 86, port: port_, ); }, @@ -2813,7 +3078,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 81, + funcId: 87, port: port_, ); }, @@ -2840,7 +3105,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 82, + funcId: 88, port: port_, ); }, @@ -2868,7 +3133,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 83, + funcId: 89, port: port_, ); }, @@ -3135,6 +3400,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + BackendRecord dco_decode_backend_record(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 5) + throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + return BackendRecord( + id: dco_decode_Uuid(arr[0]), + name: dco_decode_String(arr[1]), + enabled: dco_decode_bool(arr[2]), + schema: dco_decode_String(arr[3]), + config: dco_decode_String(arr[4]), + ); + } + @protected bool dco_decode_bool(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3154,9 +3434,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - EncryptionKey dco_decode_box_autoadd_encryption_key(dynamic raw) { + BackendRecord dco_decode_box_autoadd_backend_record(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return dco_decode_encryption_key(raw); + return dco_decode_backend_record(raw); } @protected @@ -3261,15 +3541,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw as int; } - @protected - EncryptionKey dco_decode_encryption_key(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - final arr = raw as List; - if (arr.length != 1) - throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); - return EncryptionKey(key: dco_decode_String(arr[0])); - } - @protected double dco_decode_f_32(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3397,6 +3668,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (raw as List).map(dco_decode_annotation).toList(); } + @protected + List dco_decode_list_backend_record(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_backend_record).toList(); + } + @protected List dco_decode_list_filter(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3557,9 +3834,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - EncryptionKey? dco_decode_opt_box_autoadd_encryption_key(dynamic raw) { + BackendRecord? dco_decode_opt_box_autoadd_backend_record(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return raw == null ? null : dco_decode_box_autoadd_encryption_key(raw); + return raw == null ? null : dco_decode_box_autoadd_backend_record(raw); } @protected @@ -3695,17 +3972,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RepositorySpecification dco_decode_repository_specification(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) - throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return RepositorySpecification( uuid: dco_decode_Uuid(arr[0]), name: dco_decode_String(arr[1]), - origin: dco_decode_String(arr[2]), - author: dco_decode_String(arr[3]), - email: dco_decode_String(arr[4]), - branch: dco_decode_String(arr[5]), - sshKeyUuid: dco_decode_opt_Uuid(arr[6]), - encryption: dco_decode_opt_box_autoadd_encryption_key(arr[7]), ); } @@ -4071,6 +4342,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + BackendRecord sse_decode_backend_record(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + final var_id = sse_decode_Uuid(deserializer); + final var_name = sse_decode_String(deserializer); + final var_enabled = sse_decode_bool(deserializer); + final var_schema = sse_decode_String(deserializer); + final var_config = sse_decode_String(deserializer); + return BackendRecord( + id: var_id, + name: var_name, + enabled: var_enabled, + schema: var_schema, + config: var_config, + ); + } + @protected bool sse_decode_bool(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4092,11 +4380,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - EncryptionKey sse_decode_box_autoadd_encryption_key( + BackendRecord sse_decode_box_autoadd_backend_record( SseDeserializer deserializer, ) { // Codec=Sse (Serialization based), see doc to use other codecs - return sse_decode_encryption_key(deserializer); + return sse_decode_backend_record(deserializer); } @protected @@ -4213,13 +4501,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return sse_decode_u_32(deserializer); } - @protected - EncryptionKey sse_decode_encryption_key(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - final var_key = sse_decode_String(deserializer); - return EncryptionKey(key: var_key); - } - @protected double sse_decode_f_32(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4367,6 +4648,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + List sse_decode_list_backend_record( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + final len_ = sse_decode_i_32(deserializer); + final ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_backend_record(deserializer)); + } + return ans_; + } + @protected List sse_decode_list_filter(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4592,13 +4887,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - EncryptionKey? sse_decode_opt_box_autoadd_encryption_key( + BackendRecord? sse_decode_opt_box_autoadd_backend_record( SseDeserializer deserializer, ) { // Codec=Sse (Serialization based), see doc to use other codecs if (sse_decode_bool(deserializer)) { - return sse_decode_box_autoadd_encryption_key(deserializer); + return sse_decode_box_autoadd_backend_record(deserializer); } else { return null; } @@ -4798,24 +5093,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs final var_uuid = sse_decode_Uuid(deserializer); final var_name = sse_decode_String(deserializer); - final var_origin = sse_decode_String(deserializer); - final var_author = sse_decode_String(deserializer); - final var_email = sse_decode_String(deserializer); - final var_branch = sse_decode_String(deserializer); - final var_sshKeyUuid = sse_decode_opt_Uuid(deserializer); - final var_encryption = sse_decode_opt_box_autoadd_encryption_key( - deserializer, - ); - return RepositorySpecification( - uuid: var_uuid, - name: var_name, - origin: var_origin, - author: var_author, - email: var_email, - branch: var_branch, - sshKeyUuid: var_sshKeyUuid, - encryption: var_encryption, - ); + return RepositorySpecification(uuid: var_uuid, name: var_name); } @protected @@ -5229,6 +5507,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.logPath, serializer); } + @protected + void sse_encode_backend_record(BackendRecord self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_Uuid(self.id, serializer); + sse_encode_String(self.name, serializer); + sse_encode_bool(self.enabled, serializer); + sse_encode_String(self.schema, serializer); + sse_encode_String(self.config, serializer); + } + @protected void sse_encode_bool(bool self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5254,12 +5542,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_encryption_key( - EncryptionKey self, + void sse_encode_box_autoadd_backend_record( + BackendRecord self, SseSerializer serializer, ) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_encryption_key(self, serializer); + sse_encode_backend_record(self, serializer); } @protected @@ -5394,12 +5682,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(self, serializer); } - @protected - void sse_encode_encryption_key(EncryptionKey self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String(self.key, serializer); - } - @protected void sse_encode_f_32(double self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5525,6 +5807,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_backend_record( + List self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_backend_record(item, serializer); + } + } + @protected void sse_encode_list_filter(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5724,15 +6018,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_box_autoadd_encryption_key( - EncryptionKey? self, + void sse_encode_opt_box_autoadd_backend_record( + BackendRecord? self, SseSerializer serializer, ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); if (self != null) { - sse_encode_box_autoadd_encryption_key(self, serializer); + sse_encode_box_autoadd_backend_record(self, serializer); } } @@ -5918,12 +6212,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_Uuid(self.uuid, serializer); sse_encode_String(self.name, serializer); - sse_encode_String(self.origin, serializer); - sse_encode_String(self.author, serializer); - sse_encode_String(self.email, serializer); - sse_encode_String(self.branch, serializer); - sse_encode_opt_Uuid(self.sshKeyUuid, serializer); - sse_encode_opt_box_autoadd_encryption_key(self.encryption, serializer); } @protected @@ -6090,9 +6378,26 @@ class RepositoryImpl extends RustOpaque implements Repository { RustLib.instance.api.rust_arc_decrement_strong_count_RepositoryPtr, ); + Future addBackend({required String name}) => RustLib.instance.api + .crateApiRepositoryRepositoryAddBackend(that: this, name: name); + Future> allTasks({required Filter filter}) => RustLib.instance.api .crateApiRepositoryRepositoryAllTasks(that: this, filter: filter); + Future backend({required UuidValue id}) => RustLib + .instance + .api + .crateApiRepositoryRepositoryBackend(that: this, id: id); + + Future> backendNames() => + RustLib.instance.api.crateApiRepositoryRepositoryBackendNames(that: this); + + Future> backends() => + RustLib.instance.api.crateApiRepositoryRepositoryBackends(that: this); + + Future deleteBackend({required UuidValue id}) => RustLib.instance.api + .crateApiRepositoryRepositoryDeleteBackend(that: this, id: id); + Future insertTask({required Task task}) => RustLib.instance.api .crateApiRepositoryRepositoryInsertTask(that: this, task: task); @@ -6115,9 +6420,17 @@ class RepositoryImpl extends RustOpaque implements Repository { .api .crateApiRepositoryRepositoryTasksByStatus(that: this, status: status); + Future toggleBackend({required UuidValue id}) => RustLib.instance.api + .crateApiRepositoryRepositoryToggleBackend(that: this, id: id); + Future undo() => RustLib.instance.api.crateApiRepositoryRepositoryUndo(that: this); + Future updateBackend({required BackendRecord backend}) => RustLib + .instance + .api + .crateApiRepositoryRepositoryUpdateBackend(that: this, backend: backend); + Future updateTask({required Task task}) => RustLib.instance.api .crateApiRepositoryRepositoryUpdateTask(that: this, task: task); } diff --git a/app/lib/bridge/frb_generated.io.dart b/app/lib/bridge/frb_generated.io.dart index 0d53e6b5..eaea467b 100644 --- a/app/lib/bridge/frb_generated.io.dart +++ b/app/lib/bridge/frb_generated.io.dart @@ -23,7 +23,6 @@ import 'package:stride/bridge/api/plugin_manager.dart'; import 'package:stride/bridge/api/repository.dart'; import 'package:stride/bridge/api/settings.dart'; import 'package:stride/bridge/frb_generated.dart'; -import 'package:stride/bridge/third_party/stride_backend_git/encryption_key.dart'; import 'package:stride/bridge/third_party/stride_backend_git/known_hosts.dart'; import 'package:stride/bridge/third_party/stride_core/event.dart'; import 'package:stride/bridge/third_party/stride_core/task.dart'; @@ -177,6 +176,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ApplicationPaths dco_decode_application_paths(dynamic raw); + @protected + BackendRecord dco_decode_backend_record(dynamic raw); + @protected bool dco_decode_bool(dynamic raw); @@ -187,7 +189,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ApplicationPaths dco_decode_box_autoadd_application_paths(dynamic raw); @protected - EncryptionKey dco_decode_box_autoadd_encryption_key(dynamic raw); + BackendRecord dco_decode_box_autoadd_backend_record(dynamic raw); @protected Filter dco_decode_box_autoadd_filter(dynamic raw); @@ -243,9 +245,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int dco_decode_box_autoadd_u_32(dynamic raw); - @protected - EncryptionKey dco_decode_encryption_key(dynamic raw); - @protected double dco_decode_f_32(dynamic raw); @@ -291,6 +290,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_annotation(dynamic raw); + @protected + List dco_decode_list_backend_record(dynamic raw); + @protected List dco_decode_list_filter(dynamic raw); @@ -351,7 +353,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { DateTime? dco_decode_opt_box_autoadd_Chrono_Utc(dynamic raw); @protected - EncryptionKey? dco_decode_opt_box_autoadd_encryption_key(dynamic raw); + BackendRecord? dco_decode_opt_box_autoadd_backend_record(dynamic raw); @protected FilterSelection? dco_decode_opt_box_autoadd_filter_selection(dynamic raw); @@ -554,6 +556,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ApplicationPaths sse_decode_application_paths(SseDeserializer deserializer); + @protected + BackendRecord sse_decode_backend_record(SseDeserializer deserializer); + @protected bool sse_decode_bool(SseDeserializer deserializer); @@ -566,7 +571,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ); @protected - EncryptionKey sse_decode_box_autoadd_encryption_key( + BackendRecord sse_decode_box_autoadd_backend_record( SseDeserializer deserializer, ); @@ -634,9 +639,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int sse_decode_box_autoadd_u_32(SseDeserializer deserializer); - @protected - EncryptionKey sse_decode_encryption_key(SseDeserializer deserializer); - @protected double sse_decode_f_32(SseDeserializer deserializer); @@ -682,6 +684,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_annotation(SseDeserializer deserializer); + @protected + List sse_decode_list_backend_record( + SseDeserializer deserializer, + ); + @protected List sse_decode_list_filter(SseDeserializer deserializer); @@ -756,7 +763,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { DateTime? sse_decode_opt_box_autoadd_Chrono_Utc(SseDeserializer deserializer); @protected - EncryptionKey? sse_decode_opt_box_autoadd_encryption_key( + BackendRecord? sse_decode_opt_box_autoadd_backend_record( SseDeserializer deserializer, ); @@ -999,6 +1006,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_backend_record(BackendRecord self, SseSerializer serializer); + @protected void sse_encode_bool(bool self, SseSerializer serializer); @@ -1015,8 +1025,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ); @protected - void sse_encode_box_autoadd_encryption_key( - EncryptionKey self, + void sse_encode_box_autoadd_backend_record( + BackendRecord self, SseSerializer serializer, ); @@ -1101,9 +1111,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer); - @protected - void sse_encode_encryption_key(EncryptionKey self, SseSerializer serializer); - @protected void sse_encode_f_32(double self, SseSerializer serializer); @@ -1157,6 +1164,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_list_backend_record( + List self, + SseSerializer serializer, + ); + @protected void sse_encode_list_filter(List self, SseSerializer serializer); @@ -1248,8 +1261,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ); @protected - void sse_encode_opt_box_autoadd_encryption_key( - EncryptionKey? self, + void sse_encode_opt_box_autoadd_backend_record( + BackendRecord? self, SseSerializer serializer, ); diff --git a/app/lib/bridge/third_party/stride_backend_git/encryption_key.dart b/app/lib/bridge/third_party/stride_backend_git/encryption_key.dart deleted file mode 100644 index cc3f52a6..00000000 --- a/app/lib/bridge/third_party/stride_backend_git/encryption_key.dart +++ /dev/null @@ -1,38 +0,0 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. - -// ignore_for_file: avoid_unused_constructor_parameters -// ignore_for_file: avoid_dynamic_calls -// ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes -// ignore_for_file: argument_type_not_assignable -// ignore_for_file: inference_failure_on_instance_creation - -// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import - -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -import 'package:stride/bridge/frb_generated.dart'; - -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt` - -class EncryptionKey { - final String key; - - const EncryptionKey({required this.key}); - - static Future generate() => - RustLib.instance.api.strideBackendGitEncryptionKeyEncryptionKeyGenerate(); - - /// flutter_rust_bridge:sync - static String? validate({required String key}) => RustLib.instance.api - .strideBackendGitEncryptionKeyEncryptionKeyValidate(key: key); - - @override - int get hashCode => key.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is EncryptionKey && - runtimeType == other.runtimeType && - key == other.key; -} diff --git a/app/lib/main.dart b/app/lib/main.dart index 4dd916cb..5ae8fb77 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -38,12 +38,7 @@ Future main() async { final plugins = await pm.pluginManifests(); final pluginManagerState = PluginManagerState(plugins: plugins); - runApp( - MyApp( - settings: settings, - pluginManagerState: pluginManagerState, - ), - ); + runApp(MyApp(settings: settings, pluginManagerState: pluginManagerState)); } class MyApp extends StatelessWidget { @@ -95,8 +90,9 @@ class MyApp extends StatelessWidget { title: 'Stride', theme: generateTheme(darkMode: false), darkTheme: generateTheme(darkMode: true), - themeMode: - state.settings.darkMode ? ThemeMode.dark : ThemeMode.light, + themeMode: state.settings.darkMode + ? ThemeMode.dark + : ThemeMode.light, home: BlocListener( listener: (context, state) { if (!state.show) { @@ -131,6 +127,7 @@ class MyApp extends StatelessWidget { if (!context.mounted) return; showAlertDialog( context: context, + popRoute: false, content: description == null ? title : Column( diff --git a/app/lib/routes/backend/config_route.dart b/app/lib/routes/backend/config_route.dart new file mode 100644 index 00000000..c049eca3 --- /dev/null +++ b/app/lib/routes/backend/config_route.dart @@ -0,0 +1,573 @@ +import 'dart:convert'; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:stride/blocs/log_bloc.dart'; +import 'package:stride/bridge/api/repository.dart'; +import 'package:stride/bridge/api/settings.dart'; +import 'package:stride/utils/functions.dart'; +import 'package:stride/widgets/settings_widget.dart'; +import 'package:uuid/uuid.dart'; + +class Schema { + final String name; + final Map fields; + + Schema({required this.name, required this.fields}); + + factory Schema.fromJson(Map json) { + return Schema( + name: json['name'] as String, + fields: (json['fields'] as Map).map( + (key, value) => + MapEntry(key, SchemaValue.fromJson(value as Map)), + ), + ); + } +} + +sealed class SchemaValue { + final bool showQrCode; + const SchemaValue({required this.showQrCode}); + + factory SchemaValue.fromJson(Map map) { + final type = map['type'] as String; + return switch (type) { + 'string' => StringSchemaValue.fromJson(map), + 'url' => UrlSchemaValue.fromJson(map), + 'uuid' => UuidSchemaValue.fromJson(map), + 'bytes' => BytesSchemaValue.fromJson(map), + 'ssh-key' => SshKeySchemaValue.fromJson(map), + _ => throw UnsupportedError('Unsupported schema value type: $type'), + }; + } +} + +final class StringSchemaValue extends SchemaValue { + final String? value; + const StringSchemaValue({required super.showQrCode, this.value}); + + factory StringSchemaValue.fromJson(Map map) { + return StringSchemaValue( + value: map['default'] as String?, + showQrCode: (map['show-qr-code'] as bool?) ?? false, + ); + } +} + +final class UrlSchemaValue extends SchemaValue { + final String? value; + const UrlSchemaValue({required super.showQrCode, this.value}); + + factory UrlSchemaValue.fromJson(Map map) { + return UrlSchemaValue( + value: map['default'] as String?, + showQrCode: (map['show-qr-code'] as bool?) ?? false, + ); + } +} + +final class UuidSchemaValue extends SchemaValue { + final String? value; + const UuidSchemaValue({required super.showQrCode, this.value}); + + factory UuidSchemaValue.fromJson(Map map) { + return UuidSchemaValue( + value: map['default'] as String?, + showQrCode: (map['show-qr-code'] as bool?) ?? false, + ); + } +} + +enum BytesCategory { + password; + + factory BytesCategory.fromString(String value) { + switch (value) { + case 'password': + return BytesCategory.password; + default: + throw ArgumentError('Unknown bytes category: $value'); + } + } +} + +enum BytesGenerator { + crytoRandom; + + factory BytesGenerator.fromString(String value) { + switch (value) { + case 'crypto-random': + return BytesGenerator.crytoRandom; + default: + throw ArgumentError('Unknown bytes generator: $value'); + } + } +} + +final class BytesSchemaValue extends SchemaValue { + final Uint8List? value; + final int? min; + final int? max; + final BytesCategory? category; + final BytesGenerator? generator; + + const BytesSchemaValue({ + required super.showQrCode, + this.value, + this.min, + this.max, + this.category, + this.generator, + }); + + factory BytesSchemaValue.fromJson(Map map) { + final bytes = map['default'] as String?; + final min = map['min'] as int?; + final max = map['max'] as int?; + final category = BytesCategory.fromString(map['category'] as String); + final generator = BytesGenerator.fromString(map['generator'] as String); + + Uint8List? value; + if (bytes != null) { + value = base64Url.decode(bytes); + } + + return BytesSchemaValue( + value: value, + min: min, + max: max, + category: category, + generator: generator, + showQrCode: (map['show-qr-code'] as bool?) ?? false, + ); + } +} + +final class SshKeySchemaValue extends SchemaValue { + final String? value; + const SshKeySchemaValue({required super.showQrCode, this.value}); + + factory SshKeySchemaValue.fromJson(Map map) { + return SshKeySchemaValue( + value: map['default'] as String?, + showQrCode: (map['show-qr-code'] as bool?) ?? false, + ); + } +} + +enum ValueType { + url, + string, + bytes, + uuid; + + static ValueType fromString(String value) { + switch (value) { + case 'url': + return ValueType.url; + case 'string': + return ValueType.string; + case 'bytes': + return ValueType.bytes; + case 'uuid': + return ValueType.uuid; + default: + throw ArgumentError('Unknown ValueType: $value'); + } + } + + String toJsonString() { + switch (this) { + case ValueType.url: + return 'url'; + case ValueType.string: + return 'string'; + case ValueType.bytes: + return 'bytes'; + case ValueType.uuid: + return 'uuid'; + } + } +} + +class Value { + ValueType type; + dynamic content; + + Value({required this.type, required this.content}); + + factory Value.fromJson(Map json) { + final type = ValueType.fromString(json['type'] as String); + + dynamic content; + switch (type) { + case ValueType.url: + case ValueType.string: + content = json['content'] as String?; + case ValueType.uuid: + final value = json['content'] as String?; + content = value == null ? null : UuidValue.withValidation(value); + case ValueType.bytes: + final value = json['content'] as String?; + content = value == null ? null : Base64Codec.urlSafe().decode(value); + } + + return Value(type: type, content: content); + } + + Map toJson() { + dynamic result; + switch (type) { + case ValueType.url: + case ValueType.string: + result = content; + case ValueType.bytes: + final bytes = content as Uint8List?; + result = bytes == null ? null : Base64Codec.urlSafe().encode(bytes); + case ValueType.uuid: + result = (content as UuidValue?)?.toString(); + } + return {'type': type.toJsonString(), 'content': result}; + } + + @override + String toString() { + final map = toJson(); + return '${map['type']}:${map['content']}'; + } +} + +class Config { + Map fields; + + Config({required this.fields}); + + factory Config.fromJson(Map json) { + final fieldsJson = json['fields'] as Map; + + final fields = fieldsJson.map( + (key, value) => + MapEntry(key, Value.fromJson(value as Map)), + ); + + return Config(fields: fields); + } + + Map toJson() { + return { + 'fields': fields.map((key, value) => MapEntry(key, value.toJson())), + }; + } +} + +Uint8List generateCryptoRandomBytes(int length) { + final secureRandom = Random.secure(); + final bytes = Uint8List(length); + for (var i = 0; i < length; i++) { + bytes[i] = secureRandom.nextInt(256); + } + return bytes; +} + +class BackendConfigRoute extends StatefulWidget { + final Repository repository; + final UuidValue backendId; + const BackendConfigRoute({ + super.key, + required this.repository, + required this.backendId, + }); + + @override + State createState() => _BackendConfigRouteState(); +} + +class _BackendConfigRouteState extends State { + Future? _backend; + + @override + void initState() { + super.initState(); + _backend = widget.repository.backend(id: widget.backendId); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _backend, + builder: (context, snapshot) { + if (snapshot.hasError) { + context.read().add(LogErrorEvent(error: snapshot.error!)); + } + if (snapshot.connectionState != ConnectionState.done) { + return Center(child: CircularProgressIndicator.adaptive()); + } + + final record = snapshot.data!; + return Scaffold( + appBar: AppBar(title: Text(record.name)), + body: _ConfigSection(repository: widget.repository, record: record), + ); + }, + ); + } +} + +class _ConfigSection extends StatefulWidget { + final Repository repository; + final BackendRecord record; + const _ConfigSection({required this.record, required this.repository}); + + @override + State<_ConfigSection> createState() => _ConfigSectionState(); +} + +class _ConfigSectionState extends State<_ConfigSection> { + Future>? _sshKeys; + + late Schema _schema; + late Config _config; + + @override + void initState() { + super.initState(); + + _sshKeys = sshKeys(); + final configJson = jsonDecode(widget.record.config) as Map; + final schemaJson = jsonDecode(widget.record.schema) as Map; + + _schema = Schema.fromJson(schemaJson); + _config = Config.fromJson(configJson); + } + + @override + Widget build(BuildContext context) { + final tiles = []; + for (final entry in _schema.fields.entries) { + final name = entry.key; + final field = entry.value; + final value = _config.fields[name]; + + switch (field) { + case UrlSchemaValue(value: final defaultValue): + case StringSchemaValue(value: final defaultValue): + tiles.add( + SettingsTileText( + title: Text(name), + text: (value?.content as String?) ?? defaultValue ?? '', + onChanged: (text) async { + setState(() { + _config.fields[name] = Value( + type: ValueType.string, + content: text, + ); + }); + await _save(); + }, + ), + ); + + case BytesSchemaValue(): + tiles.add(_bytesProperty(field, name, value, context)); + + case SshKeySchemaValue(): + final uuid = value?.content as UuidValue?; + tiles.add(_sshKeyProperty(name, uuid)); + + case UuidSchemaValue(): + tiles.add(_uuidProperty(name, value)); + } + } + return SettingsList(sections: [SettingsSection(tiles: tiles)]); + } + + SettingsTileUuid _uuidProperty(String name, Value? value) { + return SettingsTileUuid( + title: Text(name), + value: value?.content as UuidValue?, + onChanged: (uuid) async { + setState(() { + _config.fields[name] = Value(type: ValueType.uuid, content: uuid); + }); + await _save(); + }, + ); + } + + FutureBuilder> _sshKeyProperty(String name, UuidValue? uuid) { + return FutureBuilder( + future: _sshKeys, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return CircularProgressIndicator.adaptive(); + } + return SettingsTileSsh( + title: Text(name), + uuid: uuid, + keys: snapshot.data!, + onChanged: (uuid) async { + setState(() { + _config.fields[name] = Value(type: ValueType.uuid, content: uuid); + }); + await _save(); + }, + trailing: Tooltip( + message: 'Generate new SSH key', + child: IconButton( + onPressed: () async { + final key = await showAlertDialog( + context: context, + content: Text( + 'Are you sure you want to generate a new SSH Key?', + ), + onConfirm: (context) async { + final key = await SshKey.generate(); + return key.uuid; + }, + ); + + if (key != null) { + setState(() { + _config.fields[name] = Value( + type: ValueType.uuid, + content: key, + ); + _sshKeys = sshKeys(); + }); + + await _save(); + } + }, + icon: Icon(Icons.generating_tokens), + ), + ), + ); + }, + ); + } + + SettingsTileText _bytesProperty( + BytesSchemaValue field, + String name, + Value? value, + BuildContext context, + ) { + final bytes = value?.content as Uint8List?; + + final BytesSchemaValue(:min, :max, :category, :generator) = field; + return SettingsTileText( + obscureText: category == BytesCategory.password, + title: Text(name), + text: bytes == null ? '' : base64Url.encode(bytes), + onChanged: (text) async { + setState(() { + _config.fields[name] = Value( + type: ValueType.bytes, + content: base64Url.decode(text), + ); + }); + await _save(); + }, + validator: (text) { + if (text == null) { + return null; + } + + try { + final bytes = base64Url.decode(text); + if (min != null && bytes.length < min) { + return 'input too small must be $min length, got: ${bytes.length}'; + } + if (max != null && bytes.length > max) { + return 'input too small must be $max length, got: ${bytes.length}'; + } + } on FormatException catch (error) { + return error.message; + } + return null; + }, + trailing: Wrap( + children: [ + if (field.showQrCode && value != null) + Tooltip( + message: 'Show QR Code', + child: IconButton( + onPressed: () async { + await showGeneralDialog( + context: context, + pageBuilder: (context, animation, secondaryAnimation) { + return GestureDetector( + onTap: () { + Navigator.of(context).pop(); + }, + child: Center( + child: Padding( + padding: const EdgeInsets.all(26.0), + child: LimitedBox( + maxWidth: 128, + maxHeight: 128, + child: QrImageView( + data: value.toString(), + backgroundColor: Colors.white, + padding: const EdgeInsets.all(16.0), + ), + ), + ), + ), + ); + }, + ); + }, + icon: Icon(Icons.qr_code), + ), + ), + if (generator == BytesGenerator.crytoRandom) + Tooltip( + message: 'Generate', + child: IconButton( + onPressed: () async { + final key = await showAlertDialog( + context: context, + content: Text( + 'Are you sure you want to generate a new encryption key?', + ), + onConfirm: (context) async { + return generateCryptoRandomBytes(max ?? min ?? 0); + }, + ); + + if (key != null) { + setState(() { + _config.fields[name] = Value( + type: ValueType.bytes, + content: key, + ); + }); + await _save(); + } + }, + icon: Icon(Icons.generating_tokens), + ), + ), + ], + ), + ); + } + + Future _save() async { + final json = _config.toJson(); + final backend = BackendRecord( + id: widget.record.id, + name: widget.record.name, + enabled: widget.record.enabled, + schema: '', + config: jsonEncode(json), + ); + return widget.repository.updateBackend(backend: backend); + } +} diff --git a/app/lib/routes/backend/list_route.dart b/app/lib/routes/backend/list_route.dart new file mode 100644 index 00000000..fe8f23aa --- /dev/null +++ b/app/lib/routes/backend/list_route.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:stride/blocs/log_bloc.dart'; +import 'package:stride/bridge/api/repository.dart'; +import 'package:stride/routes/backend/config_route.dart'; +import 'package:stride/utils/functions.dart'; +import 'package:stride/widgets/settings_widget.dart'; + +class BackendListRoute extends StatefulWidget { + final Repository repository; + const BackendListRoute({super.key, required this.repository}); + + @override + State createState() => _BackendListRouteState(); +} + +class _BackendListRouteState extends State { + TextStyle get headingStyle => const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.red, + ); + + Future>? _backends; + Future>? _backendNames; + + @override + void initState() { + super.initState(); + + _backends = widget.repository.backends(); + _backendNames = widget.repository.backendNames(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Backends')), + body: FutureBuilder( + future: _backends, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + // TODO: Factor this common pattern into a function. + return Center(child: CircularProgressIndicator.adaptive()); + } + if (snapshot.hasError) { + context.read().add(LogErrorEvent(error: snapshot.error!)); + return Center(child: CircularProgressIndicator.adaptive()); + } + final backends = snapshot.data!.map((backend) { + return SettingsTileNavigation( + title: Text(backend.name), + leading: const Icon(Icons.task), + trailing: Wrap( + children: [ + if (!backend.enabled) + IconButton( + onPressed: () async { + await showAlertDialog( + context: context, + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Are you sure you want to delete the backend? (action is irreversible)', + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, + ), + ], + ), + onConfirm: (context) async { + await widget.repository.deleteBackend( + id: backend.id, + ); + setState(() { + _backends = widget.repository.backends(); + }); + return true; + }, + ); + }, + icon: Icon(Icons.delete_forever), + ), + Switch( + value: backend.enabled, + activeColor: Colors.redAccent, + onChanged: (value) async { + await widget.repository.toggleBackend(id: backend.id); + setState(() { + _backends = widget.repository.backends(); + }); + }, + ), + ], + ), + builder: (context) => BackendConfigRoute( + repository: widget.repository, + backendId: backend.id, + ), + ); + }).toList(); + return SettingsList( + sections: [ + SettingsSection( + title: Text('Backends', style: headingStyle), + tiles: backends, + ), + ], + ); + }, + ), + floatingActionButton: FutureBuilder( + future: _backendNames, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return Center(); + } + + final names = snapshot.data!; + return FloatingActionButton( + shape: const CircleBorder(), + onPressed: () async { + await showModalBottomSheet( + context: context, + builder: (context) { + return ListView.builder( + itemCount: names.length, + itemBuilder: (context, index) { + final name = names[index]; + return ListTile( + title: Text(name), + onTap: () async { + await widget.repository.addBackend(name: name); + setState(() { + _backends = widget.repository.backends(); + _backendNames = widget.repository.backendNames(); + }); + }, + ); + }, + ); + }, + ); + }, + child: const Icon(Icons.add, size: 50), + ); + }, + ), + ); + } +} diff --git a/app/lib/routes/encryption_key_route.dart b/app/lib/routes/encryption_key_route.dart deleted file mode 100644 index 323289ca..00000000 --- a/app/lib/routes/encryption_key_route.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:qr_flutter/qr_flutter.dart'; -import 'package:stride/blocs/settings_bloc.dart'; -import 'package:stride/bridge/api/settings.dart'; -import 'package:stride/bridge/third_party/stride_backend_git/encryption_key.dart'; -import 'package:stride/widgets/settings_widget.dart'; - -class EncryptionKeyRoute extends StatefulWidget { - final RepositorySpecification repository; - const EncryptionKeyRoute({super.key, required this.repository}); - - @override - State createState() => EncryptionKeyRouteState(); -} - -class EncryptionKeyRouteState extends State { - String _key = ''; - bool showQrCode = false; - - @override - void initState() { - super.initState(); - - _key = widget.repository.encryption?.key ?? ''; - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Encryption')), - body: Container( - padding: const EdgeInsets.symmetric( - vertical: 10, - horizontal: 20, - ), - child: ListView( - children: [ - SettingsTileText( - leading: const Icon(Icons.key), - title: const Text('Key'), - text: _key, - hidden: true, - onChanged: (text) async { - _key = text; - showQrCode = false; - - if (_key.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('cannot add empty encryption key'), - behavior: SnackBarBehavior.floating, - ), - ); - return; - } - - final settingsBloc = context.read(); - final repositories = - settingsBloc.settings.repositories.toList(); - final index = repositories.indexWhere( - (repository) => repository.uuid == widget.repository.uuid, - ); - repositories[index] = widget.repository - .copyWith(encryption: EncryptionKey(key: _key)); - - settingsBloc.add( - SettingsUpdateEvent( - settings: settingsBloc.settings - .copyWith(repositories: repositories), - ), - ); - setState(() {}); - }, - ), - const Divider(), - ElevatedButton.icon( - onPressed: widget.repository.encryption == null - ? null - : () => setState(() => showQrCode = !showQrCode), - label: showQrCode - ? const Text('Hide QR Code') - : const Text('Show QR Code'), - icon: const Icon(Icons.qr_code), - ), - if (showQrCode) - Column( - children: [ - const Divider(), - Center( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: LimitedBox( - maxWidth: 512, - maxHeight: 512, - child: QrImageView( - data: _key, - backgroundColor: Colors.white, - padding: const EdgeInsets.all(16.0), - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); - } -} diff --git a/app/lib/routes/known_hosts_route.dart b/app/lib/routes/known_hosts_route.dart index 1797b141..d1333e73 100644 --- a/app/lib/routes/known_hosts_route.dart +++ b/app/lib/routes/known_hosts_route.dart @@ -9,11 +9,7 @@ class KnownHostsRoute extends StatefulWidget { final void Function(Host key)? onTap; final bool hasDelete; - const KnownHostsRoute({ - super.key, - this.onTap, - this.hasDelete = true, - }); + const KnownHostsRoute({super.key, this.onTap, this.hasDelete = true}); @override State createState() => _KnownHostsRouteState(); @@ -37,9 +33,7 @@ class _KnownHostsRouteState extends State { future: _knownHosts, builder: (context, state) { if (state.connectionState != ConnectionState.done) { - return const Center( - child: CircularProgressIndicator(), - ); + return const Center(child: CircularProgressIndicator()); } if (state.hasError) { @@ -89,14 +83,13 @@ class _KnownHostsRouteState extends State { ), onConfirm: (context) async { context.read().catch_( - () async => KnownHosts.save( - this_: KnownHosts( - hosts: knownHosts.hosts.toList() - ..removeWhere((element) => element == host), - ), - ), - ); - Navigator.of(context).pop(); + () async => KnownHosts.save( + this_: KnownHosts( + hosts: knownHosts.hosts.toList() + ..removeWhere((element) => element == host), + ), + ), + ); logging.trace(message: 'Known host deleted'); return true; }, diff --git a/app/lib/routes/plugin_list_route.dart b/app/lib/routes/plugin_list_route.dart index 609cf011..199a7bb8 100644 --- a/app/lib/routes/plugin_list_route.dart +++ b/app/lib/routes/plugin_list_route.dart @@ -15,10 +15,10 @@ class PluginListRoute extends StatelessWidget { const PluginListRoute({super.key}); TextStyle get headingStyle => const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.red, - ); + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.red, + ); @override Widget build(BuildContext context) { @@ -26,8 +26,9 @@ class PluginListRoute extends StatelessWidget { appBar: AppBar(title: const Text('Plugin List')), body: BlocBuilder( builder: (context, state) { - final plugins = - state.plugins.map((plugin) => _plugin(context, plugin)).toList(); + final plugins = state.plugins + .map((plugin) => _plugin(context, plugin)) + .toList(); return SettingsList( sections: [ SettingsSection( @@ -108,9 +109,7 @@ class PluginListRoute extends StatelessWidget { ), onTap: (context) { Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => PluginRoute(plugin: plugin), - ), + MaterialPageRoute(builder: (context) => PluginRoute(plugin: plugin)), ); }, ); @@ -133,9 +132,8 @@ class PluginListRoute extends StatelessWidget { ), onConfirm: (context) async { context.read().catch_( - () async => context.read().remove(name), - ); - Navigator.of(context).pop(); + () async => context.read().remove(name), + ); logging.trace(message: 'Plugin $name deleted'); return true; }, diff --git a/app/lib/routes/repository_new_route.dart b/app/lib/routes/repository_new_route.dart index 96caa73d..2d235bf6 100644 --- a/app/lib/routes/repository_new_route.dart +++ b/app/lib/routes/repository_new_route.dart @@ -1,10 +1,11 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:stride/blocs/plugin_manager_bloc.dart'; import 'package:stride/blocs/settings_bloc.dart'; import 'package:stride/blocs/tasks_bloc.dart'; import 'package:stride/bridge/api/settings.dart'; -import 'package:stride/bridge/third_party/stride_backend_git/encryption_key.dart'; import 'package:stride/bridge/third_party/stride_core/event.dart'; import 'package:stride/routes/ssh_keys_route.dart'; import 'package:stride/routes/tasks_route.dart'; @@ -84,10 +85,10 @@ class _RepositoryNewRouteState extends State { } List> _formKeys() => [ - _generalFormKey, - _gitIntegrationFormKey, - if (widget.cloning) _encryptionFormKey, - ]; + _generalFormKey, + _gitIntegrationFormKey, + if (widget.cloning) _encryptionFormKey, + ]; @override Widget build(BuildContext context) { @@ -115,45 +116,43 @@ class _RepositoryNewRouteState extends State { return; } - EncryptionKey? encrpytionKey; - if (widget.cloning) { - // NOTE: encryption key should be validated by form validaters - encrpytionKey = EncryptionKey(key: _encrytionKeyController.text); - } else { - encrpytionKey = await EncryptionKey.generate(); - } + // EncryptionKey? encrpytionKey; + // if (widget.cloning) { + // // NOTE: encryption key should be validated by form validaters + // encrpytionKey = EncryptionKey(key: _encrytionKeyController.text); + // } else { + // encrpytionKey = await EncryptionKey.generate(); + // } if (!mounted) return; final repositoryUuid = const Uuid().v7obj(); final settings = context.read().settings; context.read().add( - SettingsUpdateEvent( - settings: settings.copyWith( - repositories: settings.repositories.toList() - ..add( - RepositorySpecification( - uuid: repositoryUuid, - name: _nameController.text, - origin: _originController.text, - author: _authorController.text, - email: _emailController.text, - branch: _branchController.text, - encryption: encrpytionKey, - sshKeyUuid: _sshKeyController.text.isEmpty - ? null - : UuidValue.fromString(_sshKeyController.text), - ), - ), - currentRepository: repositoryUuid, + SettingsUpdateEvent( + settings: settings.copyWith( + repositories: settings.repositories.toList() + ..add( + RepositorySpecification( + uuid: repositoryUuid, + name: _nameController.text, + // origin: _originController.text, + // author: _authorController.text, + // email: _emailController.text, + // branch: _branchController.text, + // encryption: encrpytionKey, + // sshKeyUuid: _sshKeyController.text.isEmpty + // ? null + // : UuidValue.fromString(_sshKeyController.text), + ), ), - ), - ); - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (context) => const TasksRoute(), + currentRepository: repositoryUuid, + ), ), ); + Navigator.of(context).pushReplacement( + MaterialPageRoute(builder: (context) => const TasksRoute()), + ); if (widget.cloning) { context.read().add(TaskSyncEvent()); context.read().emitHostEvent(HostEvent.taskSync()); @@ -201,10 +200,7 @@ class _GeneralRepositoryForm extends StatelessWidget { final TextEditingController name; final GlobalKey formKey; - const _GeneralRepositoryForm({ - required this.formKey, - required this.name, - }); + const _GeneralRepositoryForm({required this.formKey, required this.name}); void _onChange(String _) { formKey.currentState!.validate(); @@ -275,9 +271,7 @@ class _GitIntegrationRepositoryFormState children: [ TextFormField( controller: widget.author, - decoration: const InputDecoration( - hintText: 'Enter Commit Author', - ), + decoration: const InputDecoration(hintText: 'Enter Commit Author'), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; @@ -288,9 +282,7 @@ class _GitIntegrationRepositoryFormState ), TextFormField( controller: widget.email, - decoration: const InputDecoration( - hintText: 'Enter Commit Email', - ), + decoration: const InputDecoration(hintText: 'Enter Commit Email'), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; @@ -390,14 +382,17 @@ class _EncryptionRepositoryForm extends StatelessWidget { children: [ TextFormField( controller: encryptionKey, - decoration: const InputDecoration( - hintText: 'Enter Encrypiton Key', - ), + decoration: const InputDecoration(hintText: 'Enter Encrypiton Key'), validator: (value) { if (value == null || value.isEmpty) { return 'please enter some text'; } - return EncryptionKey.validate(key: value); + + final bytes = Base64Codec.urlSafe().decode(value); + if (bytes.length != 32) { + return 'encryption key should be 32 bytes in length'; + } + return null; }, onChanged: _onChange, ), diff --git a/app/lib/routes/repository_route.dart b/app/lib/routes/repository_route.dart index c4d305d6..5756427c 100644 --- a/app/lib/routes/repository_route.dart +++ b/app/lib/routes/repository_route.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:stride/blocs/settings_bloc.dart'; import 'package:stride/blocs/tasks_bloc.dart'; -import 'package:stride/routes/encryption_key_route.dart'; -import 'package:stride/routes/ssh_keys_route.dart'; +import 'package:stride/bridge/api/repository.dart'; +import 'package:stride/routes/backend/list_route.dart'; import 'package:stride/utils/functions.dart'; import 'package:stride/widgets/settings_widget.dart'; import 'package:uuid/uuid.dart'; @@ -12,10 +11,10 @@ import 'package:uuid/uuid.dart'; class RepositoryRoute extends StatelessWidget { final UuidValue repositoryUuid; TextStyle get headingStyle => const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.red, - ); + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.red, + ); const RepositoryRoute({super.key, required this.repositoryUuid}); @@ -32,7 +31,9 @@ class RepositoryRoute extends StatelessWidget { if (repositoryIndex == -1) { return const Column(); } - final repository = settings.repositories[repositoryIndex]; + final repositorySpec = settings.repositories[repositoryIndex]; + + final repository = Repository.open(uuid: repositoryUuid); return SettingsList( sections: [ SettingsSection( @@ -41,21 +42,22 @@ class RepositoryRoute extends StatelessWidget { SettingsTileText( title: const Text('Name'), leading: const Icon(Icons.label), - text: repository.name, + text: repositorySpec.name, onChanged: (text) { final repositories = settings.repositories .map( - (e) => (e.uuid != repository.uuid) + (e) => (e.uuid != repositorySpec.uuid) ? e : e.copyWith(name: text), ) .toList(); context.read().add( - SettingsUpdateEvent( - settings: - settings.copyWith(repositories: repositories), - ), - ); + SettingsUpdateEvent( + settings: settings.copyWith( + repositories: repositories, + ), + ), + ); }, ), // TODO: Currently only work for the currently loaded repository. @@ -69,174 +71,22 @@ class RepositoryRoute extends StatelessWidget { // title: const Text('Import Tasks'), // onTap: _importTasks, // ), + SettingsTileNavigation( + leading: const Icon(Icons.backup), + title: const Text('Backends'), + builder: (context) => + BackendListRoute(repository: repository), + ), ], ), SettingsSection( title: Text('Git Integration', style: headingStyle), tiles: [ - SettingsTileText( - title: const Text('Repository URL'), - leading: const Icon(Icons.code), - text: repository.origin, - onChanged: (text) { - final repositories = settings.repositories - .map( - (e) => (e.uuid != repository.uuid) - ? e - : e.copyWith(origin: text), - ) - .toList(); - context.read().add( - SettingsUpdateEvent( - settings: - settings.copyWith(repositories: repositories), - ), - ); - }, - ), - SettingsTileText( - leading: const Icon(Icons.mail), - title: const Text('Email'), - text: repository.email, - onChanged: (text) { - final repositories = settings.repositories - .map( - (e) => (e.uuid != repository.uuid) - ? e - : e.copyWith(email: text), - ) - .toList(); - context.read().add( - SettingsUpdateEvent( - settings: - settings.copyWith(repositories: repositories), - ), - ); - }, - ), - SettingsTileText( - leading: const Icon(Icons.person), - title: const Text('Author'), - text: repository.author, - onChanged: (text) { - final repositories = settings.repositories - .map( - (e) => (e.uuid != repository.uuid) - ? e - : e.copyWith(author: text), - ) - .toList(); - context.read().add( - SettingsUpdateEvent( - settings: - settings.copyWith(repositories: repositories), - ), - ); - }, - ), - SettingsTileText( - leading: const FaIcon(FontAwesomeIcons.codeBranch), - title: const Text('Branch'), - text: repository.branch, - onChanged: (text) { - final repositories = settings.repositories - .map( - (e) => (e.uuid != repository.uuid) - ? e - : e.copyWith(branch: text), - ) - .toList(); - context.read().add( - SettingsUpdateEvent( - settings: - settings.copyWith(repositories: repositories), - ), - ); - context.read().add(TaskCheckoutBranchEvent()); - }, - ), - SettingsTileNavigation( - leading: const Icon(Icons.key), - title: const Text('SSH Key'), - builder: (context) => SshKeysRoute( - hasDelete: false, - selected: repository.sshKeyUuid, - onTap: (key) { - final repositories = settings.repositories - .map( - (e) => (e.uuid != repository.uuid) - ? e - : e.copyWith(sshKeyUuid: key.uuid), - ) - .toList(); - context.read().add( - SettingsUpdateEvent( - settings: settings.copyWith( - repositories: repositories, - ), - ), - ); - Navigator.of(context).pop(); - }, - ), - ), - // TODO: Currently this only works for the currently loaded repository. - // SettingsTileNavigation( - // leading: const Icon(Icons.commit), - // title: const Text('Commits'), - // builder: (context) => CommitsRoute( - // repository: - // context.read().repository() as TaskStorage, - // ), - // ), - SettingsTileNavigation( - leading: const Icon(Icons.lock), - title: const Text('Encryption'), - builder: (context) => EncryptionKeyRoute( - repository: repository, - ), - ), SettingsTile( - leading: const Icon(Icons.push_pin, color: Colors.red), - title: const Text('Force Push to Remote'), - onTap: (context) async { - await showAlertDialog( - context: context, - content: const Text( - 'Are you sure you want to force push local branch to remote repository?', - style: TextStyle(fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - onConfirm: (context) async { - context.read().add(TaskForcePushEvent()); - Navigator.of(context).pop(); - return true; - }, - ); - }, - ), - SettingsTile( - leading: const Icon(Icons.delete, color: Colors.red), - title: const Text('Remove Repository Files'), - onTap: (context) async { - await showAlertDialog( - context: context, - content: const Text( - 'Are you sure you want to delete the (local) repository?', - style: TextStyle(fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - onConfirm: (context) async { - context.read().add(TaskRemoveAllEvent()); - Navigator.of(context).pop(); - return true; - }, - ); - }, - ), - SettingsTile( - leading: - const Icon(Icons.delete_forever, color: Colors.red), + leading: const Icon( + Icons.delete_forever, + color: Colors.red, + ), title: const Text('Remove Repository'), onTap: (context) async { await showAlertDialog( @@ -247,10 +97,11 @@ class RepositoryRoute extends StatelessWidget { textAlign: TextAlign.center, ), onConfirm: (context) async { - context - .read() - .add(TaskRemoveAllEvent(all: true)); - Navigator.of(context).pop(); + context.read().add( + TaskRemoveRepositoryEvent( + uuid: repositorySpec.uuid, + ), + ); final settingsBloc = context.read(); final settings = settingsBloc.settings; settingsBloc.add( @@ -259,11 +110,12 @@ class RepositoryRoute extends StatelessWidget { repositories: settings.repositories.toList() ..removeWhere( (element) => - element.uuid == repository.uuid, + element.uuid == repositorySpec.uuid, ), ), ), ); + Navigator.of(context).pop(); return true; }, ); diff --git a/app/lib/routes/settings_route.dart b/app/lib/routes/settings_route.dart index 9faabf0c..31d375d7 100644 --- a/app/lib/routes/settings_route.dart +++ b/app/lib/routes/settings_route.dart @@ -13,10 +13,10 @@ import 'package:url_launcher/url_launcher_string.dart'; class SettingsRoute extends StatelessWidget { TextStyle get headingStyle => const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.red, - ); + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.red, + ); const SettingsRoute({super.key}); @@ -43,14 +43,15 @@ class SettingsRoute extends StatelessWidget { SettingsTileSwitch( title: const Text('Periodic Sync'), leading: const Icon(Icons.timer), - description: - const Text('Periodically sync every 5 minutes'), + description: const Text( + 'Periodically sync every 5 minutes', + ), value: settings.periodicSync, onChanged: (val) => context.read().add( - SettingsUpdateEvent( - settings: settings.copyWith(periodicSync: val), - ), - ), + SettingsUpdateEvent( + settings: settings.copyWith(periodicSync: val), + ), + ), ), SettingsTileNavigation( leading: const Icon(Icons.file_open), @@ -69,89 +70,6 @@ class SettingsRoute extends StatelessWidget { ), ], ), - // SettingsSection( - // title: Text('Git Integration', style: headingStyle), - // tiles: [ - // SettingsTileText( - // title: const Text('Repository URL'), - // leading: const Icon(Icons.code), - // text: settings.repositories[0].origin, - // onChanged: (text) { - // context.read().add( - // SettingsUpdateEvent( - // settings: settings.copyWith( - // repository: - // settings.repository.copyWith(origin: text), - // ), - // ), - // ); - // }, - // ), - // SettingsTileText( - // leading: const Icon(Icons.mail), - // title: const Text('Email'), - // text: settings.repository.email, - // onChanged: (text) { - // context.read().add( - // SettingsUpdateEvent( - // settings: settings.copyWith( - // repository: - // settings.repository.copyWith(email: text), - // ), - // ), - // ); - // }, - // ), - // SettingsTileText( - // leading: const Icon(Icons.person), - // title: const Text('Author'), - // text: settings.repository.author, - // onChanged: (text) { - // context.read().add( - // SettingsUpdateEvent( - // settings: settings.copyWith( - // repository: - // settings.repository.copyWith(author: text), - // ), - // ), - // ); - // }, - // ), - // SettingsTileText( - // leading: const FaIcon(FontAwesomeIcons.codeBranch), - // title: const Text('Branch'), - // text: settings.repository.branch, - // onChanged: (text) { - // context.read().add( - // SettingsUpdateEvent( - // settings: settings.copyWith( - // repository: - // settings.repository.copyWith(branch: text), - // ), - // ), - // ); - // context.read().add(TaskCheckoutBranchEvent()); - // }, - // ), - // SettingsTileNavigation( - // leading: const Icon(Icons.key), - // title: const Text('SSH Key'), - // builder: (context) => SshKeysRoute( - // hasDelete: false, - // selected: settings.repository.sshKeyUuid, - // onTap: (key) { - // context.read().add( - // SettingsUpdateEvent( - // settings: settings.copyWith( - // repository: settings.repository - // .copyWith(sshKeyUuid: key.uuid), - // ), - // ), - // ); - // Navigator.of(context).pop(); - // }, - // ), - // ), // SettingsTileNavigation( // leading: const Icon(Icons.commit), // title: const Text('Commits'), @@ -159,13 +77,6 @@ class SettingsRoute extends StatelessWidget { // repository: context.read().repository, // ), // ), - // SettingsTileNavigation( - // leading: const Icon(Icons.lock), - // title: const Text('Encryption'), - // builder: (context) => EncryptionKeyRoute( - // encryption: settings.repository.encryption, - // ), - // ), // SettingsTile( // leading: const Icon(Icons.save_alt), // title: const Text('Export Tasks'), @@ -195,27 +106,6 @@ class SettingsRoute extends StatelessWidget { // ); // }, // ), - // SettingsTile( - // leading: const Icon(Icons.push_pin, color: Colors.red), - // title: const Text('Force Push to Remote'), - // onTap: (context) async { - // await showAlertDialog( - // context: context, - // content: const Text( - // 'Are you sure you want to force push local branch to remote repository?', - // style: TextStyle(fontWeight: FontWeight.bold), - // textAlign: TextAlign.center, - // ), - // onConfirm: (context) async { - // context.read().add(TaskForcePushEvent()); - // Navigator.of(context).pop(); - // return true; - // }, - // ); - // }, - // ), - // ], - // ), SettingsSection( title: Text('Security', style: headingStyle), tiles: [ @@ -225,16 +115,12 @@ class SettingsRoute extends StatelessWidget { builder: (context) => SshKeysRoute( onTap: (key) async { await Clipboard.setData( - ClipboardData( - text: key.publicKey, - ), + ClipboardData(text: key.publicKey), ); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( - content: Text( - 'Copied to clipbard!', - ), + content: Text('Copied to clipbard!'), ), ); } @@ -259,10 +145,7 @@ class SettingsRoute extends StatelessWidget { // maybe use package_info_plus to get the version. '0.0.1+1', overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12.0, - color: Colors.grey, - ), + style: TextStyle(fontSize: 12.0, color: Colors.grey), ), ), // TODO: Deduplicate string by using the SettingsTileText @@ -272,18 +155,15 @@ class SettingsRoute extends StatelessWidget { description: const Text( 'https://github.com/stride-tasks/stride/issues', overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12.0, - color: Colors.grey, - ), + style: TextStyle(fontSize: 12.0, color: Colors.grey), ), title: const Text('Issue Tracker'), onTap: (context) async { const url = 'https://github.com/stride-tasks/stride/issues'; - await context - .read() - .catch_(() async => launchUrlString(url)); + await context.read().catch_( + () async => launchUrlString(url), + ); }, ), SettingsTile( @@ -292,16 +172,13 @@ class SettingsRoute extends StatelessWidget { description: const Text( 'https://github.com/stride-tasks/stride', overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12.0, - color: Colors.grey, - ), + style: TextStyle(fontSize: 12.0, color: Colors.grey), ), onTap: (context) async { const url = 'https://github.com/stride-tasks/stride'; - await context - .read() - .catch_(() async => launchUrlString(url)); + await context.read().catch_( + () async => launchUrlString(url), + ); }, ), SettingsTile( @@ -310,17 +187,14 @@ class SettingsRoute extends StatelessWidget { description: const Text( 'AGPL-3.0-or-later', overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12.0, - color: Colors.grey, - ), + style: TextStyle(fontSize: 12.0, color: Colors.grey), ), onTap: (context) async { const url = 'https://www.gnu.org/licenses/agpl-3.0.en.html'; - await context - .read() - .catch_(() async => launchUrlString(url)); + await context.read().catch_( + () async => launchUrlString(url), + ); }, ), ], diff --git a/app/lib/routes/ssh_keys_route.dart b/app/lib/routes/ssh_keys_route.dart index 27e54f84..fee12135 100644 --- a/app/lib/routes/ssh_keys_route.dart +++ b/app/lib/routes/ssh_keys_route.dart @@ -62,9 +62,7 @@ class _SshKeysRouteState extends State { } if (snapshot.connectionState != ConnectionState.done) { - return const Center( - child: CircularProgressIndicator.adaptive(), - ); + return const Center(child: CircularProgressIndicator.adaptive()); } final keys = snapshot.data!; @@ -116,22 +114,23 @@ class _SshKeysRouteState extends State { final publicKey = key.publicKey; final uuid = key.uuid; - final subtitle = switch (settings.repositories.any( - (element) => element.sshKeyUuid == uuid, - )) { - false => Text(uuid.toString()), - true => RichText( - text: TextSpan( - children: [ - TextSpan(text: '$uuid '), - WidgetSpan( - child: Icon(Icons.info, size: 16, color: Colors.blue[200]), - ), - const TextSpan(text: ' Key In Use'), - ], - ), - ), - }; + final subtitle = Text(uuid.toString()); + // final subtitle = switch (settings.repositories.any( + // (element) => element.sshKeyUuid == uuid, + // )) { + // false => Text(uuid.toString()), + // true => RichText( + // text: TextSpan( + // children: [ + // TextSpan(text: '$uuid '), + // WidgetSpan( + // child: Icon(Icons.info, size: 16, color: Colors.blue[200]), + // ), + // const TextSpan(text: ' Key In Use'), + // ], + // ), + // ), + // }; return ListTile( title: Text(publicKey), @@ -140,8 +139,8 @@ class _SshKeysRouteState extends State { leading: widget.selected == null ? null : key.uuid != widget.selected - ? const Icon(Icons.circle_outlined) - : const Icon(Icons.check_circle_outline_rounded), + ? const Icon(Icons.circle_outlined) + : const Icon(Icons.check_circle_outline_rounded), trailing: !widget.hasDelete ? null : IconButton( @@ -163,10 +162,9 @@ class _SshKeysRouteState extends State { ), onConfirm: (context) async { await context.read().catch_( - message: 'ssh key', - () async => SshKey.removeKey(uuid: key.uuid), - ); - if (context.mounted) Navigator.of(context).pop(); + message: 'ssh key', + () async => SshKey.removeKey(uuid: key.uuid), + ); logging.trace( message: 'SSH Key deleted with UUID: ${key.uuid}', ); diff --git a/app/lib/routes/task_filter_route.dart b/app/lib/routes/task_filter_route.dart index 2cd9266c..4d7ad881 100644 --- a/app/lib/routes/task_filter_route.dart +++ b/app/lib/routes/task_filter_route.dart @@ -12,10 +12,7 @@ import 'package:uuid/uuid.dart'; class TaskFilterRoute extends StatefulWidget { final Filter? filter; - const TaskFilterRoute({ - super.key, - this.filter, - }); + const TaskFilterRoute({super.key, this.filter}); @override State createState() => _TaskFilterRouteState(); @@ -131,20 +128,15 @@ class _TaskFilterRouteState extends State { search: searchController.text, ); final newSettings = state.settings.copyWith( - selectedFilter: FilterSelection.temporary( - filter: filter, - ), + selectedFilter: FilterSelection.temporary(filter: filter), + ); + context.read().add( + SettingsUpdateEvent(settings: newSettings), ); - context - .read() - .add(SettingsUpdateEvent(settings: newSettings)); context.read().add(TaskFilterEvent(filter: filter)); // Pop to first route. - Navigator.popUntil( - context, - (route) => route.isFirst, - ); + Navigator.popUntil(context, (route) => route.isFirst); }, ), const SizedBox(width: 20), @@ -154,13 +146,12 @@ class _TaskFilterRouteState extends State { onPressed: () async { await showAlertDialog( context: context, + popRoute: false, content: TextField( controller: nameController, autocorrect: false, autofocus: true, - decoration: const InputDecoration( - hintText: 'Filter name...', - ), + decoration: const InputDecoration(hintText: 'Filter name...'), ), onConfirm: (context) async { if (nameController.text.isEmpty) { @@ -195,12 +186,10 @@ class _TaskFilterRouteState extends State { } context.read().add( - SettingsUpdateEvent( - settings: state.settings.copyWith( - filters: filters, - ), - ), - ); + SettingsUpdateEvent( + settings: state.settings.copyWith(filters: filters), + ), + ); // Pop to first route. Navigator.popUntil(context, (route) => route.isFirst); @@ -230,6 +219,7 @@ class _TaskFilterRouteState extends State { onPressed: () async { await showAlertDialog( context: context, + popRoute: false, content: Text( 'Are you sure you want to delete ${filter.name} filter?', style: const TextStyle(fontWeight: FontWeight.bold), @@ -237,32 +227,30 @@ class _TaskFilterRouteState extends State { ), onConfirm: (context) { final filters = state.settings.filters.toList() - ..removeWhere( - (element) => element.uuid == filter.uuid, - ); + ..removeWhere((element) => element.uuid == filter.uuid); - if (state.settings.selectedFilter - case FilterSelection_Predefined(:final uuid)) { + if (state.settings.selectedFilter case FilterSelection_Predefined( + :final uuid, + )) { if (uuid == filter.uuid) { context.read().add(TaskFilterEvent()); context.read().add( - SettingsUpdateEvent( - settings: - state.settings.copyWith(selectedFilter: null), - ), - ); + SettingsUpdateEvent( + settings: state.settings.copyWith(selectedFilter: null), + ), + ); } } context.read().add( - SettingsUpdateEvent( - settings: state.settings.copyWith(filters: filters), - ), - ); + SettingsUpdateEvent( + settings: state.settings.copyWith(filters: filters), + ), + ); // Pop to first route. Navigator.popUntil(context, (route) => route.isFirst); - return Future.value(true); + return true; }, ); }, diff --git a/app/lib/routes/tasks_route.dart b/app/lib/routes/tasks_route.dart index 5391b3b6..d4bc2575 100644 --- a/app/lib/routes/tasks_route.dart +++ b/app/lib/routes/tasks_route.dart @@ -99,49 +99,53 @@ class _TasksRouteState extends State { task.status == TaskStatus.deleted) { status = TaskStatus.pending; } - context - .read() - .add(TaskChangeStatusEvent(task: task, status: status)); + context.read().add( + TaskChangeStatusEvent(task: task, status: status), + ); context.read().emitHostEvent( - HostEvent.taskModify( - current: task.copyWith(status: status), - previous: task, - ), - ); + HostEvent.taskModify( + current: task.copyWith(status: status), + previous: task, + ), + ); return true; } Future onSwipeLeft() async { - final additionalMessage = - task.status == TaskStatus.deleted ? ' forever' : ''; + final additionalMessage = task.status == TaskStatus.deleted + ? ' forever' + : ''; - return showAlertDialog( - context: context, - content: Text( - 'Are you sure you want to delete this task$additionalMessage?', - style: const TextStyle(fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - onConfirm: (context) async { - context.read().add(TaskRemoveEvent(task: task)); - Navigator.of(context).pop(); - return true; - }, - ); + return await showAlertDialog( + context: context, + content: Text( + 'Are you sure you want to delete this task$additionalMessage?', + style: const TextStyle(fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + ), + onConfirm: (context) async { + context.read().add(TaskRemoveEvent(task: task)); + return true; + }, + ) ?? + false; } return TaskItem( task: task, onSwipeRight: onSwipeRight, - swipeRightIcon: (task.status == TaskStatus.complete || + swipeRightIcon: + (task.status == TaskStatus.complete || task.status == TaskStatus.deleted) ? const Icon(Icons.calendar_month, color: Colors.white) : const Icon(Icons.check, color: Colors.white), - swipeRightColor: (task.status == TaskStatus.complete || + swipeRightColor: + (task.status == TaskStatus.complete || task.status == TaskStatus.deleted) ? Colors.purpleAccent : Colors.greenAccent, - swipeRightText: (task.status == TaskStatus.complete || + swipeRightText: + (task.status == TaskStatus.complete || task.status == TaskStatus.deleted) ? 'Pending' : null, @@ -211,12 +215,12 @@ class _TasksRouteState extends State { onTap: selected ? null : () => context.read().add( - SettingsUpdateEvent( - settings: settings.copyWith( - currentRepository: repository.uuid, - ), + SettingsUpdateEvent( + settings: settings.copyWith( + currentRepository: repository.uuid, ), ), + ), onLongPress: () { Navigator.of(context).push( MaterialPageRoute( @@ -244,8 +248,9 @@ class _TasksRouteState extends State { var selected = false; if (settings.selectedFilter is FilterSelection_Predefined) { - final predefined = settings.selectedFilter! - as FilterSelection_Predefined; + final predefined = + settings.selectedFilter! + as FilterSelection_Predefined; selected = filter.uuid == predefined.uuid; } return Card( @@ -264,29 +269,28 @@ class _TasksRouteState extends State { onTap: () { if (selected) { context.read().add( - SettingsUpdateEvent( - settings: settings.copyWith( - selectedFilter: null, - ), - ), - ); + SettingsUpdateEvent( + settings: settings.copyWith( + selectedFilter: null, + ), + ), + ); context.read().add(TaskFilterEvent()); return; } context.read().add( - SettingsUpdateEvent( - settings: settings.copyWith( - selectedFilter: - FilterSelection.predefined( - uuid: filter.uuid, - ), - ), + SettingsUpdateEvent( + settings: settings.copyWith( + selectedFilter: FilterSelection.predefined( + uuid: filter.uuid, ), - ); - context - .read() - .add(TaskFilterEvent(filter: filter)); + ), + ), + ); + context.read().add( + TaskFilterEvent(filter: filter), + ); }, ), ); diff --git a/app/lib/utils/functions.dart b/app/lib/utils/functions.dart index fe284aec..bb7c459d 100644 --- a/app/lib/utils/functions.dart +++ b/app/lib/utils/functions.dart @@ -31,14 +31,14 @@ Future showPickDateTime({required BuildContext context}) async { ).toUtc(); } -Future showAlertDialog({ +Future showAlertDialog({ required BuildContext context, required Widget content, - FutureOr Function(BuildContext context)? onCancel, - required FutureOr Function(BuildContext context) onConfirm, + FutureOr Function(BuildContext context)? onCancel, + required FutureOr Function(BuildContext context) onConfirm, + bool popRoute = true, }) async { - var result = false; - await showDialog( + return showDialog( context: context, builder: (context) => AlertDialog( content: SizedBox( @@ -54,18 +54,19 @@ Future showAlertDialog({ Navigator.pop(context); return; } - await onCancel(context); + final result = await onCancel(context); + + if (context.mounted && popRoute) Navigator.pop(context, result); }, ), IconButton( icon: const Icon(Icons.check), onPressed: () async { - await onConfirm(context); - result = true; + final result = await onConfirm(context); + if (context.mounted && popRoute) Navigator.pop(context, result); }, ), ], ), ); - return result; } diff --git a/app/lib/widgets/settings_widget.dart b/app/lib/widgets/settings_widget.dart index f21a662f..24b0e126 100644 --- a/app/lib/widgets/settings_widget.dart +++ b/app/lib/widgets/settings_widget.dart @@ -1,5 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:stride/bridge/api/settings.dart'; +import 'package:stride/routes/ssh_keys_route.dart'; import 'package:stride/utils/functions.dart'; +import 'package:uuid/uuid_value.dart'; +import 'package:uuid/validation.dart'; Iterable insertBetween(Iterable iterable, T element) sync* { final iterator = iterable.iterator; @@ -36,20 +40,16 @@ class SettingsList extends StatelessWidget { } class SettingsSection extends StatelessWidget { - final Widget title; - final List tiles; + final Widget? title; + final List tiles; - const SettingsSection({ - super.key, - required this.title, - required this.tiles, - }); + const SettingsSection({super.key, this.title, required this.tiles}); @override Widget build(BuildContext context) { return Column( children: [ - Row(children: [title]), + if (title != null) Row(children: [title!]), ...insertBetween(tiles, const Divider()), ], ); @@ -91,13 +91,14 @@ class SettingsTileNavigation extends SettingsTile { required super.title, super.description, super.leading, + super.trailing, required this.builder, }) : super( - onTap: (context) { - // ignore: inference_failure_on_instance_creation - Navigator.of(context).push(MaterialPageRoute(builder: builder)); - }, - ); + onTap: (context) { + // ignore: inference_failure_on_instance_creation + Navigator.of(context).push(MaterialPageRoute(builder: builder)); + }, + ); } class SettingsTileSwitch extends SettingsTile { @@ -111,15 +112,15 @@ class SettingsTileSwitch extends SettingsTile { required this.value, required this.onChanged, }) : super( - trailing: Switch( - value: value, - activeColor: Colors.redAccent, - onChanged: onChanged, - ), - onTap: (context) { - onChanged(value); - }, - ); + trailing: Switch( + value: value, + activeColor: Colors.redAccent, + onChanged: onChanged, + ), + onTap: (context) { + onChanged(value); + }, + ); } class SettingsTileText extends SettingsTile { @@ -128,41 +129,149 @@ class SettingsTileText extends SettingsTile { required super.title, Widget? description, super.leading, + Widget? trailing, required String text, required void Function(String text) onChanged, + String? Function(String? text)? validator, bool hidden = false, bool multiline = false, + bool obscureText = false, + }) : super( + trailing: trailing ?? const Icon(Icons.arrow_forward), + description: hidden + ? null + : description != null || text.isEmpty + ? description + : Text( + obscureText ? text.replaceAll(RegExp('.'), '*') : text, + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 12.0, color: Colors.grey), + ), + onTap: (context) async { + final controller = TextEditingController(text: text); + await showAlertDialog( + context: context, + popRoute: false, + content: StatefulBuilder( + builder: (context, setState) => TextFormField( + controller: controller, + autocorrect: false, + autofocus: true, + maxLines: multiline ? null : 1, + keyboardType: multiline ? TextInputType.multiline : null, + decoration: InputDecoration( + errorText: validator?.call(controller.text), + ), + validator: validator, + onChanged: (_) => setState(() {}), + ), + ), + onConfirm: (context) async { + if (validator?.call(controller.text) != null) { + return false; + } + onChanged(controller.text); + Navigator.of(context).pop(); + return true; + }, + ); + }, + ); +} + +String? uuidValidator(String? text) { + if (text == null) { + return 'empty UUID'; + } + return UuidValidation.isValidUUID(fromString: text) ? null : 'Invalid UUID'; +} + +class SettingsTileUuid extends SettingsTile { + final UuidValue? value; + final void Function(UuidValue value) onChanged; + SettingsTileUuid({ + super.key, + required super.title, + super.leading, + required this.value, + required this.onChanged, + }) : super( + trailing: const Icon(Icons.arrow_forward), + description: value == null + ? null + : Text( + value.toString(), + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 12.0, color: Colors.grey), + ), + onTap: (context) async { + final controller = TextEditingController(text: value?.toString()); + await showAlertDialog( + context: context, + content: StatefulBuilder( + builder: (context, setState) => TextFormField( + controller: controller, + autocorrect: false, + autofocus: true, + decoration: InputDecoration( + errorText: uuidValidator(controller.text), + ), + validator: uuidValidator, + onChanged: (_) => setState(() {}), + ), + ), + onConfirm: (context) { + try { + final uuid = UuidValue.withValidation(controller.text); + onChanged(uuid); + } on FormatException { + return false; + } + return true; + }, + ); + }, + ); +} + +class SettingsTileSsh extends SettingsTile { + SettingsTileSsh({ + super.key, + required super.title, + super.leading, + required UuidValue? uuid, + required void Function(UuidValue value) onChanged, + List? keys, + Widget? trailing, }) : super( - trailing: const Icon(Icons.arrow_forward), - description: hidden - ? null - : description != null || text.isEmpty - ? description - : Text( - text, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 12.0, - color: Colors.grey, - ), - ), - onTap: (context) async { - final controller = TextEditingController(text: text); - await showAlertDialog( - context: context, - content: TextField( - controller: controller, - autocorrect: false, - autofocus: true, - maxLines: multiline ? null : 1, - keyboardType: multiline ? TextInputType.multiline : null, - ), - onConfirm: (context) async { - onChanged(controller.text); - Navigator.pop(context); - return true; - }, - ); - }, - ); + trailing: trailing ?? const Icon(Icons.arrow_forward), + description: uuid == null + ? null + : Text( + keys + ?.cast() + .firstWhere( + (element) => element!.uuid == uuid, + orElse: () => null, + ) + ?.publicKey ?? + 'key not found!', + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 12.0, color: Colors.grey), + ), + onTap: (context) async { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => SshKeysRoute( + selected: uuid, + onTap: (key) { + onChanged(key.uuid); + Navigator.of(context).pop(); + }, + hasDelete: false, + ), + ), + ); + }, + ); } diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 628020bb..27a9b145 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -71,7 +71,7 @@ flutter_native_splash: web: false flutter_rust_bridge: - rust_input: crate::api,stride_core,stride_backend_git::known_hosts,stride_backend_git::encryption_key,stride_plugin_manager::manifest + rust_input: crate::api,stride_core,stride_backend_git::known_hosts,stride_plugin_manager::manifest rust_root: ../crates/flutter_bridge/ dart_output: lib/bridge web: false diff --git a/cli/src/backend.rs b/cli/src/backend.rs index 13ef120f..6c14f227 100644 --- a/cli/src/backend.rs +++ b/cli/src/backend.rs @@ -1,43 +1,37 @@ use std::process::ExitCode; use anyhow::{Context, bail}; -use stride_core::{ - backend::{BackendRecord, Config}, - state::KnownPaths, -}; -use stride_flutter_bridge::api::repository::Repository; +use stride_backend::registry::Registry; +use stride_core::backend::{BackendRecord, Config, Value}; +use stride_database::Database; use uuid::Uuid; -use crate::{cli::BackendCommand, get_backend_registry}; +use crate::cli::BackendCommand; // TODO: Remove lints. #[allow(clippy::missing_panics_doc)] #[allow(clippy::too_many_lines)] pub(crate) fn handle_command( command: Option<&BackendCommand>, - repository: &mut Repository, - known_paths: &KnownPaths, + backend_registry: &Registry, + database: &mut Database, ) -> anyhow::Result { - let registry = get_backend_registry(known_paths)?; - match command { None | Some(BackendCommand::List) => { - let backends = repository.database().lock().unwrap().backends()?; + let backends = database.backends()?; for (i, backend) in backends.iter().enumerate() { println!("{i:2}. {}", backend.name); } } Some(BackendCommand::New { backend_name: name }) => { - let Some(handler) = registry.get(name.as_str()) else { - bail!("unknown backend name: {name}"); - }; + let handler = backend_registry.get_or_error(name.as_str())?; let record = BackendRecord { id: Uuid::now_v7(), enabled: true, name: handler.name(), config: Config::default(), }; - repository.database().lock().unwrap().add_backend(&record)?; + database.add_backend(&record)?; } Some(BackendCommand::Config { backend_name: name, @@ -45,26 +39,20 @@ pub(crate) fn handle_command( unset, property_value, }) => { - let mut backends = repository.database().lock().unwrap().backends()?; + let mut backends = database.backends()?; let backend = backends .iter_mut() .find(|backend_record| backend_record.name.contains(name)) .with_context(|| format!("Could not find field with name {name}"))?; - let Some(handler) = registry.get(name.as_str()) else { - bail!("unknown backend name: {name}"); - }; + let handler = backend_registry.get_or_error(name.as_str())?; let schema = handler.config_schema(); let config = backend.config.align(&schema)?; if config != backend.config { backend.config = config; - repository - .database() - .lock() - .unwrap() - .update_backend(backend)?; + database.update_backend(backend)?; } let Some(property_name) = property_name else { @@ -85,7 +73,7 @@ pub(crate) fn handle_command( schema_field.value.as_type_name(), value.map_or_else( || String::from("none").into(), - |value| value.as_value_string() + |value: Value| value.as_value_string() ) ); } @@ -108,11 +96,7 @@ pub(crate) fn handle_command( } let has_value = value.is_some(); - repository - .database_mut() - .get_mut() - .unwrap() - .update_backend(backend)?; + database.update_backend(backend)?; return Ok(ExitCode::from(u8::from(!has_value))); }; @@ -121,25 +105,17 @@ pub(crate) fn handle_command( .config .set(schema_field, property_name, property_value)?; - repository - .database_mut() - .get_mut() - .unwrap() - .update_backend(backend)?; + database.update_backend(backend)?; } Some(BackendCommand::Remove { backend_name }) => { - let backends = repository.database().lock().unwrap().backends()?; + let backends = database.backends()?; let backend = backends .iter() .find(|backend_record| backend_record.name.contains(backend_name)) .with_context(|| format!("Could not find field with name {backend_name}"))?; - repository - .database_mut() - .get_mut() - .unwrap() - .delete_backend(backend.id)?; + database.delete_backend(backend.id)?; } } Ok(ExitCode::SUCCESS) diff --git a/cli/src/main.rs b/cli/src/main.rs index 0d258d00..53b7d267 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -3,12 +3,11 @@ use chrono::Local; use clap::Parser; use cli::{CliArgs, Mode}; use std::{ - collections::HashMap, io::Write, path::{Path, PathBuf}, process::ExitCode, }; -use stride_backend::{Backend, BackendHandler}; +use stride_backend::{Backend, registry::Registry}; use stride_backend_git::{GitBackend, known_hosts::KnownHosts}; use stride_backend_taskchampion::TaskchampionBackend; use stride_core::{ @@ -16,14 +15,10 @@ use stride_core::{ state::KnownPaths, task::{Task, TaskStatus}, }; -use stride_database::operation::OperationKind; -use stride_flutter_bridge::{ - RustError, - api::{ - filter::Filter, - repository::Repository, - settings::{ApplicationPaths, RepositorySpecification, Settings, SshKey, ssh_keys}, - }, +use stride_database::{Database, operation::OperationKind}; +use stride_flutter_bridge::api::{ + filter::Filter, + settings::{ApplicationPaths, RepositorySpecification, Settings, SshKey, ssh_keys}, }; use stride_plugin_manager::{PluginManager, manifest::PluginAction}; @@ -74,20 +69,6 @@ fn print_tasks(tasks: &[Task]) { } } -#[allow(clippy::unnecessary_wraps)] -pub(crate) fn get_backend_registry( - _known_paths: &KnownPaths, -) -> Result, Box>, RustError> { - let mut registry: HashMap<_, Box> = HashMap::new(); - let git_handler = GitBackend::handler(); - registry.insert(git_handler.name(), git_handler); - - let taskchampion_handler = TaskchampionBackend::handler(); - registry.insert(taskchampion_handler.name(), taskchampion_handler); - - Ok(registry) -} - #[allow(clippy::too_many_lines)] fn main() -> anyhow::Result { // TODO(@bpeetz): Re-add the functionality of running `stride` without @@ -117,13 +98,7 @@ fn main() -> anyhow::Result { .to_string(), })?; - let known_paths = KnownPaths { - support: support_dir.clone(), - logs: cache_dir.join("logs").join("log.txt"), - cache: cache_dir, - download: document_dir, - ssh_keys: support_dir.join(".ssh").join("keys"), - }; + let known_paths = KnownPaths::new(support_dir.clone(), cache_dir.clone()); let current_repository = settings.current_repository.or_else(|| { settings @@ -147,7 +122,14 @@ fn main() -> anyhow::Result { let mut plugin_manager = PluginManager::new(&plugins_path)?; plugin_manager.load()?; - let mut repository = Repository::open(current_repository)?; + let repository_path = known_paths.repository_path(current_repository); + let database_filepath = known_paths.database_filepath(current_repository); + let mut database = Database::open(&database_filepath)?; + database.apply_migrations()?; + + let mut backend_registry = Registry::new(); + backend_registry.insert(GitBackend::handler()); + backend_registry.insert(TaskchampionBackend::handler()); match args.mode { Mode::Search { filter } => { @@ -156,7 +138,10 @@ fn main() -> anyhow::Result { status: [TaskStatus::Pending].into(), ..Default::default() }; - let tasks = repository.all_tasks(&filter)?; + + let search = filter.search.to_lowercase(); + let mut tasks = database.tasks_by_status(&filter.status)?; + tasks.retain(|task| task.title.to_lowercase().contains(&search)); print_tasks(&tasks); } Mode::Add { content } => { @@ -176,7 +161,7 @@ fn main() -> anyhow::Result { let event = HostEvent::TaskCreate { task: Some(Box::new(task.clone())), }; - repository.insert_task(&task)?; + database.insert_task(&task)?; plugin_manager.emit_event(None, &event)?; while plugin_manager.process_host_event()? {} @@ -195,16 +180,20 @@ fn main() -> anyhow::Result { match event { PluginEvent::TaskCreate { task } => { - repository.insert_task(&task)?; + database.insert_task(&task)?; } PluginEvent::TaskModify { task } => { - repository.update_task(&task)?; + database.update_task(&task)?; } PluginEvent::TaskSync => { - repository.sync()?; + backend_registry.sync_all( + current_repository, + &mut database, + &known_paths, + )?; } PluginEvent::TaskQuery { query } => { - let tasks = repository.task_query(&query)?; + let tasks = database.task_query(&query)?; plugin_manager .emit_event(Some(&plugin_name), &HostEvent::TaskQuery { tasks })?; } @@ -217,7 +206,6 @@ fn main() -> anyhow::Result { Mode::Undo { count } => { let count = count.unwrap_or(1); - let mut database = repository.database().lock().unwrap(); let operations = database.undoable_operation(count)?; for (i, (_, operation)) in operations.iter().rev().enumerate() { @@ -308,43 +296,31 @@ fn main() -> anyhow::Result { } } Mode::Sync { backend: name } => { - let registry = get_backend_registry(&known_paths)?; - - let Some(handler) = registry.get(name.as_str()) else { - bail!("unknown backend name: {name}"); - }; + let handler = backend_registry.get_or_error(name.as_str())?; - let mut backends = repository.database().lock().unwrap().backends()?; + let mut backends = database.backends()?; let backend = backends .iter_mut() .find(|backend_record| backend_record.name.contains(&name)) .with_context(|| format!("Could not find field with name: {name}"))?; - let path = repository - .root_path() - .join("backend") - .join(handler.name().as_ref()) - .join(backend.id.to_string()); - let schema = handler.config_schema(); let config = backend.config.align(&schema)?; if config != backend.config { backend.config = config; - repository - .database() - .lock() - .unwrap() - .update_backend(backend)?; + database.update_backend(backend)?; } - std::fs::create_dir_all(&path)?; + let path = repository_path + .join("backend") + .join(handler.name().as_ref()) + .join(backend.id.to_string()); let config = backend.config.fill(&schema)?; let mut backend = handler.create(&config, &path, &known_paths)?; - let db = repository.database_mut().get_mut().unwrap(); - backend.sync(db)?; + backend.sync(&mut database)?; } Mode::Log { .. } => { /// This is to prevent going though the git history in one go which allocates uses a of memory. @@ -432,7 +408,7 @@ fn main() -> anyhow::Result { Settings::save(settings)?; } Mode::Backend { command } => { - backend::handle_command(command.as_ref(), &mut repository, &known_paths)?; + backend::handle_command(command.as_ref(), &backend_registry, &mut database)?; } Mode::Plugin { command } => match command { None => { diff --git a/crates/backend/src/error.rs b/crates/backend/src/error.rs index 839a81c7..218b3298 100644 --- a/crates/backend/src/error.rs +++ b/crates/backend/src/error.rs @@ -12,6 +12,9 @@ pub enum Error { #[error("config error: {0}")] Config(#[from] stride_core::backend::Error), + #[error("unknown backend: {name}")] + UnknownBackend { name: Box }, + #[error("{0}")] Other(Box), } diff --git a/crates/backend/src/lib.rs b/crates/backend/src/lib.rs index 85f444dd..90934bd9 100644 --- a/crates/backend/src/lib.rs +++ b/crates/backend/src/lib.rs @@ -4,7 +4,10 @@ #![allow(clippy::missing_errors_doc)] #![allow(clippy::missing_panics_doc)] -use std::path::{Path, PathBuf}; +use std::{ + fmt::Debug, + path::{Path, PathBuf}, +}; use stride_core::{ backend::{Config, Schema}, @@ -14,10 +17,11 @@ use stride_database::Database; use uuid::Uuid; pub mod error; +pub mod registry; pub use error::{Error, Result}; -pub trait BackendHandler { +pub trait BackendHandler: Debug + Sync + Send { // TODO: encapsulate name in a newtype, to restrict to ascii, no space, etc. fn name(&self) -> Box; diff --git a/crates/backend/src/registry.rs b/crates/backend/src/registry.rs new file mode 100644 index 00000000..9bbacafa --- /dev/null +++ b/crates/backend/src/registry.rs @@ -0,0 +1,80 @@ +use std::collections::HashMap; + +use stride_core::state::KnownPaths; +use stride_database::Database; +use uuid::Uuid; + +use crate::{BackendHandler, Error}; + +#[derive(Debug, Default)] +pub struct Registry { + map: HashMap, Box>, +} + +impl Registry { + #[must_use] + pub fn new() -> Self { + Self::default() + } + + pub fn insert(&mut self, value: T) -> Option> + where + T: Into>, + { + let handler = value.into(); + self.map.insert(handler.name(), handler) + } + + #[must_use] + pub fn get(&self, name: &str) -> Option<&dyn BackendHandler> { + self.map.get(name).map(Box::as_ref) + } + + pub fn get_or_error(&self, name: &str) -> Result<&dyn BackendHandler, Error> { + self.get(name) + .ok_or_else(|| Error::UnknownBackend { name: name.into() }) + } + + pub fn keys(&self) -> impl Iterator { + self.map.keys().map(Box::as_ref) + } + + pub fn sync_all( + &self, + repository_id: Uuid, + database: &mut Database, + known_paths: &KnownPaths, + ) -> Result<(), Error> { + let backends = database.backends()?; + for mut backend in backends { + if !backend.enabled { + continue; + } + + let Some(handler) = self.get(&backend.name) else { + continue; + }; + + let config = backend + .config + .align(&handler.config_schema()) + .map_err(Error::Config)?; + + if config != backend.config { + backend.config = config; + database.update_backend(&backend)?; + } + + let path = known_paths + .backend_path(repository_id) + .join(handler.name().as_ref()) + .join(backend.id.to_string()); + + let mut backend = handler.create(&backend.config, &path, known_paths)?; + + backend.sync(database)?; + } + + Ok(()) + } +} diff --git a/crates/backends/git/src/config.rs b/crates/backends/git/src/config.rs index 476965cc..78ab6730 100644 --- a/crates/backends/git/src/config.rs +++ b/crates/backends/git/src/config.rs @@ -1,6 +1,5 @@ use std::path::{Path, PathBuf}; -use base64::Engine; use stride_backend::{Backend, BackendHandler}; use stride_core::{ backend::{Config, Schema, SchemaValue}, @@ -9,7 +8,7 @@ use stride_core::{ use crate::{Error, GitBackend}; -use super::{encryption_key::EncryptionKey, ssh_key::SshKey}; +use super::ssh_key::SshKey; #[derive(Debug, Clone, Copy)] pub(crate) struct Handler; @@ -21,13 +20,19 @@ impl BackendHandler for Handler { fn config_schema(&self) -> Schema { Schema::builder(self.name()) - .field("origin", "Origin", SchemaValue::String { default: None }) + .field( + "origin", + "Origin", + SchemaValue::String { default: None }, + false, + ) .field( "author", "Author", SchemaValue::String { default: Some("Stride".into()), }, + false, ) .field( "email", @@ -35,6 +40,7 @@ impl BackendHandler for Handler { SchemaValue::String { default: Some("noreply.stride.tasks@gmail.com".into()), }, + false, ) .field( "branch", @@ -42,6 +48,7 @@ impl BackendHandler for Handler { SchemaValue::String { default: Some("main".into()), }, + false, ) .field( "encryption_key", @@ -50,9 +57,17 @@ impl BackendHandler for Handler { default: None, min: Some(32), max: Some(32), + category: Some(stride_core::backend::BytesCategory::Password), + generator: Some(stride_core::backend::BytesGenerator::CryptoRandom), }, + true, + ) + .field( + "ssh_key", + "SSH Key", + SchemaValue::SshKey { default: None }, + false, ) - .field("ssh_key", "SSH Key", SchemaValue::SshKey { default: None }) .build() } @@ -62,19 +77,19 @@ impl BackendHandler for Handler { path: &Path, known_paths: &KnownPaths, ) -> stride_backend::Result> { + let schema = self.config_schema(); + let config = config.align(&schema)?.fill(&schema)?; + let config = GitConfig { root_path: path.to_path_buf(), author: config.string_value("author")?.into(), email: config.string_value("email")?.into(), branch: config.string_value("branch")?.into(), origin: config.string_value("origin")?.into(), - encryption_key: EncryptionKey { - key: base64::engine::general_purpose::URL_SAFE_NO_PAD - .encode(config.bytes_value("encryption_key")?), - }, + encryption_key: config.bytes_value("encryption_key")?.into(), ssh_key: { let id = config.uuid_value("ssh_key")?; - SshKey::load_key(id, known_paths).map_err(Error::from)? + SshKey::load_key(id, &known_paths.ssh_keys).map_err(Error::from)? }, }; @@ -90,7 +105,7 @@ pub struct GitConfig { pub email: Box, pub branch: Box, pub origin: Box, - pub encryption_key: EncryptionKey, + pub encryption_key: Box<[u8]>, pub ssh_key: SshKey, } diff --git a/crates/backends/git/src/encryption_key.rs b/crates/backends/git/src/encryption_key.rs deleted file mode 100644 index 49c84b0b..00000000 --- a/crates/backends/git/src/encryption_key.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::base64_decode; - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct EncryptionKey { - pub key: String, -} - -impl EncryptionKey { - #[must_use] - #[allow(clippy::cast_possible_truncation)] - pub fn generate() -> Self { - let key = stride_crypto::crypter::Crypter::generate(); - Self { - key: key.to_base64(), - } - } - - #[must_use] - /// flutter_rust_bridge:sync - pub fn validate(key: &str) -> Option { - let Ok(decoded) = base64_decode(key) else { - return Some("invalid base64".to_owned()); - }; - - if decoded.len() != 32 { - return Some("encryption key must be ${32 * 8} bits".to_owned()); - } - None - } -} diff --git a/crates/backends/git/src/error.rs b/crates/backends/git/src/error.rs index 266afddc..d6f18684 100644 --- a/crates/backends/git/src/error.rs +++ b/crates/backends/git/src/error.rs @@ -4,7 +4,10 @@ use stride_crypto::crypter::Error as EncryptionError; use std::{env::VarError, io::Error as IoError}; -use crate::known_hosts::{Host, KnownHostsError}; +use crate::{ + known_hosts::{Host, KnownHostsError}, + ssh_key::SshError, +}; pub type Result = std::result::Result; @@ -52,6 +55,9 @@ pub enum Error { #[error("config error: {0}")] Config(#[from] stride_core::backend::Error), + + #[error("ssh error: {0}")] + Ssh(#[from] SshError), } impl BackendError for Error {} diff --git a/crates/backends/git/src/lib.rs b/crates/backends/git/src/lib.rs index c758b9fa..90c3531a 100644 --- a/crates/backends/git/src/lib.rs +++ b/crates/backends/git/src/lib.rs @@ -64,7 +64,6 @@ mod serialization; /// flutter_rust_bridge:ignore pub mod config; -pub mod encryption_key; pub mod known_hosts; pub mod ssh_key; @@ -324,7 +323,7 @@ impl GitBackend { std::fs::create_dir_all(&repository_path)?; - let key = base64_decode(&config.encryption_key.key)?; + let key = config.encryption_key.as_ref(); let crypter = Arc::new(Crypter::new(key.try_into().unwrap())); let key_store = Arc::new(KeyStore::new(&keys_filepath, crypter)); diff --git a/crates/backends/git/src/ssh_key.rs b/crates/backends/git/src/ssh_key.rs index 17adc1f0..2277e381 100644 --- a/crates/backends/git/src/ssh_key.rs +++ b/crates/backends/git/src/ssh_key.rs @@ -1,22 +1,28 @@ use std::path::{Path, PathBuf}; -use stride_core::state::KnownPaths; use uuid::Uuid; use crate::Result; +#[derive(thiserror::Error, Debug)] +pub enum SshError { + #[error("I/O error: {0}")] + Io(#[from] std::io::Error), + #[error("SSH key was not found with ID: {id}")] + NotFound { id: Uuid }, +} + #[derive(Debug, Clone)] pub struct SshKey { - pub uuid: Uuid, + pub id: Uuid, pub public_key: String, pub public_path: PathBuf, pub private_path: PathBuf, } impl SshKey { - pub fn load_keys(known_path: &KnownPaths) -> Result> { - let ssh_key_path = &known_path.ssh_keys; - let Ok(entries) = ssh_key_path.read_dir() else { + pub fn load_keys(keys_path: &Path) -> Result, SshError> { + let Ok(entries) = keys_path.read_dir() else { return Ok(Vec::new()); }; @@ -30,19 +36,18 @@ impl SshKey { continue; }; - let Ok(uuid) = Uuid::try_parse(&name) else { + let Ok(id) = Uuid::try_parse(&name) else { continue; }; - let key_path = ssh_key_path.join(uuid.to_string()); + let key_path = keys_path.join(id.to_string()); let public_path = key_path.join("key.pub"); let private_path = key_path.join("key"); - let public_key = std::fs::read_to_string(&public_path) - .unwrap_or_else(|_| panic!("missing public key in {uuid} SSH key")); + let public_key = std::fs::read_to_string(&public_path)?; result.push(SshKey { - uuid, + id, public_key, public_path, private_path, @@ -52,40 +57,42 @@ impl SshKey { Ok(result) } - pub fn load_key(uuid: Uuid, known_path: &KnownPaths) -> Result { - let ssh_key_path = &known_path.ssh_keys; + pub fn load_key(id: Uuid, keys_path: &Path) -> Result { + let key_path = keys_path.join(id.to_string()); + if !key_path.exists() { + return Err(SshError::NotFound { id }); + } - let key_path = ssh_key_path.join(uuid.to_string()); let public_path = key_path.join("key.pub"); let private_path = key_path.join("key"); let public_key = std::fs::read_to_string(&public_path)?; Ok(SshKey { - uuid, + id, public_key, public_path, private_path, }) } - pub fn generate(keys_path: &Path) -> Result { + pub fn generate(keys_path: &Path) -> Result { let keys = stride_crypto::ed25519::Ed25519::generate(); Self::save(keys_path, &keys.public, &keys.private) } - pub fn save(keys_path: &Path, public_key: &str, private_key: &str) -> Result { + pub fn save(keys_path: &Path, public_key: &str, private_key: &str) -> Result { Self::update(keys_path, Uuid::now_v7(), public_key, private_key) } pub fn update( keys_path: &Path, - uuid: Uuid, + id: Uuid, public_key: &str, private_key: &str, - ) -> Result { - let key_path = keys_path.join(uuid.to_string()); + ) -> Result { + let key_path = keys_path.join(id.to_string()); if !key_path.exists() { std::fs::create_dir_all(&key_path)?; } @@ -97,15 +104,15 @@ impl SshKey { std::fs::write(&private_path, private_key)?; Ok(Self { - uuid, + id, public_key: public_key.to_string(), public_path, private_path, }) } - pub fn remove_key(keys_path: &Path, uuid: Uuid) -> Result<()> { - let key_path = keys_path.join(uuid.to_string()); + pub fn remove_key(keys_path: &Path, id: Uuid) -> Result<(), SshError> { + let key_path = keys_path.join(id.to_string()); if key_path.exists() { std::fs::remove_dir_all(key_path)?; } @@ -113,8 +120,8 @@ impl SshKey { } #[must_use] - pub fn uuid(&self) -> Uuid { - self.uuid + pub fn id(&self) -> Uuid { + self.id } #[must_use] diff --git a/crates/backends/taskchampion/src/error.rs b/crates/backends/taskchampion/src/error.rs index 9200e212..01773e9a 100644 --- a/crates/backends/taskchampion/src/error.rs +++ b/crates/backends/taskchampion/src/error.rs @@ -2,6 +2,9 @@ use stride_backend::error::BackendError; #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("I/O error: {0}")] + Io(#[from] std::io::Error), + #[error("taskchampion error: {0}")] TaskChampion(#[from] ::taskchampion::Error), } diff --git a/crates/backends/taskchampion/src/lib.rs b/crates/backends/taskchampion/src/lib.rs index f6c26936..5aa2d9c9 100644 --- a/crates/backends/taskchampion/src/lib.rs +++ b/crates/backends/taskchampion/src/lib.rs @@ -11,7 +11,7 @@ use std::{ use stride_backend::{Backend, BackendHandler}; use stride_core::{ - backend::{Config, Schema, SchemaValue}, + backend::{BytesCategory, Config, Schema, SchemaValue}, state::KnownPaths, task::Task, }; @@ -33,11 +33,17 @@ impl BackendHandler for Handler { fn config_schema(&self) -> Schema { Schema::builder(self.name()) - .field("url", "Server URL", SchemaValue::Url { default: None }) + .field( + "url", + "Server URL", + SchemaValue::Url { default: None }, + false, + ) .field( "client_id", "Client ID", SchemaValue::Uuid { default: None }, + false, ) .field( "encryption_secret", @@ -46,7 +52,10 @@ impl BackendHandler for Handler { default: None, min: None, max: None, + category: Some(BytesCategory::Password), + generator: None, }, + true, ) .build() } @@ -92,6 +101,8 @@ pub struct TaskchampionBackend { impl TaskchampionBackend { pub fn new(config: TaskchampionConfig) -> Result { + std::fs::create_dir_all(&config.root_path)?; + let storage = StorageConfig::OnDisk { taskdb_dir: config.root_path, create_if_missing: true, diff --git a/crates/core/src/backend/mod.rs b/crates/core/src/backend/mod.rs index 818f53bf..a0d2dac8 100644 --- a/crates/core/src/backend/mod.rs +++ b/crates/core/src/backend/mod.rs @@ -30,7 +30,7 @@ impl SchemaBuilder { /// /// If the same is field is passed twice. #[must_use] - pub fn field(mut self, id: T, name: U, value: D) -> Self + pub fn field(mut self, id: T, name: U, value: D, show_qr_code: bool) -> Self where T: Into>, U: Into>, @@ -44,6 +44,7 @@ impl SchemaBuilder { SchemaField { name, value: value.into(), + show_qr_code, }, ); assert!(inserted.is_none(), "field added twice: {id}"); @@ -89,6 +90,18 @@ impl Schema { } } +#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum BytesCategory { + Password, +} + +#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum BytesGenerator { + CryptoRandom, +} + #[derive(Debug, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "kebab-case")] #[serde(tag = "type")] @@ -116,6 +129,14 @@ pub enum SchemaValue { #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] max: Option, + + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + category: Option, + + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + generator: Option, }, Url { #[serde(default)] @@ -174,6 +195,7 @@ pub struct SchemaField { pub name: Box, #[serde(flatten)] pub value: SchemaValue, + pub show_qr_code: bool, } #[derive(thiserror::Error, Debug)] @@ -219,10 +241,16 @@ pub enum Error { #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "kebab-case")] +#[serde(tag = "type", content = "content")] pub enum Value { String(Box), Uuid(Uuid), - Bytes(#[serde(with = "::serde_with::As::")] Box<[u8]>), + Bytes( + #[serde( + with = "::serde_with::As::>" + )] + Box<[u8]>, + ), Url(Url), } @@ -484,7 +512,8 @@ impl Config { } } -#[derive(Debug)] +#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "kebab-case")] pub struct BackendRecord { pub id: Uuid, pub name: Box, diff --git a/crates/core/src/state.rs b/crates/core/src/state.rs index fef53924..ca206169 100644 --- a/crates/core/src/state.rs +++ b/crates/core/src/state.rs @@ -6,13 +6,24 @@ use uuid::Uuid; pub struct KnownPaths { pub support: PathBuf, pub cache: PathBuf, - pub download: PathBuf, pub logs: PathBuf, pub ssh_keys: PathBuf, } impl KnownPaths { + const DATABASE_FILE_NAME: &str = "db.sqlite"; + + #[must_use] + pub fn new(support: PathBuf, cache: PathBuf) -> Self { + Self { + ssh_keys: support.join(".ssh").join("keys"), + support, + logs: cache.join("logs").join("log.txt"), + cache, + } + } + #[must_use] pub fn repository_path(&self, id: Uuid) -> PathBuf { self.support.join("repository").join(id.to_string()) @@ -21,6 +32,11 @@ impl KnownPaths { pub fn backend_path(&self, repository_id: Uuid) -> PathBuf { self.repository_path(repository_id).join("backend") } + #[must_use] + pub fn database_filepath(&self, repository_id: Uuid) -> PathBuf { + self.repository_path(repository_id) + .join(Self::DATABASE_FILE_NAME) + } } #[derive(Debug, Clone)] diff --git a/crates/database/src/database/mod.rs b/crates/database/src/database/mod.rs index 358cb987..fddd71fb 100644 --- a/crates/database/src/database/mod.rs +++ b/crates/database/src/database/mod.rs @@ -894,6 +894,20 @@ impl Database { Ok(backends) } + pub fn toggle_backend(&mut self, id: Uuid) -> Result<()> { + self.execute( + indoc! {" + UPDATE backend_table + SET + enabled = (CASE WHEN enabled = 0 THEN 1 ELSE 0 END) + WHERE + id = ?1 + "}, + (id.as_bytes(),), + )?; + Ok(()) + } + pub fn update_backend(&mut self, backend: &BackendRecord) -> Result<()> { let transaction = self.transaction()?; @@ -913,21 +927,20 @@ impl Database { value.as_value_boxed_slice(), ))?; } + drop(sql); transaction.execute( indoc! {" - UPDATE backend_table - SET - name = ?2, - enabled = ?3 - WHERE - id = ?1 + UPDATE backend_table + SET + name = ?2, + enabled = ?3 + WHERE + id = ?1 "}, (backend.id.as_bytes(), &backend.name, &backend.enabled), )?; - drop(sql); - transaction.commit()?; Ok(()) } diff --git a/crates/database/src/migrations/v001_task.rs b/crates/database/src/migrations/v001_task.rs index 225afda7..29e6e39a 100644 --- a/crates/database/src/migrations/v001_task.rs +++ b/crates/database/src/migrations/v001_task.rs @@ -64,7 +64,7 @@ CREATE TABLE IF NOT EXISTS backend_table ( CREATE TABLE IF NOT EXISTS backend_config_table ( `backend_id` BLOB NOT NULL, - `name` TEXT NOT NULL PRIMARY KEY, + `name` TEXT NOT NULL, `type` TEXT NOT NULL, `value` BLOB NOT NULL, diff --git a/crates/flutter_bridge/Cargo.toml b/crates/flutter_bridge/Cargo.toml index 1b2c5e47..edcaa9f3 100644 --- a/crates/flutter_bridge/Cargo.toml +++ b/crates/flutter_bridge/Cargo.toml @@ -17,11 +17,12 @@ crate-type = ["lib", "cdylib", "staticlib"] [dependencies] stride_core = { workspace = true, features = ["taskchampion"] } stride_logging.workspace = true -stride_crypto.workspace = true stride_database.workspace = true stride_backend.workspace = true stride_backend_git.workspace = true +stride_backend_taskchampion.workspace = true stride_plugin_manager.workspace = true + flutter_rust_bridge = { version = "=2.11.1", features = ["chrono", "uuid"] } serde.workspace = true serde_json.workspace = true diff --git a/crates/flutter_bridge/src/api/error.rs b/crates/flutter_bridge/src/api/error.rs index 554aa04b..dfaae02d 100644 --- a/crates/flutter_bridge/src/api/error.rs +++ b/crates/flutter_bridge/src/api/error.rs @@ -4,6 +4,7 @@ use stride_backend_git::{ Error as GitBackendError, error::KeyStoreError, known_hosts::{Host, KnownHostsError}, + ssh_key::SshError, }; use stride_database::Error as DatabaseError; use stride_plugin_manager::Error as PluginError; @@ -80,6 +81,8 @@ pub enum ErrorKind { Database(#[from] DatabaseError), #[error("backend error: {0}")] Backend(#[from] BackendError), + #[error("ssh error: {0}")] + Ssh(#[from] SshError), #[error("other error: {message}")] Other { message: Box }, } diff --git a/crates/flutter_bridge/src/api/repository.rs b/crates/flutter_bridge/src/api/repository.rs index 99874632..f94b82a0 100644 --- a/crates/flutter_bridge/src/api/repository.rs +++ b/crates/flutter_bridge/src/api/repository.rs @@ -5,31 +5,34 @@ use std::{ }; use flutter_rust_bridge::frb; -use stride_backend::{Backend, Error as BackendError}; -use stride_backend_git::{ - Error as GitBackendError, GitBackend, config::GitConfig, encryption_key::EncryptionKey, - ssh_key::SshKey, -}; +use stride_backend::{Backend, registry::Registry}; +use stride_backend_git::GitBackend; +use stride_backend_taskchampion::TaskchampionBackend; use stride_core::{ + backend::{BackendRecord as CoreBackendRecord, Config}, event::TaskQuery, + state::KnownPaths, task::{Task, TaskStatus}, }; use stride_database::Database; use uuid::Uuid; -use crate::RustError; - -use super::{ - filter::Filter, - settings::{Settings, application_support_path, ssh_keys}, +use crate::{ + RustError, + api::{ + filter::Filter, + settings::{application_cache_path, application_support_path}, + }, }; #[frb(opaque)] #[derive(Debug)] pub struct Repository { uuid: Uuid, - root_path: PathBuf, - db: Mutex, + pub(crate) root_path: PathBuf, + pub(crate) db: Mutex, + + pub(crate) backend_registry: Registry, } impl Repository { @@ -42,13 +45,26 @@ impl Repository { let db_path = root_path.join("db.sqlite"); let mut db = Database::open(&db_path).map_err(Into::::into)?; db.apply_migrations()?; + + let mut backend_registry = Registry::new(); + backend_registry.insert(GitBackend::handler()); + backend_registry.insert(TaskchampionBackend::handler()); Ok(Self { uuid, db: db.into(), root_path, + backend_registry, }) } + pub fn remove(uuid: Uuid) -> Result<(), RustError> { + let root_path = application_support_path() + .join("repository") + .join(uuid.to_string()); + std::fs::remove_dir_all(&root_path)?; + Ok(()) + } + pub fn all_tasks(&mut self, filter: &Filter) -> Result, RustError> { let search = filter.search.to_lowercase(); self.db.clear_poison(); @@ -93,53 +109,12 @@ impl Repository { } pub fn sync(&mut self) -> Result<(), RustError> { - let mut settings = Settings::get(); - let specification = settings - .repositories - .iter_mut() - .find(|repository| repository.uuid == self.uuid) - .unwrap(); - - let encryption = if let Some(encrpytion) = &specification.encryption { - encrpytion - } else { - specification - .encryption - .get_or_insert(EncryptionKey::generate()) - }; - - let Some(ssh_key_uuid) = specification.ssh_key_uuid else { - return Err(BackendError::from(GitBackendError::NoSshKeysProvided).into()); - }; - - let ssh_keys = ssh_keys()?; - let Some(ssh_key) = ssh_keys.iter().find(|ssh_key| ssh_key.uuid == ssh_key_uuid) else { - return Err(BackendError::from(GitBackendError::NoSshKeysProvided).into()); - }; - - let git_backend_path = self.root_path.join("backend").join("git"); - std::fs::create_dir_all(&git_backend_path)?; - - let config = GitConfig { - root_path: git_backend_path, - author: specification.author.clone().into_boxed_str(), - email: specification.author.clone().into_boxed_str(), - branch: specification.branch.clone().into_boxed_str(), - origin: specification.origin.clone().into_boxed_str(), - encryption_key: encryption.clone(), - ssh_key: SshKey { - uuid: ssh_key.uuid, - public_key: ssh_key.public_key.clone(), - public_path: ssh_key.public_path.clone(), - private_path: ssh_key.private_path.clone(), - }, - }; - - Settings::save(settings.clone())?; - - let mut backend = GitBackend::new(config).map_err(BackendError::from)?; - self.db.clear_poison(); - backend.sync(self.db.get_mut().expect("poison valued cleared"))?; + let known_paths = KnownPaths::new(application_support_path(), application_cache_path()); + + let db = self.db.get_mut().unwrap(); + self.backend_registry + .sync_all(self.uuid, db, &known_paths)?; + Ok(()) } @@ -162,4 +137,81 @@ impl Repository { pub fn database_mut(&mut self) -> &mut Mutex { &mut self.db } + + pub fn backends(&self) -> Result, RustError> { + let backends = self.database().lock().unwrap().backends()?; + + Ok(backends + .into_iter() + .map(|backend| BackendRecord { + id: backend.id, + name: backend.name.to_string(), + enabled: backend.enabled, + schema: serde_json::to_string_pretty(&GitBackend::handler().config_schema()) + .expect("should not fail"), + config: serde_json::to_string_pretty(&backend.config).expect("should not fail"), + }) + .collect::>()) + } + + pub fn toggle_backend(&self, id: Uuid) -> Result<(), RustError> { + self.database().lock().unwrap().toggle_backend(id)?; + Ok(()) + } + + pub fn update_backend(&self, backend: &BackendRecord) -> Result<(), RustError> { + let config = serde_json::from_str(&backend.config).expect("invalid backend config json"); + self.database() + .lock() + .unwrap() + .update_backend(&CoreBackendRecord { + id: backend.id, + name: backend.name.clone().into_boxed_str(), + enabled: backend.enabled, + config, + })?; + Ok(()) + } + + pub fn add_backend(&self, name: &str) -> Result<(), RustError> { + let handler = self.backend_registry.get_or_error(name)?; + let name = handler.name(); + self.database() + .lock() + .unwrap() + .add_backend(&CoreBackendRecord { + id: Uuid::now_v7(), + name, + enabled: false, + config: Config::default(), + })?; + Ok(()) + } + + pub fn delete_backend(&self, id: Uuid) -> Result<(), RustError> { + self.database().lock().unwrap().delete_backend(id)?; + Ok(()) + } + + pub fn backend(&self, id: Uuid) -> Result, RustError> { + let backends = self.backends()?; + + Ok(backends + .into_iter() + .filter(|backend| backend.id == id) + .nth(0)) + } + + pub fn backend_names(&self) -> Vec { + self.backend_registry.keys().map(Into::into).collect() + } +} + +#[derive(Debug)] +pub struct BackendRecord { + pub id: Uuid, + pub name: String, + pub enabled: bool, + pub schema: String, + pub config: String, } diff --git a/crates/flutter_bridge/src/api/settings.rs b/crates/flutter_bridge/src/api/settings.rs index 56fbde6a..4adda97f 100644 --- a/crates/flutter_bridge/src/api/settings.rs +++ b/crates/flutter_bridge/src/api/settings.rs @@ -4,7 +4,6 @@ use std::{ path::{Path, PathBuf}, sync::{LazyLock, Mutex}, }; -use stride_backend_git::encryption_key::EncryptionKey; use uuid::Uuid; use crate::{RustError, frb_generated::StreamSink}; @@ -14,6 +13,8 @@ use super::{ filter::{Filter, FilterSelection}, }; +use stride_backend_git::ssh_key::SshKey as InnerSshKey; + pub(crate) static APPLICATION_STATE_INSTANCE: LazyLock> = LazyLock::new(Mutex::default); @@ -88,108 +89,50 @@ pub(crate) fn ssh_key_path() -> PathBuf { } pub fn ssh_keys() -> Result, RustError> { - let ssh_key_path = ssh_key_path(); - let Ok(entries) = ssh_key_path.read_dir() else { - return Ok(Vec::new()); - }; - - let mut result = Vec::new(); - for entry in entries { - let Ok(entry) = entry else { - continue; - }; - - let Ok(name) = entry.file_name().into_string() else { - continue; - }; - - let Ok(uuid) = Uuid::try_parse(&name) else { - continue; - }; - - let key_path = ssh_key_path.join(uuid.to_string()); - let public_path = key_path.join("key.pub"); - let private_path = key_path.join("key"); - - let public_key = std::fs::read_to_string(&public_path) - .unwrap_or_else(|_| panic!("missing public key in {uuid} SSH key")); - - result.push(SshKey { - uuid, - public_key, - public_path, - private_path, - }); - } - - Ok(result) + Ok(InnerSshKey::load_keys(&ssh_key_path())? + .into_iter() + .map(|key| SshKey { inner: key }) + .collect()) } #[frb(opaque)] #[derive(Debug)] pub struct SshKey { - pub(crate) uuid: Uuid, - pub(crate) public_key: String, - pub(crate) public_path: PathBuf, - pub(crate) private_path: PathBuf, + pub(crate) inner: InnerSshKey, } impl SshKey { pub fn generate() -> Result { - let keys = stride_crypto::ed25519::Ed25519::generate(); - - Self::save(&keys.public, &keys.private) + Ok(Self { + inner: InnerSshKey::generate(&ssh_key_path())?, + }) } pub fn save(public_key: &str, private_key: &str) -> Result { - Self::update(Uuid::now_v7(), public_key, private_key) + Ok(Self { + inner: InnerSshKey::save(&ssh_key_path(), public_key, private_key)?, + }) } pub fn update(uuid: Uuid, public_key: &str, private_key: &str) -> Result { - let key_path = ssh_key_path().join(uuid.to_string()); - if !key_path.exists() { - std::fs::create_dir_all(&key_path)?; - } - - let public_path = key_path.join("key.pub"); - let private_path = key_path.join("key"); - - std::fs::write(&public_path, public_key)?; - std::fs::write(&private_path, private_key)?; - Ok(Self { - uuid, - public_key: public_key.to_string(), - public_path, - private_path, + inner: InnerSshKey::update(&ssh_key_path(), uuid, public_key, private_key)?, }) } pub fn remove_key(uuid: Uuid) -> Result<(), RustError> { - let mut settings = Settings::get(); - - for repository in &mut settings.repositories { - if repository.ssh_key_uuid != Some(uuid) { - continue; - } - repository.ssh_key_uuid = None; - } - - let key_path = ssh_key_path().join(uuid.to_string()); - if key_path.exists() { - std::fs::remove_dir_all(key_path)?; - } - Settings::save(settings) + InnerSshKey::remove_key(&ssh_key_path(), uuid)?; + Ok(()) } #[frb(sync, getter)] pub fn uuid(&self) -> Uuid { - self.uuid + self.inner.id } #[frb(sync, getter)] pub fn public_key(&self) -> String { - self.public_key.to_string() + self.inner.public_key.to_string() } } @@ -197,18 +140,6 @@ const fn default_theme_mode() -> bool { true } -fn default_email() -> String { - String::from("noreply.stride.tasks@gmail.com") -} - -fn default_author() -> String { - String::from("stride") -} - -fn default_branch_name() -> String { - String::from("main") -} - fn default_repository_name() -> String { String::from("unnamed") } @@ -221,21 +152,6 @@ pub struct RepositorySpecification { #[serde(default = "default_repository_name")] pub name: String, - - pub origin: String, - - #[serde(default = "default_author")] - pub author: String, - - #[serde(default = "default_email")] - pub email: String, - - #[serde(default = "default_branch_name")] - pub branch: String, - - pub ssh_key_uuid: Option, - #[serde(default)] - pub encryption: Option, } impl Default for RepositorySpecification { @@ -243,12 +159,6 @@ impl Default for RepositorySpecification { Self { uuid: Uuid::now_v7(), name: default_repository_name(), - origin: String::new(), - author: default_author(), - email: default_email(), - branch: default_branch_name(), - ssh_key_uuid: None, - encryption: None, } } } diff --git a/crates/flutter_bridge/src/frb_generated.rs b/crates/flutter_bridge/src/frb_generated.rs index 103a7044..81c65bdc 100644 --- a/crates/flutter_bridge/src/frb_generated.rs +++ b/crates/flutter_bridge/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -97564000; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1297363159; // Section: executor @@ -239,6 +239,59 @@ fn wire__stride_core__event__HostEvent_timer_impl( }, ) } +fn wire__crate__api__repository__Repository_add_backend_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_add_backend", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_name = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, RustError>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::repository::Repository::add_backend( + &*api_that_guard, + &api_name, + )?; + Ok(output_ok) + })()) + } + }, + ) +} fn wire__crate__api__repository__Repository_all_tasks_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -292,7 +345,380 @@ fn wire__crate__api__repository__Repository_all_tasks_impl( }, ) } -fn wire__crate__api__repository__Repository_insert_task_impl( +fn wire__crate__api__repository__Repository_backend_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_backend", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_id = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, RustError>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = + crate::api::repository::Repository::backend(&*api_that_guard, api_id)?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__repository__Repository_backend_names_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_backend_names", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok( + crate::api::repository::Repository::backend_names(&*api_that_guard), + )?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__repository__Repository_backends_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_backends", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, RustError>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::repository::Repository::backends(&*api_that_guard)?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__repository__Repository_delete_backend_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_delete_backend", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_id = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, RustError>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::repository::Repository::delete_backend( + &*api_that_guard, + api_id, + )?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__repository__Repository_insert_task_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_insert_task", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_task = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, RustError>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, true, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref_mut()), + _ => unreachable!(), + } + } + let mut api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::repository::Repository::insert_task( + &mut *api_that_guard, + &api_task, + )?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__repository__Repository_open_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_open", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_uuid = ::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse::<_, RustError>((move || { + let output_ok = crate::api::repository::Repository::open(api_uuid)?; + Ok(output_ok) + })()) + }, + ) +} +fn wire__crate__api__repository__Repository_purge_task_by_id_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_purge_task_by_id", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_id = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, RustError>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, true, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref_mut()), + _ => unreachable!(), + } + } + let mut api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::repository::Repository::purge_task_by_id( + &mut *api_that_guard, + api_id, + )?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__repository__Repository_remove_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "Repository_remove", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_uuid = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, RustError>((move || { + let output_ok = crate::api::repository::Repository::remove(api_uuid)?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__repository__Repository_sync_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -300,7 +726,7 @@ fn wire__crate__api__repository__Repository_insert_task_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "Repository_insert_task", + debug_name: "Repository_sync", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -317,7 +743,6 @@ fn wire__crate__api__repository__Repository_insert_task_impl( let api_that = , >>::sse_decode(&mut deserializer); - let api_task = ::sse_decode(&mut deserializer); deserializer.end(); move |context| { transform_result_sse::<_, RustError>((move || { @@ -335,47 +760,14 @@ fn wire__crate__api__repository__Repository_insert_task_impl( } } let mut api_that_guard = api_that_guard.unwrap(); - let output_ok = crate::api::repository::Repository::insert_task( - &mut *api_that_guard, - &api_task, - )?; + let output_ok = crate::api::repository::Repository::sync(&mut *api_that_guard)?; Ok(output_ok) })()) } }, ) } -fn wire__crate__api__repository__Repository_open_impl( - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "Repository_open", - port: None, - mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_uuid = ::sse_decode(&mut deserializer); - deserializer.end(); - transform_result_sse::<_, RustError>((move || { - let output_ok = crate::api::repository::Repository::open(api_uuid)?; - Ok(output_ok) - })()) - }, - ) -} -fn wire__crate__api__repository__Repository_purge_task_by_id_impl( +fn wire__crate__api__repository__Repository_task_by_id_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -383,7 +775,7 @@ fn wire__crate__api__repository__Repository_purge_task_by_id_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "Repository_purge_task_by_id", + debug_name: "Repository_task_by_id", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -418,7 +810,7 @@ fn wire__crate__api__repository__Repository_purge_task_by_id_impl( } } let mut api_that_guard = api_that_guard.unwrap(); - let output_ok = crate::api::repository::Repository::purge_task_by_id( + let output_ok = crate::api::repository::Repository::task_by_id( &mut *api_that_guard, api_id, )?; @@ -428,7 +820,7 @@ fn wire__crate__api__repository__Repository_purge_task_by_id_impl( }, ) } -fn wire__crate__api__repository__Repository_sync_impl( +fn wire__crate__api__repository__Repository_task_query_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -436,7 +828,7 @@ fn wire__crate__api__repository__Repository_sync_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "Repository_sync", + debug_name: "Repository_task_query", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -453,6 +845,7 @@ fn wire__crate__api__repository__Repository_sync_impl( let api_that = , >>::sse_decode(&mut deserializer); + let api_query = ::sse_decode(&mut deserializer); deserializer.end(); move |context| { transform_result_sse::<_, RustError>((move || { @@ -470,14 +863,17 @@ fn wire__crate__api__repository__Repository_sync_impl( } } let mut api_that_guard = api_that_guard.unwrap(); - let output_ok = crate::api::repository::Repository::sync(&mut *api_that_guard)?; + let output_ok = crate::api::repository::Repository::task_query( + &mut *api_that_guard, + &api_query, + )?; Ok(output_ok) })()) } }, ) } -fn wire__crate__api__repository__Repository_task_by_id_impl( +fn wire__crate__api__repository__Repository_tasks_by_status_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -485,7 +881,7 @@ fn wire__crate__api__repository__Repository_task_by_id_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "Repository_task_by_id", + debug_name: "Repository_tasks_by_status", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -502,7 +898,9 @@ fn wire__crate__api__repository__Repository_task_by_id_impl( let api_that = , >>::sse_decode(&mut deserializer); - let api_id = ::sse_decode(&mut deserializer); + let api_status = >::sse_decode( + &mut deserializer, + ); deserializer.end(); move |context| { transform_result_sse::<_, RustError>((move || { @@ -520,9 +918,9 @@ fn wire__crate__api__repository__Repository_task_by_id_impl( } } let mut api_that_guard = api_that_guard.unwrap(); - let output_ok = crate::api::repository::Repository::task_by_id( + let output_ok = crate::api::repository::Repository::tasks_by_status( &mut *api_that_guard, - api_id, + &api_status, )?; Ok(output_ok) })()) @@ -530,7 +928,7 @@ fn wire__crate__api__repository__Repository_task_by_id_impl( }, ) } -fn wire__crate__api__repository__Repository_task_query_impl( +fn wire__crate__api__repository__Repository_toggle_backend_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -538,7 +936,7 @@ fn wire__crate__api__repository__Repository_task_query_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "Repository_task_query", + debug_name: "Repository_toggle_backend", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -555,7 +953,7 @@ fn wire__crate__api__repository__Repository_task_query_impl( let api_that = , >>::sse_decode(&mut deserializer); - let api_query = ::sse_decode(&mut deserializer); + let api_id = ::sse_decode(&mut deserializer); deserializer.end(); move |context| { transform_result_sse::<_, RustError>((move || { @@ -563,19 +961,19 @@ fn wire__crate__api__repository__Repository_task_query_impl( let decode_indices_ = flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ flutter_rust_bridge::for_generated::LockableOrderInfo::new( - &api_that, 0, true, + &api_that, 0, false, ), ]); for i in decode_indices_ { match i { - 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref_mut()), + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), _ => unreachable!(), } } - let mut api_that_guard = api_that_guard.unwrap(); - let output_ok = crate::api::repository::Repository::task_query( - &mut *api_that_guard, - &api_query, + let api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::repository::Repository::toggle_backend( + &*api_that_guard, + api_id, )?; Ok(output_ok) })()) @@ -583,7 +981,7 @@ fn wire__crate__api__repository__Repository_task_query_impl( }, ) } -fn wire__crate__api__repository__Repository_tasks_by_status_impl( +fn wire__crate__api__repository__Repository_undo_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -591,7 +989,7 @@ fn wire__crate__api__repository__Repository_tasks_by_status_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "Repository_tasks_by_status", + debug_name: "Repository_undo", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -608,9 +1006,6 @@ fn wire__crate__api__repository__Repository_tasks_by_status_impl( let api_that = , >>::sse_decode(&mut deserializer); - let api_status = >::sse_decode( - &mut deserializer, - ); deserializer.end(); move |context| { transform_result_sse::<_, RustError>((move || { @@ -618,27 +1013,24 @@ fn wire__crate__api__repository__Repository_tasks_by_status_impl( let decode_indices_ = flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ flutter_rust_bridge::for_generated::LockableOrderInfo::new( - &api_that, 0, true, + &api_that, 0, false, ), ]); for i in decode_indices_ { match i { - 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref_mut()), + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), _ => unreachable!(), } } - let mut api_that_guard = api_that_guard.unwrap(); - let output_ok = crate::api::repository::Repository::tasks_by_status( - &mut *api_that_guard, - &api_status, - )?; + let api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::repository::Repository::undo(&*api_that_guard)?; Ok(output_ok) })()) } }, ) } -fn wire__crate__api__repository__Repository_undo_impl( +fn wire__crate__api__repository__Repository_update_backend_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -646,7 +1038,7 @@ fn wire__crate__api__repository__Repository_undo_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "Repository_undo", + debug_name: "Repository_update_backend", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -663,6 +1055,8 @@ fn wire__crate__api__repository__Repository_undo_impl( let api_that = , >>::sse_decode(&mut deserializer); + let api_backend = + ::sse_decode(&mut deserializer); deserializer.end(); move |context| { transform_result_sse::<_, RustError>((move || { @@ -680,7 +1074,10 @@ fn wire__crate__api__repository__Repository_undo_impl( } } let api_that_guard = api_that_guard.unwrap(); - let output_ok = crate::api::repository::Repository::undo(&*api_that_guard)?; + let output_ok = crate::api::repository::Repository::update_backend( + &*api_that_guard, + &api_backend, + )?; Ok(output_ok) })()) } @@ -1457,72 +1854,6 @@ fn wire__crate__api__plugin_manager__emit_broadcast_impl( }, ) } -fn wire__stride_backend_git__encryption_key__encryption_key_generate_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "encryption_key_generate", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - deserializer.end(); - move |context| { - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok( - stride_backend_git::encryption_key::EncryptionKey::generate(), - )?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__stride_backend_git__encryption_key__encryption_key_validate_impl( - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "encryption_key_validate", - port: None, - mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_key = ::sse_decode(&mut deserializer); - deserializer.end(); - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok( - stride_backend_git::encryption_key::EncryptionKey::validate(&api_key), - )?; - Ok(output_ok) - })()) - }, - ) -} fn wire__crate__api__logging__error_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -3192,10 +3523,6 @@ const _: fn() = || { let _: chrono::DateTime = Annotation.entry; let _: String = Annotation.description; } - { - let EncryptionKey = None::.unwrap(); - let _: String = EncryptionKey.key; - } { let Host = None::.unwrap(); let _: String = Host.hostname; @@ -3529,18 +3856,28 @@ impl SseDecode for crate::api::settings::ApplicationPaths { } } -impl SseDecode for bool { +impl SseDecode for crate::api::repository::BackendRecord { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_u8().unwrap() != 0 + let mut var_id = ::sse_decode(deserializer); + let mut var_name = ::sse_decode(deserializer); + let mut var_enabled = ::sse_decode(deserializer); + let mut var_schema = ::sse_decode(deserializer); + let mut var_config = ::sse_decode(deserializer); + return crate::api::repository::BackendRecord { + id: var_id, + name: var_name, + enabled: var_enabled, + schema: var_schema, + config: var_config, + }; } } -impl SseDecode for stride_backend_git::encryption_key::EncryptionKey { +impl SseDecode for bool { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_key = ::sse_decode(deserializer); - return stride_backend_git::encryption_key::EncryptionKey { key: var_key }; + deserializer.cursor.read_u8().unwrap() != 0 } } @@ -3703,6 +4040,20 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -3930,13 +4281,13 @@ impl SseDecode for Option> { } } -impl SseDecode for Option { +impl SseDecode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { if (::sse_decode(deserializer)) { - return Some( - ::sse_decode(deserializer), - ); + return Some(::sse_decode( + deserializer, + )); } else { return None; } @@ -4152,22 +4503,9 @@ impl SseDecode for crate::api::settings::RepositorySpecification { fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { let mut var_uuid = ::sse_decode(deserializer); let mut var_name = ::sse_decode(deserializer); - let mut var_origin = ::sse_decode(deserializer); - let mut var_author = ::sse_decode(deserializer); - let mut var_email = ::sse_decode(deserializer); - let mut var_branch = ::sse_decode(deserializer); - let mut var_sshKeyUuid = >::sse_decode(deserializer); - let mut var_encryption = - >::sse_decode(deserializer); return crate::api::settings::RepositorySpecification { uuid: var_uuid, name: var_name, - origin: var_origin, - author: var_author, - email: var_email, - branch: var_branch, - ssh_key_uuid: var_sshKeyUuid, - encryption: var_encryption, }; } } @@ -4337,200 +4675,236 @@ fn pde_ffi_dispatcher_primary_impl( ) { // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { - 7 => wire__crate__api__repository__Repository_all_tasks_impl( + 7 => wire__crate__api__repository__Repository_add_backend_impl( port, ptr, rust_vec_len, data_len, ), - 8 => wire__crate__api__repository__Repository_insert_task_impl( + 8 => wire__crate__api__repository__Repository_all_tasks_impl( port, ptr, rust_vec_len, data_len, ), - 10 => wire__crate__api__repository__Repository_purge_task_by_id_impl( + 9 => { + wire__crate__api__repository__Repository_backend_impl(port, ptr, rust_vec_len, data_len) + } + 10 => wire__crate__api__repository__Repository_backend_names_impl( port, ptr, rust_vec_len, data_len, ), - 11 => wire__crate__api__repository__Repository_sync_impl(port, ptr, rust_vec_len, data_len), - 12 => wire__crate__api__repository__Repository_task_by_id_impl( + 11 => wire__crate__api__repository__Repository_backends_impl( port, ptr, rust_vec_len, data_len, ), - 13 => wire__crate__api__repository__Repository_task_query_impl( + 12 => wire__crate__api__repository__Repository_delete_backend_impl( port, ptr, rust_vec_len, data_len, ), - 14 => wire__crate__api__repository__Repository_tasks_by_status_impl( + 13 => wire__crate__api__repository__Repository_insert_task_impl( port, ptr, rust_vec_len, data_len, ), - 15 => wire__crate__api__repository__Repository_undo_impl(port, ptr, rust_vec_len, data_len), - 16 => wire__crate__api__repository__Repository_update_task_impl( + 15 => wire__crate__api__repository__Repository_purge_task_by_id_impl( port, ptr, rust_vec_len, data_len, ), - 22 => wire__crate__api__settings__SshKey_generate_impl(port, ptr, rust_vec_len, data_len), - 24 => wire__crate__api__settings__SshKey_remove_key_impl(port, ptr, rust_vec_len, data_len), - 25 => wire__crate__api__settings__SshKey_save_impl(port, ptr, rust_vec_len, data_len), - 26 => wire__crate__api__settings__SshKey_update_impl(port, ptr, rust_vec_len, data_len), - 28 => wire__stride_core__task__annotation__annotation_now_impl( + 16 => { + wire__crate__api__repository__Repository_remove_impl(port, ptr, rust_vec_len, data_len) + } + 17 => wire__crate__api__repository__Repository_sync_impl(port, ptr, rust_vec_len, data_len), + 18 => wire__crate__api__repository__Repository_task_by_id_impl( port, ptr, rust_vec_len, data_len, ), - 29 => wire__crate__api__settings__application_paths_default_impl( + 19 => wire__crate__api__repository__Repository_task_query_impl( port, ptr, rust_vec_len, data_len, ), - 30 => { - wire__crate__api__plugin_manager__create_stream_impl(port, ptr, rust_vec_len, data_len) - } - 31 => wire__crate__api__logging__debug_impl(port, ptr, rust_vec_len, data_len), - 32 => wire__crate__api__plugin_manager__disable_impl(port, ptr, rust_vec_len, data_len), - 33 => wire__crate__api__plugin_manager__emit_impl(port, ptr, rust_vec_len, data_len), - 34 => { - wire__crate__api__plugin_manager__emit_broadcast_impl(port, ptr, rust_vec_len, data_len) - } - 35 => wire__stride_backend_git__encryption_key__encryption_key_generate_impl( + 20 => wire__crate__api__repository__Repository_tasks_by_status_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 21 => wire__crate__api__repository__Repository_toggle_backend_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 22 => wire__crate__api__repository__Repository_undo_impl(port, ptr, rust_vec_len, data_len), + 23 => wire__crate__api__repository__Repository_update_backend_impl( port, ptr, rust_vec_len, data_len, ), - 37 => wire__crate__api__logging__error_impl(port, ptr, rust_vec_len, data_len), - 38 => wire__crate__api__filter__filter_default_impl(port, ptr, rust_vec_len, data_len), - 39 => wire__crate__api__logging__get_logs_impl(port, ptr, rust_vec_len, data_len), - 41 => wire__crate__api__plugin_manager__import_impl(port, ptr, rust_vec_len, data_len), - 42 => wire__crate__api__logging__info_impl(port, ptr, rust_vec_len, data_len), - 43 => wire__stride_backend_git__known_hosts__known_hosts_default_impl( + 24 => wire__crate__api__repository__Repository_update_task_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 30 => wire__crate__api__settings__SshKey_generate_impl(port, ptr, rust_vec_len, data_len), + 32 => wire__crate__api__settings__SshKey_remove_key_impl(port, ptr, rust_vec_len, data_len), + 33 => wire__crate__api__settings__SshKey_save_impl(port, ptr, rust_vec_len, data_len), + 34 => wire__crate__api__settings__SshKey_update_impl(port, ptr, rust_vec_len, data_len), + 36 => wire__stride_core__task__annotation__annotation_now_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 37 => wire__crate__api__settings__application_paths_default_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 38 => { + wire__crate__api__plugin_manager__create_stream_impl(port, ptr, rust_vec_len, data_len) + } + 39 => wire__crate__api__logging__debug_impl(port, ptr, rust_vec_len, data_len), + 40 => wire__crate__api__plugin_manager__disable_impl(port, ptr, rust_vec_len, data_len), + 41 => wire__crate__api__plugin_manager__emit_impl(port, ptr, rust_vec_len, data_len), + 42 => { + wire__crate__api__plugin_manager__emit_broadcast_impl(port, ptr, rust_vec_len, data_len) + } + 43 => wire__crate__api__logging__error_impl(port, ptr, rust_vec_len, data_len), + 44 => wire__crate__api__filter__filter_default_impl(port, ptr, rust_vec_len, data_len), + 45 => wire__crate__api__logging__get_logs_impl(port, ptr, rust_vec_len, data_len), + 47 => wire__crate__api__plugin_manager__import_impl(port, ptr, rust_vec_len, data_len), + 48 => wire__crate__api__logging__info_impl(port, ptr, rust_vec_len, data_len), + 49 => wire__stride_backend_git__known_hosts__known_hosts_default_impl( port, ptr, rust_vec_len, data_len, ), - 44 => wire__stride_backend_git__known_hosts__known_hosts_load_impl( + 50 => wire__stride_backend_git__known_hosts__known_hosts_load_impl( port, ptr, rust_vec_len, data_len, ), - 45 => wire__stride_backend_git__known_hosts__known_hosts_save_impl( + 51 => wire__stride_backend_git__known_hosts__known_hosts_save_impl( port, ptr, rust_vec_len, data_len, ), - 46 => wire__crate__api__plugin_manager__load_impl(port, ptr, rust_vec_len, data_len), - 47 => wire__stride_plugin_manager__manifest__manifest_event_default_impl( + 52 => wire__crate__api__plugin_manager__load_impl(port, ptr, rust_vec_len, data_len), + 53 => wire__stride_plugin_manager__manifest__manifest_event_default_impl( port, ptr, rust_vec_len, data_len, ), - 48 => wire__stride_plugin_manager__manifest__manifest_event_task_default_impl( + 54 => wire__stride_plugin_manager__manifest__manifest_event_task_default_impl( port, ptr, rust_vec_len, data_len, ), - 49 => wire__stride_plugin_manager__manifest__manifest_event_timer_default_impl( + 55 => wire__stride_plugin_manager__manifest__manifest_event_timer_default_impl( port, ptr, rust_vec_len, data_len, ), - 50 => wire__stride_plugin_manager__manifest__manifest_permission_default_impl( + 56 => wire__stride_plugin_manager__manifest__manifest_permission_default_impl( port, ptr, rust_vec_len, data_len, ), - 51 => wire__stride_plugin_manager__manifest__manifest_permission_network_default_impl( + 57 => wire__stride_plugin_manager__manifest__manifest_permission_network_default_impl( port, ptr, rust_vec_len, data_len, ), - 52 => wire__stride_plugin_manager__manifest__manifest_permission_storage_default_impl( + 58 => wire__stride_plugin_manager__manifest__manifest_permission_storage_default_impl( port, ptr, rust_vec_len, data_len, ), - 53 => wire__stride_plugin_manager__manifest__manifest_permission_task_default_impl( + 59 => wire__stride_plugin_manager__manifest__manifest_permission_task_default_impl( port, ptr, rust_vec_len, data_len, ), - 54 => { + 60 => { wire__crate__api__plugin_manager__parse_plugin_impl(port, ptr, rust_vec_len, data_len) } - 60 => wire__crate__api__plugin_manager__plugin_manifests_impl( + 66 => wire__crate__api__plugin_manager__plugin_manifests_impl( port, ptr, rust_vec_len, data_len, ), - 61 => wire__crate__api__plugin_manager__process_host_event_impl( + 67 => wire__crate__api__plugin_manager__process_host_event_impl( port, ptr, rust_vec_len, data_len, ), - 62 => wire__crate__api__plugin_manager__process_plugin_event_impl( + 68 => wire__crate__api__plugin_manager__process_plugin_event_impl( port, ptr, rust_vec_len, data_len, ), - 63 => wire__crate__api__plugin_manager__remove_impl(port, ptr, rust_vec_len, data_len), - 64 => wire__crate__api__settings__repository_specification_default_impl( + 69 => wire__crate__api__plugin_manager__remove_impl(port, ptr, rust_vec_len, data_len), + 70 => wire__crate__api__settings__repository_specification_default_impl( port, ptr, rust_vec_len, data_len, ), - 65 => wire__crate__api__settings__settings_create_stream_impl( + 71 => wire__crate__api__settings__settings_create_stream_impl( port, ptr, rust_vec_len, data_len, ), - 66 => wire__crate__api__settings__settings_default_impl(port, ptr, rust_vec_len, data_len), - 67 => wire__crate__api__settings__settings_get_impl(port, ptr, rust_vec_len, data_len), - 68 => wire__crate__api__settings__settings_load_impl(port, ptr, rust_vec_len, data_len), - 70 => wire__crate__api__settings__settings_save_impl(port, ptr, rust_vec_len, data_len), - 71 => wire__crate__api__settings__ssh_keys_impl(port, ptr, rust_vec_len, data_len), - 72 => wire__stride_core__task__task_default_impl(port, ptr, rust_vec_len, data_len), - 74 => wire__stride_core__task__task_priority_as_str_impl(port, ptr, rust_vec_len, data_len), - 75 => { + 72 => wire__crate__api__settings__settings_default_impl(port, ptr, rust_vec_len, data_len), + 73 => wire__crate__api__settings__settings_get_impl(port, ptr, rust_vec_len, data_len), + 74 => wire__crate__api__settings__settings_load_impl(port, ptr, rust_vec_len, data_len), + 76 => wire__crate__api__settings__settings_save_impl(port, ptr, rust_vec_len, data_len), + 77 => wire__crate__api__settings__ssh_keys_impl(port, ptr, rust_vec_len, data_len), + 78 => wire__stride_core__task__task_default_impl(port, ptr, rust_vec_len, data_len), + 80 => wire__stride_core__task__task_priority_as_str_impl(port, ptr, rust_vec_len, data_len), + 81 => { wire__stride_core__task__task_priority_default_impl(port, ptr, rust_vec_len, data_len) } - 76 => wire__stride_core__task__task_status_default_impl(port, ptr, rust_vec_len, data_len), - 77 => { + 82 => wire__stride_core__task__task_status_default_impl(port, ptr, rust_vec_len, data_len), + 83 => { wire__stride_core__task__task_status_is_pending_impl(port, ptr, rust_vec_len, data_len) } - 79 => wire__stride_core__task__task_with_uuid_impl(port, ptr, rust_vec_len, data_len), - 80 => wire__crate__api__plugin_manager__toggle_impl(port, ptr, rust_vec_len, data_len), - 81 => wire__crate__api__logging__trace_impl(port, ptr, rust_vec_len, data_len), - 82 => wire__stride_core__task__uda__uda_default_impl(port, ptr, rust_vec_len, data_len), - 83 => wire__crate__api__logging__warn_impl(port, ptr, rust_vec_len, data_len), + 85 => wire__stride_core__task__task_with_uuid_impl(port, ptr, rust_vec_len, data_len), + 86 => wire__crate__api__plugin_manager__toggle_impl(port, ptr, rust_vec_len, data_len), + 87 => wire__crate__api__logging__trace_impl(port, ptr, rust_vec_len, data_len), + 88 => wire__stride_core__task__uda__uda_default_impl(port, ptr, rust_vec_len, data_len), + 89 => wire__crate__api__logging__warn_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -4549,56 +4923,51 @@ fn pde_ffi_dispatcher_sync_impl( 4 => wire__stride_core__event__HostEvent_task_query_impl(ptr, rust_vec_len, data_len), 5 => wire__stride_core__event__HostEvent_task_sync_impl(ptr, rust_vec_len, data_len), 6 => wire__stride_core__event__HostEvent_timer_impl(ptr, rust_vec_len, data_len), - 9 => wire__crate__api__repository__Repository_open_impl(ptr, rust_vec_len, data_len), - 17 => wire__crate__api__error__RustError_as_unknown_host_impl(ptr, rust_vec_len, data_len), - 18 => wire__crate__api__error__RustError_is_key_store_verification_impl( - ptr, - rust_vec_len, - data_len, - ), - 19 => wire__crate__api__error__RustError_is_out_of_fuel_trap_code_impl( + 14 => wire__crate__api__repository__Repository_open_impl(ptr, rust_vec_len, data_len), + 25 => wire__crate__api__error__RustError_as_unknown_host_impl(ptr, rust_vec_len, data_len), + 26 => wire__crate__api__error__RustError_is_key_store_verification_impl( ptr, rust_vec_len, data_len, ), - 20 => wire__crate__api__error__RustError_plugin_name_impl(ptr, rust_vec_len, data_len), - 21 => wire__crate__api__error__RustError_to_error_string_impl(ptr, rust_vec_len, data_len), - 23 => wire__crate__api__settings__SshKey_public_key_impl(ptr, rust_vec_len, data_len), - 27 => wire__crate__api__settings__SshKey_uuid_impl(ptr, rust_vec_len, data_len), - 36 => wire__stride_backend_git__encryption_key__encryption_key_validate_impl( + 27 => wire__crate__api__error__RustError_is_out_of_fuel_trap_code_impl( ptr, rust_vec_len, data_len, ), - 40 => wire__crate__api__git__host_key_type_name_impl(ptr, rust_vec_len, data_len), - 55 => wire__crate__api__plugin__plugin_instance_manifest_disabled_reason_impl( + 28 => wire__crate__api__error__RustError_plugin_name_impl(ptr, rust_vec_len, data_len), + 29 => wire__crate__api__error__RustError_to_error_string_impl(ptr, rust_vec_len, data_len), + 31 => wire__crate__api__settings__SshKey_public_key_impl(ptr, rust_vec_len, data_len), + 35 => wire__crate__api__settings__SshKey_uuid_impl(ptr, rust_vec_len, data_len), + 46 => wire__crate__api__git__host_key_type_name_impl(ptr, rust_vec_len, data_len), + 61 => wire__crate__api__plugin__plugin_instance_manifest_disabled_reason_impl( ptr, rust_vec_len, data_len, ), - 56 => wire__crate__api__plugin__plugin_instance_manifest_enabled_impl( + 62 => wire__crate__api__plugin__plugin_instance_manifest_enabled_impl( ptr, rust_vec_len, data_len, ), - 57 => wire__crate__api__plugin__plugin_instance_manifest_event_impl( + 63 => wire__crate__api__plugin__plugin_instance_manifest_event_impl( ptr, rust_vec_len, data_len, ), - 58 => wire__crate__api__plugin__plugin_instance_manifest_name_impl( + 64 => wire__crate__api__plugin__plugin_instance_manifest_name_impl( ptr, rust_vec_len, data_len, ), - 59 => wire__crate__api__plugin__plugin_instance_manifest_permission_impl( + 65 => wire__crate__api__plugin__plugin_instance_manifest_permission_impl( ptr, rust_vec_len, data_len, ), - 69 => wire__crate__api__settings__settings_new_impl(ptr, rust_vec_len, data_len), - 73 => wire__stride_core__task__task_new_impl(ptr, rust_vec_len, data_len), - 78 => wire__stride_core__task__task_urgency_impl(ptr, rust_vec_len, data_len), + 75 => wire__crate__api__settings__settings_new_impl(ptr, rust_vec_len, data_len), + 79 => wire__stride_core__task__task_new_impl(ptr, rust_vec_len, data_len), + 84 => wire__stride_core__task__task_urgency_impl(ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -4730,23 +5099,27 @@ impl flutter_rust_bridge::IntoIntoDart } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart - for FrbWrapper -{ +impl flutter_rust_bridge::IntoDart for crate::api::repository::BackendRecord { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [self.0.key.into_into_dart().into_dart()].into_dart() + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.enabled.into_into_dart().into_dart(), + self.schema.into_into_dart().into_dart(), + self.config.into_into_dart().into_dart(), + ] + .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for FrbWrapper + for crate::api::repository::BackendRecord { } -impl - flutter_rust_bridge::IntoIntoDart> - for stride_backend_git::encryption_key::EncryptionKey +impl flutter_rust_bridge::IntoIntoDart + for crate::api::repository::BackendRecord { - fn into_into_dart(self) -> FrbWrapper { - self.into() + fn into_into_dart(self) -> crate::api::repository::BackendRecord { + self } } // Codec=Dco (DartCObject based), see doc to use other codecs @@ -5124,12 +5497,6 @@ impl flutter_rust_bridge::IntoDart for crate::api::settings::RepositorySpecifica [ self.uuid.into_into_dart().into_dart(), self.name.into_into_dart().into_dart(), - self.origin.into_into_dart().into_dart(), - self.author.into_into_dart().into_dart(), - self.email.into_into_dart().into_dart(), - self.branch.into_into_dart().into_dart(), - self.ssh_key_uuid.into_into_dart().into_dart(), - self.encryption.into_into_dart().into_dart(), ] .into_dart() } @@ -5471,17 +5838,21 @@ impl SseEncode for crate::api::settings::ApplicationPaths { } } -impl SseEncode for bool { +impl SseEncode for crate::api::repository::BackendRecord { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_u8(self as _).unwrap(); + ::sse_encode(self.id, serializer); + ::sse_encode(self.name, serializer); + ::sse_encode(self.enabled, serializer); + ::sse_encode(self.schema, serializer); + ::sse_encode(self.config, serializer); } } -impl SseEncode for stride_backend_git::encryption_key::EncryptionKey { +impl SseEncode for bool { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.key, serializer); + serializer.cursor.write_u8(self as _).unwrap(); } } @@ -5624,6 +5995,16 @@ impl SseEncode for Vec { } } +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -5808,12 +6189,12 @@ impl SseEncode for Option> { } } -impl SseEncode for Option { +impl SseEncode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.is_some(), serializer); if let Some(value) = self { - ::sse_encode(value, serializer); + ::sse_encode(value, serializer); } } } @@ -5994,15 +6375,6 @@ impl SseEncode for crate::api::settings::RepositorySpecification { fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.uuid, serializer); ::sse_encode(self.name, serializer); - ::sse_encode(self.origin, serializer); - ::sse_encode(self.author, serializer); - ::sse_encode(self.email, serializer); - ::sse_encode(self.branch, serializer); - >::sse_encode(self.ssh_key_uuid, serializer); - >::sse_encode( - self.encryption, - serializer, - ); } }