diff --git a/Cargo.lock b/Cargo.lock index c19b7b6..3c77232 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" @@ -66,10 +57,19 @@ dependencies = [ ] [[package]] -name = "anyhow" -version = "1.0.65" +name = "ansi_term" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "async-broadcast" @@ -82,6 +82,19 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "async-compression" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +dependencies = [ + "brotli", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-oneshot" version = "0.5.0" @@ -91,6 +104,15 @@ dependencies = [ "futures-micro", ] +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + [[package]] name = "atty" version = "0.2.14" @@ -108,26 +130,11 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "backtrace" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bit_field" @@ -150,6 +157,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + [[package]] name = "brotli" version = "3.3.4" @@ -172,10 +188,22 @@ dependencies = [ ] [[package]] -name = "bumpalo" -version = "3.11.0" +name = "bstr" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bytemuck" @@ -197,8 +225,8 @@ checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cairo-rs" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "bitflags", "cairo-sys-rs", @@ -210,8 +238,8 @@ dependencies = [ [[package]] name = "cairo-sys-rs" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "glib-sys", "libc", @@ -235,13 +263,19 @@ checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-expr" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" +checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa" dependencies = [ "smallvec", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -250,19 +284,49 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.22" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim 0.8.0", + "textwrap 0.11.0", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", "bitflags", - "clap_derive", - "clap_lex", + "clap_derive 3.2.18", + "clap_lex 0.2.4", "indexmap", "once_cell", - "strsim", + "strsim 0.10.0", + "termcolor", + "textwrap 0.16.0", +] + +[[package]] +name = "clap" +version = "4.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b" +dependencies = [ + "atty", + "bitflags", + "clap_derive 4.0.18", + "clap_lex 0.3.0", + "once_cell", + "strsim 0.10.0", "termcolor", - "textwrap", ] [[package]] @@ -278,6 +342,19 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_derive" +version = "4.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -287,6 +364,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -324,13 +410,38 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" + [[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", +] + +[[package]] +name = "crossbeam-channel" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" +dependencies = [ + "crossbeam-utils 0.7.2", + "maybe-uninit", ] [[package]] @@ -339,8 +450,8 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ - "cfg-if", - "crossbeam-utils", + "cfg-if 1.0.0", + "crossbeam-utils 0.8.12", ] [[package]] @@ -349,33 +460,90 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils", + "crossbeam-utils 0.8.12", ] [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" dependencies = [ "autocfg", - "cfg-if", - "crossbeam-utils", + "cfg-if 1.0.0", + "crossbeam-utils 0.8.12", "memoffset", - "once_cell", "scopeguard", ] [[package]] -name = "crossbeam-utils" -version = "0.8.11" +name = "crossbeam-queue" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" dependencies = [ - "cfg-if", - "once_cell", + "cfg-if 1.0.0", + "crossbeam-utils 0.8.12", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", ] [[package]] @@ -384,7 +552,7 @@ version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "num_cpus", ] @@ -398,10 +566,20 @@ dependencies = [ ] [[package]] -name = "edit-distance" -version = "2.1.0" +name = "digest" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbaaaf38131deb9ca518a274a45bfdb8771f139517b073b16c2d3d32ae5037b" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +dependencies = [ + "block-buffer 0.10.3", + "crypto-common", +] + +[[package]] +name = "dotenvy" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" [[package]] name = "either" @@ -415,7 +593,7 @@ version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -439,41 +617,19 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "exr" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a7880199e74c6d3fe45579df2f436c5913a71405494cb89d59234d86b47dc5" +checksum = "8eb5f255b5980bb0c8cf676b675d1a99be40f316881444f44e0462eaf5df5ded" dependencies = [ "bit_field", "flume", "half", "lebe", - "miniz_oxide", + "miniz_oxide 0.6.2", "smallvec", "threadpool", ] -[[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "fastrand" version = "1.8.0" @@ -500,16 +656,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "float-cmp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" -dependencies = [ - "num-traits", + "miniz_oxide 0.5.4", ] [[package]] @@ -555,6 +702,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fragile" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7464c5c4a3f014d9b2ec4073650e5c06596f385060af740fc45ad5a19f959e8" +dependencies = [ + "fragile 2.0.0", +] + +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + [[package]] name = "futf" version = "0.1.5" @@ -567,9 +729,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" +checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", @@ -582,9 +744,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -592,15 +754,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-executor" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" dependencies = [ "futures-core", "futures-task", @@ -608,16 +770,27 @@ dependencies = [ ] [[package]] -name = "futures-io" -version = "0.3.24" +name = "futures-intrusive" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" +checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-macro" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", @@ -635,21 +808,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-channel", "futures-core", @@ -665,8 +838,8 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "bitflags", "gdk-pixbuf-sys", @@ -677,8 +850,8 @@ dependencies = [ [[package]] name = "gdk-pixbuf-sys" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "gio-sys", "glib-sys", @@ -689,8 +862,8 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.5.0" -source = "git+https://github.com/gtk-rs/gtk4-rs#58c7187169ae74fac6a68d9454c33ad15da761b7" +version = "0.6.0" +source = "git+https://github.com/gtk-rs/gtk4-rs#62f4173507d944e08dd8f09659491c55725a789d" dependencies = [ "bitflags", "cairo-rs", @@ -704,8 +877,8 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.5.0" -source = "git+https://github.com/gtk-rs/gtk4-rs#58c7187169ae74fac6a68d9454c33ad15da761b7" +version = "0.6.0" +source = "git+https://github.com/gtk-rs/gtk4-rs#62f4173507d944e08dd8f09659491c55725a789d" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -730,11 +903,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "libc", "wasi", @@ -751,16 +924,10 @@ dependencies = [ "weezl", ] -[[package]] -name = "gimli" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" - [[package]] name = "gio" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "bitflags", "futures-channel", @@ -771,13 +938,15 @@ dependencies = [ "glib", "libc", "once_cell", + "pin-project-lite", + "smallvec", "thiserror", ] [[package]] name = "gio-sys" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "glib-sys", "gobject-sys", @@ -788,8 +957,8 @@ dependencies = [ [[package]] name = "glib" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "bitflags", "futures-channel", @@ -797,6 +966,7 @@ dependencies = [ "futures-executor", "futures-task", "futures-util", + "gio-sys", "glib-macros", "glib-sys", "gobject-sys", @@ -808,8 +978,8 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "anyhow", "heck", @@ -822,17 +992,30 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "libc", "system-deps", ] +[[package]] +name = "globset" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + [[package]] name = "gobject-sys" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "glib-sys", "libc", @@ -841,8 +1024,8 @@ dependencies = [ [[package]] name = "graphene-rs" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "glib", "graphene-sys", @@ -851,8 +1034,8 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "glib-sys", "libc", @@ -862,8 +1045,8 @@ dependencies = [ [[package]] name = "gsk4" -version = "0.5.0" -source = "git+https://github.com/gtk-rs/gtk4-rs#58c7187169ae74fac6a68d9454c33ad15da761b7" +version = "0.6.0" +source = "git+https://github.com/gtk-rs/gtk4-rs#62f4173507d944e08dd8f09659491c55725a789d" dependencies = [ "bitflags", "cairo-rs", @@ -877,8 +1060,8 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.5.0" -source = "git+https://github.com/gtk-rs/gtk4-rs#58c7187169ae74fac6a68d9454c33ad15da761b7" +version = "0.6.0" +source = "git+https://github.com/gtk-rs/gtk4-rs#62f4173507d944e08dd8f09659491c55725a789d" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -892,8 +1075,8 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.5.0" -source = "git+https://github.com/gtk-rs/gtk4-rs#58c7187169ae74fac6a68d9454c33ad15da761b7" +version = "0.6.0" +source = "git+https://github.com/gtk-rs/gtk4-rs#62f4173507d944e08dd8f09659491c55725a789d" dependencies = [ "bitflags", "cairo-rs", @@ -914,8 +1097,8 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.5.0" -source = "git+https://github.com/gtk-rs/gtk4-rs#58c7187169ae74fac6a68d9454c33ad15da761b7" +version = "0.6.0" +source = "git+https://github.com/gtk-rs/gtk4-rs#62f4173507d944e08dd8f09659491c55725a789d" dependencies = [ "anyhow", "proc-macro-crate", @@ -927,8 +1110,8 @@ dependencies = [ [[package]] name = "gtk4-sys" -version = "0.5.0" -source = "git+https://github.com/gtk-rs/gtk4-rs#58c7187169ae74fac6a68d9454c33ad15da761b7" +version = "0.6.0" +source = "git+https://github.com/gtk-rs/gtk4-rs#62f4173507d944e08dd8f09659491c55725a789d" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -945,9 +1128,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -964,18 +1147,11 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "halfbrown" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce69ed202df415a3d4a01e6f3341320ca88b9bd4f0bf37be6fa239cdea06d9bf" +checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" dependencies = [ - "hashbrown 0.12.3", - "serde", + "crunchy", ] [[package]] @@ -993,11 +1169,23 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashlink" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" +dependencies = [ + "hashbrown 0.12.3", +] + [[package]] name = "heck" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "hermit-abi" @@ -1052,7 +1240,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 1.0.4", ] [[package]] @@ -1102,7 +1290,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 1.0.4", "pin-project-lite", "socket2", "tokio", @@ -1134,6 +1322,24 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ignore" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +dependencies = [ + "crossbeam-utils 0.8.12", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + [[package]] name = "ijson" version = "0.1.3" @@ -1181,7 +1387,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1191,10 +1397,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] -name = "itoa" -version = "1.0.3" +name = "itertools" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jpeg-decoder" @@ -1228,8 +1449,8 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libadwaita" -version = "0.2.0" -source = "git+https://gitlab.gnome.org/World/Rust/libadwaita-rs#2161931a19f43a6764c7006da87914cddb6429c8" +version = "0.3.0" +source = "git+https://gitlab.gnome.org/World/Rust/libadwaita-rs#4be42706a24225a737e706f44b5605d6dbc295d4" dependencies = [ "bitflags", "futures-channel", @@ -1246,8 +1467,8 @@ dependencies = [ [[package]] name = "libadwaita-sys" -version = "0.2.0" -source = "git+https://gitlab.gnome.org/World/Rust/libadwaita-rs#2161931a19f43a6764c7006da87914cddb6429c8" +version = "0.3.0" +source = "git+https://gitlab.gnome.org/World/Rust/libadwaita-rs#4be42706a24225a737e706f44b5605d6dbc295d4" dependencies = [ "gdk4-sys", "gio-sys", @@ -1261,9 +1482,20 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.133" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" + +[[package]] +name = "libsqlite3-sys" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] [[package]] name = "linkify" @@ -1290,7 +1522,7 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1331,6 +1563,12 @@ dependencies = [ "xml5ever", ] +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + [[package]] name = "memchr" version = "2.5.0" @@ -1352,6 +1590,12 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.5.4" @@ -1362,15 +1606,24 @@ dependencies = [ ] [[package]] -name = "mio" -version = "0.8.4" +name = "miniz_oxide" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1407,30 +1660,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] -name = "nix-editor" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf248c2a02080d305cf67a51b989755e29a4256e896ed091cbb5fad578cf032" +name = "nix-data" +version = "0.0.2" +source = "git+https://github.com/snowflakelinux/nix-data?rev=a5168c768e8cf8bd3e1afe1772f8e05e5b03ed95#a5168c768e8cf8bd3e1afe1772f8e05e5b03ed95" dependencies = [ - "clap", - "failure", + "anyhow", + "csv", + "ijson", + "lazy_static", + "log", + "nix-editor", + "pretty_env_logger", + "reqwest", + "serde", + "serde_json", + "sqlx", + "tokio", +] + +[[package]] +name = "nix-editor" +version = "0.3.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cc1d93deb37efb27faaf8ffbdf9d0a536a371fb0c1e9dae2bffe01ba55f65a" +dependencies = [ + "clap 4.0.18", + "nixpkgs-fmt", "owo-colors", "rnix", + "thiserror", ] [[package]] name = "nix-software-center" -version = "0.0.3" +version = "0.1.0" dependencies = [ - "brotli", - "edit-distance", + "anyhow", "flate2", "gtk4", "html2pango", - "ijson", "image", "libadwaita", "log", + "nix-data", "nix-editor", "pretty_env_logger", "quick-xml", @@ -1442,20 +1714,45 @@ dependencies = [ "serde_json", "serde_yaml", "sha256", - "simd-json", "spdx", + "sqlx", "strum", "strum_macros", "tokio", "tracker", - "which", +] + +[[package]] +name = "nixpkgs-fmt" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1bdfcb88bb9dc3ae8a6ef55cda89eb33d7c69a98411b4cdb845adf391a7587" +dependencies = [ + "clap 2.34.0", + "crossbeam-channel 0.4.4", + "ignore", + "libc", + "rnix", + "rowan", + "serde_json", + "smol_str", +] + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", ] [[package]] name = "nsc-helper" version = "0.1.0" dependencies = [ - "clap", + "clap 3.2.23", "users", ] @@ -1499,15 +1796,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.15.0" @@ -1527,7 +1815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", - "cfg-if", + "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", @@ -1554,9 +1842,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.76" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg", "cc", @@ -1579,8 +1867,8 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "pango" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "bitflags", "gio", @@ -1592,8 +1880,8 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.16.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#61a082e6fb3cb50af8c936dc8858b7a67db4ac9a" +version = "0.17.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#01fa572c4fc8f0796ada8a191780b32076727d5e" dependencies = [ "glib-sys", "gobject-sys", @@ -1613,17 +1901,23 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] +[[package]] +name = "paste" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" + [[package]] name = "percent-encoding" version = "2.2.0" @@ -1632,9 +1926,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" +checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a" dependencies = [ "thiserror", "ucd-trie", @@ -1712,9 +2006,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "png" @@ -1725,7 +2019,7 @@ dependencies = [ "bitflags", "crc32fast", "flate2", - "miniz_oxide", + "miniz_oxide 0.5.4", ] [[package]] @@ -1787,9 +2081,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.44" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -1867,9 +2161,9 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ - "crossbeam-channel", + "crossbeam-channel 0.5.6", "crossbeam-deque", - "crossbeam-utils", + "crossbeam-utils 0.8.12", "num_cpus", ] @@ -1893,6 +2187,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-syntax" version = "0.6.27" @@ -1901,12 +2201,13 @@ checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "relm4" -version = "0.5.0-beta.2" -source = "git+https://github.com/Relm4/Relm4?tag=v0.5.0-beta.2#7b0a9387833e6a1d6bf6afbba323451b06b0fb08" +version = "0.5.0-beta.3" +source = "git+https://github.com/Relm4/Relm4?tag=v0.5.0-beta.3#cf23f21de3c1a38648db48df1197fd82e74b9862" dependencies = [ "async-broadcast", "async-oneshot", "flume", + "fragile 1.2.2", "futures", "gtk4", "libadwaita", @@ -1919,8 +2220,8 @@ dependencies = [ [[package]] name = "relm4-components" -version = "0.5.0-beta.2" -source = "git+https://github.com/Relm4/Relm4?tag=v0.5.0-beta.2#7b0a9387833e6a1d6bf6afbba323451b06b0fb08" +version = "0.5.0-beta.3" +source = "git+https://github.com/Relm4/Relm4?tag=v0.5.0-beta.3#cf23f21de3c1a38648db48df1197fd82e74b9862" dependencies = [ "log", "once_cell", @@ -1930,8 +2231,8 @@ dependencies = [ [[package]] name = "relm4-macros" -version = "0.5.0-beta.2" -source = "git+https://github.com/Relm4/Relm4?tag=v0.5.0-beta.2#7b0a9387833e6a1d6bf6afbba323451b06b0fb08" +version = "0.5.0-beta.3" +source = "git+https://github.com/Relm4/Relm4?tag=v0.5.0-beta.3#cf23f21de3c1a38648db48df1197fd82e74b9862" dependencies = [ "proc-macro2", "quote", @@ -1953,6 +2254,7 @@ version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ + "async-compression", "base64", "bytes", "encoding_rs", @@ -1976,6 +2278,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-native-tls", + "tokio-util", "tower-service", "url", "wasm-bindgen", @@ -2005,15 +2308,10 @@ dependencies = [ "hashbrown 0.9.1", "memoffset", "rustc-hash", + "serde", "text-size", ] -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -2041,6 +2339,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.20" @@ -2048,7 +2355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -2106,18 +2413,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.145" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.145" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -2126,11 +2433,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" dependencies = [ - "itoa", + "itoa 1.0.4", "ryu", "serde", ] @@ -2142,19 +2449,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.4", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.9.13" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8613d593412a0deb7bbd8de9d908efff5a0cb9ccd8f62c641e7b2ed2f57291d1" +checksum = "6d232d893b10de3eb7258ff01974d6ee20663d8e833263c99409d4b13a0209da" dependencies = [ "indexmap", - "itoa", + "itoa 1.0.4", "ryu", "serde", "unsafe-libyaml", @@ -2166,21 +2473,32 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", - "cfg-if", + "block-buffer 0.9.0", + "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] [[package]] -name = "sha256" -version = "1.0.3" +name = "sha2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e84a7f596c081d359de5e06a83877138bc3c4483591e1af1916e1472e6e146e" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.5", +] + +[[package]] +name = "sha256" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e334db67871c14c18fc066ad14af13f9fdf5f9a91c61af432d1e3a39c8c6a141" dependencies = [ "hex", - "sha2", + "sha2 0.9.9", ] [[package]] @@ -2192,25 +2510,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd-json" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd78b840b9de64fa3f7d72909b76343849f68e8c3d32608db8d38e4e5481f84" -dependencies = [ - "halfbrown", - "serde", - "serde_json", - "simdutf8", - "value-trait", -] - -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - [[package]] name = "siphasher" version = "0.3.10" @@ -2228,9 +2527,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smol_str" @@ -2269,6 +2568,101 @@ dependencies = [ "lock_api", ] +[[package]] +name = "sqlformat" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" +dependencies = [ + "ahash", + "atoi", + "bitflags", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "hashlink", + "hex", + "indexmap", + "itoa 1.0.4", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "sha2 0.10.6", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" +dependencies = [ + "dotenvy", + "either", + "heck", + "once_cell", + "proc-macro2", + "quote", + "sha2 0.10.6", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" +dependencies = [ + "native-tls", + "once_cell", + "tokio", + "tokio-native-tls", +] + [[package]] name = "string_cache" version = "0.8.4" @@ -2295,6 +2689,22 @@ dependencies = [ "quote", ] +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.10.0" @@ -2322,32 +2732,20 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - [[package]] name = "system-deps" -version = "6.0.2" +version = "6.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709" +checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" dependencies = [ "cfg-expr", "heck", @@ -2362,7 +2760,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "libc", "redox_syscall", @@ -2395,33 +2793,54 @@ name = "text-size" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a" +dependencies = [ + "serde", +] [[package]] name = "textwrap" -version = "0.15.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a99cb8c4b9a8ef0e7907cd3b617cc8dc04d571c4e73c8ae403d80ac160bb122" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a891860d3c8d66fec8e73ddb3765f90082374dbaaa833407b904a94f1a7eb43" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + [[package]] name = "threadpool" version = "1.8.1" @@ -2469,6 +2888,7 @@ dependencies = [ "memchr", "mio", "num_cpus", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -2497,6 +2917,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.4" @@ -2528,11 +2959,11 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -2541,9 +2972,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", @@ -2552,9 +2983,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] @@ -2605,9 +3036,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" @@ -2619,10 +3050,22 @@ dependencies = [ ] [[package]] -name = "unicode-xid" -version = "0.2.4" +name = "unicode-segmentation" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unsafe-libyaml" @@ -2657,24 +3100,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "value-trait" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0a635407649b66e125e4d2ffd208153210179f8c7c8b71c030aa2ad3eeb4c8f" -dependencies = [ - "float-cmp", - "halfbrown", - "itoa", - "ryu", -] - [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version-compare" version = "0.1.0" @@ -2687,6 +3124,17 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" @@ -2709,7 +3157,7 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -2734,7 +3182,7 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -2785,17 +3233,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" -[[package]] -name = "which" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" -dependencies = [ - "either", - "libc", - "once_cell", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2833,43 +3270,100 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "winreg" version = "0.10.1" diff --git a/Cargo.toml b/Cargo.toml index 8c33182..fbf4d74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "nix-software-center" -version = "0.0.3" +version = "0.1.0" edition = "2021" default-run = "nix-software-center" [dependencies] -relm4 = { git = "https://github.com/Relm4/Relm4", tag = "v0.5.0-beta.2", features = ["all"] } -relm4-components = { package = "relm4-components", git = "https://github.com/Relm4/Relm4", tag = "v0.5.0-beta.2"} +relm4 = { git = "https://github.com/Relm4/Relm4", tag = "v0.5.0-beta.3", features = ["all"] } +relm4-components = { package = "relm4-components", git = "https://github.com/Relm4/Relm4", tag = "v0.5.0-beta.3"} adw = { package = "libadwaita", git = "https://gitlab.gnome.org/World/Rust/libadwaita-rs", features = ["v1_2", "gtk_v4_6"] } gtk = { package = "gtk4", git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_6"] } tokio = { version = "1.21", features = ["rt", "macros", "time", "rt-multi-thread", "sync", "process"] } @@ -15,12 +15,13 @@ tracker = "0.1" serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" -simd-json = { version = "0.6", features = ["allow-non-simd"] } -nix-editor = "0.2.12" +nix-editor = "0.3.0-beta.1" +nix-data = { git = "https://github.com/snowflakelinux/nix-data", rev = "a5168c768e8cf8bd3e1afe1772f8e05e5b03ed95" } + +sqlx = { version = "0.6", features = [ "runtime-tokio-native-tls" , "sqlite" ] } html2pango = "0.5" -brotli = "3.3" log = "0.4" pretty_env_logger = "0.4" flate2 = "1.0" @@ -30,11 +31,10 @@ reqwest = { version = "0.11", features = ["blocking"] } sha256 = "1.0" image = "0.24" spdx = "0.9" -edit-distance = "2.1" -ijson = "0.1" strum = "0.24" strum_macros = "0.24" -which = "4.3" + +anyhow = "1.0" [workspace] members = [".", "nsc-helper"] diff --git a/default.nix b/default.nix index ec2bce7..6dda1ff 100644 --- a/default.nix +++ b/default.nix @@ -2,16 +2,6 @@ , lib ? import }: let - libadwaita-git = pkgs.libadwaita.overrideAttrs (oldAttrs: rec { - version = "1.2.0"; - src = pkgs.fetchFromGitLab { - domain = "gitlab.gnome.org"; - owner = "GNOME"; - repo = "libadwaita"; - rev = version; - hash = "sha256-3lH7Vi9M8k+GSrCpvruRpLrIpMoOakKbcJlaAc/FK+U="; - }; - }); nixos-appstream-data = (import (pkgs.fetchFromGitHub { owner = "vlinkz"; @@ -23,14 +13,14 @@ let in pkgs.stdenv.mkDerivation rec { pname = "nix-software-center"; - version = "0.0.3"; + version = "0.1.0"; src = [ ./. ]; cargoDeps = pkgs.rustPlatform.fetchCargoTarball { inherit src; name = "${pname}-${version}"; - hash = "sha256-8eUFl3N1tVZ2j+S6iIIpFSH5F5fXAl5+Yz3xS/NxF2I="; + hash = "sha256-NqjBlNHt9rlej5Y3R6cYDZFwpDIFa3ZmfsxSXaTUOUI="; }; nativeBuildInputs = with pkgs; [ @@ -54,7 +44,8 @@ pkgs.stdenv.mkDerivation rec { glib gtk4 gtksourceview5 - libadwaita-git + libadwaita + libxml2 openssl wayland gnome.adwaita-icon-theme diff --git a/flake.lock b/flake.lock index ca6be2f..be0cee2 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1664195620, - "narHash": "sha256-/0V1a1gAR+QbiQe4aCxBoivhkxss0xyt2mBD6yDrgjw=", + "lastModified": 1665732960, + "narHash": "sha256-WBZ+uSHKFyjvd0w4inbm0cNExYTn8lpYFcHEes8tmec=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "62228ccc672ed000f35b1e5c82e4183e46767e52", + "rev": "4428e23312933a196724da2df7ab78eb5e67a88e", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 2fdf9ff..4dab869 100644 --- a/flake.nix +++ b/flake.nix @@ -10,16 +10,6 @@ pkgs = import nixpkgs { inherit system; }; - libadwaita-git = pkgs.libadwaita.overrideAttrs (oldAttrs: rec { - version = "1.2.0"; - src = pkgs.fetchFromGitLab { - domain = "gitlab.gnome.org"; - owner = "GNOME"; - repo = "libadwaita"; - rev = version; - hash = "sha256-3lH7Vi9M8k+GSrCpvruRpLrIpMoOakKbcJlaAc/FK+U="; - }; - }); nixos-appstream-data = pkgs.fetchFromGitHub { owner = "vlinkz"; repo = "nixos-appstream-data"; @@ -58,7 +48,7 @@ graphene gtk4 gtksourceview5 - libadwaita-git + libadwaita meson ninja openssl diff --git a/meson.build b/meson.build index 103573f..bc8ab73 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'nix-software-center', 'rust', - version: '0.0.3', + version: '0.1.0', meson_version: '>= 0.59', license: 'GPL-3.0-only', ) diff --git a/src/main.rs b/src/main.rs index b4d168b..34d2814 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,5 @@ fn main() { gio::resources_register(&res); } let app = RelmApp::new(nix_software_center::config::APP_ID); - let application = app.app.clone(); - app.run::(application); + app.run::(()); } diff --git a/src/parse/config.rs b/src/parse/config.rs index 87ae87a..a4e6f59 100644 --- a/src/parse/config.rs +++ b/src/parse/config.rs @@ -1,56 +1,15 @@ -use std::{ - env, - error::Error, - fs::{self, File}, - io::Write, - path::Path, -}; +use anyhow::Result; +use nix_data::config::configfile::NixDataConfig; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] -pub struct NscConfig { - pub systemconfig: Option, - pub flake: Option, - pub flakearg: Option, -} - -pub fn getconfig() -> Option { - if let Ok(c) = getconfigval() { +pub fn getconfig() -> Option { + if let Ok(c) = nix_data::config::configfile::getconfig() { Some(c) } else { None } } -fn getconfigval() -> Result> { - let configfile = checkconfig()?; - let config: NscConfig = - serde_json::from_reader(File::open(format!("{}/config.json", configfile))?)?; - Ok(config) -} - -fn checkconfig() -> Result> { - let cfgdir = format!("{}/.config/nix-software-center", env::var("HOME")?); - if !Path::is_file(Path::new(&format!("{}/config.json", &cfgdir))) { - if !Path::is_file(Path::new("/etc/nix-software-center/config.json")) { - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "No config file found", - ))) - } else { - Ok("/etc/nix-software-center/".to_string()) - } - } else { - Ok(cfgdir) - } -} - -pub fn editconfig(config: NscConfig) -> Result<(), Box> { - let cfgdir = format!("{}/.config/nix-software-center", env::var("HOME")?); - fs::create_dir_all(&cfgdir)?; - let json = serde_json::to_string_pretty(&config)?; - let mut file = File::create(format!("{}/config.json", cfgdir))?; - file.write_all(json.as_bytes())?; +pub fn editconfig(config: NixDataConfig) -> Result<()> { + nix_data::config::configfile::setuserconfig(config)?; Ok(()) -} \ No newline at end of file +} diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 199c472..d06be6d 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,3 +1,3 @@ -pub mod cache; +// pub mod cache; pub mod packages; pub mod config; \ No newline at end of file diff --git a/src/parse/packages.rs b/src/parse/packages.rs index 0745c74..9f12d8d 100644 --- a/src/parse/packages.rs +++ b/src/parse/packages.rs @@ -1,91 +1,58 @@ use flate2::bufread::GzDecoder; -use ijson::IString; use serde::{Deserialize, Serialize}; -use std::fs; -use std::io::Read; -use std::{self, fs::File, collections::HashMap, error::Error, env, io::BufReader}; +use std::{self, fs::File, collections::HashMap, io::{BufReader, Read}}; use log::*; +use anyhow::Result; use crate::APPINFO; -#[derive(Serialize, Deserialize, Debug)] -pub struct PackageBase { - packages: HashMap, -} - -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -pub struct Package { - pub system: IString, - pub pname: IString, - pub meta: Meta, - pub version: IString, - #[serde(skip_deserializing)] - pub appdata: Option, -} - -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -pub struct Meta { - pub broken: Option, - pub insecure: Option, - pub unsupported: Option, - pub unfree: Option, - pub description: Option, - #[serde(rename = "longDescription")] - pub longdescription: Option, - pub homepage: Option, - pub maintainers: Option, - pub position: Option, - pub license: Option, - pub platforms: Option -} - -#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] #[serde(untagged)] pub enum StrOrVec { - Single(IString), - List(Vec), + Single(String), + List(Vec), } -#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] #[serde(untagged)] pub enum Platform { - Single(IString), - List(Vec), - ListList(Vec>), + Single(String), + List(Vec), + ListList(Vec>), } -#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] #[serde(untagged)] pub enum LicenseEnum { Single(License), List(Vec), - SingleStr(IString), - VecStr(Vec), + SingleStr(String), + VecStr(Vec), Mixed(Vec) } -#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] pub struct License { pub free: Option, #[serde(rename = "fullName")] - pub fullname: Option, + pub fullname: Option, #[serde(rename = "spdxId")] - pub spdxid: Option, - pub url: Option, + pub spdxid: Option, + pub url: Option, } -#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] pub struct PkgMaintainer { - pub email: Option, - pub github: Option, - pub matrix: Option, - pub name: Option + pub email: Option, + pub github: Option, + pub matrix: Option, + pub name: Option } -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct AppData { #[serde(rename = "Type")] - pub metatype: IString, + pub metatype: String, #[serde(rename = "ID")] pub id: String, #[serde(rename = "Package")] @@ -110,7 +77,7 @@ pub struct AppData { pub categories: Option>, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct AppUrl { pub homepage: Option, pub bugtracker: Option, @@ -118,27 +85,27 @@ pub struct AppUrl { pub donation: Option, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct AppIconList { pub cached: Option>, pub stock: Option, // TODO: add support for other icon types } -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct AppIcon { pub name: String, pub width: u32, pub height: u32, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct AppLaunchable { #[serde(rename = "desktop-id")] pub desktopid: Vec } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct AppProvides { pub binaries: Option>, pub ids: Option>, @@ -146,7 +113,7 @@ pub struct AppProvides { pub libraries: Option>, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct AppScreenshot { pub default: Option, pub thumbnails: Option>, @@ -154,33 +121,12 @@ pub struct AppScreenshot { pub sourceimage: Option, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct AppScreenshotImage { pub url: String, } -#[derive(Debug, Serialize, Deserialize)] -struct FlakePkgs { - packages: HashMap -} - -#[derive(Debug, Serialize, Deserialize)] -struct FlakeJson { - pname: IString, - version: IString, -} - -pub async fn readpkgs() -> Result, Box> { - info!("Reading package list"); - let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?); - let cachefile = format!("{}/packages.json", cachedir); - let file = File::open(cachefile)?; - let reader = BufReader::new(file); - trace!("Reading packages.json"); - let pkgbase: PackageBase = simd_json::serde::from_reader(reader)?; - trace!("Finished reading packages.json"); - let mut pkgs = pkgbase.packages; - debug!("APPDATADIR {}", APPINFO); +pub fn appsteamdata() -> Result> { let appdata = File::open(&format!("{}/xmls/nixos_x86_64_linux.yml.gz", APPINFO))?; let appreader = BufReader::new(appdata); let mut d = GzDecoder::new(appreader); @@ -188,61 +134,15 @@ pub async fn readpkgs() -> Result, Box>(); files.remove(0); + + let mut out = HashMap::new(); + for f in files { if let Ok(appstream) = serde_yaml::from_str::(f) { - if let Some(p) = pkgs.get_mut(&appstream.package.to_string()) { - p.appdata = Some(appstream); - } + out.insert(appstream.package.to_string(), appstream); } else { warn!("Failed to parse some appstream data"); } } - Ok(pkgs) + Ok(out) } - -pub fn readlegacysyspkgs() -> Result, Box> { - info!("Reading legacy system package list"); - let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?); - let cachefile = format!("{}/syspackages.json", cachedir); - if let Ok(f) = fs::read_to_string(&cachefile) { - if f.trim().is_empty() { - return Ok(HashMap::new()); - } - } - let file = File::open(cachefile)?; - let reader = BufReader::new(file); - let newpkgs: HashMap = simd_json::serde::from_reader(reader)?; - Ok(newpkgs) -} - -pub fn readflakesyspkgs() -> Result, Box> { - info!("Reading flake system package list"); - let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?); - let cachefile = format!("{}/syspackages.json", cachedir); - if let Ok(f) = fs::read_to_string(&cachefile) { - if f.trim().is_empty() { - return Ok(HashMap::new()); - } - } - let file = File::open(cachefile)?; - let reader = BufReader::new(file); - let newpkgs: HashMap = simd_json::serde::from_reader(reader)?; - let newpkgs = newpkgs.into_iter().filter_map(|(k, v)| if let Some(pkg) = k.strip_prefix("legacyPackages.x86_64-linux.") { Some((pkg.to_string(), v.version.to_string())) } else { None }).collect::>(); - Ok(newpkgs) -} - -pub fn readprofilepkgs() -> Result, Box> { - info!("Reading profile package list"); - let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?); - let cachefile = format!("{}/profilepackages.json", cachedir); - if let Ok(f) = fs::read_to_string(&cachefile) { - if f.trim().is_empty() { - return Ok(HashMap::new()); - } - } - let file = File::open(cachefile)?; - let reader = BufReader::new(file); - let profilepkgs: FlakePkgs = simd_json::serde::from_reader(reader)?; - let profilepkgs = profilepkgs.packages.into_iter().map(|(pkg, v)| (pkg.to_string(), v.version.to_string())).collect::>(); - Ok(profilepkgs) -} \ No newline at end of file diff --git a/src/ui/about.rs b/src/ui/about.rs index 2e75ad6..c07066c 100644 --- a/src/ui/about.rs +++ b/src/ui/about.rs @@ -17,7 +17,7 @@ pub enum AboutPageMsg { #[relm4::component(pub)] impl SimpleComponent for AboutPageModel { - type InitParams = gtk::Window; + type Init = gtk::Window; type Input = AboutPageMsg; type Output = AppMsg; type Widgets = AboutPageWidgets; @@ -40,7 +40,7 @@ impl SimpleComponent for AboutPageModel { } fn init( - parent_window: Self::InitParams, + parent_window: Self::Init, root: &Self::Root, _sender: ComponentSender, ) -> ComponentParts { diff --git a/src/ui/categories.rs b/src/ui/categories.rs index 09ca47d..cd2acbf 100644 --- a/src/ui/categories.rs +++ b/src/ui/categories.rs @@ -5,7 +5,7 @@ use strum_macros::{EnumIter, Display}; use super::window::AppMsg; -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub struct PkgGroup { pub category: PkgCategory, } @@ -33,7 +33,7 @@ impl FactoryComponent for PkgGroup { type Output = PkgCategoryMsg; type Widgets = PkgGroupWidgets; type ParentWidget = gtk::FlowBox; - type ParentMsg = AppMsg; + type ParentInput = AppMsg; view! { gtk::FlowBoxChild { @@ -95,7 +95,7 @@ impl FactoryComponent for PkgGroup { } } - fn output_to_parent_msg(output: Self::Output) -> Option { + fn output_to_parent_input(output: Self::Output) -> Option { Some(match output { PkgCategoryMsg::Open(x) => AppMsg::OpenCategoryPage(x), }) diff --git a/src/ui/categorypage.rs b/src/ui/categorypage.rs index 4e8bffc..6552194 100644 --- a/src/ui/categorypage.rs +++ b/src/ui/categorypage.rs @@ -1,6 +1,7 @@ use super::{window::*, categories::PkgCategory, categorytile::CategoryTile}; use adw::prelude::*; use relm4::{factory::*, *}; +use log::*; #[tracker::track] #[derive(Debug)] @@ -22,12 +23,19 @@ pub enum CategoryPageMsg { UpdateInstalled(Vec, Vec) } +#[derive(Debug)] +pub enum CategoryPageAsyncMsg { + PushRec(CategoryTile), + Push(CategoryTile), +} + #[relm4::component(pub)] -impl SimpleComponent for CategoryPageModel { - type InitParams = (); +impl Component for CategoryPageModel { + type Init = (); type Input = CategoryPageMsg; type Output = AppMsg; type Widgets = CategoryPageWidgets; + type CommandOutput = CategoryPageAsyncMsg; view! { gtk::Box { @@ -59,11 +67,14 @@ impl SimpleComponent for CategoryPageModel { set_maximum_size: 1000, set_tightening_threshold: 750, if model.busy { + #[name(spinner)] gtk::Spinner { + set_hexpand: true, + set_vexpand: true, set_halign: gtk::Align::Center, set_valign: gtk::Align::Center, set_spinning: true, - set_height_request: 32, + set_size_request: (64, 64), } } else { gtk::Box { @@ -115,14 +126,14 @@ impl SimpleComponent for CategoryPageModel { } fn init( - (): Self::InitParams, + (): Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { let model = CategoryPageModel { category: PkgCategory::Audio, - recommendedapps: FactoryVecDeque::new(gtk::FlowBox::new(), &sender.input), - apps: FactoryVecDeque::new(gtk::FlowBox::new(), &sender.input), + recommendedapps: FactoryVecDeque::new(gtk::FlowBox::new(), sender.input_sender()), + apps: FactoryVecDeque::new(gtk::FlowBox::new(), sender.input_sender()), busy: true, tracker: 0 }; @@ -139,30 +150,39 @@ impl SimpleComponent for CategoryPageModel { self.reset(); match msg { CategoryPageMsg::Close => { - let mut recapps_guard = self.recommendedapps.guard(); - let mut apps_guard = self.apps.guard(); - recapps_guard.clear(); - apps_guard.clear(); + // let mut recapps_guard = self.recommendedapps.guard(); + // let mut apps_guard = self.apps.guard(); + // recapps_guard.clear(); + // apps_guard.clear(); sender.output(AppMsg::FrontFrontPage) } CategoryPageMsg::OpenPkg(pkg) => { sender.output(AppMsg::OpenPkg(pkg)) } CategoryPageMsg::Open(category, catrec, catall) => { + info!("CategoryPageMsg::Open"); self.set_category(category); let mut recapps_guard = self.recommendedapps.guard(); recapps_guard.clear(); + recapps_guard.drop(); for app in catrec { - recapps_guard.push_back(app); + sender.oneshot_command(async move { + CategoryPageAsyncMsg::PushRec(app) + }); } let mut apps_guard = self.apps.guard(); apps_guard.clear(); + apps_guard.drop(); for app in catall { - apps_guard.push_back(app); + sender.oneshot_command(async move { + CategoryPageAsyncMsg::Push(app) + }); } self.busy = false; + info!("DONE CategoryPageMsg::Open"); } CategoryPageMsg::Loading(category) => { + info!("CategoryPageMsg::Loading"); self.set_category(category); self.busy = true; } @@ -199,4 +219,19 @@ impl SimpleComponent for CategoryPageModel { } } + fn update_cmd(&mut self, msg: Self::CommandOutput, _sender: ComponentSender) { + match msg { + CategoryPageAsyncMsg::PushRec(tile) => { + let mut recapps_guard = self.recommendedapps.guard(); + recapps_guard.push_back(tile); + recapps_guard.drop(); + } + CategoryPageAsyncMsg::Push(tile) => { + let mut apps_guard = self.apps.guard(); + apps_guard.push_back(tile); + apps_guard.drop(); + } + } + } + } \ No newline at end of file diff --git a/src/ui/categorytile.rs b/src/ui/categorytile.rs index 44f9c04..834bb0e 100644 --- a/src/ui/categorytile.rs +++ b/src/ui/categorytile.rs @@ -7,7 +7,7 @@ use relm4::adw::prelude::*; use relm4::gtk::pango; use relm4::{factory::*, *}; -#[derive(Default, Debug, PartialEq, Clone)] +#[derive(Default, Debug, PartialEq, Eq, Clone)] pub struct CategoryTile { pub name: String, pub pkg: String, @@ -31,7 +31,7 @@ impl FactoryComponent for CategoryTile { type Output = CategoryTileMsg; type Widgets = CategoryTileWidgets; type ParentWidget = gtk::FlowBox; - type ParentMsg = CategoryPageMsg; + type ParentInput = CategoryPageMsg; view! { gtk::FlowBoxChild { @@ -176,7 +176,7 @@ impl FactoryComponent for CategoryTile { } } - fn output_to_parent_msg(output: Self::Output) -> Option { + fn output_to_parent_input(output: Self::Output) -> Option { Some(match output { CategoryTileMsg::Open(x) => CategoryPageMsg::OpenPkg(x), }) diff --git a/src/ui/installedpage.rs b/src/ui/installedpage.rs index edbdaa0..e9dcff7 100644 --- a/src/ui/installedpage.rs +++ b/src/ui/installedpage.rs @@ -28,7 +28,7 @@ pub enum InstalledPageMsg { #[relm4::component(pub)] impl SimpleComponent for InstalledPageModel { - type InitParams = (SystemPkgs, UserPkgs); + type Init = (SystemPkgs, UserPkgs); type Input = InstalledPageMsg; type Output = AppMsg; type Widgets = InstalledPageWidgets; @@ -93,13 +93,13 @@ impl SimpleComponent for InstalledPageModel { } fn init( - (systempkgtype, userpkgtype): Self::InitParams, + (systempkgtype, userpkgtype): Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { let model = InstalledPageModel { - installeduserlist: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input), - installedsystemlist: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input), + installeduserlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()), + installedsystemlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()), updatetracker: 0, userpkgtype, systempkgtype, @@ -196,7 +196,7 @@ impl SimpleComponent for InstalledPageModel { -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct InstalledItem { pub name: String, pub pkg: Option, @@ -207,7 +207,7 @@ pub struct InstalledItem { pub busy: bool, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct InstalledItemModel { pub item: InstalledItem, } @@ -230,7 +230,7 @@ impl FactoryComponent for InstalledItemModel { type Output = InstalledItemMsg; type Widgets = InstalledItemWidgets; type ParentWidget = adw::gtk::ListBox; - type ParentMsg = InstalledPageMsg; + type ParentInput = InstalledPageMsg; view! { adw::PreferencesRow { @@ -363,7 +363,7 @@ impl FactoryComponent for InstalledItemModel { } } - fn output_to_parent_msg(output: Self::Output) -> Option { + fn output_to_parent_input(output: Self::Output) -> Option { Some(match output { InstalledItemMsg::Delete(item) => InstalledPageMsg::Remove(item), }) diff --git a/src/ui/installworker.rs b/src/ui/installworker.rs index ac7b018..d8a191f 100644 --- a/src/ui/installworker.rs +++ b/src/ui/installworker.rs @@ -1,8 +1,7 @@ -use crate::parse::config::NscConfig; - use super::pkgpage::{InstallType, PkgAction, PkgMsg, WorkPkg}; use super::window::{SystemPkgs, UserPkgs}; use log::*; +use nix_data::config::configfile::NixDataConfig; use relm4::*; use std::error::Error; use std::path::Path; @@ -25,7 +24,7 @@ pub struct InstallAsyncHandler { #[derive(Debug)] pub enum InstallAsyncHandlerMsg { - SetConfig(NscConfig), + SetConfig(NixDataConfig), SetPkgTypes(SystemPkgs, UserPkgs), Process(WorkPkg), CancelProcess, @@ -39,11 +38,11 @@ pub struct InstallAsyncHandlerInit { } impl Worker for InstallAsyncHandler { - type InitParams = InstallAsyncHandlerInit; + type Init = InstallAsyncHandlerInit; type Input = InstallAsyncHandlerMsg; type Output = PkgMsg; - fn init(params: Self::InitParams, _sender: relm4::ComponentSender) -> Self { + fn init(params: Self::Init, _sender: relm4::ComponentSender) -> Self { Self { process: None, work: None, diff --git a/src/ui/pkgpage.rs b/src/ui/pkgpage.rs index 8efebcd..f7b8d98 100644 --- a/src/ui/pkgpage.rs +++ b/src/ui/pkgpage.rs @@ -2,6 +2,7 @@ use adw::gio; use adw::prelude::*; use html2pango; use image::{imageops::FilterType, ImageFormat}; +use nix_data::config::configfile::NixDataConfig; use relm4::actions::RelmAction; use relm4::actions::RelmActionGroup; use relm4::gtk::pango; @@ -22,9 +23,7 @@ use std::{ }; use log::*; -use crate::parse::config::NscConfig; use crate::parse::packages::PkgMaintainer; -use crate::parse::packages::StrOrVec; use crate::ui::installworker::InstallAsyncHandlerMsg; use super::installworker::InstallAsyncHandler; @@ -36,7 +35,7 @@ use super::{screenshotfactory::ScreenshotItem, window::AppMsg}; #[tracker::track] #[derive(Debug)] pub struct PkgModel { - config: NscConfig, + config: NixDataConfig, name: String, pkg: String, pname: String, @@ -87,13 +86,13 @@ pub enum PkgAction { } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum Launch { GtkApp(String), TerminalApp(String), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum CarouselPage { First, Middle, @@ -107,7 +106,7 @@ pub enum InstallType { System, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct License { pub free: Option, pub fullname: String, @@ -126,7 +125,7 @@ pub struct PkgInitModel { pub description: Option, pub icon: Option, pub screenshots: Vec, - pub homepage: Option, + pub homepage: Option, pub licenses: Vec, pub platforms: Vec, pub maintainers: Vec, @@ -135,7 +134,7 @@ pub struct PkgInitModel { #[derive(Debug)] pub enum PkgMsg { - UpdateConfig(NscConfig), + UpdateConfig(NixDataConfig), UpdatePkgTypes(SystemPkgs, UserPkgs), Open(Box), LoadScreenshot(String, usize, String), @@ -168,7 +167,7 @@ pub enum PkgAsyncMsg { pub struct PkgPageInit { pub syspkgs: SystemPkgs, pub userpkgs: UserPkgs, - pub config: NscConfig, + pub config: NixDataConfig, } #[relm4::component(pub)] @@ -1123,22 +1122,23 @@ impl Component for PkgModel { self.description = Some(pango.strip_prefix('\n').unwrap_or(&pango).to_string()); } - if let Some(h) = pkgmodel.homepage { - match h { - StrOrVec::Single(h) => { - self.homepage = Some(h.to_string()); - } - StrOrVec::List(h) => { - if let Some(first) = h.get(0) { - self.homepage = Some(first.to_string()); - } else { - self.homepage = None; - } - } - } - } else { - self.homepage = None; - } + self.homepage = pkgmodel.homepage; + // if let Some(h) = pkgmodel.homepage { + // match h { + // StrOrVec::Single(h) => { + // self.homepage = Some(h.to_string()); + // } + // StrOrVec::List(h) => { + // if let Some(first) = h.get(0) { + // self.homepage = Some(first.to_string()); + // } else { + // self.homepage = None; + // } + // } + // } + // } else { + // self.homepage = None; + // } if pkgmodel.screenshots.len() <= 1 { self.carpage = CarouselPage::Single; @@ -1150,14 +1150,14 @@ impl Component for PkgModel { let mut scrn_guard = self.screenshots.guard(); scrn_guard.clear(); for _i in 0..pkgmodel.screenshots.len() { - scrn_guard.push_back(()) + scrn_guard.push_back(()); } } for (i, url) in pkgmodel.screenshots.into_iter().enumerate() { if let Ok(home) = env::var("HOME") { let cachedir = format!("{}/.cache/nix-software-center", home); - let sha = digest(&url); + let sha = digest(url.to_string()); let scrnpath = format!("{}/screenshots/{}", cachedir, sha); let pkg = self.pkg.clone(); @@ -1289,13 +1289,13 @@ impl Component for PkgModel { } } PkgMsg::Close => { - self.pkg = String::default(); - self.name = String::default(); - self.summary = None; - self.description = None; - self.icon = None; - let mut scrn_guard = self.screenshots.guard(); - scrn_guard.clear(); + // self.pkg = String::default(); + // self.name = String::default(); + // self.summary = None; + // self.description = None; + // self.icon = None; + // let mut scrn_guard = self.screenshots.guard(); + // scrn_guard.clear(); sender.output(AppMsg::FrontPage) } PkgMsg::InstallUser => { @@ -1391,10 +1391,11 @@ impl Component for PkgModel { self.installedsystempkgs.remove(&work.pkg); } }; - sender.output(AppMsg::UpdateUpdatePkgs); + // sender.output(AppMsg::UpdateUpdatePkgs); + // sender.output(AppMsg::UpdateInstalledPkgs); } } - sender.output(AppMsg::UpdatePkgs(None)); + sender.output(AppMsg::UpdateInstalledPkgs); if let Some(n) = &work.notify { match n { NotifyPage::Installed => { @@ -1556,29 +1557,7 @@ impl Component for PkgModel { } fn launchterm(cmd: &str) { - if which::which("kgx").is_ok() { - let _ = Command::new("kgx").arg("-e").arg(&cmd).spawn(); - } else if which::which("gnome-terminal").is_ok() { - let _ = Command::new("gnome-terminal").arg("--").arg(&cmd).spawn(); - } else if which::which("konsole").is_ok() { - let _ = Command::new("konsole").arg("-e").arg(&cmd).spawn(); - } else if which::which("mate-terminal").is_ok() { - let _ = Command::new("mate-terminal").arg("-e").arg(&cmd).spawn(); - } else if which::which("xfce4-terminal").is_ok() { - let _ = Command::new("xfce4-terminal").arg("-e").arg(&cmd).spawn(); - } else if which::which("tilix").is_ok() { - let _ = Command::new("tilix").arg("-e").arg(&cmd).spawn(); - } else if which::which("terminology").is_ok() { - let _ = Command::new("terminology").arg("-e").arg(&cmd).spawn(); - } else if which::which("alacritty").is_ok() { - let _ = Command::new("alacritty").arg("-e").arg(&cmd).spawn(); - } else if which::which("urxvt").is_ok() { - let _ = Command::new("urxvt").arg("-e").arg(&cmd).spawn(); - } else if which::which("xterm").is_ok() { - let _ = Command::new("xterm").arg("-e").arg(&cmd).spawn(); - } else { - error!("No terminal detected!") - } + let _ = Command::new("kgx").arg("-e").arg(&cmd).spawn(); } relm4::new_action_group!(ModeActionGroup, "mode"); diff --git a/src/ui/pkgtile.rs b/src/ui/pkgtile.rs index ef3e80d..bfed941 100644 --- a/src/ui/pkgtile.rs +++ b/src/ui/pkgtile.rs @@ -8,7 +8,7 @@ use crate::APPINFO; use super::window::AppMsg; -#[derive(Default, Debug, PartialEq)] +#[derive(Default, Debug, PartialEq, Eq)] pub struct PkgTile { pub name: String, pub pkg: String, @@ -32,7 +32,7 @@ impl FactoryComponent for PkgTile { type Output = PkgTileMsg; type Widgets = PkgTileWidgets; type ParentWidget = gtk::FlowBox; - type ParentMsg = AppMsg; + type ParentInput = AppMsg; view! { gtk::FlowBoxChild { @@ -171,7 +171,7 @@ impl FactoryComponent for PkgTile { } } - fn output_to_parent_msg(output: Self::Output) -> Option { + fn output_to_parent_input(output: Self::Output) -> Option { Some(match output { PkgTileMsg::Open(x) => AppMsg::OpenPkg(x), }) diff --git a/src/ui/preferencespage.rs b/src/ui/preferencespage.rs index c78215a..f95ddd6 100644 --- a/src/ui/preferencespage.rs +++ b/src/ui/preferencespage.rs @@ -1,9 +1,7 @@ use std::path::PathBuf; - -use crate::parse::config::NscConfig; - use super::window::AppMsg; use adw::prelude::*; +use nix_data::config::configfile::NixDataConfig; use relm4::*; use relm4_components::open_dialog::*; @@ -22,7 +20,7 @@ pub struct PreferencesPageModel { #[derive(Debug)] pub enum PreferencesPageMsg { - Show(NscConfig), + Show(NixDataConfig), Open, OpenFlake, SetConfigPath(Option), @@ -34,7 +32,7 @@ pub enum PreferencesPageMsg { #[relm4::component(pub)] impl SimpleComponent for PreferencesPageModel { - type InitParams = gtk::Window; + type Init = gtk::Window; type Input = PreferencesPageMsg; type Output = AppMsg; type Widgets = PreferencesPageWidgets; @@ -165,7 +163,7 @@ impl SimpleComponent for PreferencesPageModel { } @flakeentry, #[track(model.changed(PreferencesPageModel::flake()))] #[block_signal(flakeentry)] - set_text: &model.flakearg.as_ref().unwrap_or(&String::new()) + set_text: model.flakearg.as_ref().unwrap_or(&String::new()) } } @@ -174,21 +172,21 @@ impl SimpleComponent for PreferencesPageModel { } fn init( - parent_window: Self::InitParams, + parent_window: Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { let open_dialog = OpenDialog::builder() .transient_for_native(root) .launch(OpenDialogSettings::default()) - .forward(&sender.input, |response| match response { + .forward(sender.input_sender(), |response| match response { OpenDialogResponse::Accept(path) => PreferencesPageMsg::SetConfigPath(Some(path)), OpenDialogResponse::Cancel => PreferencesPageMsg::Ignore, }); let flake_file_dialog = OpenDialog::builder() .transient_for_native(root) .launch(OpenDialogSettings::default()) - .forward(&sender.input, |response| match response { + .forward(sender.input_sender(), |response| match response { OpenDialogResponse::Accept(path) => PreferencesPageMsg::SetFlakePath(Some(path)), OpenDialogResponse::Cancel => PreferencesPageMsg::Ignore, }); @@ -211,9 +209,9 @@ impl SimpleComponent for PreferencesPageModel { self.reset(); match msg { PreferencesPageMsg::Show(config) => { - self.configpath = config.systemconfig.as_ref().map(|x| PathBuf::from(x)); - self.set_flake(config.flake.as_ref().map(|x| PathBuf::from(x))); - self.set_flakearg(config.flakearg.clone()); + self.configpath = config.systemconfig.as_ref().map(PathBuf::from); + self.set_flake(config.flake.as_ref().map(PathBuf::from)); + self.set_flakearg(config.flakearg); self.hidden = false; } PreferencesPageMsg::Open => self.open_dialog.emit(OpenDialogMsg::Open), diff --git a/src/ui/screenshotfactory.rs b/src/ui/screenshotfactory.rs index 5f791a3..f653a30 100644 --- a/src/ui/screenshotfactory.rs +++ b/src/ui/screenshotfactory.rs @@ -3,7 +3,7 @@ use relm4::{factory::*, *}; use super::pkgpage::PkgMsg; -#[derive(Default, Debug, PartialEq)] +#[derive(Default, Debug, PartialEq, Eq)] pub struct ScreenshotItem { pub path: Option, pub error: bool, @@ -20,7 +20,7 @@ impl FactoryComponent for ScreenshotItem { type Output = ScreenshotItemMsg; type Widgets = PkgTileWidgets; type ParentWidget = adw::Carousel; - type ParentMsg = PkgMsg; + type ParentInput = PkgMsg; view! { gtk::Box { diff --git a/src/ui/searchpage.rs b/src/ui/searchpage.rs index 17de67f..6007d7e 100644 --- a/src/ui/searchpage.rs +++ b/src/ui/searchpage.rs @@ -25,7 +25,7 @@ pub enum SearchPageMsg { #[relm4::component(pub)] impl SimpleComponent for SearchPageModel { - type InitParams = (); + type Init = (); type Input = SearchPageMsg; type Output = AppMsg; type Widgets = SearchPageWidgets; @@ -53,12 +53,12 @@ impl SimpleComponent for SearchPageModel { } fn init( - (): Self::InitParams, + (): Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { let model = SearchPageModel { - searchitems: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input), + searchitems: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()), searchitemtracker: 0, tracker: 0, }; @@ -110,7 +110,7 @@ impl SimpleComponent for SearchPageModel { } } -#[derive(Default, Debug, PartialEq)] +#[derive(Default, Debug, PartialEq, Eq)] pub struct SearchItem { pub name: String, pub pkg: String, @@ -122,7 +122,7 @@ pub struct SearchItem { } #[tracker::track] -#[derive(Default, Debug, PartialEq)] +#[derive(Default, Debug, PartialEq, Eq)] pub struct SearchItemModel { pub item: SearchItem, } @@ -138,7 +138,7 @@ impl FactoryComponent for SearchItemModel { type Output = SearchItemMsg; type Widgets = SearchItemWidgets; type ParentWidget = adw::gtk::ListBox; - type ParentMsg = SearchPageMsg; + type ParentInput = SearchPageMsg; view! { adw::PreferencesRow { diff --git a/src/ui/updatedialog.rs b/src/ui/updatedialog.rs index 301ba5d..33639e8 100644 --- a/src/ui/updatedialog.rs +++ b/src/ui/updatedialog.rs @@ -21,7 +21,7 @@ pub enum UpdateDialogMsg { #[relm4::component(pub)] impl SimpleComponent for UpdateDialogModel { - type InitParams = gtk::Window; + type Init = gtk::Window; type Input = UpdateDialogMsg; type Output = UpdatePageMsg; type Widgets = UpdateDialogWidgets; @@ -99,7 +99,7 @@ impl SimpleComponent for UpdateDialogModel { } fn init( - parent_window: Self::InitParams, + parent_window: Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { diff --git a/src/ui/updatepage.rs b/src/ui/updatepage.rs index 35f420f..34c7b71 100644 --- a/src/ui/updatepage.rs +++ b/src/ui/updatepage.rs @@ -1,7 +1,8 @@ -use crate::{parse::{cache::channelver, config::NscConfig}, APPINFO}; +use crate::APPINFO; use super::{pkgpage::InstallType, window::*, updatedialog::{UpdateDialogModel, UpdateDialogMsg}, updateworker::{UpdateAsyncHandler, UpdateAsyncHandlerMsg, UpdateAsyncHandlerInit}}; use adw::prelude::*; +use nix_data::config::configfile::NixDataConfig; use relm4::{factory::*, gtk::pango, *}; use std::{path::Path, convert::identity}; use log::*; @@ -18,7 +19,7 @@ pub struct UpdatePageModel { updatedialog: Controller, #[tracker::no_eq] updateworker: WorkerController, - config: NscConfig, + config: NixDataConfig, systype: SystemPkgs, usertype: UserPkgs, updatetracker: u8, @@ -26,7 +27,7 @@ pub struct UpdatePageModel { #[derive(Debug)] pub enum UpdatePageMsg { - UpdateConfig(NscConfig), + UpdateConfig(NixDataConfig), UpdatePkgTypes(SystemPkgs, UserPkgs), Update(Vec, Vec), OpenRow(usize, InstallType), @@ -45,12 +46,12 @@ pub struct UpdatePageInit { pub window: gtk::Window, pub systype: SystemPkgs, pub usertype: UserPkgs, - pub config: NscConfig, + pub config: NixDataConfig, } #[relm4::component(pub)] impl SimpleComponent for UpdatePageModel { - type InitParams = UpdatePageInit; + type Init = UpdatePageInit; type Input = UpdatePageMsg; type Output = AppMsg; type Widgets = UpdatePageWidgets; @@ -277,7 +278,7 @@ impl SimpleComponent for UpdatePageModel { } fn init( - initparams: Self::InitParams, + initparams: Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { @@ -292,8 +293,8 @@ impl SimpleComponent for UpdatePageModel { updateworker.emit(UpdateAsyncHandlerMsg::UpdateConfig(config.clone())); let model = UpdatePageModel { - updateuserlist: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input), - updatesystemlist: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input), + updateuserlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()), + updatesystemlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()), channelupdate: None, updatetracker: 0, updatedialog, @@ -320,15 +321,21 @@ impl SimpleComponent for UpdatePageModel { self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateConfig(self.config.clone())); } UpdatePageMsg::UpdatePkgTypes(systype, usertype) => { - self.systype = systype.clone(); - self.usertype = usertype.clone(); + self.systype = systype; + self.usertype = usertype; self.updateworker.emit(UpdateAsyncHandlerMsg::UpdatePkgTypes(self.systype.clone(), self.usertype.clone())); } UpdatePageMsg::Update(updateuserlist, updatesystemlist) => { info!("UpdatePageMsg::Update"); debug!("UPDATEUSERLIST: {:?}", updateuserlist); debug!("UPDATESYSTEMLIST: {:?}", updatesystemlist); - self.channelupdate = channelver().unwrap_or(None); + self.channelupdate = match nix_data::cache::channel::uptodate() { + Ok(x) => { + x + }, + Err(_) => None, + }; + debug!("CHANNELUPDATE: {:?}", self.channelupdate); self.update_updatetracker(|_| ()); let mut updateuserlist_guard = self.updateuserlist.guard(); updateuserlist_guard.clear(); @@ -384,7 +391,7 @@ impl SimpleComponent for UpdatePageModel { self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateAll); } UpdatePageMsg::DoneWorking => { - sender.output(AppMsg::ReloadUpdate); + sender.output(AppMsg::UpdateInstalledPkgs); } UpdatePageMsg::DoneLoading => { self.updatedialog.emit(UpdateDialogMsg::Done); @@ -396,7 +403,7 @@ impl SimpleComponent for UpdatePageModel { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct UpdateItem { pub name: String, pub pkg: Option, @@ -408,7 +415,7 @@ pub struct UpdateItem { pub verto: Option, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct UpdateItemModel { item: UpdateItem, } @@ -424,7 +431,7 @@ impl FactoryComponent for UpdateItemModel { type Output = UpdateItemMsg; type Widgets = UpdateItemWidgets; type ParentWidget = adw::gtk::ListBox; - type ParentMsg = UpdatePageMsg; + type ParentInput = UpdatePageMsg; view! { adw::PreferencesRow { diff --git a/src/ui/updateworker.rs b/src/ui/updateworker.rs index f90b347..5dc7f1b 100644 --- a/src/ui/updateworker.rs +++ b/src/ui/updateworker.rs @@ -1,10 +1,9 @@ +use nix_data::config::configfile::NixDataConfig; use relm4::*; use std::{error::Error, path::Path, process::Stdio}; use tokio::io::AsyncBufReadExt; use log::*; -use crate::parse::config::NscConfig; - use super::{ updatepage::UpdatePageMsg, window::{SystemPkgs, UserPkgs}, @@ -23,7 +22,7 @@ pub struct UpdateAsyncHandler { #[derive(Debug)] pub enum UpdateAsyncHandlerMsg { - UpdateConfig(NscConfig), + UpdateConfig(NixDataConfig), UpdatePkgTypes(SystemPkgs, UserPkgs), UpdateChannels, @@ -47,11 +46,11 @@ pub struct UpdateAsyncHandlerInit { } impl Worker for UpdateAsyncHandler { - type InitParams = UpdateAsyncHandlerInit; + type Init = UpdateAsyncHandlerInit; type Input = UpdateAsyncHandlerMsg; type Output = UpdatePageMsg; - fn init(params: Self::InitParams, _sender: relm4::ComponentSender) -> Self { + fn init(params: Self::Init, _sender: relm4::ComponentSender) -> Self { Self { process: None, systemconfig: None, diff --git a/src/ui/welcome.rs b/src/ui/welcome.rs index 19ec4e0..9cd0904 100644 --- a/src/ui/welcome.rs +++ b/src/ui/welcome.rs @@ -2,11 +2,10 @@ use std::path::{PathBuf, Path}; use adw::prelude::*; use log::info; +use nix_data::config::configfile::NixDataConfig; use relm4::*; use relm4_components::open_dialog::*; -use crate::parse::config::NscConfig; - use super::window::AppMsg; #[tracker::track] @@ -36,7 +35,7 @@ pub enum WelcomeMsg { #[relm4::component(pub)] impl SimpleComponent for WelcomeModel { - type InitParams = gtk::Window; + type Init = gtk::Window; type Input = WelcomeMsg; type Output = AppMsg; type Widgets = WelcomeWidgets; @@ -176,7 +175,7 @@ impl SimpleComponent for WelcomeModel { } fn init( - parent_window: Self::InitParams, + parent_window: Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { @@ -184,7 +183,7 @@ impl SimpleComponent for WelcomeModel { let conf_dialog = OpenDialog::builder() .transient_for_native(root) .launch(OpenDialogSettings::default()) - .forward(&sender.input, |response| match response { + .forward(sender.input_sender(), |response| match response { OpenDialogResponse::Accept(path) => WelcomeMsg::UpdateConfPath(path), OpenDialogResponse::Cancel => WelcomeMsg::Ignore, }); @@ -193,7 +192,7 @@ impl SimpleComponent for WelcomeModel { let flake_dialog = OpenDialog::builder() .transient_for_native(root) .launch(OpenDialogSettings::default()) - .forward(&sender.input, |response| match response { + .forward(sender.input_sender(), |response| match response { OpenDialogResponse::Accept(path) => WelcomeMsg::UpdateFlakePath(path), OpenDialogResponse::Cancel => WelcomeMsg::Ignore, }); @@ -222,7 +221,7 @@ impl SimpleComponent for WelcomeModel { self.hidden = false; } WelcomeMsg::Close => { - let config = NscConfig { + let config = NixDataConfig { systemconfig: self.confpath.as_ref().map(|x| x.to_string_lossy().to_string()), flake: self.flakepath.as_ref().map(|x| x.to_string_lossy().to_string()), flakearg: None, diff --git a/src/ui/window.rs b/src/ui/window.rs index 2f4b0a1..74bda87 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -1,18 +1,40 @@ -use std::{collections::{HashMap, HashSet}, convert::identity, error::Error, process::Command, fs, io, path::{PathBuf, Path}}; -use ijson::IValue; -use relm4::{actions::*, factory::*, *}; +use crate::{ + config, + parse::{ + config::{editconfig, getconfig}, + packages::{AppData, LicenseEnum, PkgMaintainer, Platform}, + }, + ui::{installedpage::InstalledItem, pkgpage::PkgPageInit, welcome::WelcomeMsg}, + APPINFO, +}; use adw::prelude::*; -use edit_distance; -use serde_json::Value; -use spdx::Expression; -use crate::{parse::{packages::{Package, LicenseEnum, Platform, PkgMaintainer}, cache::{uptodatelegacy, uptodateflake}, config::{NscConfig, getconfig, editconfig}}, ui::{installedpage::InstalledItem, pkgpage::PkgPageInit, welcome::WelcomeMsg}, APPINFO, config}; use log::*; +use nix_data::config::configfile::NixDataConfig; +use relm4::{actions::*, factory::*, *}; +use spdx::Expression; +use sqlx::{QueryBuilder, Sqlite, SqlitePool}; +use std::{ + collections::{HashMap, HashSet}, + convert::identity, + fs, + path::Path, +}; use super::{ - categories::{PkgGroup, PkgCategory}, + about::{AboutPageModel, AboutPageMsg}, + categories::{PkgCategory, PkgGroup}, + categorypage::{CategoryPageModel, CategoryPageMsg}, + categorytile::CategoryTile, + installedpage::{InstalledPageModel, InstalledPageMsg}, + pkgpage::{self, InstallType, PkgInitModel, PkgModel, PkgMsg, WorkPkg}, pkgtile::PkgTile, - pkgpage::{PkgModel, PkgMsg, PkgInitModel, self, InstallType, WorkPkg}, - windowloading::{LoadErrorModel, LoadErrorMsg, WindowAsyncHandler, WindowAsyncHandlerMsg, CacheReturn}, searchpage::{SearchPageModel, SearchPageMsg, SearchItem}, installedpage::{InstalledPageModel, InstalledPageMsg}, updatepage::{UpdatePageModel, UpdatePageMsg, UpdateItem, UpdatePageInit}, about::{AboutPageModel, AboutPageMsg}, preferencespage::{PreferencesPageModel, PreferencesPageMsg}, categorypage::{CategoryPageModel, CategoryPageMsg}, categorytile::CategoryTile, welcome::WelcomeModel, + preferencespage::{PreferencesPageModel, PreferencesPageMsg}, + searchpage::{SearchItem, SearchPageModel, SearchPageMsg}, + updatepage::{UpdateItem, UpdatePageInit, UpdatePageModel, UpdatePageMsg}, + welcome::WelcomeModel, + windowloading::{ + LoadErrorModel, LoadErrorMsg, WindowAsyncHandler, WindowAsyncHandlerMsg, + }, }; #[derive(PartialEq)] @@ -27,25 +49,23 @@ enum MainPage { CategoryPage, } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum SystemPkgs { Legacy, Flake, None, } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum UserPkgs { Env, Profile, } - #[tracker::track] pub struct AppModel { - application: adw::Application, mainwindow: adw::ApplicationWindow, - config: NscConfig, + config: NixDataConfig, #[tracker::no_eq] windowloading: WorkerController, #[tracker::no_eq] @@ -53,11 +73,18 @@ pub struct AppModel { busy: bool, page: Page, mainpage: MainPage, + // #[tracker::no_eq] + // pkgs: HashMap, + // syspkgs: HashMap, + // profilepkgs: Option>, + // pkgitems: HashMap, #[tracker::no_eq] - pkgs: HashMap, - syspkgs: HashMap, - profilepkgs: Option>, - pkgitems: HashMap, + pkgdb: String, + #[tracker::no_eq] + nixpkgsdb: Option, + #[tracker::no_eq] + systemdb: Option, + appdata: HashMap, installeduserpkgs: HashMap, installedsystempkgs: HashSet, syspkgtype: SystemPkgs, @@ -91,18 +118,25 @@ pub enum AppMsg { UpdateSysconfig(Option), UpdateFlake(Option, Option), TryLoad, - ReloadUpdate, - LoadConfig(NscConfig), + LoadConfig(NixDataConfig), Close, LoadError(String, String), - Initialize(HashMap, Vec, HashMap, HashMap>, HashMap>, Option> /* profile pkgs */), - ReloadUpdateItems(HashMap, HashMap), + Initialize( + String, + Option, + Option, + HashMap, + Vec, + HashMap>, + HashMap>, + ), OpenPkg(String), FrontPage, FrontFrontPage, - UpdatePkgs(Option>), + // UpdatePkgs(Option>), UpdateInstalledPkgs, - UpdateUpdatePkgs, + UpdateInstalledPage, + // UpdateUpdatePkgs, UpdateCategoryPkgs, SetSearch(bool), SetVsBar(bool), @@ -113,10 +147,12 @@ pub enum AppMsg { AddInstalledToWorkQueue(WorkPkg), RemoveInstalledBusy(WorkPkg), OpenCategoryPage(PkgCategory), - LoadCategory(PkgCategory) + LoadCategory(PkgCategory), + + UpdateRecPkgs(Vec), } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct PkgItem { pkg: String, pname: String, @@ -128,12 +164,15 @@ pub struct PkgItem { #[derive(Debug)] pub enum AppAsyncMsg { - Search(String, Vec) + Search(String, Vec), + UpdateRecPkgs(Vec), + UpdateInstalledPkgs(HashSet, HashMap), + LoadCategory(PkgCategory, Vec, Vec), } #[relm4::component(pub)] impl Component for AppModel { - type Init = adw::Application; + type Init = (); type Input = AppMsg; type Output = (); type Widgets = AppWidgets; @@ -202,7 +241,7 @@ impl Component for AppModel { connect_toggled[sender] => move |x| { sender.input(AppMsg::SetSearch(x.is_active())) } @searchtoggle - + }, #[name(viewswitchertitle)] #[wrap(Some)] @@ -344,12 +383,12 @@ impl Component for AppModel { } } - fn init( - application: Self::Init, + #[tokio::main] + async fn init( + _application: Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { - let (config, welcome) = if let Some(config) = getconfig() { debug!("Got config: {:?}", config); let mut out = false; @@ -363,33 +402,31 @@ impl Component for AppModel { if !Path::new(&flakepath).exists() { warn!("Invalid flake path: {}", flakepath); out = true - } else { - out = false } - } else { - out = false } (config, out) } else { // Show welcome page debug!("No config found"); - (NscConfig { - systemconfig: None, - flake: None, - flakearg: None, - }, true) + ( + NixDataConfig { + systemconfig: None, + flake: None, + flakearg: None, + }, + true, + ) }; let userpkgtype = if let Ok(h) = std::env::var("HOME") { - if Path::new(&format!("{}/.nix-profile/manifest.json", h)).exists() - || !Path::new("/nix/var/nix/profiles/per-user/root/channels/nixos").exists() - || !Path::new(&format!("{}/.nix-profile/manifest.nix", h)).exists() - || if let Ok(m) = fs::read_to_string(&format!("{}/.nix-profile/manifest.nix", h)) { - m == "[ ]" - } else { - false - } + || !Path::new("/nix/var/nix/profiles/per-user/root/channels/nixos").exists() + || !Path::new(&format!("{}/.nix-profile/manifest.nix", h)).exists() + || if let Ok(m) = fs::read_to_string(&format!("{}/.nix-profile/manifest.nix", h)) { + m == "[ ]" + } else { + false + } { UserPkgs::Profile } else { @@ -404,7 +441,9 @@ impl Component for AppModel { } else { match fs::read_to_string("/run/current-system/nixos-version") { Ok(s) => { - if !Path::new("/nix/var/nix/profiles/per-user/root/channels/nixos").exists() || config.flake.is_some() { + if !Path::new("/nix/var/nix/profiles/per-user/root/channels/nixos").exists() + || config.flake.is_some() + { SystemPkgs::Flake } else if let Some(last) = s.split('.').last() { if last.len() == 7 || last == "dirty" || last == "git" { @@ -423,8 +462,6 @@ impl Component for AppModel { debug!("userpkgtype: {:?}", userpkgtype); debug!("syspkgtype: {:?}", syspkgtype); - - let windowloading = WindowAsyncHandler::builder() .detach_worker(()) .forward(sender.input_sender(), identity); @@ -448,12 +485,16 @@ impl Component for AppModel { .launch((syspkgtype.clone(), userpkgtype.clone())) .forward(sender.input_sender(), identity); let updatepage = UpdatePageModel::builder() - .launch(UpdatePageInit { window: root.clone().upcast(), systype: syspkgtype.clone(), usertype: userpkgtype.clone(), config: config.clone() }) + .launch(UpdatePageInit { + window: root.clone().upcast(), + systype: syspkgtype.clone(), + usertype: userpkgtype.clone(), + config: config.clone(), + }) .forward(sender.input_sender(), identity); let viewstack = adw::ViewStack::new(); let model = AppModel { - application, mainwindow: root.clone(), config, windowloading, @@ -461,18 +502,18 @@ impl Component for AppModel { busy: true, page: Page::FrontPage, mainpage: MainPage::FrontPage, - pkgs: HashMap::new(), - syspkgs: HashMap::new(), - pkgitems: HashMap::new(), + pkgdb: String::new(), + nixpkgsdb: None, + systemdb: None, + appdata: HashMap::new(), installeduserpkgs: HashMap::new(), installedsystempkgs: HashSet::new(), - profilepkgs: None, syspkgtype, userpkgtype, categoryrec: HashMap::new(), categoryall: HashMap::new(), - recommendedapps: FactoryVecDeque::new(gtk::FlowBox::new(), &sender.input), - categories: FactoryVecDeque::new(gtk::FlowBox::new(), &sender.input), + recommendedapps: FactoryVecDeque::new(gtk::FlowBox::new(), sender.input_sender()), + categories: FactoryVecDeque::new(gtk::FlowBox::new(), sender.input_sender()), pkgpage, searchpage, categorypage, @@ -493,7 +534,11 @@ impl Component for AppModel { .forward(sender.input_sender(), identity); welcomepage.emit(WelcomeMsg::Show); } else { - model.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Init, model.syspkgtype.clone(), model.userpkgtype.clone(), model.config.clone())); + model.windowloading.emit(WindowAsyncHandlerMsg::CheckCache( + model.syspkgtype.clone(), + model.userpkgtype.clone(), + model.config.clone(), + )); } let recbox = model.recommendedapps.widget(); let categorybox = model.categories.widget(); @@ -542,34 +587,68 @@ impl Component for AppModel { ComponentParts { model, widgets } } - fn update(&mut self, msg: Self::Input, sender: ComponentSender) { + #[tokio::main] + async fn update(&mut self, msg: Self::Input, sender: ComponentSender) { self.reset(); match msg { AppMsg::TryLoad => { self.busy = true; - self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Init, self.syspkgtype.clone(), self.userpkgtype.clone(), self.config.clone())); - } - AppMsg::ReloadUpdate => { - self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Update, self.syspkgtype.clone(), self.userpkgtype.clone(), self.config.clone())); + self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache( + self.syspkgtype.clone(), + self.userpkgtype.clone(), + self.config.clone(), + )); } AppMsg::LoadConfig(config) => { + info!("AppMsg::LoadConfig"); self.config = config; if let Err(e) = editconfig(self.config.clone()) { warn!("Error editing config: {}", e); } + + + self.syspkgtype = if self.config.systemconfig.is_none() { + SystemPkgs::None + } else { + match fs::read_to_string("/run/current-system/nixos-version") { + Ok(s) => { + if !Path::new("/nix/var/nix/profiles/per-user/root/channels/nixos").exists() + || self.config.flake.is_some() + { + SystemPkgs::Flake + } else if let Some(last) = s.split('.').last() { + if last.len() == 7 || last == "dirty" || last == "git" { + SystemPkgs::Flake + } else { + SystemPkgs::Legacy + } + } else { + SystemPkgs::Legacy + } + } + Err(_) => SystemPkgs::None + } + }; + self.pkgpage.emit(PkgMsg::UpdatePkgTypes(self.syspkgtype.clone(), self.userpkgtype.clone())); self.pkgpage.emit(PkgMsg::UpdateConfig(self.config.clone())); - self.updatepage.emit(UpdatePageMsg::UpdateConfig(self.config.clone())); - self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Init, self.syspkgtype.clone(), self.userpkgtype.clone(), self.config.clone())); + self.updatepage.emit(UpdatePageMsg::UpdatePkgTypes(self.syspkgtype.clone(), self.userpkgtype.clone())); + self.updatepage + .emit(UpdatePageMsg::UpdateConfig(self.config.clone())); + self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache( + self.syspkgtype.clone(), + self.userpkgtype.clone(), + self.config.clone(), + )); } AppMsg::Close => { - self.application.quit(); + relm4::main_application().quit(); } AppMsg::LoadError(msg, msg2) => { self.busy = false; self.loaderrordialog.emit(LoadErrorMsg::Show(msg, msg2)); } AppMsg::UpdateSysconfig(systemconfig) => { - self.config = NscConfig { + self.config = NixDataConfig { systemconfig: systemconfig.clone(), flake: self.config.flake.clone(), flakearg: self.config.flakearg.clone(), @@ -591,15 +670,23 @@ impl Component for AppModel { } self.pkgpage.emit(PkgMsg::UpdateConfig(self.config.clone())); - self.updatepage.emit(UpdatePageMsg::UpdateConfig(self.config.clone())); - self.pkgpage.emit(PkgMsg::UpdatePkgTypes(self.syspkgtype.clone(), self.userpkgtype.clone())); - self.updatepage.emit(UpdatePageMsg::UpdatePkgTypes(self.syspkgtype.clone(), self.userpkgtype.clone())); - self.installedpage.emit(InstalledPageMsg::UpdatePkgTypes(self.syspkgtype.clone(), self.userpkgtype.clone())); - sender.input(AppMsg::UpdatePkgs(None)); - + self.updatepage + .emit(UpdatePageMsg::UpdateConfig(self.config.clone())); + self.pkgpage.emit(PkgMsg::UpdatePkgTypes( + self.syspkgtype.clone(), + self.userpkgtype.clone(), + )); + self.updatepage.emit(UpdatePageMsg::UpdatePkgTypes( + self.syspkgtype.clone(), + self.userpkgtype.clone(), + )); + self.installedpage.emit(InstalledPageMsg::UpdatePkgTypes( + self.syspkgtype.clone(), + self.userpkgtype.clone(), + )); } AppMsg::UpdateFlake(flake, flakearg) => { - self.config = NscConfig { + self.config = NixDataConfig { systemconfig: self.config.systemconfig.clone(), flake: flake.clone(), flakearg, @@ -615,53 +702,43 @@ impl Component for AppModel { } self.pkgpage.emit(PkgMsg::UpdateConfig(self.config.clone())); - self.updatepage.emit(UpdatePageMsg::UpdateConfig(self.config.clone())); - self.pkgpage.emit(PkgMsg::UpdatePkgTypes(self.syspkgtype.clone(), self.userpkgtype.clone())); - self.updatepage.emit(UpdatePageMsg::UpdatePkgTypes(self.syspkgtype.clone(), self.userpkgtype.clone())); - self.installedpage.emit(InstalledPageMsg::UpdatePkgTypes(self.syspkgtype.clone(), self.userpkgtype.clone())); + self.updatepage + .emit(UpdatePageMsg::UpdateConfig(self.config.clone())); + self.pkgpage.emit(PkgMsg::UpdatePkgTypes( + self.syspkgtype.clone(), + self.userpkgtype.clone(), + )); + self.updatepage.emit(UpdatePageMsg::UpdatePkgTypes( + self.syspkgtype.clone(), + self.userpkgtype.clone(), + )); + self.installedpage.emit(InstalledPageMsg::UpdatePkgTypes( + self.syspkgtype.clone(), + self.userpkgtype.clone(), + )); } - AppMsg::Initialize(pkgs, recommendedapps, syspkgs, categoryrec, categoryall, profilepkgs) => { - self.syspkgs = syspkgs; - self.profilepkgs = profilepkgs; + AppMsg::Initialize( + pkgdb, + nixpkgsdb, + systemdb, + appdata, + recommendedapps, + categoryrec, + categoryall, + ) => { + info!("AppMsg::Initialize"); + self.pkgdb = pkgdb; + self.nixpkgsdb = nixpkgsdb; + self.systemdb = systemdb; + self.appdata = appdata; self.categoryrec = categoryrec; self.categoryall = categoryall; - let mut pkgitems = HashMap::new(); - for (pkg, pkgdata) in &pkgs { - let pname = pkgdata.pname.to_string(); - let mut name = pkgdata.pname.to_string(); - let version = pkgdata.version.to_string(); - let mut icon = None; - let mut summary = pkgdata.meta.description.as_ref().map(|x| x.to_string()); - if let Some(appdata) = &pkgdata.appdata { - if let Some(i) = &appdata.icon { - if let Some(mut iconvec) = i.cached.clone() { - iconvec.sort_by(|a, b| a.height.cmp(&b.height)); - icon = Some(iconvec[0].name.clone()); - } - } - if let Some(s) = &appdata.summary { - summary = Some(s.get("C").unwrap_or(&summary.unwrap_or_default()).to_string()); - } - if let Some(n) = &appdata.name { - name = n.get("C").unwrap_or(&name).to_string(); - } - } - pkgitems.insert(pkg.to_string(), PkgItem { - pkg: pkg.to_string(), - pname, - name, - version, - icon, - summary, - }); - } - self.pkgitems = pkgitems; + self.page = Page::FrontPage; self.pkgpage.emit(PkgMsg::UpdateConfig(self.config.clone())); - self.updatepage.emit(UpdatePageMsg::UpdateConfig(self.config.clone())); - self.pkgs = pkgs; - sender.input(AppMsg::UpdatePkgs(Some(recommendedapps))); - + self.updatepage + .emit(UpdatePageMsg::UpdateConfig(self.config.clone())); + sender.input(AppMsg::UpdateRecPkgs(recommendedapps)); let mut cat_guard = self.categories.guard(); for c in vec![ PkgCategory::Audio, @@ -676,233 +753,356 @@ impl Component for AppModel { cat_guard.drop(); self.busy = false; } - AppMsg::ReloadUpdateItems(pkgs, syspkgs) => { - self.syspkgs = syspkgs; - let mut pkgitems = HashMap::new(); - for (pkg, pkgdata) in &pkgs { - let pname = pkgdata.pname.to_string(); - let mut name = pkgdata.pname.to_string(); - let version = pkgdata.version.to_string(); - let mut icon = None; - let mut summary = pkgdata.meta.description.as_ref().map(|x| x.to_string()); - if let Some(appdata) = &pkgdata.appdata { - if let Some(i) = &appdata.icon { - if let Some(mut iconvec) = i.cached.clone() { - iconvec.sort_by(|a, b| a.height.cmp(&b.height)); - icon = Some(iconvec[0].name.clone()); + AppMsg::UpdateRecPkgs(pkgs) => { + info!("AppMsg::UpdateRecPkgs"); + let appdata: HashMap = self + .appdata + .iter() + .filter_map(|(k, v)| { + if pkgs.contains(k) { + Some((k.to_string(), v.clone())) + } else { + None + } + }) + .collect(); + let installeduser = self.installeduserpkgs.clone(); + let installedsystem = self.installedsystempkgs.clone(); + let poolref = self.pkgdb.clone(); + sender.oneshot_command(async move { + let mut pkgtiles = vec![]; + if let Ok(pool) = &SqlitePool::connect(&format!("sqlite://{}", poolref)).await { + for pkg in pkgs { + if let Some(data) = appdata.get(&pkg) { + let pname: (String,) = + sqlx::query_as("SELECT pname FROM pkgs WHERE attribute = $1") + .bind(&pkg) + .fetch_one(pool) + .await + .unwrap(); + pkgtiles.push(PkgTile { + pkg: pkg.to_string(), + name: if let Some(name) = &data.name { + name.get("C").unwrap_or(&pname.0).to_string() + } else { + pname.0.to_string() + }, + pname: pname.0, + icon: data + .icon + .as_ref() + .and_then(|x| x.cached.as_ref()) + .map(|x| x[0].name.clone()), + summary: data + .summary + .as_ref() + .and_then(|x| x.get("C")) + .map(|x| x.to_string()) + .unwrap_or_default(), + installeduser: installeduser.contains_key(&pkg), + installedsystem: installedsystem.contains(&pkg), + }) } } - if let Some(s) = &appdata.summary { - summary = Some(s.get("C").unwrap_or(&summary.unwrap_or_default()).to_string()); - } - if let Some(n) = &appdata.name { - name = n.get("C").unwrap_or(&name).to_string(); - } } - pkgitems.insert(pkg.to_string(), PkgItem { - pkg: pkg.to_string(), - pname, - name, - version, - icon, - summary, - }); - } - self.pkgitems = pkgitems; - sender.input(AppMsg::UpdatePkgs(None)); - self.updatepage.emit(UpdatePageMsg::DoneLoading); + AppAsyncMsg::UpdateRecPkgs(pkgtiles) + }); } AppMsg::OpenPkg(pkg) => { - if let Some(input) = self.pkgs.get(&pkg) { - let mut name = input.pname.to_string(); - let mut summary = input.meta.description.as_ref().map(|x| x.to_string()); - let mut description = input.meta.longdescription.as_ref().map(|x| x.to_string()); - let mut icon = None; - let mut screenshots = vec![]; - let mut licenses = vec![]; - let mut platforms = vec![]; - let mut maintainers = vec![]; - let mut launchable = None; + info!("AppMsg::OpenPkg {}", pkg); + if let Ok(pool) = &SqlitePool::connect(&format!("sqlite://{}", self.pkgdb)).await { + let pkgdata: Result< + ( + String, + String, + String, + String, + String, + String, + String, + String, + ), + _, + > = sqlx::query_as( + r#" +SELECT pname, system, description, longdescription, homepage, license, platforms, maintainers +FROM pkgs JOIN meta ON (pkgs.attribute = meta.attribute) WHERE pkgs.attribute = $1 + "#, + ) + .bind(&pkg) + .fetch_one(pool) + .await; - fn addlicense(pkglicense: &LicenseEnum, licenses: &mut Vec) { - match pkglicense { - LicenseEnum::Single(l) => { - if let Some(n) = &l.fullname { - let parsed = if let Some(id) = &l.spdxid { - if let Ok(Some(license)) = Expression::parse(id).map(|p| p.requirements().map(|er| er.req.license.id()).collect::>()[0]) { + if let Ok(( + pname, + system, + description, + longdescription, + homepage, + licensejson, + platformsjson, + maintainersjson, + )) = pkgdata + { + let mut name = pname.to_string(); + let mut summary = if description.is_empty() { + None + } else { + Some(description) + }; + let mut description = if longdescription.is_empty() { + None + } else { + Some(longdescription) + }; + let mut icon = None; + let mut screenshots = vec![]; + let mut licenses = vec![]; + let mut platforms = vec![]; + let mut maintainers = vec![]; + let mut launchable = None; + + if let Some(data) = self.appdata.get(&pkg) { + if let Some(n) = &data.name { + if let Some(n) = n.get("C") { + name = n.to_string(); + } + } + if let Some(s) = &data.summary { + if let Some(s) = s.get("C") { + summary = Some(s.to_string()); + } + } + if let Some(d) = &data.description { + if let Some(d) = d.get("C") { + description = Some(d.to_string()); + } + } + if let Some(i) = &data.icon { + if let Some(mut i) = i.cached.clone() { + i.sort_by(|x, y| x.height.cmp(&y.height)); + if let Some(i) = i.last() { + icon = Some(format!( + "{}/icons/nixos/{}x{}/{}", + APPINFO, i.width, i.height, i.name + )); + } + } + } + if let Some(s) = &data.screenshots { + for s in s { + if let Some(u) = &s.sourceimage { + if !screenshots.contains(&u.url) { + if s.default == Some(true) { + screenshots.insert(0, u.url.clone()); + } else { + screenshots.push(u.url.clone()); + } + } else if s.default == Some(true) { + if let Some(index) = + screenshots.iter().position(|x| *x == u.url) + { + screenshots.remove(index); + screenshots.insert(0, u.url.clone()); + } + } + } + } + } + if let Some(l) = &data.launchable { + if let Some(d) = l.desktopid.get(0) { + launchable = Some(d.to_string()); + } + } + } + + fn addlicense( + pkglicense: &LicenseEnum, + licenses: &mut Vec, + ) { + match pkglicense { + LicenseEnum::Single(l) => { + if let Some(n) = &l.fullname { + let parsed = if let Some(id) = &l.spdxid { + if let Ok(Some(license)) = + Expression::parse(id).map(|p| { + p.requirements() + .map(|er| er.req.license.id()) + .collect::>()[0] + }) + { + Some(license) + } else { + None + } + } else if let Ok(Some(license)) = + Expression::parse(n).map(|p| { + p.requirements() + .map(|er| er.req.license.id()) + .collect::>()[0] + }) + { Some(license) } else { None - } - } else if let Ok(Some(license)) = Expression::parse(n).map(|p| p.requirements().map(|er| er.req.license.id()).collect::>()[0]) { - Some(license) - } else { - None - }; - licenses.push(pkgpage::License { - free: if let Some(f) = l.free { Some(f) } else { parsed.map(|p| p.is_osi_approved() || p.is_fsf_free_libre() )}, - fullname: n.to_string(), - spdxid: l.spdxid.clone().map(|x| x.to_string()), - url: if let Some(u) = &l.url { Some(u.to_string()) } else { parsed.map(|p| format!("https://spdx.org/licenses/{}.html", p.name))}, - }) - } else if let Some(s) = &l.spdxid { - if let Ok(Some(license)) = Expression::parse(s).map(|p| p.requirements().map(|er| er.req.license.id()).collect::>()[0]) { + }; licenses.push(pkgpage::License { - free: Some(license.is_osi_approved() || license.is_fsf_free_libre() || l.free.unwrap_or(false)), + free: if let Some(f) = l.free { + Some(f) + } else { + parsed.map(|p| { + p.is_osi_approved() || p.is_fsf_free_libre() + }) + }, + fullname: n.to_string(), + spdxid: l.spdxid.clone(), + url: if let Some(u) = &l.url { + Some(u.to_string()) + } else { + parsed.map(|p| { + format!( + "https://spdx.org/licenses/{}.html", + p.name + ) + }) + }, + }) + } else if let Some(s) = &l.spdxid { + if let Ok(Some(license)) = Expression::parse(s).map(|p| { + p.requirements() + .map(|er| er.req.license.id()) + .collect::>()[0] + }) { + licenses.push(pkgpage::License { + free: Some( + license.is_osi_approved() + || license.is_fsf_free_libre() + || l.free.unwrap_or(false), + ), + fullname: license.full_name.to_string(), + spdxid: Some(license.name.to_string()), + url: if l.url.is_some() { + l.url.clone() + } else { + Some(format!( + "https://spdx.org/licenses/{}.html", + license.name + )) + }, + }) + } + } + } + LicenseEnum::List(lst) => { + for l in lst { + addlicense(&LicenseEnum::Single(l.clone()), licenses); + } + } + LicenseEnum::SingleStr(s) => { + if let Ok(Some(license)) = Expression::parse(s).map(|p| { + p.requirements() + .map(|er| er.req.license.id()) + .collect::>()[0] + }) { + licenses.push(pkgpage::License { + free: Some( + license.is_osi_approved() + || license.is_fsf_free_libre(), + ), fullname: license.full_name.to_string(), spdxid: Some(license.name.to_string()), - url: if l.url.is_some() { - l.url.clone().map(|x| x.to_string()) - } else { - Some(format!("https://spdx.org/licenses/{}.html", license.name)) - }, + url: Some(format!( + "https://spdx.org/licenses/{}.html", + license.name + )), }) } } - }, - LicenseEnum::List(lst) => { - for l in lst { - addlicense(&LicenseEnum::Single(l.clone()), licenses); + LicenseEnum::VecStr(lst) => { + for s in lst { + addlicense(&LicenseEnum::SingleStr(s.clone()), licenses); + } } - }, - LicenseEnum::SingleStr(s) => { - if let Ok(Some(license)) = Expression::parse(s).map(|p| p.requirements().map(|er| er.req.license.id()).collect::>()[0]) { - licenses.push(pkgpage::License { - free: Some(license.is_osi_approved() || license.is_fsf_free_libre()), - fullname: license.full_name.to_string(), - spdxid: Some(license.name.to_string()), - url: Some(format!("https://spdx.org/licenses/{}.html", license.name)), - }) - } - }, - LicenseEnum::VecStr(lst) => { - for s in lst { - addlicense(&LicenseEnum::SingleStr(s.clone()), licenses); - } - }, - LicenseEnum::Mixed(v) => { - for l in v { - addlicense(l, licenses); - } - } - } - } - - if let Some(pkglicense) = &input.meta.license { - addlicense(pkglicense, &mut licenses); - } - - if let Some(data) = &input.appdata { - if let Some(n) = &data.name { - if let Some(n) = n.get("C") { - name = n.to_string(); - } - } - if let Some(s) = &data.summary { - if let Some(s) = s.get("C") { - summary = Some(s.to_string()); - } - } - if let Some(d) = &data.description { - if let Some(d) = d.get("C") { - description = Some(d.to_string()); - } - } - if let Some(i) = &data.icon { - if let Some(mut i) = i.cached.clone() { - i.sort_by(|x, y| x.height.cmp(&y.height)); - if let Some(i) = i.last() { - icon = Some(format!( - "{}/icons/nixos/{}x{}/{}", - APPINFO, i.width, i.height, i.name - )); - } - } - } - if let Some(s) = &data.screenshots { - for s in s { - if let Some(u) = &s.sourceimage { - if !screenshots.contains(&u.url) { - if s.default == Some(true) { - screenshots.insert(0, u.url.clone()); - } else { - screenshots.push(u.url.clone()); - } - } else if s.default == Some(true) { - if let Some(index) = screenshots.iter().position(|x| *x == u.url) { - screenshots.remove(index); - screenshots.insert(0, u.url.clone()); - } + LicenseEnum::Mixed(v) => { + for l in v { + addlicense(l, licenses); } } } } - if let Some(l) = &data.launchable { - if let Some(d) = l.desktopid.get(0) { - launchable = Some(d.to_string()); - } - } - } - if let Some(p) = &input.meta.platforms { - match p { - Platform::Single(p) => { - if !platforms.contains(&p.to_string()) && p != &input.system { - platforms.push(p.to_string()); - } - }, - Platform::List(v) => { - for p in v { - if !platforms.contains(&p.to_string()) && p != &input.system { - platforms.push(p.to_string()); + if let Ok(pkglicense) = serde_json::from_str::(&licensejson) { + addlicense(&pkglicense, &mut licenses); + } + + let platformslst = serde_json::from_str::(&platformsjson); + if let Ok(p) = platformslst { + match p { + Platform::Single(p) => { + if !platforms.contains(&p) && p != system { + platforms.push(p); } } - }, - Platform::ListList(vv) => { - for v in vv { + Platform::List(v) => { for p in v { - if !platforms.contains(&p.to_string()) && p != &input.system { + if !platforms.contains(&p.to_string()) && p != system { platforms.push(p.to_string()); } } } + Platform::ListList(vv) => { + for v in vv { + for p in v { + if !platforms.contains(&p.to_string()) && p != system { + platforms.push(p.to_string()); + } + } + } + } } } - } - platforms.sort(); - platforms.insert(0, input.system.to_string()); + platforms.sort(); + platforms.insert(0, system); - if let Some(m) = input.meta.maintainers.clone() { - if let Ok(m) = ijson::from_value::>(&m) { + if let Ok(m) = serde_json::from_str::>(&maintainersjson) + { for m in m { maintainers.push(m); } } - } - let out = PkgInitModel { - name, - pname: input.pname.to_string(), - summary, - description, - icon, - pkg, - screenshots, - homepage: input.meta.homepage.clone(), - platforms, - licenses, - maintainers, - installeduserpkgs: self.installeduserpkgs.keys().cloned().collect(), - installedsystempkgs: self.installedsystempkgs.clone(), - launchable - }; - self.page = Page::PkgPage; - if self.viewstack.visible_child_name() != Some(gtk::glib::GString::from("search")) { - self.searching = false; + let out = PkgInitModel { + name, + pname, + summary, + description, + icon, + pkg, + screenshots, + homepage: if homepage.is_empty() { + None + } else { + Some(homepage) + }, + platforms, + licenses, + maintainers, + installeduserpkgs: self.installeduserpkgs.keys().cloned().collect(), + installedsystempkgs: self.installedsystempkgs.clone(), + launchable, + }; + self.page = Page::PkgPage; + if self.viewstack.visible_child_name() + != Some(gtk::glib::GString::from("search")) + { + self.searching = false; + } + self.busy = false; + self.pkgpage.emit(PkgMsg::Open(Box::new(out))); } - self.busy = false; - self.pkgpage.emit(PkgMsg::Open(Box::new(out))); - } + } else { + eprintln!("No pkgdb!!!!!!!!!!!!!!!!!!"); + } } AppMsg::FrontPage => { self.page = Page::FrontPage; @@ -911,369 +1111,369 @@ impl Component for AppModel { self.page = Page::FrontPage; self.mainpage = MainPage::FrontPage; } - AppMsg::UpdatePkgs(rec) => { - info!("AppMsg::UpdatePkgs"); - fn getsystempkgs(config: &str) -> Result, Box> { - let f = fs::read_to_string(config)?; - match nix_editor::read::getarrvals(&f, "environment.systemPackages") { - Ok(x) => Ok(HashSet::from_iter(x.into_iter())), - Err(_) => Err(Box::new(io::Error::new( - io::ErrorKind::InvalidData, - "Failed to read value from configuration", - ))) - } - } - - fn getuserenvpkgs() -> Result, Box> { - let out = Command::new("nix-env").arg("-q").arg("--json").output()?; - let data: IValue = serde_json::from_str(&String::from_utf8_lossy(&out.stdout))?; - let mut pcurrpkgs = HashMap::new(); - for (_, pkg) in data.as_object().unwrap() { - pcurrpkgs.insert( - pkg.as_object().unwrap()["pname"] - .as_string() - .unwrap() - .to_string(), - pkg.as_object().unwrap()["version"] - .as_string() - .unwrap() - .to_string() - ); - } - Ok(pcurrpkgs) - } - - fn getuserprofilepkgs() -> Result, Box> { - let data: IValue = serde_json::from_str(&fs::read_to_string(Path::new(&format!("{}/.nix-profile/manifest.json", std::env::var("HOME")?)))?)?; - let mut pcurrpkgs = HashMap::new(); - for pkg in data.as_object().unwrap()["elements"].as_array().unwrap().iter() { - if let Some(p) = pkg.get("attrPath") { - if let Some(pkgname) = p.as_string() - .unwrap() - // Change to current platform - .strip_prefix("legacyPackages.x86_64-linux.") { - if let Some(sp) = pkg.get("storePaths") { - if let Some(sp) = sp.as_array().unwrap().get(0) { - let storepath = sp.as_string().unwrap().to_string(); - let output = Command::new("nix") - .arg("show-derivation") - .arg(&storepath) - .output()?; - if let Ok(data) = serde_json::from_str::(&String::from_utf8_lossy(&output.stdout)) { - if let Some(version) = data.as_object().unwrap().values().next().unwrap()["env"].get("version") { - let version = version.as_str().unwrap().to_string(); - pcurrpkgs.insert( - pkgname.to_string(), - version, - ); - } else { - pcurrpkgs.insert( - pkgname.to_string(), - String::default(), - ); - } - } - } - } - } - } - } - Ok(pcurrpkgs) - } - - let systempkgs = if let Some(sysconfig) = &self.config.systemconfig { - match getsystempkgs(sysconfig) { - Ok(x) => x, - Err(_) => { - self.installedsystempkgs.clone() - } - } - } else { - HashSet::new() - }; - - let userpkgs = match self.userpkgtype { - UserPkgs::Env => { - match getuserenvpkgs() { - Ok(out) => out, - Err(_) => { - self.installeduserpkgs.clone() - } - } - }, - UserPkgs::Profile => { - match getuserprofilepkgs() { - Ok(out) => out, - Err(_) => { - self.installeduserpkgs.clone() - } - } - } - }; - - self.installedsystempkgs = systempkgs; - self.installeduserpkgs = userpkgs; - - if let Some(recommendedapps) = rec { - let mut recapps_guard = self.recommendedapps.guard(); - for app in recommendedapps { - if let Some(x) = self.pkgs.get(&app) { - if let Some(data) = &x.appdata { - if let Some(icon) = &data.icon { - if let Some(summary) = &data.summary { - if let Some(name) = &data.name { - let name = name.get("C").unwrap().to_string(); - let mut iconvec = icon.cached.as_ref().unwrap().to_vec(); - iconvec.sort_by(|a, b| a.height.cmp(&b.height)); - let summary = - summary.get("C").unwrap_or(&String::new()).to_string(); - recapps_guard.push_back(PkgTile { - pkg: app, - name, - pname: x.pname.to_string(), - icon: Some(iconvec[0].name.clone()), - summary, - installeduser: self.installeduserpkgs.contains_key(&x.pname.to_string()), - installedsystem: self.installedsystempkgs.contains(&x.pname.to_string()), - }); - } - } - } - } - } - } - recapps_guard.drop(); - } else { - let mut pkgtile_guard = self.recommendedapps.guard(); - for i in 0..pkgtile_guard.len() { - if let Some(pkgtile) = &mut pkgtile_guard.get_mut(i) { - pkgtile.installedsystem = self.installedsystempkgs.contains(&pkgtile.pkg); - pkgtile.installeduser = self.installeduserpkgs.contains_key(&pkgtile.pname); - } - } - pkgtile_guard.drop(); - } - - sender.input(AppMsg::UpdateInstalledPkgs); - sender.input(AppMsg::UpdateUpdatePkgs); - sender.input(AppMsg::UpdateCategoryPkgs); - - if self.searching { - self.update_searching(|_| ()); - self.searchpage.emit(SearchPageMsg::UpdateInstalled(self.installeduserpkgs.keys().cloned().collect(), self.installedsystempkgs.clone())); - } - } AppMsg::UpdateInstalledPkgs => { - let mut installeduseritems = vec![]; - match self.userpkgtype { - UserPkgs::Env => { - for installedpname in self.installeduserpkgs.keys() { - let possibleitems = self.pkgitems.iter().filter(|(_, x)| &x.pname == installedpname); - let count = possibleitems.clone().count(); - match count { - 1 => { - let (pkg, data) = possibleitems.collect::>()[0]; - installeduseritems.push(InstalledItem { - name: data.name.clone(), - pname: data.pname.clone(), - pkg: Some(pkg.clone()), - summary: data.summary.clone(), - icon: data.icon.clone(), - pkgtype: InstallType::User, - busy: self.installedpagebusy.contains(&(data.pname.clone(), InstallType::User)), - }) + info!("AppMsg::UpdateInstalledPkgs"); + let systemconfig = self.config.systemconfig.clone(); + let syspkgtype = self.syspkgtype.clone(); + let userpkgtype = self.userpkgtype.clone(); + sender.oneshot_command(async move { + let installedsystempkgs = if let Some(config) = &systemconfig { + match syspkgtype { + SystemPkgs::Flake => { + let pkgs = nix_data::cache::flakes::getflakepkgs(&[config]).await; + if let Ok(pkgs) = pkgs { + pkgs.keys().cloned().collect::>() + } else { + HashSet::new() } - 2.. => { - installeduseritems.push(InstalledItem { - name: installedpname.clone(), - pname: installedpname.clone(), - pkg: None, - summary: None, //data.summary.clone(), - icon: None, //data.icon.clone(), - pkgtype: InstallType::User, - busy: self.installedpagebusy.contains(&(installedpname.clone(), InstallType::User)), - }) + } + SystemPkgs::Legacy => { + let pkgs = nix_data::cache::channel::getlegacypkgs(&[config]).await; + if let Ok(pkgs) = pkgs { + pkgs.keys().cloned().collect::>() + } else { + HashSet::new() } - _ => {} } + _ => HashSet::new(), } - } - UserPkgs::Profile => { - for installedpkg in self.installeduserpkgs.keys() { - if let Some(item) = self.pkgitems.get(installedpkg) { - installeduseritems.push(InstalledItem { - name: item.name.clone(), - pname: item.pname.clone(), - pkg: Some(item.pkg.clone()), - summary: item.summary.clone(), - icon: item.icon.clone(), - pkgtype: InstallType::User, - busy: self.installedpagebusy.contains(&(item.pkg.clone(), InstallType::User)), - }) - } - } - } - } + } else { + HashSet::new() + }; - installeduseritems.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); - let mut installedsystemitems = vec![]; - for installedpkg in &self.installedsystempkgs { - if let Some(item) = self.pkgitems.get(installedpkg) { - installedsystemitems.push(InstalledItem { - name: item.name.clone(), - pname: item.pname.clone(), - pkg: Some(item.pkg.clone()), - summary: item.summary.clone(), - icon: item.icon.clone(), - pkgtype: InstallType::System, - busy: self.installedpagebusy.contains(&(item.pkg.clone(), InstallType::System)), - }) - } - } - installedsystemitems.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); - self.installedpage.emit(InstalledPageMsg::Update(installeduseritems, installedsystemitems)); + let installeduserpkgs = match userpkgtype { + UserPkgs::Profile => { + let pkgs = nix_data::cache::profile::getprofilepkgs_versioned().await; + if let Ok(pkgs) = pkgs { + pkgs + } else { + HashMap::new() + } + } + UserPkgs::Env => { + let pkgs = nix_data::cache::channel::getenvpkgs(); + if let Ok(pkgs) = pkgs { + pkgs + } else { + HashMap::new() + } + } + }; + AppAsyncMsg::UpdateInstalledPkgs(installedsystempkgs, installeduserpkgs) + }); } - AppMsg::UpdateUpdatePkgs => { - info!("AppMsg::UpdateUpdatePkgs"); - debug!("InstalledUserPkgs: {:?}", self.installeduserpkgs); - debug!("InstalledSystemPkgs: {:?}", self.installedsystempkgs); + AppMsg::UpdateInstalledPage => { + info!("AppMsg::UpdateInstalledPage"); + let mut installeduseritems = vec![]; let mut updateuseritems = vec![]; - match self.userpkgtype { - UserPkgs::Env => { - for (installedpname, version) in self.installeduserpkgs.iter() { - let possibleitems = self.pkgitems.iter().filter(|(_, x)| &x.pname == installedpname); - let count = possibleitems.clone().count(); - match count { - 1 => { - let (pkg, data) = possibleitems.collect::>()[0]; - if &data.version != version { - updateuseritems.push(UpdateItem { - name: data.name.clone(), - pname: data.pname.clone(), - pkg: Some(pkg.clone()), - summary: data.summary.clone(), - icon: data.icon.clone(), - pkgtype: InstallType::User, - verfrom: Some(version.clone()), - verto: Some(data.version.clone()), - }) - } else { - trace!("Pkg {} is up to date", pkg); - } - } - 2.. => { - let mut update = true; - for (pkg, _) in possibleitems { - if let Some(ver) = self.syspkgs.get(pkg) { - if version == ver { - update = false; - } - + // let pool = SqlitePool::connect(&self.pkgdb).await.unwrap(); + println!("Installed user pkgs: {:?}", self.installeduserpkgs); + println!("Installed system pkgs: {:?}", self.installedsystempkgs); + if let Ok(pool) = &SqlitePool::connect(&format!("sqlite://{}", self.pkgdb)).await { + match self.userpkgtype { + UserPkgs::Env => { + updateuseritems.push(UpdateItem { + name: String::from("Nix Env"), + pname: String::from("nix-env packages do not contain enough version information to determine if they are up to date."), + pkg: None, + summary: None, //data.summary.clone(), + icon: None, //data.icon.clone(), + pkgtype: InstallType::User, + verfrom: None, + verto: None, + }); + for installedpname in self.installeduserpkgs.keys() { + installeduseritems.push(InstalledItem { + name: installedpname.clone(), + pname: installedpname.clone(), + pkg: None, + summary: None, //data.summary.clone(), + icon: None, //data.icon.clone(), + pkgtype: InstallType::User, + busy: self + .installedpagebusy + .contains(&(installedpname.clone(), InstallType::User)), + }); + + // match count { + // 1 => { + // let (pkg,) = &possibleitems[0]; + // let (description,): (String,) = sqlx::query_as("SELECT description FROM meta WHERE attribute LIKE $1").bind(&format!("'%{}%'", pkg)).fetch_one(&pool).await.unwrap(); + // let mut name = installedpname.to_string(); + // let mut summary = if description.is_empty() { None } else { Some(description.to_string()) }; + // let mut icon = None; + // if let Some(data) = self.appdata.get(pkg) { + // if let Some(n) = &data.name { + // if let Some(n) = n.get("C") { + // name = n.to_string(); + // } + // } + // if let Some(s) = &data.summary { + // if let Some(s) = s.get("C") { + // summary = Some(s.to_string()); + // } + // } + // if let Some(i) = &data.icon { + // if let Some(i) = &i.cached { + // icon = Some(i[0].name.clone()); + // } + // } + // } + // installeduseritems.push(InstalledItem { + // name, + // pname: installedpname.to_string(), + // pkg: Some(pkg.clone()), + // summary, + // icon, + // pkgtype: InstallType::User, + // busy: self + // .installedpagebusy + // .contains(&(installedpname.to_string(), InstallType::User)), + // }) + // } + // 2.. => { + // installeduseritems.push(InstalledItem { + // name: installedpname.clone(), + // pname: installedpname.clone(), + // pkg: None, + // summary: None, //data.summary.clone(), + // icon: None, //data.icon.clone(), + // pkgtype: InstallType::User, + // busy: self + // .installedpagebusy + // .contains(&(installedpname.clone(), InstallType::User)), + // }) + // } + // _ => {} + // } + } + } + UserPkgs::Profile => { + for installedpkg in self.installeduserpkgs.keys() { + println!("Checking package {}", installedpkg); + let (pname, version): (String, String) = sqlx::query_as( + "SELECT pname, version FROM pkgs WHERE attribute = $1", + ) + .bind(installedpkg) + .fetch_one(pool) + .await + .unwrap(); + let (description,): (String,) = sqlx::query_as( + "SELECT description FROM meta WHERE attribute LIKE $1", + ) + .bind(installedpkg) + .fetch_one(pool) + .await + .unwrap(); + let mut name = pname.to_string(); + let mut summary = if description.is_empty() { + None + } else { + Some(description) + }; + let mut icon = None; + if let Some(data) = self.appdata.get(installedpkg) { + if let Some(n) = &data.name { + if let Some(n) = n.get("C") { + name = n.to_string(); } } - if update { - updateuseritems.push(UpdateItem { - name: installedpname.clone(), - pname: installedpname.clone(), - pkg: None, - summary: None, //data.summary.clone(), - icon: None, //data.icon.clone(), - pkgtype: InstallType::User, - verfrom: Some(version.clone()), - verto: None, - }) - } else { - trace!("Pkg {} is up to date", installedpname); + if let Some(s) = &data.summary { + if let Some(s) = s.get("C") { + summary = Some(s.to_string()); + } + } + if let Some(i) = &data.icon { + if let Some(i) = &i.cached { + icon = Some(i[0].name.clone()); + } } } - _ => {} - } - } - } - UserPkgs::Profile => { - for (installedpkg, version) in &self.installeduserpkgs { - if let Some(item) = self.pkgitems.get(installedpkg) { - if let Some(profilepkgs) = &self.profilepkgs { - if let Some(newver) = profilepkgs.get(installedpkg) { + // if let Some(item) = self.pkgitems.get(installedpkg) { + installeduseritems.push(InstalledItem { + name: name.to_string(), + pname: pname.to_string(), + pkg: Some(installedpkg.clone()), + summary: summary.clone(), + icon: icon.clone(), + pkgtype: InstallType::User, + busy: self + .installedpagebusy + .contains(&(installedpkg.clone(), InstallType::User)), + }); + if let Some(latest) = &self.nixpkgsdb { + if let Ok(latestpool) = + &SqlitePool::connect(&format!("sqlite://{}", latest)).await + { + let (newver,): (String,) = sqlx::query_as( + "SELECT version FROM pkgs WHERE attribute = $1", + ) + .bind(installedpkg) + .fetch_one(latestpool) + .await + .unwrap(); + println!( + "PROFILE: {} {} {}", + installedpkg, version, newver + ); if version != newver { updateuseritems.push(UpdateItem { - name: item.name.clone(), - pname: item.pname.clone(), - pkg: Some(item.pkg.clone()), - summary: item.summary.clone(), - icon: item.icon.clone(), - pkgtype: InstallType::User, + name, + pname, + pkg: Some(installedpkg.clone()), + summary, + icon, + pkgtype: InstallType::System, verfrom: Some(version.clone()), verto: Some(newver.clone()), }) - } else { - trace!("Pkg {} is up to date. Ver: {}", item.pname, version); } } } } } } - } - updateuseritems.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); - let mut updatesystemitems = vec![]; - for installedpkg in &self.installedsystempkgs { - if let Some(item) = self.pkgitems.get(installedpkg) { - if let Some(sysver) = self.syspkgs.get(installedpkg) { - if &item.version != sysver { - updatesystemitems.push(UpdateItem { - name: item.name.clone(), - pname: item.pname.clone(), - pkg: Some(item.pkg.clone()), - summary: item.summary.clone(), - icon: item.icon.clone(), - pkgtype: InstallType::System, - verfrom: Some(sysver.clone()), - verto: Some(item.version.clone()), - }) - } else { - trace!("Pkg {} is up to date", item.pkg); + installeduseritems + .sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); + let mut installedsystemitems = vec![]; + let mut updatesystemitems = vec![]; + for installedpkg in &self.installedsystempkgs { + let (pname, version): (String, String) = + sqlx::query_as("SELECT pname, version FROM pkgs where attribute = $1") + .bind(installedpkg) + .fetch_one(pool) + .await + .unwrap(); + let (description,): (String,) = + sqlx::query_as("SELECT description FROM meta WHERE attribute = $1") + .bind(installedpkg) + .fetch_one(pool) + .await + .unwrap(); + let mut name = pname.to_string(); + let mut summary = if description.is_empty() { + None + } else { + Some(description) + }; + let mut icon = None; + if let Some(data) = self.appdata.get(installedpkg) { + if let Some(n) = &data.name { + if let Some(n) = n.get("C") { + name = n.to_string(); + } + } + if let Some(s) = &data.summary { + if let Some(s) = s.get("C") { + summary = Some(s.to_string()); + } + } + if let Some(i) = &data.icon { + if let Some(i) = &i.cached { + icon = Some(i[0].name.clone()); + } + } + } + // if let Some(item) = self.pkgitems.get(installedpkg) { + installedsystemitems.push(InstalledItem { + name: name.to_string(), + pname: pname.to_string(), + pkg: Some(installedpkg.clone()), + summary: summary.clone(), + icon: icon.clone(), + pkgtype: InstallType::System, + busy: self + .installedpagebusy + .contains(&(installedpkg.clone(), InstallType::System)), + }); + if let Some(current) = &self.systemdb { + if let Ok(currentpool) = + &SqlitePool::connect(&format!("sqlite://{}", current)).await + { + let (currver,): (String,) = + sqlx::query_as("SELECT version FROM pkgs WHERE attribute = $1") + .bind(installedpkg) + .fetch_one(currentpool) + .await + .unwrap(); + println!("SYSTEM: {} {} {}", installedpkg, currver, version); + if version != currver { + updatesystemitems.push(UpdateItem { + name, + pname, + pkg: Some(installedpkg.clone()), + summary, + icon, + pkgtype: InstallType::System, + verfrom: Some(currver.clone()), + verto: Some(version.clone()), + }) + } } } } - } - updatesystemitems.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); - match self.syspkgtype { - SystemPkgs::Legacy => { - if let Ok(Some((old, new))) = uptodatelegacy() { - updatesystemitems.insert(0, UpdateItem { - name: String::from("NixOS System"), - pname: String::new(), - pkg: None, - summary: Some(String::from("NixOS internal packages and modules")), - icon: None, - pkgtype: InstallType::System, - verfrom: Some(old), - verto: Some(new), - }) + + // Add NixOS system to update list + match self.syspkgtype { + SystemPkgs::Legacy => { + if let Ok(Some((old, new))) = nix_data::cache::channel::uptodate() { + updatesystemitems.insert( + 0, + UpdateItem { + name: String::from("NixOS System"), + pname: String::new(), + pkg: None, + summary: Some(String::from( + "NixOS internal packages and modules", + )), + icon: None, + pkgtype: InstallType::System, + verfrom: Some(old), + verto: Some(new), + }, + ) + } } - } - SystemPkgs::Flake => { - if let Ok(Some((old, new))) = uptodateflake() { - updatesystemitems.insert(0, UpdateItem { - name: String::from("NixOS System"), - pname: String::new(), - pkg: None, - summary: Some(String::from("NixOS internal packages and modules")), - icon: None, - pkgtype: InstallType::System, - verfrom: Some(old), - verto: Some(new), - }) + SystemPkgs::Flake => { + if let Ok(Some((old, new))) = nix_data::cache::flakes::uptodate() { + updatesystemitems.insert( + 0, + UpdateItem { + name: String::from("NixOS System"), + pname: String::new(), + pkg: None, + summary: Some(String::from( + "NixOS internal packages and modules", + )), + icon: None, + pkgtype: InstallType::System, + verfrom: Some(old), + verto: Some(new), + }, + ) + } } + SystemPkgs::None => {} } - SystemPkgs::None => {} + + installedsystemitems + .sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); + self.installedpage.emit(InstalledPageMsg::Update( + installeduseritems, + installedsystemitems, + )); + self.updatepage + .emit(UpdatePageMsg::Update(updateuseritems, updatesystemitems)); + } else { + error!("Could not connect to pkgdb"); } - self.updatepage.emit(UpdatePageMsg::Update(updateuseritems, updatesystemitems)); } AppMsg::UpdateCategoryPkgs => { - self.categorypage.emit(CategoryPageMsg::UpdateInstalled(self.installeduserpkgs.keys().cloned().collect::>(), self.installedsystempkgs.iter().cloned().collect::>())); + self.categorypage.emit(CategoryPageMsg::UpdateInstalled( + self.installeduserpkgs.keys().cloned().collect::>(), + self.installedsystempkgs.iter().cloned().collect::>(), + )); } AppMsg::SetSearch(show) => { self.set_searching(show); @@ -1302,65 +1502,118 @@ impl Component for AppModel { self.viewstack.set_visible_child_name("search"); self.searchpage.emit(SearchPageMsg::Open); self.set_searchquery(search.to_string()); - let pkgitems: Vec = self.pkgitems.values().cloned().collect(); + // // let pkgitems: Vec = self.pkgitems.values().cloned().collect(); let installeduserpkgs = self.installeduserpkgs.clone(); let installedsystempkgs = self.installedsystempkgs.clone(); let userpkgtype = self.userpkgtype.clone(); + let pkgdb = self.pkgdb.clone(); + let appdata = self.appdata.clone(); sender.command(move |out, shutdown| { - let pkgs = pkgitems.clone(); + // let pkgs = pkgitems.clone(); let search = search.clone(); let installeduserpkgs = installeduserpkgs.clone(); let installedsystempkgs = installedsystempkgs; let userpkgtype = userpkgtype.clone(); shutdown.register(async move { let searchsplit: Vec = search.split(' ').filter(|x| x.len() > 1).map(|x| x.to_string()).collect(); - let mut namepkgs = pkgs.iter().filter(|x| searchsplit.iter().any(|s| x.name.to_lowercase().contains(&s.to_lowercase()))).collect::>(); - let mut pnamepkgs = pkgs.iter().filter(|x| searchsplit.iter().any(|s| x.pname.to_lowercase().contains(&s.to_lowercase())) && !namepkgs.contains(x)).collect::>(); - let mut pkgpkgs = pkgs.iter().filter(|x| searchsplit.iter().any(|s| x.pkg.to_lowercase().contains(&s.to_lowercase())) && !namepkgs.contains(x) && !pnamepkgs.contains(x)).collect::>(); - let mut sumpkgs = pkgs.iter().filter(|x| if let Some(sum) = &x.summary { searchsplit.iter().any(|s| sum.to_lowercase().contains(&s.to_lowercase())) } else { false } && !namepkgs.contains(x) && !pnamepkgs.contains(x) && !pkgpkgs.contains(x)).collect::>(); - namepkgs.sort_by(|a, b| edit_distance::edit_distance(&a.name.to_lowercase(), &search.to_lowercase()).cmp(&edit_distance::edit_distance(&b.name.to_lowercase(), &search.to_lowercase()))); - pnamepkgs.sort_by(|a, b| edit_distance::edit_distance(&a.pname.to_lowercase(), &search.to_lowercase()).cmp(&edit_distance::edit_distance(&b.pname.to_lowercase(), &search.to_lowercase()))); - pkgpkgs.sort_by(|a, b| edit_distance::edit_distance(&a.pkg.to_lowercase(), &search.to_lowercase()).cmp(&edit_distance::edit_distance(&b.pkg.to_lowercase(), &search.to_lowercase()))); - sumpkgs.sort_by(|a, b| { - let mut x = 0; - for s in &searchsplit { - x += a.summary.as_ref().unwrap_or(&String::new()).to_lowercase().matches(&s.to_lowercase()).count() + warn!("Searchsplit: {:?}", searchsplit); + if let Ok(pkgpool) = &SqlitePool::connect(&format!("sqlite://{}", pkgdb)).await { + let mut queryb: QueryBuilder = QueryBuilder::new( + "SELECT pkgs.attribute, pkgs.pname, description, version FROM pkgs JOIN meta ON (pkgs.attribute = meta.attribute) WHERE (", + ); + for (i, q) in searchsplit.iter().enumerate() { + if i == searchsplit.len() - 1 { + queryb + .push(r#"pkgs.attribute LIKE "#) + .push_bind(format!("%{}%", q)) + .push(r#" OR description LIKE "#) + .push_bind(format!("%{}%", q)) + .push(")"); + } else { + queryb + .push(r#"pkgs.attribute LIKE "#) + .push_bind(format!("%{}%", q)) + .push(r#" OR description LIKE "#) + .push_bind(format!("%{}%", q)) + .push(r#") AND ("#); + } } - let mut y = 0; - for s in &searchsplit { - y += b.summary.as_ref().unwrap_or(&String::new()).to_lowercase().matches(&s.to_lowercase()).count() + queryb.push("ORDER BY LENGTH(pkgs.attribute) ASC"); + let q: Vec<(String, String, String, String)> = + queryb.build_query_as().fetch_all(pkgpool).await.unwrap(); + let mut outpkgs = Vec::new(); + for (i, (attr, pname, desc, _version)) in q.into_iter().enumerate() { + if let Some(data) = appdata.get(&attr) { + outpkgs.push(SearchItem { + pkg: attr.to_string(), + pname: pname.to_string(), + name: if let Some(name) = &data.name { name.get("C").unwrap_or(&attr).to_string() } else { attr.to_string() }, + summary: if desc.is_empty() { None } else { Some(desc) }, + icon: data + .icon + .as_ref() + .and_then(|x| x.cached.as_ref()) + .map(|x| x[0].name.clone()), + installeduser: match userpkgtype { + UserPkgs::Env => installeduserpkgs.contains_key(&pname), + UserPkgs::Profile => installeduserpkgs.contains_key(&attr) + }, + installedsystem: installedsystempkgs.contains(&attr), + }) + } else { + outpkgs.push(SearchItem { + pkg: attr.to_string(), + pname: pname.to_string(), + name: pname.to_string(), + summary: if desc.is_empty() { None } else { Some(desc) }, + icon: None, + installeduser: match userpkgtype { + UserPkgs::Env => installeduserpkgs.contains_key(&pname), + UserPkgs::Profile => installeduserpkgs.contains_key(&attr) + }, + installedsystem: installedsystempkgs.contains(&attr), + }); + } + if i >= 200 { + break; + } } - x.cmp(&y) - }); - - - let mut combpkgs = namepkgs; - combpkgs.append(&mut pnamepkgs); - combpkgs.append(&mut pkgpkgs); - combpkgs.append(&mut sumpkgs); - - combpkgs.sort_by(|a, b| { - b.icon.is_some().cmp(&a.icon.is_some()) - }); - let mut outpkgs: Vec = vec![]; - for (i, p) in combpkgs.iter().enumerate() { - outpkgs.push(SearchItem { - pkg: p.pkg.to_string(), - pname: p.pname.to_string(), - name: p.name.to_string(), - summary: p.summary.clone(), - icon: p.icon.clone(), - installeduser: match userpkgtype { - UserPkgs::Env => installeduserpkgs.contains_key(&p.pname), - UserPkgs::Profile => installeduserpkgs.contains_key(&p.pkg) - }, - installedsystem: installedsystempkgs.contains(&p.pkg), + outpkgs.sort_by(|a, b| { + let mut aleft = a.pkg.to_lowercase(); + let mut bleft = b.pkg.to_lowercase(); + for q in searchsplit.iter() { + let q = &q.to_lowercase(); + if aleft.contains(q) { + aleft = aleft.replace(q, ""); + } else { + aleft.push_str(q); + } + if bleft.contains(q) { + bleft = bleft.replace(q, ""); + } else { + bleft.push_str(q); + } + } + let mut apoints = aleft.len(); + let mut bpoints = bleft.len(); + // for q in searchsplit.iter() { + // if a.name.contains(q) { + // apoints -= 1; + // } + // if b.name.contains(q) { + // bpoints -= 1; + // } + // } + if a.icon.is_some() { + apoints -= 3; + } + if b.icon.is_some() { + bpoints -= 3; + } + apoints.cmp(&bpoints) }); - if i > 100 { - break; - } + out.send(AppAsyncMsg::Search(search.to_string(), outpkgs)) } - out.send(AppAsyncMsg::Search(search.to_string(), outpkgs)) }).drop_on_shutdown() }) } @@ -1389,95 +1642,181 @@ impl Component for AppModel { InstallType::User => work.pname.to_string(), InstallType::System => work.pkg.to_string(), }; - self.installedpagebusy.retain(|(x, y)| x != &p && y != &work.pkgtype); + self.installedpagebusy + .retain(|(x, y)| x != &p && y != &work.pkgtype); self.installedpage.emit(InstalledPageMsg::UnsetBusy(work)); } AppMsg::OpenCategoryPage(category) => { info!("AppMsg::OpenCategoryPage({})", category); self.page = Page::FrontPage; self.mainpage = MainPage::CategoryPage; + self.categorypage.emit(CategoryPageMsg::Loading(category.clone())); sender.input(AppMsg::LoadCategory(category)); } AppMsg::LoadCategory(category) => { - let mut catrec = vec![]; - for app in self.categoryrec.get(&category).unwrap_or(&vec![]) { - if let Some(x) = self.pkgs.get(app) { - let mut name = x.pname.to_string(); - let mut icon = None; - let mut summary = x.meta.description.clone().map(|x| x.to_string()); - if let Some(data) = &x.appdata { - if let Some(i) = &data.icon { - let mut iconvec = i.cached.as_ref().unwrap().to_vec(); - iconvec.sort_by(|a, b| a.height.cmp(&b.height)); - icon = Some(iconvec[0].name.clone()); - } - if let Some(s) = &data.summary { - summary = - s.get("C").map(|x| x.to_string()); - - } - if let Some(n) = &data.name { - name = n.get("C").unwrap().to_string(); + info!("AppMsg::LoadCategory({})", category); + let pkgdb = self.pkgdb.clone(); + let categoryrec = self.categoryrec.get(&category).unwrap_or(&vec![]).to_vec(); + let categoryall = self.categoryall.get(&category).unwrap_or(&vec![]).to_vec(); + let appdata = self.appdata.clone(); + let installeduser = self.installeduserpkgs.clone(); + let installedsystem = self.installedsystempkgs.clone(); + let category = category; + sender.oneshot_command(async move { + let mut catrec = vec![]; + let mut catall = vec![]; + if let Ok(pool) = &SqlitePool::connect(&format!("sqlite://{}", pkgdb)).await { + for pkg in categoryrec { + if let Some(data) = appdata.get(&pkg) { + let pname: (String,) = + sqlx::query_as("SELECT pname FROM pkgs WHERE attribute = $1") + .bind(&pkg) + .fetch_one(pool) + .await + .unwrap(); + catrec.push(CategoryTile { + pkg: pkg.to_string(), + name: if let Some(name) = &data.name { + name.get("C").unwrap_or(&pname.0).to_string() + } else { + pname.0.to_string() + }, + pname: pname.0, + icon: data + .icon + .as_ref() + .and_then(|x| x.cached.as_ref()) + .map(|x| x[0].name.clone()), + summary: data + .summary + .as_ref() + .and_then(|x| x.get("C")) + .map(|x| x.to_string()), + installeduser: installeduser.contains_key(&pkg), + installedsystem: installedsystem.contains(&pkg), + }) + } else { + let (pname, description): (String, String) = + sqlx::query_as("SELECT pname, description FROM pkgs JOIN meta ON (pkgs.attribute = meta.attribute) WHERE pkgs.attribute = $1") + .bind(&pkg) + .fetch_one(pool) + .await + .unwrap(); + catrec.push(CategoryTile { + pkg: pkg.to_string(), + name: pname.to_string(), + pname: pname.to_string(), + icon: None, + summary: if description.is_empty() { None } else { Some(description) }, + installeduser: installeduser.contains_key(&pkg), + installedsystem: installedsystem.contains(&pkg), + }) } } - catrec.push(CategoryTile { - pkg: app.to_string(), - name, - pname: x.pname.to_string(), - icon, - summary, - installeduser: self.installeduserpkgs.contains_key(&x.pname.to_string()), - installedsystem: self.installedsystempkgs.contains(&x.pname.to_string()), - }); - } - } - - let mut catall = vec![]; - for app in self.categoryall.get(&category).unwrap_or(&vec![]) { - if let Some(x) = self.pkgs.get(app) { - let mut name = x.pname.to_string(); - let mut icon = None; - let mut summary = x.meta.description.clone().map(|x| x.to_string()); - if let Some(data) = &x.appdata { - if let Some(i) = &data.icon { - let mut iconvec = i.cached.as_ref().unwrap().to_vec(); - iconvec.sort_by(|a, b| a.height.cmp(&b.height)); - icon = Some(iconvec[0].name.clone()); - } - if let Some(s) = &data.summary { - summary = - s.get("C").map(|x| x.to_string()); - - } - if let Some(n) = &data.name { - name = n.get("C").unwrap().to_string(); + for pkg in categoryall { + if let Some(data) = appdata.get(&pkg) { + let pname: (String,) = + sqlx::query_as("SELECT pname FROM pkgs WHERE attribute = $1") + .bind(&pkg) + .fetch_one(pool) + .await + .unwrap(); + catall.push(CategoryTile { + pkg: pkg.to_string(), + name: if let Some(name) = &data.name { + name.get("C").unwrap_or(&pname.0).to_string() + } else { + pname.0.to_string() + }, + pname: pname.0, + icon: data + .icon + .as_ref() + .and_then(|x| x.cached.as_ref()) + .map(|x| x[0].name.clone()), + summary: data + .summary + .as_ref() + .and_then(|x| x.get("C")) + .map(|x| x.to_string()), + installeduser: installeduser.contains_key(&pkg), + installedsystem: installedsystem.contains(&pkg), + }) + } else { + let (pname, description): (String, String) = + sqlx::query_as("SELECT pname, description FROM pkgs JOIN meta ON (pkgs.attribute = meta.attribute) WHERE pkgs.attribute = $1") + .bind(&pkg) + .fetch_one(pool) + .await + .unwrap(); + catall.push(CategoryTile { + pkg: pkg.to_string(), + name: pname.to_string(), + pname: pname.to_string(), + icon: None, + summary: if description.is_empty() { None } else { Some(description) }, + installeduser: installeduser.contains_key(&pkg), + installedsystem: installedsystem.contains(&pkg), + }) } } - catall.push(CategoryTile { - pkg: app.to_string(), - name, - pname: x.pname.to_string(), - icon, - summary, - installeduser: self.installeduserpkgs.contains_key(&x.pname.to_string()), - installedsystem: self.installedsystempkgs.contains(&x.pname.to_string()), - }); + } else { + error!("Failed to connect to pkgdb") } - } - - self.categorypage.emit(CategoryPageMsg::Open(category, catrec, catall)); - + AppAsyncMsg::LoadCategory(category, catrec, catall) + }); } } } - fn update_cmd(&mut self, msg: Self::CommandOutput, _sender: ComponentSender) { + fn update_cmd(&mut self, msg: Self::CommandOutput, sender: ComponentSender) { match msg { AppAsyncMsg::Search(search, pkgitems) => { if search == self.searchquery { self.searchpage.emit(SearchPageMsg::Search(pkgitems)) } } + AppAsyncMsg::UpdateRecPkgs(pkgtiles) => { + info!("AppAsyncMsg::UpdateRecPkgs"); + let mut recapps_guard = self.recommendedapps.guard(); + recapps_guard.clear(); + for tile in pkgtiles { + recapps_guard.push_back(tile); + } + recapps_guard.drop(); + sender.input(AppMsg::UpdateInstalledPkgs); + info!("DONE AppAsyncMsg::UpdateRecPkgs"); + } + AppAsyncMsg::UpdateInstalledPkgs(installedsystempkgs, installeduserpkgs) => { + info!("AppAsyncMsg::UpdateInstalledPkgs"); + if installedsystempkgs != self.installedsystempkgs + || installeduserpkgs != self.installeduserpkgs + { + warn!("Changes needed!"); + self.installedsystempkgs = installedsystempkgs; + self.installeduserpkgs = installeduserpkgs; + sender.input(AppMsg::UpdateInstalledPage); + debug!("Getting recommended apps guard"); + let mut recommendedapps_guard = self.recommendedapps.guard(); + debug!("Got recommended apps guard"); + for item in recommendedapps_guard.iter_mut() { + debug!("Got item {}", item.pkg); + item.installeduser = self.installeduserpkgs.contains_key(&item.pname); + item.installedsystem = self.installedsystempkgs.contains(&item.pname); + } + if self.searching { + // self.update_searching(|_| ()); + self.searchpage.emit(SearchPageMsg::UpdateInstalled( + self.installeduserpkgs.keys().cloned().collect(), + self.installedsystempkgs.clone(), + )); + } + } + info!("DONE AppAsyncMsg::UpdateInstalledPkgs"); + } + AppAsyncMsg::LoadCategory(category, catrec, catall) => { + self.categorypage.emit(CategoryPageMsg::Open(category, catrec, catall)); + } } } } diff --git a/src/ui/windowloading.rs b/src/ui/windowloading.rs index 4f3466e..ac5603f 100644 --- a/src/ui/windowloading.rs +++ b/src/ui/windowloading.rs @@ -1,423 +1,375 @@ use super::window::AppMsg; use super::window::SystemPkgs; -use crate::parse::cache::checkcache; -use crate::parse::config::NscConfig; -use crate::parse::packages::readflakesyspkgs; -use crate::parse::packages::readpkgs; -use crate::parse::packages::readlegacysyspkgs; -use crate::parse::packages::Package; -use crate::parse::packages::readprofilepkgs; +use crate::parse::packages::appsteamdata; +use crate::parse::packages::AppData; use crate::ui::categories::PkgCategory; use crate::ui::window::UserPkgs; +use log::*; +use nix_data::config::configfile::NixDataConfig; use rand::prelude::SliceRandom; use rand::thread_rng; use relm4::adw::prelude::*; use relm4::*; +use sqlx::SqlitePool; use std::{collections::HashMap, env}; use strum::IntoEnumIterator; -use log::*; pub struct WindowAsyncHandler; #[derive(Debug)] pub enum WindowAsyncHandlerMsg { - CheckCache(CacheReturn, SystemPkgs, UserPkgs, NscConfig), -} - -#[derive(Debug, PartialEq)] -pub enum CacheReturn { - Init, - Update, + CheckCache(SystemPkgs, UserPkgs, NixDataConfig), } impl Worker for WindowAsyncHandler { - type InitParams = (); + type Init = (); type Input = WindowAsyncHandlerMsg; type Output = AppMsg; - fn init(_params: Self::InitParams, _sender: relm4::ComponentSender) -> Self { + fn init(_params: Self::Init, _sender: relm4::ComponentSender) -> Self { Self } fn update(&mut self, msg: Self::Input, sender: ComponentSender) { match msg { - WindowAsyncHandlerMsg::CheckCache(cr, syspkgs, userpkgs, config) => { + WindowAsyncHandlerMsg::CheckCache(syspkgs, userpkgs, _config) => { info!("WindowAsyncHandlerMsg::CheckCache"); - let syspkgs2 = syspkgs.clone(); - let userpkgs2 = userpkgs.clone(); - let config = config.clone(); relm4::spawn(async move { - match checkcache(syspkgs2, userpkgs2, config) { - Ok(_) => {} - Err(e) => { - warn!("FAILED TO CHECK CACHE"); - warn!("{}", e); - sender.output(AppMsg::LoadError( - String::from("Could not load cache"), - String::from( - "Try connecting to the internet or launching the application again", - ), - )); - return; - } - } - let pkgs = match readpkgs().await { - Ok(pkgs) => pkgs, - Err(e) => { - warn!("FAILED TO LOAD PKGS"); - warn!("{}", e); - sender.output(AppMsg::LoadError( - String::from("Could not load packages"), - String::from( - "Try connecting to the internet or launching the application again", - ), - )); - return; - } - }; - - let newpkgs = match syspkgs { - SystemPkgs::Legacy => { - match readlegacysyspkgs() { - Ok(newpkgs) => newpkgs, - Err(e) => { - warn!("FAILED TO LOAD NEW PKGS"); - warn!("{}", e); - sender.output(AppMsg::LoadError( - String::from("Could not load new packages"), - String::from( - "Try connecting to the internet or launching the application again", - ), - )); - return; - } - } - } - SystemPkgs::Flake => { - match readflakesyspkgs() { - Ok(newpkgs) => newpkgs, - Err(e) => { - warn!("FAILED TO LOAD NEW PKGS"); - warn!("{}", e); - sender.output(AppMsg::LoadError( - String::from("Could not load new packages"), - String::from( - "Try connecting to the internet or launching the application again", - ), - )); - return; - } - } - } - SystemPkgs::None => { - HashMap::new() - } - }; - - let profilepkgs = match userpkgs { - UserPkgs::Env => None, - UserPkgs::Profile => if let Ok(r) = readprofilepkgs() { Some(r) } else { None }, - }; - let mut recpicks = vec![]; let mut catpicks: HashMap> = HashMap::new(); let mut catpkgs: HashMap> = HashMap::new(); + println!("Connecting to DB"); + let pkgdb = nix_data::cache::nixos::nixospkgs().await.unwrap(); + let pool = SqlitePool::connect(&format!("sqlite://{}", pkgdb)) + .await + .unwrap(); - if cr == CacheReturn::Init { - let desktopenv = env::var("XDG_CURRENT_DESKTOP").unwrap_or_default(); - let appdatapkgs = pkgs - .iter() - .filter(|(x, _)| { - if let Some(p) = pkgs.get(*x) { - if let Some(data) = &p.appdata { - (if let Some(i) = &data.icon { - i.cached.is_some() - } else { - false - }) && data.description.is_some() - && data.name.is_some() - && data.launchable.is_some() - && data.screenshots.is_some() - && (!x.starts_with("gnome.") || desktopenv == "GNOME") - && (!x.starts_with("xfce.") || desktopenv == "XFCE") - && (!x.starts_with("mate.") || desktopenv == "MATE") - && (!x.starts_with("cinnamon.") - || desktopenv == "X-Cinnamon") - && (!x.starts_with("libsForQt5") || desktopenv == "KDE") - && (!x.starts_with("pantheon.") - || desktopenv == "Pantheon") - } else { - false - } - } else { - false - } - }) - .collect::>(); - - let mut recommendedpkgs = appdatapkgs - .keys() - .map(|x| x.to_string()) - .collect::>(); - let mut rng = thread_rng(); - recommendedpkgs.shuffle(&mut rng); - - let mut desktoppicks = recommendedpkgs - .iter() - .filter(|x| { - if desktopenv == "GNOME" { - x.starts_with("gnome.") || x.starts_with("gnome-") - } else if desktopenv == "XFCE" { - x.starts_with("xfce.") - } else if desktopenv == "MATE" { - x.starts_with("mate.") - } else if desktopenv == "X-Cinnamon" { - x.starts_with("cinnamon.") - } else if desktopenv == "KDE" { - x.starts_with("libsForQt5") - } else if desktopenv == "Pantheon" { - x.starts_with("pantheon.") - } else { - false - } - }) - .collect::>(); - - for p in desktoppicks.iter().take(3) { - recpicks.push(p.to_string()); + let nixpkgsdb = match userpkgs { + UserPkgs::Profile => { + if let Ok(x) = nix_data::cache::profile::nixpkgslatest().await { + Some(x) + } else { + None + } } - for category in PkgCategory::iter() { - desktoppicks.shuffle(&mut rng); - let mut cvec = vec![]; - let mut allvec = vec![]; - let mut rpkgs = recommendedpkgs.clone(); - fn checkpkgs( - pkg: String, - pkgs: &HashMap<&String, &Package>, - category: PkgCategory, - ) -> bool { - match category { - PkgCategory::Audio => { - // Audio: - // - pkgs/applications/audio - if let Some(p) = pkgs.get(&pkg) { - if let Some(pos) = &p.meta.position { - if pos.starts_with("pkgs/applications/audio") { + UserPkgs::Env => None, + }; + + let systemdb = match syspkgs { + SystemPkgs::None => None, + SystemPkgs::Legacy => { + if let Ok(x) = nix_data::cache::channel::legacypkgs().await { + Some(x) + } else { + None + } + } + SystemPkgs::Flake => { + if let Ok(x) = nix_data::cache::flakes::flakespkgs().await { + Some(x) + } else { + None + } + } + }; + + let pkglist: Vec<(String,)> = sqlx::query_as("SELECT attribute FROM pkgs") + .fetch_all(&pool) + .await + .unwrap(); + let pkglist = pkglist.iter().map(|x| x.0.clone()).collect::>(); + + let posvec: Vec<(String, String)> = + sqlx::query_as("SELECT attribute, position FROM meta") + .fetch_all(&pool) + .await + .unwrap(); + println!("Got DB data"); + let appdata = appsteamdata().unwrap(); + + let desktopenv = env::var("XDG_CURRENT_DESKTOP").unwrap_or_default(); + + let mut recpkgs = pkglist + .iter() + .filter(|x| { + if let Some(data) = appdata.get(&x.to_string()) { + (if let Some(i) = &data.icon { + i.cached.is_some() + } else { + false + }) && data.description.is_some() + && data.name.is_some() + && data.launchable.is_some() + && data.screenshots.is_some() + && (!x.starts_with("gnome.") || desktopenv == "GNOME") + && (!x.starts_with("xfce.") || desktopenv == "XFCE") + && (!x.starts_with("mate.") || desktopenv == "MATE") + && (!x.starts_with("cinnamon.") || desktopenv == "X-Cinnamon") + && (!x.starts_with("libsForQt5") || desktopenv == "KDE") + && (!x.starts_with("pantheon.") || desktopenv == "Pantheon") + } else { + false + } + }) + .collect::>(); + + let mut rng = thread_rng(); + recpkgs.shuffle(&mut rng); + + let mut desktoppicks = recpkgs + .iter() + .filter(|x| { + if desktopenv == "GNOME" { + x.starts_with("gnome.") || x.starts_with("gnome-") + } else if desktopenv == "XFCE" { + x.starts_with("xfce.") + } else if desktopenv == "MATE" { + x.starts_with("mate.") + } else if desktopenv == "X-Cinnamon" { + x.starts_with("cinnamon.") + } else if desktopenv == "KDE" { + x.starts_with("libsForQt5") + } else if desktopenv == "Pantheon" { + x.starts_with("pantheon.") + } else { + false + } + }) + .collect::>(); + + for p in desktoppicks.iter().take(3) { + recpicks.push(p.to_string()); + } + + let pospkgs = posvec + .into_iter() + .map(|(x, y)| (x, if y.is_empty() { None } else { Some(y) })) + .collect::>>(); + + println!("Starting category"); + for category in PkgCategory::iter() { + desktoppicks.shuffle(&mut rng); + let mut cvec = vec![]; + let mut allvec = vec![]; + let mut rpkgs = recpkgs.clone(); + fn checkpkgs( + pkg: String, + pospkgs: &HashMap>, + appdata: &HashMap, + category: PkgCategory, + ) -> bool { + match category { + PkgCategory::Audio => { + // Audio: + // - pkgs/applications/audio + if let Some(Some(pos)) = pospkgs.get(&pkg) { + if pos.starts_with("pkgs/applications/audio") { + return true; + } + if let Some(data) = appdata.get(&pkg) { + if let Some(categories) = &data.categories { + if categories.contains(&String::from("Audio")) { return true; } } - if let Some(data) = &p.appdata { - if let Some(categories) = &data.categories { - if categories.contains(&String::from("Audio")) { - return true; - } - } - } } - false } - PkgCategory::Development => { - // Development: - // - pkgs/development - // - pkgs/applications/terminal-emulators - // - xdg: Development - if let Some(p) = pkgs.get(&pkg) { - if let Some(pos) = &p.meta.position { - if pos.starts_with("pkgs/development") - || pos.starts_with( - "pkgs/applications/terminal-emulators", - ) + false + } + PkgCategory::Development => { + // Development: + // - pkgs/development + // - pkgs/applications/terminal-emulators + // - xdg: Development + if let Some(Some(pos)) = pospkgs.get(&pkg) { + if pos.starts_with("pkgs/development") + || pos + .starts_with("pkgs/applications/terminal-emulators") + { + return true; + } + if let Some(data) = appdata.get(&pkg) { + if let Some(categories) = &data.categories { + if categories.contains(&String::from("Development")) { return true; } } - if let Some(data) = &p.appdata { - if let Some(categories) = &data.categories { - if categories - .contains(&String::from("Development")) - { - return true; - } - } - } } - false } - PkgCategory::Games => { - // Games: - // - pkgs/games - // - pkgs/applications/emulators - // - pkgs/tools/games - // - xdg::Games - if let Some(p) = pkgs.get(&pkg) { - if let Some(pos) = &p.meta.position { - if pos.starts_with("pkgs/games") - || pos.starts_with( - "pkgs/applications/emulators", - ) - || pos.starts_with("pkgs/tools/games") - { + false + } + PkgCategory::Games => { + // Games: + // - pkgs/games + // - pkgs/applications/emulators + // - pkgs/tools/games + // - xdg::Games + if let Some(Some(pos)) = pospkgs.get(&pkg) { + if pos.starts_with("pkgs/games") + || pos.starts_with("pkgs/applications/emulators") + || pos.starts_with("pkgs/tools/games") + { + return true; + } + if let Some(data) = &appdata.get(&pkg) { + if let Some(categories) = &data.categories { + if categories.contains(&String::from("Games")) { return true; } } - if let Some(data) = &p.appdata { - if let Some(categories) = &data.categories { - if categories.contains(&String::from("Games")) { - return true; - } - } - } } - false } - PkgCategory::Graphics => { - // Graphics: - // - pkgs/applications/graphics - // - xdg: Graphics - if let Some(p) = pkgs.get(&pkg) { - if let Some(pos) = &p.meta.position { - if pos.starts_with("pkgs/applications/graphics") - || pos.starts_with("xdg:Graphics") - { + false + } + PkgCategory::Graphics => { + // Graphics: + // - pkgs/applications/graphics + // - xdg: Graphics + if let Some(Some(pos)) = pospkgs.get(&pkg) { + if pos.starts_with("pkgs/applications/graphics") + || pos.starts_with("xdg:Graphics") + { + return true; + } + if let Some(data) = &appdata.get(&pkg) { + if let Some(categories) = &data.categories { + if categories.contains(&String::from("Graphics")) { return true; } } - if let Some(data) = &p.appdata { - if let Some(categories) = &data.categories { - if categories.contains(&String::from("Graphics")) { - return true; - } - } - } - } - false - } - PkgCategory::Network => { - // Network: - // - pkgs/applications/networking - // - xdg: Network - if let Some(p) = pkgs.get(&pkg) { - if let Some(pos) = &p.meta.position { - if pos.starts_with("pkgs/applications/networking") - || pos.starts_with("xdg:Network") - { - return true; - } - } - if let Some(data) = &p.appdata { - if let Some(categories) = &data.categories { - if categories.contains(&String::from("Network")) { - return true; - } - } - } - } - false - } - PkgCategory::Video => { - // Video: - // - pkgs/applications/video - // - xdg: Video - if let Some(p) = pkgs.get(&pkg) { - if let Some(pos) = &p.meta.position { - if pos.starts_with("pkgs/applications/video") - || pos.starts_with("xdg:Video") - { - return true; - } - } - if let Some(data) = &p.appdata { - if let Some(categories) = &data.categories { - if categories.contains(&String::from("Video")) { - return true; - } - } - } } - false } + false + } + PkgCategory::Network => { + // Network: + // - pkgs/applications/networking + // - xdg: Network + if let Some(Some(pos)) = pospkgs.get(&pkg) { + if pos.starts_with("pkgs/applications/networking") + || pos.starts_with("xdg:Network") + { + return true; + } + if let Some(data) = &appdata.get(&pkg) { + if let Some(categories) = &data.categories { + if categories.contains(&String::from("Network")) { + return true; + } + } + } + } + false + } + PkgCategory::Video => { + // Video: + // - pkgs/applications/video + // - xdg: Video + if let Some(Some(pos)) = pospkgs.get(&pkg) { + if pos.starts_with("pkgs/applications/video") + || pos.starts_with("xdg:Video") + { + return true; + } + if let Some(data) = &appdata.get(&pkg) { + if let Some(categories) = &data.categories { + if categories.contains(&String::from("Video")) { + return true; + } + } + } + } + false } } + } - for pkg in desktoppicks.iter().take(3) { - if checkpkgs(pkg.to_string(), &appdatapkgs, category.clone()) { + for pkg in desktoppicks.iter().take(3) { + if checkpkgs(pkg.to_string(), &pospkgs, &appdata, category.clone()) { + cvec.push(pkg.to_string()); + } + } + + while cvec.len() < 12 { + if let Some(pkg) = rpkgs.pop() { + if !cvec.contains(&pkg.to_string()) + && checkpkgs( + pkg.to_string(), + &pospkgs, + &appdata, + category.clone(), + ) + { cvec.push(pkg.to_string()); } - } - - while cvec.len() < 12 { - if let Some(pkg) = rpkgs.pop() { - if !cvec.contains(&pkg.to_string()) - && checkpkgs( - pkg.to_string(), - &appdatapkgs, - category.clone(), - ) - { - cvec.push(pkg.to_string()); - } - } else { - break; - } - } - - let catagortypkgs = pkgs - .iter() - .filter(|(x, _)| { - if let Some(p) = appdatapkgs.get(*x) { - if let Some(position) = &p.meta.position { - (position.starts_with("pkgs/applications/audio") && category == PkgCategory::Audio) - || (position.starts_with("pkgs/applications/terminal-emulators") && category == PkgCategory::Development) - || (position.starts_with("pkgs/applications/emulators") && category == PkgCategory::Games) - || (position.starts_with("pkgs/applications/graphics") && category == PkgCategory::Graphics) - || (position.starts_with("pkgs/applications/networking") && category == PkgCategory::Network) - || (position.starts_with("pkgs/applications/video") && category == PkgCategory::Video) - || (position.starts_with("pkgs/tools/games") && category == PkgCategory::Games) - || (position.starts_with("pkgs/games") && category == PkgCategory::Games) - || (position.starts_with("pkgs/development") && category == PkgCategory::Development) - || appdatapkgs.contains_key(x) - } else { - false - } - } else { - false - } - }) - .collect::>(); - - for pkg in catagortypkgs.keys() { - if checkpkgs(pkg.to_string(), &catagortypkgs, category.clone()) { - allvec.push(pkg.to_string()); - } - } - - cvec.shuffle(&mut rng); - allvec.sort_by_key(|x| x.to_lowercase()); - catpicks.insert(category.clone(), cvec); - catpkgs.insert(category.clone(), allvec); - } - - while recpicks.len() < 12 { - if let Some(p) = recommendedpkgs.pop() { - if !recpicks.contains(&p.to_string()) { - recpicks.push(p); - } } else { break; } } - recpicks.shuffle(&mut rng); + + let catagortypkgs = pkglist + .iter() + .filter(|x| { + if appdata.get(*x).is_some() { + if let Some(Some(position)) = &pospkgs.get(*x) { + (position.starts_with("pkgs/applications/audio") + && category == PkgCategory::Audio) + || (position.starts_with( + "pkgs/applications/terminal-emulators", + ) && category == PkgCategory::Development) + || (position.starts_with("pkgs/applications/emulators") + && category == PkgCategory::Games) + || (position.starts_with("pkgs/applications/graphics") + && category == PkgCategory::Graphics) + || (position + .starts_with("pkgs/applications/networking") + && category == PkgCategory::Network) + || (position.starts_with("pkgs/applications/video") + && category == PkgCategory::Video) + || (position.starts_with("pkgs/tools/games") + && category == PkgCategory::Games) + || (position.starts_with("pkgs/games") + && category == PkgCategory::Games) + || (position.starts_with("pkgs/development") + && category == PkgCategory::Development) + || recpkgs.contains(x) + } else { + false + } + } else { + false + } + }) + .collect::>(); + + for pkg in catagortypkgs { + if checkpkgs(pkg.to_string(), &pospkgs, &appdata, category.clone()) { + allvec.push(pkg.to_string()); + } + } + + cvec.shuffle(&mut rng); + allvec.sort_by_key(|x| x.to_lowercase()); + catpicks.insert(category.clone(), cvec); + catpkgs.insert(category.clone(), allvec); } - match cr { - CacheReturn::Init => { - sender.output(AppMsg::Initialize(pkgs, recpicks, newpkgs, catpicks, catpkgs, profilepkgs)); - } - CacheReturn::Update => { - sender.output(AppMsg::ReloadUpdateItems(pkgs, newpkgs)); + while recpicks.len() < 12 { + if let Some(p) = recpkgs.pop() { + if !recpicks.contains(&p.to_string()) { + recpicks.push(p.to_string()); + } + } else { + break; } } + recpicks.shuffle(&mut rng); + + sender.output(AppMsg::Initialize( + pkgdb, nixpkgsdb, systemdb, appdata, recpicks, catpicks, catpkgs, + )); }); } } @@ -435,12 +387,11 @@ pub enum LoadErrorMsg { Show(String, String), Retry, Close, - // Preferences, } #[relm4::component(pub)] impl SimpleComponent for LoadErrorModel { - type InitParams = gtk::Window; + type Init = gtk::Window; type Input = LoadErrorMsg; type Output = AppMsg; type Widgets = LoadErrorWidgets; @@ -472,7 +423,7 @@ impl SimpleComponent for LoadErrorModel { } fn init( - parent_window: Self::InitParams, + parent_window: Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts {