diff --git a/.github/workflows/spot-snapshots.yml b/.github/workflows/spot-snapshots.yml index 46899bfb..d3cc56de 100644 --- a/.github/workflows/spot-snapshots.yml +++ b/.github/workflows/spot-snapshots.yml @@ -12,7 +12,7 @@ jobs: name: "Flatpak Builder" runs-on: ubuntu-latest container: - image: bilelmoussaoui/flatpak-github-actions:gnome-40 + image: bilelmoussaoui/flatpak-github-actions:gnome-42 options: --privileged steps: - uses: actions/checkout@v2 diff --git a/AUTHORS b/AUTHORS index 10985ad3..af000c4e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -17,4 +17,5 @@ Fridolin Weisser Jan Przebor Warren Hu bbb651 -Julius Rüberg \ No newline at end of file +Julius Rüberg +janbrummer \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 6b596c77..4d2078c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aes" version = "0.6.0" @@ -10,7 +25,19 @@ checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" dependencies = [ "aes-soft", "aesni", - "cipher", + "cipher 0.2.5", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "opaque-debug", ] [[package]] @@ -21,7 +48,7 @@ checksum = "7729c3cde54d67063be556aeac75a81330d802f0259500ca40cb52967f975763" dependencies = [ "aes-soft", "aesni", - "cipher", + "cipher 0.2.5", "ctr", ] @@ -31,7 +58,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" dependencies = [ - "cipher", + "cipher 0.2.5", "opaque-debug", ] @@ -41,31 +68,19 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" dependencies = [ - "cipher", + "cipher 0.2.5", "opaque-debug", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] -[[package]] -name = "alsa" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18" -dependencies = [ - "alsa-sys", - "bitflags", - "libc", - "nix 0.20.0", -] - [[package]] name = "alsa" version = "0.6.0" @@ -75,7 +90,7 @@ dependencies = [ "alsa-sys", "bitflags", "libc", - "nix 0.23.1", + "nix 0.23.2", ] [[package]] @@ -88,28 +103,37 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" -version = "1.0.53" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "async-broadcast" -version = "0.3.4" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90622698a1218e0b2fb846c97b5f19a0831f6baddee73d9454156365ccfa473b" +checksum = "1b19760fa2b7301cf235360ffd6d3558b1ed4249edd16d6cca8d690cee265b95" dependencies = [ - "easy-parallel", "event-listener", "futures-core", + "parking_lot 0.12.1", ] [[package]] name = "async-channel" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" dependencies = [ "concurrent-queue", "event-listener", @@ -118,76 +142,68 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", "concurrent-queue", "fastrand", "futures-lite", - "once_cell", "slab", ] [[package]] name = "async-global-executor" -version = "2.0.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", "async-io", - "async-mutex", + "async-lock", "blocking", "futures-lite", - "num_cpus", "once_cell", ] [[package]] name = "async-io" -version = "1.6.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ + "async-lock", + "autocfg", "concurrent-queue", "futures-lite", "libc", "log", - "once_cell", "parking", "polling", "slab", "socket2", "waker-fn", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-mutex" -version = "1.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] name = "async-recursion" -version = "0.3.2" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" +checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" dependencies = [ "proc-macro2", "quote", @@ -196,9 +212,9 @@ dependencies = [ [[package]] name = "async-std" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ "async-channel", "async-global-executor", @@ -213,7 +229,6 @@ dependencies = [ "kv-log-macro", "log", "memchr", - "num_cpus", "once_cell", "pin-project-lite", "pin-utils", @@ -223,15 +238,15 @@ dependencies = [ [[package]] name = "async-task" -version = "4.1.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] name = "async-trait" -version = "0.1.52" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -240,9 +255,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" [[package]] name = "atty" @@ -250,7 +265,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -261,17 +276,32 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +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 = "bindgen" -version = "0.56.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" +checksum = "8a022e58a142a46fea340d68012b9201c094e93ec3d033a944a24f8fd4a4f09a" dependencies = [ "bitflags", "cexpr", @@ -284,6 +314,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", + "syn", ] [[package]] @@ -307,14 +338,23 @@ 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 = "block-modes" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0" +checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" dependencies = [ "block-padding", - "cipher", + "cipher 0.3.0", ] [[package]] @@ -325,23 +365,23 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" dependencies = [ "async-channel", + "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", - "once_cell", ] [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byteorder" @@ -351,34 +391,29 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "cache-padded" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cairo-rs" -version = "0.15.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b869e97a87170f96762f9f178eae8c461147e722ba21dd8814105bf5716bf14a" +checksum = "a8af54f5d48af1226928adc1f57edd22f5df1349e7da1fc96ae15cf43db0e871" dependencies = [ "bitflags", "cairo-sys-rs", "glib", "libc", + "once_cell", "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.15.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" +checksum = "f55382a01d30e5e53f185eee269124f5e21ab526595b872751278dfbb463594e" dependencies = [ "glib-sys", "libc", @@ -393,9 +428,9 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" [[package]] name = "cc" -version = "1.0.72" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -408,28 +443,22 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cexpr" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfg-expr" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7" +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" @@ -438,14 +467,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "time", + "wasm-bindgen", "winapi", ] @@ -458,22 +489,41 @@ dependencies = [ "generic-array", ] +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "clang-sys" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", "libloading", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "combine" -version = "4.6.3" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ "bytes", "memchr", @@ -481,11 +531,11 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "1.2.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" dependencies = [ - "cache-padded", + "crossbeam-utils", ] [[package]] @@ -506,9 +556,9 @@ dependencies = [ [[package]] name = "coreaudio-sys" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca4679a59dbd8c15f064c012dfe8c1163b9453224238b59bb9328c142b8b248b" +checksum = "1a9444b94b8024feecc29e01a9706c69c1e26bfee480221c90764200cfd778fb" dependencies = [ "bindgen", ] @@ -519,7 +569,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74117836a5124f3629e4b474eed03e479abaf98988b4bb317e29f08cfe0e4116" dependencies = [ - "alsa 0.6.0", + "alsa", "core-foundation-sys", "coreaudio-rs", "jni", @@ -529,9 +579,9 @@ dependencies = [ "mach", "ndk", "ndk-glue", - "nix 0.23.1", + "nix 0.23.2", "oboe", - "parking_lot", + "parking_lot 0.11.2", "stdweb", "thiserror", "web-sys", @@ -540,31 +590,30 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] [[package]] name = "crossbeam-utils" -version = "0.8.7" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ - "cfg-if 1.0.0", - "lazy_static", + "cfg-if", ] [[package]] -name = "crypto-mac" -version = "0.10.1" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", - "subtle", + "typenum", ] [[package]] @@ -579,9 +628,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.21" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", "syn", @@ -593,14 +642,14 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" dependencies = [ - "cipher", + "cipher 0.2.5", ] [[package]] name = "curl" -version = "0.4.42" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de97b894edd5b5bcceef8b78d7da9b75b1d2f2f9a910569d0bde3dd31d84939" +checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" dependencies = [ "curl-sys", "libc", @@ -613,9 +662,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.52+curl-7.81.0" +version = "0.4.59+curl-7.86.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b8c2d1023ea5fded5b7b892e4b8e95f70038a421126a056761a84246a28971" +checksum = "6cfce34829f448b08f55b7db6d0009e23e2e86a34e8c2b366269bf5799b4a407" dependencies = [ "cc", "libc", @@ -627,11 +676,55 @@ dependencies = [ "winapi", ] +[[package]] +name = "cxx" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90d59d9acd2a682b4e40605a242f6670eaa58c5957471cbf85e8aa6a0b97a5e8" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebfa40bda659dd5c864e65f4c9a2b0aff19bea56b017b9b77c73d3766a453a38" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457ce6757c5c70dc6ecdbda6925b958aae7f959bda7d8fb9bde889e34a09dc03" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebf883b7aacd7b2aeb2a7b338648ee19f57c140d4ee8e52c68979c6b2f7f2263" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "darling" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ "darling_core", "darling_macro", @@ -639,9 +732,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", @@ -653,9 +746,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", @@ -683,56 +776,60 @@ dependencies = [ ] [[package]] -name = "easy-parallel" -version = "3.2.0" +name = "digest" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer 0.10.3", + "crypto-common", + "subtle", +] [[package]] -name = "encoding_rs" -version = "0.8.30" +name = "dirs" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "cfg-if 1.0.0", + "dirs-sys", ] [[package]] -name = "enumflags2" -version = "0.6.4" +name = "dirs-sys" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ - "enumflags2_derive 0.6.4", - "serde", + "libc", + "redox_users", + "winapi", ] [[package]] -name = "enumflags2" -version = "0.7.3" +name = "encoding_rs" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25c90b056b3f84111cf183cbeddef0d3a0bbe9a674f057e1a1533c315f24def" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ - "enumflags2_derive 0.7.3", - "serde", + "cfg-if", ] [[package]] -name = "enumflags2_derive" -version = "0.6.4" +name = "enumflags2" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" +checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "enumflags2_derive", + "serde", ] [[package]] name = "enumflags2_derive" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144ec79496cbab6f84fa125dc67be9264aef22eb8a28da8454d9c33f15108da4" +checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" dependencies = [ "proc-macro2", "quote", @@ -741,21 +838,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "atty", - "humantime", - "log", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.9.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", @@ -766,15 +851,15 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -789,6 +874,12 @@ dependencies = [ "rustc_version 0.3.3", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fnv" version = "1.0.7" @@ -797,19 +888,18 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "futures" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -822,9 +912,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -832,15 +922,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -849,9 +939,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-lite" @@ -870,9 +960,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -881,21 +971,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -911,22 +1001,23 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.15.6" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8750501d75f318c2ec0314701bc8403901303210def80bafd13f6b6059a3f45" +checksum = "b023fbe0c6b407bd3d9805d107d9800da3829dc5a676653210f1d5f16d7f59bf" dependencies = [ "bitflags", "gdk-pixbuf-sys", "gio", "glib", "libc", + "once_cell", ] [[package]] name = "gdk-pixbuf-sys" -version = "0.15.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413424d9818621fa3cfc8a3a915cdb89a7c3c507d56761b4ec83a9a98e587171" +checksum = "7b41bd2b44ed49d99277d3925652a163038bd5ed943ec9809338ffb2f4391e3b" dependencies = [ "gio-sys", "glib-sys", @@ -937,9 +1028,9 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.4.6" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9df40006277ff44538fe758400fc671146f6f2665978b6b57d2408db3c2becf" +checksum = "6e4887e17b6926db51f1e538d871a8b1f5ceb5dfa3bd0034dc42ec355b390d8f" dependencies = [ "bitflags", "cairo-rs", @@ -953,9 +1044,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.4.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48a39e34abe35ee2cf54a1e29dd983accecd113ad30bdead5050418fa92f2a1b" +checksum = "f4993c019bf03d18137c00ddafb2b23e73f7cbb45ae244f52af2542a3f4a9452" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -970,9 +1061,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -989,13 +1080,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -1010,36 +1101,45 @@ dependencies = [ [[package]] name = "gettext-sys" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa9e06ab9e7514cc9ae668ea3b71ea1536259d767dff0289ac23ad134f99929" +checksum = "c63ce2e00f56a206778276704bbe38564c8695249fdc8f354b4ef71c57c3839d" dependencies = [ "cc", "temp-dir", ] +[[package]] +name = "gimli" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec" + [[package]] name = "gio" -version = "0.15.7" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb50e113645fba48bc36c8abaee1fe5e43d353e8763966e29dfe69660514e461" +checksum = "1981edf8679d2f2c8ec3120015867f45aa0a1c2d5e3e129ca2f7dda174d3d2a9" dependencies = [ "bitflags", "futures-channel", "futures-core", "futures-io", + "futures-util", "gio-sys", "glib", "libc", "once_cell", + "pin-project-lite", + "smallvec", "thiserror", ] [[package]] name = "gio-sys" -version = "0.15.5" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f0bc4cfc9ebcdd05cc5057bc51b99c32f8f9bf246274f6a556ffd27279f8fe3" +checksum = "b5d3076ecb86c8c3a672c9843d6232b3a344fb81d304d0ba1ac64b23343efa46" dependencies = [ "glib-sys", "gobject-sys", @@ -1050,19 +1150,22 @@ dependencies = [ [[package]] name = "glib" -version = "0.15.9" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89528258cfdc79b1e54591202705be67896ad254f99e3cc2ea3710e0307148f2" +checksum = "91b429154ec5943185aeeaf79e646297567b6a056965f1e89da2657a0e23255b" dependencies = [ "bitflags", "futures-channel", "futures-core", "futures-executor", "futures-task", + "futures-util", + "gio-sys", "glib-macros", "glib-sys", "gobject-sys", "libc", + "memchr", "once_cell", "smallvec", "thiserror", @@ -1070,13 +1173,13 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.15.3" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58b262ff65ef771003873cea8c10e0fe854f1c508d48d62a4111a1ff163f7d1" +checksum = "9bc80ac951300ca288dd9ab3863743c37a608fb0e5ca12863495640ec6b781ab" dependencies = [ "anyhow", "heck", - "proc-macro-crate 1.1.0", + "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", @@ -1085,9 +1188,9 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.15.5" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1d4e1a63d8574541e5b92931e4e669ddc87ffa85d58e84e631dba13ad2e10c" +checksum = "9ddcb73fa8236277bedadaaadb76aef49c85d66340f83bece244f46c2d4f0e01" dependencies = [ "libc", "system-deps", @@ -1095,15 +1198,15 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gloo-timers" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", @@ -1113,9 +1216,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.15.5" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a" +checksum = "9a0155d388840c77d61b033b66ef4f9bc7f4133d83df83572d6b4fb234a3be7d" dependencies = [ "glib-sys", "libc", @@ -1124,9 +1227,9 @@ dependencies = [ [[package]] name = "graphene-rs" -version = "0.15.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c54f9fbbeefdb62c99f892dfca35f83991e2cb5b46a8dc2a715e58612f85570" +checksum = "21cf11565bb0e4dfc2f99d4775b6c329f0d40a2cff9c0066214d31a0e1b46256" dependencies = [ "glib", "graphene-sys", @@ -1135,9 +1238,9 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.15.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03f311acb023cf7af5537f35de028e03706136eead7f25a31e8fd26f5011e0b3" +checksum = "cf80a4849a8d9565410a8fec6fc3678e9c617f4ac7be182ca55ab75016e07af9" dependencies = [ "glib-sys", "libc", @@ -1147,9 +1250,9 @@ dependencies = [ [[package]] name = "gsk4" -version = "0.4.6" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf63d454e2f75abd92ee6de0ac9fc5aaf1018cd9c458aaf9de296c5cbab6bb9" +checksum = "432f981e4ea9f0739a5731d8a649acb794a3a729d2254e559ce7d613b17caf95" dependencies = [ "bitflags", "cairo-rs", @@ -1163,9 +1266,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.4.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31d21d7ce02ba261bb24c50c4ab238a10b41a2c97c32afffae29471b7cca69b" +checksum = "096cb59175b0915ebf69c05a45263c0c989bd8537b8f2169912d0de644ba6a76" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -1179,9 +1282,9 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.4.6" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e841556e3fe55d8a43ada76b7b08a5f65570bbdfe3b8f72c333053b8832c626" +checksum = "73421200ad9c3919d0720779b345b05d31a6ce9998e74fc27012f12580822e46" dependencies = [ "bitflags", "cairo-rs", @@ -1202,12 +1305,12 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.4.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573db42bb64973a4d5f718b73caa7204285a1a665308a23b11723d0ee56ec305" +checksum = "db4676c4f90d8b010e88cb4558f61f47d76d6f6b8e6f6b89e62640f443907f61" dependencies = [ "anyhow", - "proc-macro-crate 1.1.0", + "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", @@ -1216,9 +1319,9 @@ dependencies = [ [[package]] name = "gtk4-sys" -version = "0.4.5" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c47c075e8f795c38f6e9a47b51a73eab77b325f83c0154979ed4d4245c36490d" +checksum = "e13cf3bc9559f71963c957eb639060b643e1276ae47b892ef6091d5bc15c3e1b" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -1235,15 +1338,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "headers" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84c647447a07ca16f5fbd05b633e535cc41a08d2d74ab1e08648df53be9cb89" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ "base64", "bitflags", @@ -1252,7 +1355,7 @@ dependencies = [ "http", "httpdate", "mime", - "sha-1", + "sha1", ] [[package]] @@ -1266,9 +1369,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -1279,6 +1382,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -1287,32 +1399,30 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hkdf" -version = "0.10.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" dependencies = [ - "digest", - "hmac 0.10.1", + "hmac 0.12.1", ] [[package]] name = "hmac" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ - "crypto-mac 0.10.1", - "digest", + "crypto-mac", + "digest 0.9.0", ] [[package]] name = "hmac" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "crypto-mac 0.11.1", - "digest", + "digest 0.10.6", ] [[package]] @@ -1328,20 +1438,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa", ] [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -1350,9 +1460,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -1368,9 +1478,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -1380,7 +1490,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -1404,6 +1514,30 @@ dependencies = [ "tower-service", ] +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1412,41 +1546,29 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] [[package]] name = "if-addrs" -version = "0.6.7" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2273e421f7c4f0fc99e1934fe4776f59d8df2972f4199d703fc0da9f2a9f73de" +checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" dependencies = [ - "if-addrs-sys", "libc", "winapi", ] -[[package]] -name = "if-addrs-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de74b9dd780476e837e5eb5ab7c88b49ed304126e412030a0adba99c8efe79ea" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "indexmap" -version = "1.8.0" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -1458,14 +1580,14 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "isahc" -version = "1.7.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437f8808009c031df3c1d532c8fd7e3d73239dfe522ebf0b94b5e34d5d01044b" +checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" dependencies = [ "async-channel", "castaway", @@ -1492,15 +1614,9 @@ dependencies = [ [[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.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jni" @@ -1524,18 +1640,18 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.56" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -1574,10 +1690,12 @@ dependencies = [ [[package]] name = "libadwaita" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4b1d54d907dfa5d6663fdf4bdbe46c34747258b85c787adbf66187ccbaac81" +checksum = "674cbf1bd796f3d4f0c24466c15d91180e33e497ae2e07eea3f3d545468dc839" dependencies = [ + "bitflags", + "futures-channel", "gdk-pixbuf", "gdk4", "gio", @@ -1591,9 +1709,9 @@ dependencies = [ [[package]] name = "libadwaita-sys" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18b6ac4cadd252a89f5cba0a5a4e99836131795d6fad37b859ac79e8cb7d2c8" +checksum = "0727b85b4fe2b1bed5ac90df6343de15cbf8118bfb96d7c3cc1512681a4b34ac" dependencies = [ "gdk4-sys", "gio-sys", @@ -1601,36 +1719,37 @@ dependencies = [ "gobject-sys", "gtk4-sys", "libc", + "pango-sys", "system-deps", ] [[package]] name = "libc" -version = "0.2.117" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "winapi", ] [[package]] name = "libm" -version = "0.2.2" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libmdns" -version = "0.6.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac185a4d02e873c6d1ead59d674651f8ae5ec23ffe1637bee8de80665562a6a" +checksum = "6a60d8339ad1ddf68a81335fcafb6c6cf20d5036138a1e4ef86b8ce87f076c92" dependencies = [ "byteorder", "futures-util", @@ -1638,10 +1757,12 @@ dependencies = [ "if-addrs", "log", "multimap", + "nix 0.23.2", "rand", "socket2", "thiserror", "tokio", + "winapi", ] [[package]] @@ -1656,9 +1777,9 @@ dependencies = [ [[package]] name = "libpulse-binding" -version = "2.26.0" +version = "2.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17be42160017e0ae993c03bfdab4ecb6f82ce3f8d515bd8da8fdf18d10703663" +checksum = "1745b20bfc194ac12ef828f144f0ec2d4a7fe993281fa3567a0bd4969aee6890" dependencies = [ "bitflags", "libc", @@ -1670,9 +1791,9 @@ dependencies = [ [[package]] name = "libpulse-simple-binding" -version = "2.25.0" +version = "2.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cbf1a1dfd69a48cb60906399fa1d17f1b75029ef51c0789597be792dfd0bcd5" +checksum = "5ced94199e6e44133431374e4043f34e1f0697ebfb7b7d6c244a65bfaedf0e31" dependencies = [ "libpulse-binding", "libpulse-simple-sys", @@ -1681,9 +1802,9 @@ dependencies = [ [[package]] name = "libpulse-simple-sys" -version = "1.19.2" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c73f96f9ca34809692c4760cfe421225860aa000de50edab68a16221fd27cc1" +checksum = "84e423d9c619c908ce9b4916080e65ab586ca55b8c4939379f15e6e72fb43842" dependencies = [ "libpulse-sys", "pkg-config", @@ -1691,9 +1812,9 @@ dependencies = [ [[package]] name = "libpulse-sys" -version = "1.19.3" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991e6bd0efe2a36e6534e136e7996925e4c1a8e35b7807fe533f2beffff27c30" +checksum = "2191e6880818d1df4cf72eac8e91dce7a5a52ba0da4b2a5cdafabc22b937eadb" dependencies = [ "libc", "num-derive", @@ -1704,12 +1825,12 @@ dependencies = [ [[package]] name = "librespot" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb49bc466977d940fae6e9219d56e1355a2f3d77a348fe7f708fa8f36905491" +checksum = "ea4c9952ef48968f8184a4a87f8576982426ebe623342d5a28f7d9c4978e4a44" dependencies = [ "base64", - "env_logger 0.8.4", + "env_logger", "futures-util", "getopts", "hex", @@ -1731,9 +1852,9 @@ dependencies = [ [[package]] name = "librespot-audio" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f7cc7e4d1c2596191be523668c933e07ec8a318d099fd66658258a4fe4a2dc" +checksum = "c176a31355e1ea8e0b9c4ced19df4947bfe4770661c25c142b6fba2365940d9d" dependencies = [ "aes-ctr", "byteorder", @@ -1747,9 +1868,9 @@ dependencies = [ [[package]] name = "librespot-connect" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9dbfd8ee475a0874dc284f29c60d214bee43504979b244dd33763979f5ba76" +checksum = "4ffafb6a443e9445ccb3d5d591573b5b1da3c89a9b8846c63ba2c3710210d3ec" dependencies = [ "form_urlencoded", "futures-util", @@ -1768,11 +1889,11 @@ dependencies = [ [[package]] name = "librespot-core" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255e8d8d719c020895079d140baf0b0edec8447d39a7e4760708f33b7cafaafb" +checksum = "046349f25888e644bf02d9c5de0164b2a493d29aa4ce18e1ad0b756da9b55d6d" dependencies = [ - "aes", + "aes 0.6.0", "base64", "byteorder", "bytes", @@ -1786,7 +1907,7 @@ dependencies = [ "hyper-proxy", "librespot-protocol", "log", - "num-bigint 0.4.3", + "num-bigint", "num-integer", "num-traits", "once_cell", @@ -1809,13 +1930,12 @@ dependencies = [ [[package]] name = "librespot-discovery" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4adeff34212261a291f6519331f9232699a3b0208116f48cb47a97224ff5b63" +checksum = "2aa877d18f6150364012cb4be5682d62d7c712c88bae2d0d01720fd7c15e2f06" dependencies = [ "aes-ctr", "base64", - "cfg-if 1.0.0", "form_urlencoded", "futures-core", "hmac 0.11.0", @@ -1832,9 +1952,9 @@ dependencies = [ [[package]] name = "librespot-metadata" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624ac29bb3ad2e565ef78a049a6c554d94e48b673aaba0bf7e7efd946d0b66cd" +checksum = "6b80361fcbcb5092056fd47c08c34d5d51b08385d8efb6941c0d3e46d032c21c" dependencies = [ "async-trait", "byteorder", @@ -1846,11 +1966,11 @@ dependencies = [ [[package]] name = "librespot-playback" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "188b252b690ae7387f84a481ff4211df1a5c21eb9bddfc25cbde48793f2e0ef2" +checksum = "5190a0b9bcc7f70ee4196a6b4a1c731d405ca130d4a6fcd4c561cfdde8b7cfb7" dependencies = [ - "alsa 0.5.0", + "alsa", "byteorder", "cpal", "futures-executor", @@ -1863,6 +1983,7 @@ dependencies = [ "librespot-metadata", "log", "ogg", + "parking_lot 0.12.1", "rand", "rand_distr", "rodio", @@ -1874,9 +1995,9 @@ dependencies = [ [[package]] name = "librespot-protocol" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b3699b05cb4c50caa5a5b7f5b3aadb928dfcc91cf1aa632c0dabce3ccc3ee4" +checksum = "5d6d3ac6196ac0ea67bbe039f56d6730a5d8b31502ef9bce0f504ed729dcb39f" dependencies = [ "glob", "protobuf", @@ -1885,9 +2006,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "libc", @@ -1895,6 +2016,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + [[package]] name = "locale_config" version = "0.3.0" @@ -1910,20 +2040,21 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "value-bag", ] @@ -1951,17 +2082,11 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -1979,25 +2104,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] -name = "mio" -version = "0.8.0" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "winapi", + "adler", ] [[package]] -name = "miow" -version = "0.3.7" +name = "mio" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ - "winapi", + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.42.0", ] [[package]] @@ -2009,16 +2139,6 @@ dependencies = [ "serde", ] -[[package]] -name = "nb-connect" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bb540dc6ef51cfe1916ec038ce7a620daf3a111e2502d745197cd53d6bca15" -dependencies = [ - "libc", - "socket2", -] - [[package]] name = "ndk" version = "0.6.0" @@ -2032,16 +2152,23 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "ndk-glue" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c0d14b0858eb9962a5dac30b809b19f19da7e4547d64af2b0bb051d2e55d79" +checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f" dependencies = [ "lazy_static", "libc", "log", "ndk", + "ndk-context", "ndk-macro", "ndk-sys", ] @@ -2053,7 +2180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" dependencies = [ "darling", - "proc-macro-crate 1.1.0", + "proc-macro-crate", "proc-macro2", "quote", "syn", @@ -2070,68 +2197,57 @@ dependencies = [ [[package]] name = "nix" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" -dependencies = [ - "bitflags", - "cc", - "cfg-if 0.1.10", - "libc", - "void", -] - -[[package]] -name = "nix" -version = "0.20.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", + "memoffset", ] [[package]] name = "nix" -version = "0.23.1" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ + "autocfg", "bitflags", - "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset", + "pin-utils", ] [[package]] name = "nom" -version = "5.1.2" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", - "version_check", + "minimal-lexical", ] [[package]] -name = "ntapi" -version = "0.3.6" +name = "nom8" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" dependencies = [ - "winapi", + "memchr", ] [[package]] name = "num" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" dependencies = [ - "num-bigint 0.3.3", + "num-bigint", "num-complex", "num-integer", "num-iter", @@ -2139,17 +2255,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.3" @@ -2164,9 +2269,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.3.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" dependencies = [ "num-traits", ] @@ -2184,9 +2289,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -2194,9 +2299,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg", "num-integer", @@ -2205,21 +2310,21 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", - "num-bigint 0.3.3", + "num-bigint", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", "libm", @@ -2227,30 +2332,30 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] [[package]] name = "num_enum" -version = "0.5.6" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad" +checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.6" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21" +checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate", "proc-macro2", "quote", "syn", @@ -2285,15 +2390,24 @@ dependencies = [ "objc", ] +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + [[package]] name = "oboe" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2463c8f2e19b4e0d0710a21f8e4011501ff28db1c95d7a5482a553b2100502d2" +checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1" dependencies = [ "jni", "ndk", - "ndk-glue", + "ndk-context", "num-derive", "num-traits", "oboe-sys", @@ -2319,9 +2433,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "opaque-debug" @@ -2337,9 +2451,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.72" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg", "cc", @@ -2350,9 +2464,9 @@ dependencies = [ [[package]] name = "ordered-stream" -version = "0.0.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" dependencies = [ "futures-core", "pin-project-lite", @@ -2360,11 +2474,12 @@ dependencies = [ [[package]] name = "pango" -version = "0.15.2" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79211eff430c29cc38c69e0ab54bc78fa1568121ca9737707eee7f92a8417a94" +checksum = "243c048be90312220fb3bd578176eed8290568274a93c95040289d39349384bc" dependencies = [ "bitflags", + "gio", "glib", "libc", "once_cell", @@ -2373,9 +2488,9 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.15.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7022c2fb88cd2d9d55e1a708a8c53a3ae8678234c4a54bf623400aeb7f31fac2" +checksum = "4293d0f0b5525eb5c24734d30b0ed02cd02aa734f216883f376b54de49625de8" dependencies = [ "glib-sys", "gobject-sys", @@ -2397,16 +2512,26 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall", @@ -2414,13 +2539,29 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "backtrace", + "cfg-if", + "libc", + "petgraph", + "redox_syscall", + "smallvec", + "thread-id", + "windows-sys 0.45.0", +] + [[package]] name = "pbkdf2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" dependencies = [ - "crypto-mac 0.11.1", + "crypto-mac", "hmac 0.11.0", ] @@ -2432,33 +2573,44 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.1.3" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660" dependencies = [ + "thiserror", "ucd-trie", ] +[[package]] +name = "petgraph" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "pin-project" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", @@ -2467,9 +2619,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -2479,34 +2631,35 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "polling" -version = "2.2.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" dependencies = [ - "cfg-if 1.0.0", + "autocfg", + "cfg-if", "libc", "log", "wepoll-ffi", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "priority-queue" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00ba480ac08d3cfc40dea10fd466fd2c14dee3ea6fc7873bc4079eda2727caf0" +checksum = "5ca9c6be70d989d21a136eb86c2d83e4b328447fac4a88dace2143c179c86267" dependencies = [ "autocfg", "indexmap", @@ -2514,21 +2667,12 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ - "thiserror", - "toml", + "once_cell", + "toml_edit", ] [[package]] @@ -2557,33 +2701,33 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "protobuf" -version = "2.27.1" +version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "protobuf-codegen" -version = "2.27.1" +version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aec1632b7c8f2e620343439a7dfd1f3c47b18906c4be58982079911482b5d707" +checksum = "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6" dependencies = [ "protobuf", ] [[package]] name = "protobuf-codegen-pure" -version = "2.27.1" +version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f8122fdb18e55190c796b088a16bdb70cd7acdcd48f7a8b796b58c62e532cc6" +checksum = "95a29399fc94bcd3eeaa951c715f7bea69409b2445356b00519740bcd6ddd865" dependencies = [ "protobuf", "protobuf-codegen", @@ -2591,9 +2735,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.15" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -2621,9 +2765,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -2640,13 +2784,24 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "ref_filter_map" version = "1.0.1" @@ -2655,9 +2810,9 @@ checksum = "2b5ceb840e4009da4841ed22a15eb49f64fdd00a2138945c5beacf506b2fb5ed" [[package]] name = "regex" -version = "1.5.5" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -2666,9 +2821,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -2681,23 +2836,31 @@ dependencies = [ [[package]] name = "rodio" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9" +checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e" dependencies = [ "cpal", ] [[package]] name = "rpassword" -version = "5.0.1" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" +checksum = "2bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956" dependencies = [ "libc", + "serde", + "serde_json", "winapi", ] +[[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" @@ -2719,14 +2882,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.5", + "semver 1.0.16", ] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "same-file" @@ -2739,44 +2902,42 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "winapi", + "windows-sys 0.42.0", ] -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "secret-service" -version = "2.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2400fb1bf2a87b303ada204946294f932ade4929477e9e2bf66d7b49a66656ec" +checksum = "5da1a5ad4d28c03536f82f77d9f36603f5e37d8869ac98f0a750d5b5686d8d95" dependencies = [ - "aes", + "aes 0.7.5", "block-modes", + "futures-util", + "generic-array", "hkdf", - "lazy_static", "num", + "once_cell", "rand", "serde", "sha2", - "zbus 1.9.1", - "zbus_macros 1.9.1", - "zvariant 2.10.0", - "zvariant_derive 2.10.0", + "zbus", ] [[package]] @@ -2790,9 +2951,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.5" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "semver-parser" @@ -2805,18 +2966,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -2825,20 +2986,20 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2", "quote", @@ -2851,39 +3012,33 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ - "block-buffer", - "cfg-if 1.0.0", + "block-buffer 0.9.0", + "cfg-if", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] [[package]] name = "sha1" -version = "0.6.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ - "sha1_smol", + "cfg-if", + "cpufeatures", + "digest 0.10.6", ] -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - [[package]] name = "sha2" -version = "0.9.9" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ - "block-buffer", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest", - "opaque-debug", + "digest 0.10.6", ] [[package]] @@ -2903,24 +3058,27 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "0.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] [[package]] name = "slab" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "sluice" @@ -2935,15 +3093,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -2951,10 +3109,10 @@ dependencies = [ [[package]] name = "spot" -version = "0.3.3" +version = "0.4.0" dependencies = [ "async-std", - "env_logger 0.9.0", + "env_logger", "form_urlencoded", "futures", "gdk-pixbuf", @@ -2978,8 +3136,8 @@ dependencies = [ "serde_json", "thiserror", "tokio", - "zbus 2.1.1", - "zvariant 3.1.2", + "zbus", + "zvariant", ] [[package]] @@ -3008,32 +3166,20 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.86" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", - "unicode-xid", -] - -[[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", + "unicode-ident", ] [[package]] name = "system-deps" -version = "6.0.1" +version = "6.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad3a97fdef3daf935d929b3e97e5a6a680cd4622e40c2941ca0875d6566416f8" +checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" dependencies = [ "cfg-expr", "heck", @@ -3054,7 +3200,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "libc", "redox_syscall", @@ -3064,82 +3210,95 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "thread-id" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fdfe0627923f7411a43ec9ec9c39c3a9b4151be313e0922042581fb6c9b717f" +dependencies = [ + "libc", + "redox_syscall", + "winapi", +] + [[package]] name = "time" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.17.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", - "once_cell", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", @@ -3148,9 +3307,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", @@ -3159,40 +3318,57 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", "futures-sink", - "log", "pin-project-lite", "tokio", + "tracing", ] [[package]] name = "toml" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.30" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -3201,9 +3377,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.19" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", @@ -3212,11 +3388,11 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.22" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] @@ -3231,75 +3407,84 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + +[[package]] +name = "uds_windows" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +dependencies = [ + "tempfile", + "winapi", +] [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" + +[[package]] +name = "unicode-ident" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] [[package]] name = "uuid" -version = "0.8.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" dependencies = [ "getrandom", ] [[package]] name = "value-bag" -version = "1.0.0-alpha.8" +version = "1.0.0-alpha.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" dependencies = [ "ctor", "version_check", @@ -3324,9 +3509,9 @@ dependencies = [ [[package]] name = "version-compare" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" [[package]] name = "version_check" @@ -3334,12 +3519,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "waker-fn" version = "1.1.0" @@ -3369,29 +3548,35 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -3400,11 +3585,11 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.29" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -3412,9 +3597,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3422,9 +3607,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -3435,15 +3620,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.56" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -3490,36 +3675,93 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "zbus" -version = "1.9.1" +name = "windows-sys" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2326acc379a3ac4e34b794089f5bdb17086bf29a5fdf619b7b4cc772dc2e9dad" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "async-io", - "byteorder", - "derivative", - "enumflags2 0.6.4", - "fastrand", - "futures", - "nb-connect", - "nix 0.17.0", - "once_cell", - "polling", - "scoped-tls", - "serde", - "serde_repr", - "zbus_macros 1.9.1", - "zvariant 2.10.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + [[package]] name = "zbus" -version = "2.1.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb86f3d4592e26a48b2719742aec94f8ae6238ebde20d98183ee185d1275e9a" +checksum = "f770930448dd412a4a7131dd968a8e6df0064db4d7916fbbd2d6c3f26b566938" dependencies = [ "async-broadcast", - "async-channel", "async-executor", "async-io", "async-lock", @@ -3528,14 +3770,14 @@ dependencies = [ "async-trait", "byteorder", "derivative", - "enumflags2 0.7.3", + "dirs", + "enumflags2", "event-listener", "futures-core", "futures-sink", "futures-util", "hex", - "lazy_static", - "nix 0.23.1", + "nix 0.25.1", "once_cell", "ordered-stream", "rand", @@ -3543,31 +3785,21 @@ dependencies = [ "serde_repr", "sha1", "static_assertions", + "tracing", + "uds_windows", "winapi", - "zbus_macros 2.1.1", + "zbus_macros", "zbus_names", - "zvariant 3.1.2", + "zvariant", ] [[package]] name = "zbus_macros" -version = "1.9.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a482c56029e48681b89b92b5db3c446db0915e8dd1052c0328a574eda38d5f93" +checksum = "4832059b438689017db7340580ebabba07f114eab91bf990c6e55052408b40d8" dependencies = [ - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zbus_macros" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36823cc10fddc3c6b19f048903262dacaf8274170e9a255784bdd8b4570a8040" -dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate", "proc-macro2", "quote", "regex", @@ -3576,20 +3808,20 @@ dependencies = [ [[package]] name = "zbus_names" -version = "2.1.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45dfcdcf87b71dad505d30cc27b1b7b88a64b6d1c435648f48f9dbc1fdc4b7e1" +checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3" dependencies = [ "serde", "static_assertions", - "zvariant 3.1.2", + "zvariant", ] [[package]] name = "zerocopy" -version = "0.3.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6580539ad917b7c026220c4b3f2c08d52ce54d6ce0dc491e66002e35388fab46" +checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236" dependencies = [ "byteorder", "zerocopy-derive", @@ -3597,62 +3829,36 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" +checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3" dependencies = [ "proc-macro2", + "quote", "syn", - "synstructure", -] - -[[package]] -name = "zvariant" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68c7b55f2074489b7e8e07d2d0a6ee6b4f233867a653c664d8020ba53692525" -dependencies = [ - "byteorder", - "enumflags2 0.6.4", - "libc", - "serde", - "static_assertions", - "zvariant_derive 2.10.0", ] [[package]] name = "zvariant" -version = "3.1.2" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ea5dc38b2058fae6a5b79009388143dadce1e91c26a67f984a0fc0381c8033" +checksum = "903169c05b9ab948ee93fefc9127d08930df4ce031d46c980784274439803e51" dependencies = [ "byteorder", - "enumflags2 0.7.3", + "enumflags2", "libc", "serde", "static_assertions", - "zvariant_derive 3.1.2", -] - -[[package]] -name = "zvariant_derive" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ca5e22593eb4212382d60d26350065bf2a02c34b85bc850474a74b589a3de9" -dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", + "zvariant_derive", ] [[package]] name = "zvariant_derive" -version = "3.1.2" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2cecc5a61c2a053f7f653a24cd15b3b0195d7f7ddb5042c837fb32e161fb7a" +checksum = "cce76636e8fab7911be67211cf378c252b115ee7f2bae14b18b84821b39260b5" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate", "proc-macro2", "quote", "syn", diff --git a/Cargo.toml b/Cargo.toml index eea8be79..945780e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,27 +1,28 @@ [package] name = "spot" -version = "0.3.3" +version = "0.4.0" edition = "2018" license = "MIT" [dependencies.gtk] -version = "^0.4.1" +version = "^0.6.0" package = "gtk4" +features = ["gnome_42"] [dependencies.gdk] -version = "^0.4.0" +version = "^0.6.0" package = "gdk4" [dependencies.gio] -version = "^0.15.7" +version = "^0.17.0" features = ["v2_60"] [dependencies.glib] -version = "^0.15.9" +version = "^0.17.0" features = ["v2_60"] [dependencies.librespot] -version = "0.3.1" +version = "0.4.2" features = ["alsa-backend", "pulseaudio-backend"] [dependencies.protobuf] @@ -31,7 +32,6 @@ version = "2.25.2" version = "1" features = ["rt", "macros", "sync"] - [dependencies.futures] package = "futures" version = "0.3.18" @@ -41,10 +41,10 @@ version = "^1.0.136" features = ["derive"] [dependencies.serde_json] -version = "^1.0.79" +version = "^1.0.93" [dependencies.isahc] -version = "^1.7.0" +version = "^1.7.2" features = ["json"] [dependencies.rand] @@ -55,16 +55,19 @@ features = ["small_rng"] version = "0.7.0" features = ["gettext-system"] +[dependencies.secret-service] +version = "3.0.0" +features = ["rt-async-io-crypto-rust"] + [dependencies] -secret-service = "^2.0.1" -gdk-pixbuf = "^0.15.6" -libadwaita = "^0.1.0-beta-1" +gdk-pixbuf = "^0.17.0" +libadwaita = "^0.3.0" ref_filter_map = "^1.0.1" regex = "^1.5.5" -async-std = "^1.10.0" +async-std = "^1.12.0" form_urlencoded = "^1.0.1" -zbus = "^2.0.1" -zvariant = "^3.1.2" +zbus = "^3.10" +zvariant = "^3.11" thiserror = "^1.0.30" lazy_static = "^1.4.0" log = "0.4.14" diff --git a/README.md b/README.md index 89042e19..3713a6ce 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ See [this comment](https://github.com/xou816/spot/issues/92#issuecomment-8018525 ### Settings -Spot can also be configured via `gsettings` if you want to change the audio backend, the song bitrate, etc. [A GUI is planned but not available yet.](https://github.com/xou816/spot/issues/142) +Spot can also be configured via `gsettings` if you want to change the audio backend, the song bitrate, etc. ### Seek bar warping It is possible to click on the seek bar to navigate to that position in a song. If you are having issues with this not working you may have [gtk-primary-button-warps-slider](https://docs.gtk.org/gtk3/property.Settings.gtk-primary-button-warps-slider.html) set to false. @@ -41,11 +41,11 @@ Scrobbling is not supported directly by Spot. However, you can use a tool such a ### Lyrics -Similarly, Spot does not display lyrics for songs, but you can use [osdlyrics](https://github.com/osdlyrics/osdlyrics) ([see #226](https://github.com/xou816/spot/issues/226)). +Similarly, Spot does not display lyrics for songs, but you can use [osdlyrics](https://github.com/osdlyrics/osdlyrics) ([see #226](https://github.com/xou816/spot/issues/226)). ### Gtk theme -Spot uses the dark theme variant by default; this can be changed using `gsettings`. +Spot uses the dark theme variant by default; this can be changed in the settings. If you are using the flatpak version, don't forget to install your theme with flatpak as well. See [this comment](https://github.com/xou816/spot/issues/209#issuecomment-860180537) for details. @@ -64,11 +64,11 @@ Similarly, snap also requires that you install the corresponding snap for your t - view album info - credentials management with Secret Service - MPRIS integration +- playlist management (creation and edition) +- liked tracks ### Planned -- playlist management (creation and edition) -- liked tracks - GNOME search provider? - improved search? (track results) - recommendations? @@ -77,13 +77,13 @@ Similarly, snap also requires that you install the corresponding snap for your t Contributions are welcome! If you wish, add yourself to the `AUTHORS` files when submitting your contribution. -For any large feature/change, please consider opening an issue first to discuss implementation and design decisions. +For any large feature/change, **please** open an issue first to discuss implementation and design decisions. ### Translating Translations are managed using `gettext` and are available in the `po/` subdirectory. -**I am now experimenting an online service, [POEditor](https://poeditor.com/join/project?hash=xfVrpQfRBM), to manage translations; PRs are still welcome if you feel like using these instead!** +**Please use [POEditor](https://poeditor.com/join/project?hash=xfVrpQfRBM) to submit translations.** If you feel like it, you are welcome to open a PR to be added to the `TRANSLATORS` file! @@ -104,6 +104,8 @@ With meson: ``` meson target -Dbuildtype=debug -Doffline=false --prefix="$HOME/.local" ninja install -C target +# to run test/linter/etc +meson test -C target --verbose ``` This will install a `.desktop` file among other things, and the spot executable will be put in `.local/bin` (you might want to add it to your path). diff --git a/build-aux/clippy.sh b/build-aux/clippy.sh index da649d85..286599b0 100644 --- a/build-aux/clippy.sh +++ b/build-aux/clippy.sh @@ -8,4 +8,8 @@ if [[ $OFFLINE = "true" ]]; then export CARGO_HOME="$SRC"/cargo fi -cargo clippy --manifest-path "$SRC"/Cargo.toml -- -D warnings -A clippy::module_inception -A clippy::new_without_default -A clippy::enum-variant-names +cargo clippy --manifest-path "$SRC"/Cargo.toml -- -D warnings \ +-A clippy::module_inception \ +-A clippy::new_without_default \ +-A clippy::enum-variant-names \ +-A clippy::uninlined_format_args #tmp diff --git a/cargo-sources.json b/cargo-sources.json index bcd8e811..00d60241 100644 --- a/cargo-sources.json +++ b/cargo-sources.json @@ -1,4 +1,30 @@ [ + { + "type": "file", + "url": "https://static.crates.io/crates/addr2line/addr2line-0.19.0.crate", + "sha256": "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97", + "dest": "cargo/vendor", + "dest-filename": "addr2line-0.19.0.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/addr2line-0.19.0", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/adler/adler-1.0.2.crate", + "sha256": "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe", + "dest": "cargo/vendor", + "dest-filename": "adler-1.0.2.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/adler-1.0.2", + "dest-filename": ".cargo-checksum.json" + }, { "type": "file", "url": "https://static.crates.io/crates/aes/aes-0.6.0.crate", @@ -12,6 +38,19 @@ "dest": "cargo/vendor/aes-0.6.0", "dest-filename": ".cargo-checksum.json" }, + { + "type": "file", + "url": "https://static.crates.io/crates/aes/aes-0.7.5.crate", + "sha256": "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8", + "dest": "cargo/vendor", + "dest-filename": "aes-0.7.5.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%229e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/aes-0.7.5", + "dest-filename": ".cargo-checksum.json" + }, { "type": "file", "url": "https://static.crates.io/crates/aes-ctr/aes-ctr-0.6.0.crate", @@ -53,28 +92,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/aho-corasick/aho-corasick-0.7.18.crate", - "sha256": "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f", + "url": "https://static.crates.io/crates/aho-corasick/aho-corasick-0.7.20.crate", + "sha256": "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac", "dest": "cargo/vendor", - "dest-filename": "aho-corasick-0.7.18.crate" + "dest-filename": "aho-corasick-0.7.20.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/aho-corasick-0.7.18", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "file", - "url": "https://static.crates.io/crates/alsa/alsa-0.5.0.crate", - "sha256": "75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18", - "dest": "cargo/vendor", - "dest-filename": "alsa-0.5.0.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%2275c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/alsa-0.5.0", + "url": "data:%7B%22package%22%3A%20%22cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/aho-corasick-0.7.20", "dest-filename": ".cargo-checksum.json" }, { @@ -105,171 +131,171 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/anyhow/anyhow-1.0.53.crate", - "sha256": "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0", + "url": "https://static.crates.io/crates/android_system_properties/android_system_properties-0.1.5.crate", + "sha256": "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311", "dest": "cargo/vendor", - "dest-filename": "anyhow-1.0.53.crate" + "dest-filename": "android_system_properties-0.1.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2294a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/anyhow-1.0.53", + "url": "data:%7B%22package%22%3A%20%22819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/android_system_properties-0.1.5", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-broadcast/async-broadcast-0.3.4.crate", - "sha256": "90622698a1218e0b2fb846c97b5f19a0831f6baddee73d9454156365ccfa473b", + "url": "https://static.crates.io/crates/anyhow/anyhow-1.0.69.crate", + "sha256": "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800", "dest": "cargo/vendor", - "dest-filename": "async-broadcast-0.3.4.crate" + "dest-filename": "anyhow-1.0.69.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2290622698a1218e0b2fb846c97b5f19a0831f6baddee73d9454156365ccfa473b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-broadcast-0.3.4", + "url": "data:%7B%22package%22%3A%20%22224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/anyhow-1.0.69", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-channel/async-channel-1.6.1.crate", - "sha256": "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319", + "url": "https://static.crates.io/crates/async-broadcast/async-broadcast-0.5.0.crate", + "sha256": "1b19760fa2b7301cf235360ffd6d3558b1ed4249edd16d6cca8d690cee265b95", "dest": "cargo/vendor", - "dest-filename": "async-channel-1.6.1.crate" + "dest-filename": "async-broadcast-0.5.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-channel-1.6.1", + "url": "data:%7B%22package%22%3A%20%221b19760fa2b7301cf235360ffd6d3558b1ed4249edd16d6cca8d690cee265b95%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-broadcast-0.5.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-executor/async-executor-1.4.1.crate", - "sha256": "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965", + "url": "https://static.crates.io/crates/async-channel/async-channel-1.8.0.crate", + "sha256": "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833", "dest": "cargo/vendor", - "dest-filename": "async-executor-1.4.1.crate" + "dest-filename": "async-channel-1.8.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-executor-1.4.1", + "url": "data:%7B%22package%22%3A%20%22cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-channel-1.8.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-global-executor/async-global-executor-2.0.2.crate", - "sha256": "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6", + "url": "https://static.crates.io/crates/async-executor/async-executor-1.5.0.crate", + "sha256": "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b", "dest": "cargo/vendor", - "dest-filename": "async-global-executor-2.0.2.crate" + "dest-filename": "async-executor-1.5.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-global-executor-2.0.2", + "url": "data:%7B%22package%22%3A%20%2217adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-executor-1.5.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-io/async-io-1.6.0.crate", - "sha256": "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b", + "url": "https://static.crates.io/crates/async-global-executor/async-global-executor-2.3.1.crate", + "sha256": "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776", "dest": "cargo/vendor", - "dest-filename": "async-io-1.6.0.crate" + "dest-filename": "async-global-executor-2.3.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-io-1.6.0", + "url": "data:%7B%22package%22%3A%20%22f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-global-executor-2.3.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-lock/async-lock-2.4.0.crate", - "sha256": "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b", + "url": "https://static.crates.io/crates/async-io/async-io-1.12.0.crate", + "sha256": "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794", "dest": "cargo/vendor", - "dest-filename": "async-lock-2.4.0.crate" + "dest-filename": "async-io-1.12.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-lock-2.4.0", + "url": "data:%7B%22package%22%3A%20%228c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-io-1.12.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-mutex/async-mutex-1.4.0.crate", - "sha256": "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e", + "url": "https://static.crates.io/crates/async-lock/async-lock-2.6.0.crate", + "sha256": "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685", "dest": "cargo/vendor", - "dest-filename": "async-mutex-1.4.0.crate" + "dest-filename": "async-lock-2.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-mutex-1.4.0", + "url": "data:%7B%22package%22%3A%20%22c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-lock-2.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-recursion/async-recursion-0.3.2.crate", - "sha256": "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2", + "url": "https://static.crates.io/crates/async-recursion/async-recursion-1.0.2.crate", + "sha256": "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796", "dest": "cargo/vendor", - "dest-filename": "async-recursion-0.3.2.crate" + "dest-filename": "async-recursion-1.0.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-recursion-0.3.2", + "url": "data:%7B%22package%22%3A%20%223b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-recursion-1.0.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-std/async-std-1.10.0.crate", - "sha256": "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952", + "url": "https://static.crates.io/crates/async-std/async-std-1.12.0.crate", + "sha256": "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d", "dest": "cargo/vendor", - "dest-filename": "async-std-1.10.0.crate" + "dest-filename": "async-std-1.12.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-std-1.10.0", + "url": "data:%7B%22package%22%3A%20%2262565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-std-1.12.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-task/async-task-4.1.0.crate", - "sha256": "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8", + "url": "https://static.crates.io/crates/async-task/async-task-4.3.0.crate", + "sha256": "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524", "dest": "cargo/vendor", - "dest-filename": "async-task-4.1.0.crate" + "dest-filename": "async-task-4.3.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-task-4.1.0", + "url": "data:%7B%22package%22%3A%20%227a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-task-4.3.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/async-trait/async-trait-0.1.52.crate", - "sha256": "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3", + "url": "https://static.crates.io/crates/async-trait/async-trait-0.1.64.crate", + "sha256": "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2", "dest": "cargo/vendor", - "dest-filename": "async-trait-0.1.52.crate" + "dest-filename": "async-trait-0.1.64.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/async-trait-0.1.52", + "url": "data:%7B%22package%22%3A%20%221cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/async-trait-0.1.64", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/atomic-waker/atomic-waker-1.0.0.crate", - "sha256": "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a", + "url": "https://static.crates.io/crates/atomic-waker/atomic-waker-1.1.0.crate", + "sha256": "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599", "dest": "cargo/vendor", - "dest-filename": "atomic-waker-1.0.0.crate" + "dest-filename": "atomic-waker-1.1.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/atomic-waker-1.0.0", + "url": "data:%7B%22package%22%3A%20%22debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/atomic-waker-1.1.0", "dest-filename": ".cargo-checksum.json" }, { @@ -300,28 +326,41 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/base64/base64-0.13.0.crate", - "sha256": "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd", + "url": "https://static.crates.io/crates/backtrace/backtrace-0.3.67.crate", + "sha256": "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca", + "dest": "cargo/vendor", + "dest-filename": "backtrace-0.3.67.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/backtrace-0.3.67", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/base64/base64-0.13.1.crate", + "sha256": "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8", "dest": "cargo/vendor", - "dest-filename": "base64-0.13.0.crate" + "dest-filename": "base64-0.13.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/base64-0.13.0", + "url": "data:%7B%22package%22%3A%20%229e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/base64-0.13.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/bindgen/bindgen-0.56.0.crate", - "sha256": "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239", + "url": "https://static.crates.io/crates/bindgen/bindgen-0.61.0.crate", + "sha256": "8a022e58a142a46fea340d68012b9201c094e93ec3d033a944a24f8fd4a4f09a", "dest": "cargo/vendor", - "dest-filename": "bindgen-0.56.0.crate" + "dest-filename": "bindgen-0.61.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/bindgen-0.56.0", + "url": "data:%7B%22package%22%3A%20%228a022e58a142a46fea340d68012b9201c094e93ec3d033a944a24f8fd4a4f09a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/bindgen-0.61.0", "dest-filename": ".cargo-checksum.json" }, { @@ -365,15 +404,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/block-modes/block-modes-0.7.0.crate", - "sha256": "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0", + "url": "https://static.crates.io/crates/block-buffer/block-buffer-0.10.3.crate", + "sha256": "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e", + "dest": "cargo/vendor", + "dest-filename": "block-buffer-0.10.3.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%2269cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/block-buffer-0.10.3", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/block-modes/block-modes-0.8.1.crate", + "sha256": "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e", "dest": "cargo/vendor", - "dest-filename": "block-modes-0.7.0.crate" + "dest-filename": "block-modes-0.8.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2257a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/block-modes-0.7.0", + "url": "data:%7B%22package%22%3A%20%222cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/block-modes-0.8.1", "dest-filename": ".cargo-checksum.json" }, { @@ -391,28 +443,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/blocking/blocking-1.1.0.crate", - "sha256": "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427", + "url": "https://static.crates.io/crates/blocking/blocking-1.3.0.crate", + "sha256": "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8", "dest": "cargo/vendor", - "dest-filename": "blocking-1.1.0.crate" + "dest-filename": "blocking-1.3.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/blocking-1.1.0", + "url": "data:%7B%22package%22%3A%20%223c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/blocking-1.3.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/bumpalo/bumpalo-3.9.1.crate", - "sha256": "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899", + "url": "https://static.crates.io/crates/bumpalo/bumpalo-3.12.0.crate", + "sha256": "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535", "dest": "cargo/vendor", - "dest-filename": "bumpalo-3.9.1.crate" + "dest-filename": "bumpalo-3.12.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/bumpalo-3.9.1", + "url": "data:%7B%22package%22%3A%20%220d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/bumpalo-3.12.0", "dest-filename": ".cargo-checksum.json" }, { @@ -430,54 +482,41 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/bytes/bytes-1.1.0.crate", - "sha256": "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8", - "dest": "cargo/vendor", - "dest-filename": "bytes-1.1.0.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%22c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/bytes-1.1.0", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "file", - "url": "https://static.crates.io/crates/cache-padded/cache-padded-1.2.0.crate", - "sha256": "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c", + "url": "https://static.crates.io/crates/bytes/bytes-1.4.0.crate", + "sha256": "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be", "dest": "cargo/vendor", - "dest-filename": "cache-padded-1.2.0.crate" + "dest-filename": "bytes-1.4.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/cache-padded-1.2.0", + "url": "data:%7B%22package%22%3A%20%2289b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/bytes-1.4.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/cairo-rs/cairo-rs-0.15.1.crate", - "sha256": "b869e97a87170f96762f9f178eae8c461147e722ba21dd8814105bf5716bf14a", + "url": "https://static.crates.io/crates/cairo-rs/cairo-rs-0.17.0.crate", + "sha256": "a8af54f5d48af1226928adc1f57edd22f5df1349e7da1fc96ae15cf43db0e871", "dest": "cargo/vendor", - "dest-filename": "cairo-rs-0.15.1.crate" + "dest-filename": "cairo-rs-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b869e97a87170f96762f9f178eae8c461147e722ba21dd8814105bf5716bf14a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/cairo-rs-0.15.1", + "url": "data:%7B%22package%22%3A%20%22a8af54f5d48af1226928adc1f57edd22f5df1349e7da1fc96ae15cf43db0e871%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cairo-rs-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/cairo-sys-rs/cairo-sys-rs-0.15.1.crate", - "sha256": "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8", + "url": "https://static.crates.io/crates/cairo-sys-rs/cairo-sys-rs-0.17.0.crate", + "sha256": "f55382a01d30e5e53f185eee269124f5e21ab526595b872751278dfbb463594e", "dest": "cargo/vendor", - "dest-filename": "cairo-sys-rs-0.15.1.crate" + "dest-filename": "cairo-sys-rs-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%223c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/cairo-sys-rs-0.15.1", + "url": "data:%7B%22package%22%3A%20%22f55382a01d30e5e53f185eee269124f5e21ab526595b872751278dfbb463594e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cairo-sys-rs-0.17.0", "dest-filename": ".cargo-checksum.json" }, { @@ -495,15 +534,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/cc/cc-1.0.72.crate", - "sha256": "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee", + "url": "https://static.crates.io/crates/cc/cc-1.0.79.crate", + "sha256": "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f", "dest": "cargo/vendor", - "dest-filename": "cc-1.0.72.crate" + "dest-filename": "cc-1.0.79.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2222a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/cc-1.0.72", + "url": "data:%7B%22package%22%3A%20%2250d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cc-1.0.79", "dest-filename": ".cargo-checksum.json" }, { @@ -521,41 +560,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/cexpr/cexpr-0.4.0.crate", - "sha256": "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27", + "url": "https://static.crates.io/crates/cexpr/cexpr-0.6.0.crate", + "sha256": "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766", "dest": "cargo/vendor", - "dest-filename": "cexpr-0.4.0.crate" + "dest-filename": "cexpr-0.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/cexpr-0.4.0", + "url": "data:%7B%22package%22%3A%20%226fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cexpr-0.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/cfg-expr/cfg-expr-0.9.1.crate", - "sha256": "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7", + "url": "https://static.crates.io/crates/cfg-expr/cfg-expr-0.11.0.crate", + "sha256": "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa", "dest": "cargo/vendor", - "dest-filename": "cfg-expr-0.9.1.crate" + "dest-filename": "cfg-expr-0.11.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%223431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/cfg-expr-0.9.1", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "file", - "url": "https://static.crates.io/crates/cfg-if/cfg-if-0.1.10.crate", - "sha256": "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822", - "dest": "cargo/vendor", - "dest-filename": "cfg-if-0.1.10.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%224785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/cfg-if-0.1.10", + "url": "data:%7B%22package%22%3A%20%22b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cfg-expr-0.11.0", "dest-filename": ".cargo-checksum.json" }, { @@ -573,15 +599,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/chrono/chrono-0.4.19.crate", - "sha256": "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73", + "url": "https://static.crates.io/crates/chrono/chrono-0.4.23.crate", + "sha256": "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f", "dest": "cargo/vendor", - "dest-filename": "chrono-0.4.19.crate" + "dest-filename": "chrono-0.4.23.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/chrono-0.4.19", + "url": "data:%7B%22package%22%3A%20%2216b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/chrono-0.4.23", "dest-filename": ".cargo-checksum.json" }, { @@ -599,41 +625,67 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/clang-sys/clang-sys-1.3.1.crate", - "sha256": "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21", + "url": "https://static.crates.io/crates/cipher/cipher-0.3.0.crate", + "sha256": "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7", + "dest": "cargo/vendor", + "dest-filename": "cipher-0.3.0.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%227ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cipher-0.3.0", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/clang-sys/clang-sys-1.4.0.crate", + "sha256": "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3", "dest": "cargo/vendor", - "dest-filename": "clang-sys-1.3.1.crate" + "dest-filename": "clang-sys-1.4.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%224cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/clang-sys-1.3.1", + "url": "data:%7B%22package%22%3A%20%22fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/clang-sys-1.4.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/combine/combine-4.6.3.crate", - "sha256": "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062", + "url": "https://static.crates.io/crates/codespan-reporting/codespan-reporting-0.11.1.crate", + "sha256": "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e", "dest": "cargo/vendor", - "dest-filename": "combine-4.6.3.crate" + "dest-filename": "codespan-reporting-0.11.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2250b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/combine-4.6.3", + "url": "data:%7B%22package%22%3A%20%223538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/codespan-reporting-0.11.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/concurrent-queue/concurrent-queue-1.2.2.crate", - "sha256": "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3", + "url": "https://static.crates.io/crates/combine/combine-4.6.6.crate", + "sha256": "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4", "dest": "cargo/vendor", - "dest-filename": "concurrent-queue-1.2.2.crate" + "dest-filename": "combine-4.6.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2230ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/concurrent-queue-1.2.2", + "url": "data:%7B%22package%22%3A%20%2235ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/combine-4.6.6", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/concurrent-queue/concurrent-queue-2.1.0.crate", + "sha256": "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e", + "dest": "cargo/vendor", + "dest-filename": "concurrent-queue-2.1.0.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/concurrent-queue-2.1.0", "dest-filename": ".cargo-checksum.json" }, { @@ -664,15 +716,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/coreaudio-sys/coreaudio-sys-0.2.9.crate", - "sha256": "ca4679a59dbd8c15f064c012dfe8c1163b9453224238b59bb9328c142b8b248b", + "url": "https://static.crates.io/crates/coreaudio-sys/coreaudio-sys-0.2.11.crate", + "sha256": "1a9444b94b8024feecc29e01a9706c69c1e26bfee480221c90764200cfd778fb", "dest": "cargo/vendor", - "dest-filename": "coreaudio-sys-0.2.9.crate" + "dest-filename": "coreaudio-sys-0.2.11.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ca4679a59dbd8c15f064c012dfe8c1163b9453224238b59bb9328c142b8b248b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/coreaudio-sys-0.2.9", + "url": "data:%7B%22package%22%3A%20%221a9444b94b8024feecc29e01a9706c69c1e26bfee480221c90764200cfd778fb%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/coreaudio-sys-0.2.11", "dest-filename": ".cargo-checksum.json" }, { @@ -690,41 +742,41 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/cpufeatures/cpufeatures-0.2.1.crate", - "sha256": "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469", + "url": "https://static.crates.io/crates/cpufeatures/cpufeatures-0.2.5.crate", + "sha256": "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320", "dest": "cargo/vendor", - "dest-filename": "cpufeatures-0.2.1.crate" + "dest-filename": "cpufeatures-0.2.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2295059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/cpufeatures-0.2.1", + "url": "data:%7B%22package%22%3A%20%2228d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cpufeatures-0.2.5", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.7.crate", - "sha256": "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6", + "url": "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.14.crate", + "sha256": "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f", "dest": "cargo/vendor", - "dest-filename": "crossbeam-utils-0.8.7.crate" + "dest-filename": "crossbeam-utils-0.8.14.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/crossbeam-utils-0.8.7", + "url": "data:%7B%22package%22%3A%20%224fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/crossbeam-utils-0.8.14", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/crypto-mac/crypto-mac-0.10.1.crate", - "sha256": "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a", + "url": "https://static.crates.io/crates/crypto-common/crypto-common-0.1.6.crate", + "sha256": "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3", "dest": "cargo/vendor", - "dest-filename": "crypto-mac-0.10.1.crate" + "dest-filename": "crypto-common-0.1.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/crypto-mac-0.10.1", + "url": "data:%7B%22package%22%3A%20%221bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/crypto-common-0.1.6", "dest-filename": ".cargo-checksum.json" }, { @@ -742,15 +794,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/ctor/ctor-0.1.21.crate", - "sha256": "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa", + "url": "https://static.crates.io/crates/ctor/ctor-0.1.26.crate", + "sha256": "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096", "dest": "cargo/vendor", - "dest-filename": "ctor-0.1.21.crate" + "dest-filename": "ctor-0.1.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/ctor-0.1.21", + "url": "data:%7B%22package%22%3A%20%226d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/ctor-0.1.26", "dest-filename": ".cargo-checksum.json" }, { @@ -768,67 +820,119 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/curl/curl-0.4.42.crate", - "sha256": "7de97b894edd5b5bcceef8b78d7da9b75b1d2f2f9a910569d0bde3dd31d84939", + "url": "https://static.crates.io/crates/curl/curl-0.4.44.crate", + "sha256": "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22", + "dest": "cargo/vendor", + "dest-filename": "curl-0.4.44.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/curl-0.4.44", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/curl-sys/curl-sys-0.4.59+curl-7.86.0.crate", + "sha256": "6cfce34829f448b08f55b7db6d0009e23e2e86a34e8c2b366269bf5799b4a407", + "dest": "cargo/vendor", + "dest-filename": "curl-sys-0.4.59+curl-7.86.0.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%226cfce34829f448b08f55b7db6d0009e23e2e86a34e8c2b366269bf5799b4a407%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/curl-sys-0.4.59+curl-7.86.0", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/cxx/cxx-1.0.90.crate", + "sha256": "90d59d9acd2a682b4e40605a242f6670eaa58c5957471cbf85e8aa6a0b97a5e8", "dest": "cargo/vendor", - "dest-filename": "curl-0.4.42.crate" + "dest-filename": "cxx-1.0.90.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227de97b894edd5b5bcceef8b78d7da9b75b1d2f2f9a910569d0bde3dd31d84939%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/curl-0.4.42", + "url": "data:%7B%22package%22%3A%20%2290d59d9acd2a682b4e40605a242f6670eaa58c5957471cbf85e8aa6a0b97a5e8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cxx-1.0.90", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/curl-sys/curl-sys-0.4.52+curl-7.81.0.crate", - "sha256": "14b8c2d1023ea5fded5b7b892e4b8e95f70038a421126a056761a84246a28971", + "url": "https://static.crates.io/crates/cxx-build/cxx-build-1.0.90.crate", + "sha256": "ebfa40bda659dd5c864e65f4c9a2b0aff19bea56b017b9b77c73d3766a453a38", "dest": "cargo/vendor", - "dest-filename": "curl-sys-0.4.52+curl-7.81.0.crate" + "dest-filename": "cxx-build-1.0.90.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2214b8c2d1023ea5fded5b7b892e4b8e95f70038a421126a056761a84246a28971%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/curl-sys-0.4.52+curl-7.81.0", + "url": "data:%7B%22package%22%3A%20%22ebfa40bda659dd5c864e65f4c9a2b0aff19bea56b017b9b77c73d3766a453a38%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cxx-build-1.0.90", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/darling/darling-0.13.1.crate", - "sha256": "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4", + "url": "https://static.crates.io/crates/cxxbridge-flags/cxxbridge-flags-1.0.90.crate", + "sha256": "457ce6757c5c70dc6ecdbda6925b958aae7f959bda7d8fb9bde889e34a09dc03", "dest": "cargo/vendor", - "dest-filename": "darling-0.13.1.crate" + "dest-filename": "cxxbridge-flags-1.0.90.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/darling-0.13.1", + "url": "data:%7B%22package%22%3A%20%22457ce6757c5c70dc6ecdbda6925b958aae7f959bda7d8fb9bde889e34a09dc03%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cxxbridge-flags-1.0.90", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/darling_core/darling_core-0.13.1.crate", - "sha256": "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324", + "url": "https://static.crates.io/crates/cxxbridge-macro/cxxbridge-macro-1.0.90.crate", + "sha256": "ebf883b7aacd7b2aeb2a7b338648ee19f57c140d4ee8e52c68979c6b2f7f2263", "dest": "cargo/vendor", - "dest-filename": "darling_core-0.13.1.crate" + "dest-filename": "cxxbridge-macro-1.0.90.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/darling_core-0.13.1", + "url": "data:%7B%22package%22%3A%20%22ebf883b7aacd7b2aeb2a7b338648ee19f57c140d4ee8e52c68979c6b2f7f2263%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/cxxbridge-macro-1.0.90", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/darling_macro/darling_macro-0.13.1.crate", - "sha256": "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b", + "url": "https://static.crates.io/crates/darling/darling-0.13.4.crate", + "sha256": "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c", "dest": "cargo/vendor", - "dest-filename": "darling_macro-0.13.1.crate" + "dest-filename": "darling-0.13.4.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2272c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/darling_macro-0.13.1", + "url": "data:%7B%22package%22%3A%20%22a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/darling-0.13.4", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/darling_core/darling_core-0.13.4.crate", + "sha256": "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610", + "dest": "cargo/vendor", + "dest-filename": "darling_core-0.13.4.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/darling_core-0.13.4", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/darling_macro/darling_macro-0.13.4.crate", + "sha256": "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835", + "dest": "cargo/vendor", + "dest-filename": "darling_macro-0.13.4.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%229c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/darling_macro-0.13.4", "dest-filename": ".cargo-checksum.json" }, { @@ -859,145 +963,145 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/easy-parallel/easy-parallel-3.2.0.crate", - "sha256": "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946", + "url": "https://static.crates.io/crates/digest/digest-0.10.6.crate", + "sha256": "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f", "dest": "cargo/vendor", - "dest-filename": "easy-parallel-3.2.0.crate" + "dest-filename": "digest-0.10.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%226907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/easy-parallel-3.2.0", + "url": "data:%7B%22package%22%3A%20%228168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/digest-0.10.6", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/encoding_rs/encoding_rs-0.8.30.crate", - "sha256": "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df", + "url": "https://static.crates.io/crates/dirs/dirs-4.0.0.crate", + "sha256": "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059", "dest": "cargo/vendor", - "dest-filename": "encoding_rs-0.8.30.crate" + "dest-filename": "dirs-4.0.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/encoding_rs-0.8.30", + "url": "data:%7B%22package%22%3A%20%22ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/dirs-4.0.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/enumflags2/enumflags2-0.6.4.crate", - "sha256": "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0", + "url": "https://static.crates.io/crates/dirs-sys/dirs-sys-0.3.7.crate", + "sha256": "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6", "dest": "cargo/vendor", - "dest-filename": "enumflags2-0.6.4.crate" + "dest-filename": "dirs-sys-0.3.7.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2283c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/enumflags2-0.6.4", + "url": "data:%7B%22package%22%3A%20%221b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/dirs-sys-0.3.7", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/enumflags2/enumflags2-0.7.3.crate", - "sha256": "a25c90b056b3f84111cf183cbeddef0d3a0bbe9a674f057e1a1533c315f24def", + "url": "https://static.crates.io/crates/encoding_rs/encoding_rs-0.8.32.crate", + "sha256": "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394", "dest": "cargo/vendor", - "dest-filename": "enumflags2-0.7.3.crate" + "dest-filename": "encoding_rs-0.8.32.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a25c90b056b3f84111cf183cbeddef0d3a0bbe9a674f057e1a1533c315f24def%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/enumflags2-0.7.3", + "url": "data:%7B%22package%22%3A%20%22071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/encoding_rs-0.8.32", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/enumflags2_derive/enumflags2_derive-0.6.4.crate", - "sha256": "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce", + "url": "https://static.crates.io/crates/enumflags2/enumflags2-0.7.5.crate", + "sha256": "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb", "dest": "cargo/vendor", - "dest-filename": "enumflags2_derive-0.6.4.crate" + "dest-filename": "enumflags2-0.7.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/enumflags2_derive-0.6.4", + "url": "data:%7B%22package%22%3A%20%22e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/enumflags2-0.7.5", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/enumflags2_derive/enumflags2_derive-0.7.3.crate", - "sha256": "144ec79496cbab6f84fa125dc67be9264aef22eb8a28da8454d9c33f15108da4", + "url": "https://static.crates.io/crates/enumflags2_derive/enumflags2_derive-0.7.4.crate", + "sha256": "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae", "dest": "cargo/vendor", - "dest-filename": "enumflags2_derive-0.7.3.crate" + "dest-filename": "enumflags2_derive-0.7.4.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22144ec79496cbab6f84fa125dc67be9264aef22eb8a28da8454d9c33f15108da4%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/enumflags2_derive-0.7.3", + "url": "data:%7B%22package%22%3A%20%22f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/enumflags2_derive-0.7.4", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/env_logger/env_logger-0.8.4.crate", - "sha256": "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3", + "url": "https://static.crates.io/crates/env_logger/env_logger-0.9.3.crate", + "sha256": "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7", "dest": "cargo/vendor", - "dest-filename": "env_logger-0.8.4.crate" + "dest-filename": "env_logger-0.9.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/env_logger-0.8.4", + "url": "data:%7B%22package%22%3A%20%22a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/env_logger-0.9.3", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/env_logger/env_logger-0.9.0.crate", - "sha256": "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3", + "url": "https://static.crates.io/crates/event-listener/event-listener-2.5.3.crate", + "sha256": "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0", "dest": "cargo/vendor", - "dest-filename": "env_logger-0.9.0.crate" + "dest-filename": "event-listener-2.5.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%220b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/env_logger-0.9.0", + "url": "data:%7B%22package%22%3A%20%220206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/event-listener-2.5.3", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/event-listener/event-listener-2.5.2.crate", - "sha256": "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71", + "url": "https://static.crates.io/crates/fastrand/fastrand-1.8.0.crate", + "sha256": "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499", "dest": "cargo/vendor", - "dest-filename": "event-listener-2.5.2.crate" + "dest-filename": "fastrand-1.8.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2277f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/event-listener-2.5.2", + "url": "data:%7B%22package%22%3A%20%22a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/fastrand-1.8.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/fastrand/fastrand-1.7.0.crate", - "sha256": "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf", + "url": "https://static.crates.io/crates/field-offset/field-offset-0.3.4.crate", + "sha256": "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92", "dest": "cargo/vendor", - "dest-filename": "fastrand-1.7.0.crate" + "dest-filename": "field-offset-0.3.4.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/fastrand-1.7.0", + "url": "data:%7B%22package%22%3A%20%221e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/field-offset-0.3.4", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/field-offset/field-offset-0.3.4.crate", - "sha256": "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92", + "url": "https://static.crates.io/crates/fixedbitset/fixedbitset-0.4.2.crate", + "sha256": "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80", "dest": "cargo/vendor", - "dest-filename": "field-offset-0.3.4.crate" + "dest-filename": "fixedbitset-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/field-offset-0.3.4", + "url": "data:%7B%22package%22%3A%20%220ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/fixedbitset-0.4.2", "dest-filename": ".cargo-checksum.json" }, { @@ -1015,80 +1119,80 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/form_urlencoded/form_urlencoded-1.0.1.crate", - "sha256": "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191", + "url": "https://static.crates.io/crates/form_urlencoded/form_urlencoded-1.1.0.crate", + "sha256": "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8", "dest": "cargo/vendor", - "dest-filename": "form_urlencoded-1.0.1.crate" + "dest-filename": "form_urlencoded-1.1.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%225fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/form_urlencoded-1.0.1", + "url": "data:%7B%22package%22%3A%20%22a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/form_urlencoded-1.1.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/futures/futures-0.3.21.crate", - "sha256": "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e", + "url": "https://static.crates.io/crates/futures/futures-0.3.26.crate", + "sha256": "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84", "dest": "cargo/vendor", - "dest-filename": "futures-0.3.21.crate" + "dest-filename": "futures-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-0.3.21", + "url": "data:%7B%22package%22%3A%20%2213e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/futures-channel/futures-channel-0.3.21.crate", - "sha256": "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010", + "url": "https://static.crates.io/crates/futures-channel/futures-channel-0.3.26.crate", + "sha256": "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5", "dest": "cargo/vendor", - "dest-filename": "futures-channel-0.3.21.crate" + "dest-filename": "futures-channel-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-channel-0.3.21", + "url": "data:%7B%22package%22%3A%20%222e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-channel-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/futures-core/futures-core-0.3.21.crate", - "sha256": "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3", + "url": "https://static.crates.io/crates/futures-core/futures-core-0.3.26.crate", + "sha256": "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608", "dest": "cargo/vendor", - "dest-filename": "futures-core-0.3.21.crate" + "dest-filename": "futures-core-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%220c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-core-0.3.21", + "url": "data:%7B%22package%22%3A%20%22ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-core-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/futures-executor/futures-executor-0.3.21.crate", - "sha256": "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6", + "url": "https://static.crates.io/crates/futures-executor/futures-executor-0.3.26.crate", + "sha256": "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e", "dest": "cargo/vendor", - "dest-filename": "futures-executor-0.3.21.crate" + "dest-filename": "futures-executor-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-executor-0.3.21", + "url": "data:%7B%22package%22%3A%20%22e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-executor-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/futures-io/futures-io-0.3.21.crate", - "sha256": "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b", + "url": "https://static.crates.io/crates/futures-io/futures-io-0.3.26.crate", + "sha256": "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531", "dest": "cargo/vendor", - "dest-filename": "futures-io-0.3.21.crate" + "dest-filename": "futures-io-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-io-0.3.21", + "url": "data:%7B%22package%22%3A%20%22bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-io-0.3.26", "dest-filename": ".cargo-checksum.json" }, { @@ -1106,119 +1210,119 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/futures-macro/futures-macro-0.3.21.crate", - "sha256": "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512", + "url": "https://static.crates.io/crates/futures-macro/futures-macro-0.3.26.crate", + "sha256": "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70", "dest": "cargo/vendor", - "dest-filename": "futures-macro-0.3.21.crate" + "dest-filename": "futures-macro-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2233c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-macro-0.3.21", + "url": "data:%7B%22package%22%3A%20%2295a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-macro-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/futures-sink/futures-sink-0.3.21.crate", - "sha256": "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868", + "url": "https://static.crates.io/crates/futures-sink/futures-sink-0.3.26.crate", + "sha256": "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364", "dest": "cargo/vendor", - "dest-filename": "futures-sink-0.3.21.crate" + "dest-filename": "futures-sink-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2221163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-sink-0.3.21", + "url": "data:%7B%22package%22%3A%20%22f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-sink-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/futures-task/futures-task-0.3.21.crate", - "sha256": "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a", + "url": "https://static.crates.io/crates/futures-task/futures-task-0.3.26.crate", + "sha256": "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366", "dest": "cargo/vendor", - "dest-filename": "futures-task-0.3.21.crate" + "dest-filename": "futures-task-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2257c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-task-0.3.21", + "url": "data:%7B%22package%22%3A%20%22dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-task-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/futures-util/futures-util-0.3.21.crate", - "sha256": "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a", + "url": "https://static.crates.io/crates/futures-util/futures-util-0.3.26.crate", + "sha256": "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1", "dest": "cargo/vendor", - "dest-filename": "futures-util-0.3.21.crate" + "dest-filename": "futures-util-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/futures-util-0.3.21", + "url": "data:%7B%22package%22%3A%20%229c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/futures-util-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gdk-pixbuf/gdk-pixbuf-0.15.6.crate", - "sha256": "d8750501d75f318c2ec0314701bc8403901303210def80bafd13f6b6059a3f45", + "url": "https://static.crates.io/crates/gdk-pixbuf/gdk-pixbuf-0.17.0.crate", + "sha256": "b023fbe0c6b407bd3d9805d107d9800da3829dc5a676653210f1d5f16d7f59bf", "dest": "cargo/vendor", - "dest-filename": "gdk-pixbuf-0.15.6.crate" + "dest-filename": "gdk-pixbuf-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d8750501d75f318c2ec0314701bc8403901303210def80bafd13f6b6059a3f45%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gdk-pixbuf-0.15.6", + "url": "data:%7B%22package%22%3A%20%22b023fbe0c6b407bd3d9805d107d9800da3829dc5a676653210f1d5f16d7f59bf%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gdk-pixbuf-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gdk-pixbuf-sys/gdk-pixbuf-sys-0.15.1.crate", - "sha256": "413424d9818621fa3cfc8a3a915cdb89a7c3c507d56761b4ec83a9a98e587171", + "url": "https://static.crates.io/crates/gdk-pixbuf-sys/gdk-pixbuf-sys-0.17.0.crate", + "sha256": "7b41bd2b44ed49d99277d3925652a163038bd5ed943ec9809338ffb2f4391e3b", "dest": "cargo/vendor", - "dest-filename": "gdk-pixbuf-sys-0.15.1.crate" + "dest-filename": "gdk-pixbuf-sys-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22413424d9818621fa3cfc8a3a915cdb89a7c3c507d56761b4ec83a9a98e587171%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gdk-pixbuf-sys-0.15.1", + "url": "data:%7B%22package%22%3A%20%227b41bd2b44ed49d99277d3925652a163038bd5ed943ec9809338ffb2f4391e3b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gdk-pixbuf-sys-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gdk4/gdk4-0.4.6.crate", - "sha256": "d9df40006277ff44538fe758400fc671146f6f2665978b6b57d2408db3c2becf", + "url": "https://static.crates.io/crates/gdk4/gdk4-0.6.0.crate", + "sha256": "6e4887e17b6926db51f1e538d871a8b1f5ceb5dfa3bd0034dc42ec355b390d8f", "dest": "cargo/vendor", - "dest-filename": "gdk4-0.4.6.crate" + "dest-filename": "gdk4-0.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d9df40006277ff44538fe758400fc671146f6f2665978b6b57d2408db3c2becf%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gdk4-0.4.6", + "url": "data:%7B%22package%22%3A%20%226e4887e17b6926db51f1e538d871a8b1f5ceb5dfa3bd0034dc42ec355b390d8f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gdk4-0.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gdk4-sys/gdk4-sys-0.4.2.crate", - "sha256": "48a39e34abe35ee2cf54a1e29dd983accecd113ad30bdead5050418fa92f2a1b", + "url": "https://static.crates.io/crates/gdk4-sys/gdk4-sys-0.6.0.crate", + "sha256": "f4993c019bf03d18137c00ddafb2b23e73f7cbb45ae244f52af2542a3f4a9452", "dest": "cargo/vendor", - "dest-filename": "gdk4-sys-0.4.2.crate" + "dest-filename": "gdk4-sys-0.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2248a39e34abe35ee2cf54a1e29dd983accecd113ad30bdead5050418fa92f2a1b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gdk4-sys-0.4.2", + "url": "data:%7B%22package%22%3A%20%22f4993c019bf03d18137c00ddafb2b23e73f7cbb45ae244f52af2542a3f4a9452%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gdk4-sys-0.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/generic-array/generic-array-0.14.5.crate", - "sha256": "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803", + "url": "https://static.crates.io/crates/generic-array/generic-array-0.14.6.crate", + "sha256": "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9", "dest": "cargo/vendor", - "dest-filename": "generic-array-0.14.5.crate" + "dest-filename": "generic-array-0.14.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/generic-array-0.14.5", + "url": "data:%7B%22package%22%3A%20%22bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/generic-array-0.14.6", "dest-filename": ".cargo-checksum.json" }, { @@ -1236,15 +1340,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/getrandom/getrandom-0.2.4.crate", - "sha256": "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c", + "url": "https://static.crates.io/crates/getrandom/getrandom-0.2.8.crate", + "sha256": "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31", "dest": "cargo/vendor", - "dest-filename": "getrandom-0.2.4.crate" + "dest-filename": "getrandom-0.2.8.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/getrandom-0.2.4", + "url": "data:%7B%22package%22%3A%20%22c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/getrandom-0.2.8", "dest-filename": ".cargo-checksum.json" }, { @@ -1262,236 +1366,249 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/gettext-sys/gettext-sys-0.21.2.crate", - "sha256": "afa9e06ab9e7514cc9ae668ea3b71ea1536259d767dff0289ac23ad134f99929", + "url": "https://static.crates.io/crates/gettext-sys/gettext-sys-0.21.3.crate", + "sha256": "c63ce2e00f56a206778276704bbe38564c8695249fdc8f354b4ef71c57c3839d", "dest": "cargo/vendor", - "dest-filename": "gettext-sys-0.21.2.crate" + "dest-filename": "gettext-sys-0.21.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22afa9e06ab9e7514cc9ae668ea3b71ea1536259d767dff0289ac23ad134f99929%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gettext-sys-0.21.2", + "url": "data:%7B%22package%22%3A%20%22c63ce2e00f56a206778276704bbe38564c8695249fdc8f354b4ef71c57c3839d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gettext-sys-0.21.3", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gio/gio-0.15.7.crate", - "sha256": "bb50e113645fba48bc36c8abaee1fe5e43d353e8763966e29dfe69660514e461", + "url": "https://static.crates.io/crates/gimli/gimli-0.27.1.crate", + "sha256": "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec", "dest": "cargo/vendor", - "dest-filename": "gio-0.15.7.crate" + "dest-filename": "gimli-0.27.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22bb50e113645fba48bc36c8abaee1fe5e43d353e8763966e29dfe69660514e461%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gio-0.15.7", + "url": "data:%7B%22package%22%3A%20%22221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gimli-0.27.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gio-sys/gio-sys-0.15.5.crate", - "sha256": "4f0bc4cfc9ebcdd05cc5057bc51b99c32f8f9bf246274f6a556ffd27279f8fe3", + "url": "https://static.crates.io/crates/gio/gio-0.17.0.crate", + "sha256": "1981edf8679d2f2c8ec3120015867f45aa0a1c2d5e3e129ca2f7dda174d3d2a9", "dest": "cargo/vendor", - "dest-filename": "gio-sys-0.15.5.crate" + "dest-filename": "gio-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%224f0bc4cfc9ebcdd05cc5057bc51b99c32f8f9bf246274f6a556ffd27279f8fe3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gio-sys-0.15.5", + "url": "data:%7B%22package%22%3A%20%221981edf8679d2f2c8ec3120015867f45aa0a1c2d5e3e129ca2f7dda174d3d2a9%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gio-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/glib/glib-0.15.9.crate", - "sha256": "89528258cfdc79b1e54591202705be67896ad254f99e3cc2ea3710e0307148f2", + "url": "https://static.crates.io/crates/gio-sys/gio-sys-0.17.0.crate", + "sha256": "b5d3076ecb86c8c3a672c9843d6232b3a344fb81d304d0ba1ac64b23343efa46", "dest": "cargo/vendor", - "dest-filename": "glib-0.15.9.crate" + "dest-filename": "gio-sys-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2289528258cfdc79b1e54591202705be67896ad254f99e3cc2ea3710e0307148f2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/glib-0.15.9", + "url": "data:%7B%22package%22%3A%20%22b5d3076ecb86c8c3a672c9843d6232b3a344fb81d304d0ba1ac64b23343efa46%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gio-sys-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/glib-macros/glib-macros-0.15.3.crate", - "sha256": "e58b262ff65ef771003873cea8c10e0fe854f1c508d48d62a4111a1ff163f7d1", + "url": "https://static.crates.io/crates/glib/glib-0.17.1.crate", + "sha256": "91b429154ec5943185aeeaf79e646297567b6a056965f1e89da2657a0e23255b", "dest": "cargo/vendor", - "dest-filename": "glib-macros-0.15.3.crate" + "dest-filename": "glib-0.17.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e58b262ff65ef771003873cea8c10e0fe854f1c508d48d62a4111a1ff163f7d1%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/glib-macros-0.15.3", + "url": "data:%7B%22package%22%3A%20%2291b429154ec5943185aeeaf79e646297567b6a056965f1e89da2657a0e23255b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/glib-0.17.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/glib-sys/glib-sys-0.15.5.crate", - "sha256": "fa1d4e1a63d8574541e5b92931e4e669ddc87ffa85d58e84e631dba13ad2e10c", + "url": "https://static.crates.io/crates/glib-macros/glib-macros-0.17.1.crate", + "sha256": "9bc80ac951300ca288dd9ab3863743c37a608fb0e5ca12863495640ec6b781ab", "dest": "cargo/vendor", - "dest-filename": "glib-sys-0.15.5.crate" + "dest-filename": "glib-macros-0.17.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22fa1d4e1a63d8574541e5b92931e4e669ddc87ffa85d58e84e631dba13ad2e10c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/glib-sys-0.15.5", + "url": "data:%7B%22package%22%3A%20%229bc80ac951300ca288dd9ab3863743c37a608fb0e5ca12863495640ec6b781ab%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/glib-macros-0.17.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/glob/glob-0.3.0.crate", - "sha256": "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574", + "url": "https://static.crates.io/crates/glib-sys/glib-sys-0.17.0.crate", + "sha256": "9ddcb73fa8236277bedadaaadb76aef49c85d66340f83bece244f46c2d4f0e01", "dest": "cargo/vendor", - "dest-filename": "glob-0.3.0.crate" + "dest-filename": "glib-sys-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/glob-0.3.0", + "url": "data:%7B%22package%22%3A%20%229ddcb73fa8236277bedadaaadb76aef49c85d66340f83bece244f46c2d4f0e01%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/glib-sys-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gloo-timers/gloo-timers-0.2.3.crate", - "sha256": "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e", + "url": "https://static.crates.io/crates/glob/glob-0.3.1.crate", + "sha256": "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b", "dest": "cargo/vendor", - "dest-filename": "gloo-timers-0.2.3.crate" + "dest-filename": "glob-0.3.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%224d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gloo-timers-0.2.3", + "url": "data:%7B%22package%22%3A%20%22d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/glob-0.3.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gobject-sys/gobject-sys-0.15.5.crate", - "sha256": "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a", + "url": "https://static.crates.io/crates/gloo-timers/gloo-timers-0.2.6.crate", + "sha256": "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c", "dest": "cargo/vendor", - "dest-filename": "gobject-sys-0.15.5.crate" + "dest-filename": "gloo-timers-0.2.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gobject-sys-0.15.5", + "url": "data:%7B%22package%22%3A%20%229b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gloo-timers-0.2.6", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/graphene-rs/graphene-rs-0.15.1.crate", - "sha256": "7c54f9fbbeefdb62c99f892dfca35f83991e2cb5b46a8dc2a715e58612f85570", + "url": "https://static.crates.io/crates/gobject-sys/gobject-sys-0.17.0.crate", + "sha256": "9a0155d388840c77d61b033b66ef4f9bc7f4133d83df83572d6b4fb234a3be7d", "dest": "cargo/vendor", - "dest-filename": "graphene-rs-0.15.1.crate" + "dest-filename": "gobject-sys-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227c54f9fbbeefdb62c99f892dfca35f83991e2cb5b46a8dc2a715e58612f85570%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/graphene-rs-0.15.1", + "url": "data:%7B%22package%22%3A%20%229a0155d388840c77d61b033b66ef4f9bc7f4133d83df83572d6b4fb234a3be7d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gobject-sys-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/graphene-sys/graphene-sys-0.15.1.crate", - "sha256": "03f311acb023cf7af5537f35de028e03706136eead7f25a31e8fd26f5011e0b3", + "url": "https://static.crates.io/crates/graphene-rs/graphene-rs-0.17.1.crate", + "sha256": "21cf11565bb0e4dfc2f99d4775b6c329f0d40a2cff9c0066214d31a0e1b46256", "dest": "cargo/vendor", - "dest-filename": "graphene-sys-0.15.1.crate" + "dest-filename": "graphene-rs-0.17.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2203f311acb023cf7af5537f35de028e03706136eead7f25a31e8fd26f5011e0b3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/graphene-sys-0.15.1", + "url": "data:%7B%22package%22%3A%20%2221cf11565bb0e4dfc2f99d4775b6c329f0d40a2cff9c0066214d31a0e1b46256%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/graphene-rs-0.17.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gsk4/gsk4-0.4.6.crate", - "sha256": "1bf63d454e2f75abd92ee6de0ac9fc5aaf1018cd9c458aaf9de296c5cbab6bb9", + "url": "https://static.crates.io/crates/graphene-sys/graphene-sys-0.17.0.crate", + "sha256": "cf80a4849a8d9565410a8fec6fc3678e9c617f4ac7be182ca55ab75016e07af9", "dest": "cargo/vendor", - "dest-filename": "gsk4-0.4.6.crate" + "dest-filename": "graphene-sys-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221bf63d454e2f75abd92ee6de0ac9fc5aaf1018cd9c458aaf9de296c5cbab6bb9%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gsk4-0.4.6", + "url": "data:%7B%22package%22%3A%20%22cf80a4849a8d9565410a8fec6fc3678e9c617f4ac7be182ca55ab75016e07af9%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/graphene-sys-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gsk4-sys/gsk4-sys-0.4.2.crate", - "sha256": "e31d21d7ce02ba261bb24c50c4ab238a10b41a2c97c32afffae29471b7cca69b", + "url": "https://static.crates.io/crates/gsk4/gsk4-0.6.0.crate", + "sha256": "432f981e4ea9f0739a5731d8a649acb794a3a729d2254e559ce7d613b17caf95", "dest": "cargo/vendor", - "dest-filename": "gsk4-sys-0.4.2.crate" + "dest-filename": "gsk4-0.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e31d21d7ce02ba261bb24c50c4ab238a10b41a2c97c32afffae29471b7cca69b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gsk4-sys-0.4.2", + "url": "data:%7B%22package%22%3A%20%22432f981e4ea9f0739a5731d8a649acb794a3a729d2254e559ce7d613b17caf95%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gsk4-0.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gtk4/gtk4-0.4.6.crate", - "sha256": "9e841556e3fe55d8a43ada76b7b08a5f65570bbdfe3b8f72c333053b8832c626", + "url": "https://static.crates.io/crates/gsk4-sys/gsk4-sys-0.6.0.crate", + "sha256": "096cb59175b0915ebf69c05a45263c0c989bd8537b8f2169912d0de644ba6a76", "dest": "cargo/vendor", - "dest-filename": "gtk4-0.4.6.crate" + "dest-filename": "gsk4-sys-0.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229e841556e3fe55d8a43ada76b7b08a5f65570bbdfe3b8f72c333053b8832c626%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gtk4-0.4.6", + "url": "data:%7B%22package%22%3A%20%22096cb59175b0915ebf69c05a45263c0c989bd8537b8f2169912d0de644ba6a76%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gsk4-sys-0.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gtk4-macros/gtk4-macros-0.4.3.crate", - "sha256": "573db42bb64973a4d5f718b73caa7204285a1a665308a23b11723d0ee56ec305", + "url": "https://static.crates.io/crates/gtk4/gtk4-0.6.1.crate", + "sha256": "73421200ad9c3919d0720779b345b05d31a6ce9998e74fc27012f12580822e46", "dest": "cargo/vendor", - "dest-filename": "gtk4-macros-0.4.3.crate" + "dest-filename": "gtk4-0.6.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22573db42bb64973a4d5f718b73caa7204285a1a665308a23b11723d0ee56ec305%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gtk4-macros-0.4.3", + "url": "data:%7B%22package%22%3A%20%2273421200ad9c3919d0720779b345b05d31a6ce9998e74fc27012f12580822e46%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gtk4-0.6.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/gtk4-sys/gtk4-sys-0.4.5.crate", - "sha256": "c47c075e8f795c38f6e9a47b51a73eab77b325f83c0154979ed4d4245c36490d", + "url": "https://static.crates.io/crates/gtk4-macros/gtk4-macros-0.6.0.crate", + "sha256": "db4676c4f90d8b010e88cb4558f61f47d76d6f6b8e6f6b89e62640f443907f61", "dest": "cargo/vendor", - "dest-filename": "gtk4-sys-0.4.5.crate" + "dest-filename": "gtk4-macros-0.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c47c075e8f795c38f6e9a47b51a73eab77b325f83c0154979ed4d4245c36490d%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/gtk4-sys-0.4.5", + "url": "data:%7B%22package%22%3A%20%22db4676c4f90d8b010e88cb4558f61f47d76d6f6b8e6f6b89e62640f443907f61%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gtk4-macros-0.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/hashbrown/hashbrown-0.11.2.crate", - "sha256": "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e", + "url": "https://static.crates.io/crates/gtk4-sys/gtk4-sys-0.6.0.crate", + "sha256": "e13cf3bc9559f71963c957eb639060b643e1276ae47b892ef6091d5bc15c3e1b", "dest": "cargo/vendor", - "dest-filename": "hashbrown-0.11.2.crate" + "dest-filename": "gtk4-sys-0.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/hashbrown-0.11.2", + "url": "data:%7B%22package%22%3A%20%22e13cf3bc9559f71963c957eb639060b643e1276ae47b892ef6091d5bc15c3e1b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/gtk4-sys-0.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/headers/headers-0.3.6.crate", - "sha256": "c84c647447a07ca16f5fbd05b633e535cc41a08d2d74ab1e08648df53be9cb89", + "url": "https://static.crates.io/crates/hashbrown/hashbrown-0.12.3.crate", + "sha256": "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888", "dest": "cargo/vendor", - "dest-filename": "headers-0.3.6.crate" + "dest-filename": "hashbrown-0.12.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c84c647447a07ca16f5fbd05b633e535cc41a08d2d74ab1e08648df53be9cb89%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/headers-0.3.6", + "url": "data:%7B%22package%22%3A%20%228a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/hashbrown-0.12.3", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/headers/headers-0.3.8.crate", + "sha256": "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584", + "dest": "cargo/vendor", + "dest-filename": "headers-0.3.8.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/headers-0.3.8", "dest-filename": ".cargo-checksum.json" }, { @@ -1509,15 +1626,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/heck/heck-0.4.0.crate", - "sha256": "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9", + "url": "https://static.crates.io/crates/heck/heck-0.4.1.crate", + "sha256": "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8", "dest": "cargo/vendor", - "dest-filename": "heck-0.4.0.crate" + "dest-filename": "heck-0.4.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/heck-0.4.0", + "url": "data:%7B%22package%22%3A%20%2295505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/heck-0.4.1", "dest-filename": ".cargo-checksum.json" }, { @@ -1535,41 +1652,41 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/hex/hex-0.4.3.crate", - "sha256": "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70", + "url": "https://static.crates.io/crates/hermit-abi/hermit-abi-0.2.6.crate", + "sha256": "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7", "dest": "cargo/vendor", - "dest-filename": "hex-0.4.3.crate" + "dest-filename": "hermit-abi-0.2.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/hex-0.4.3", + "url": "data:%7B%22package%22%3A%20%22ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/hermit-abi-0.2.6", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/hkdf/hkdf-0.10.0.crate", - "sha256": "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f", + "url": "https://static.crates.io/crates/hex/hex-0.4.3.crate", + "sha256": "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70", "dest": "cargo/vendor", - "dest-filename": "hkdf-0.10.0.crate" + "dest-filename": "hex-0.4.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2251ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/hkdf-0.10.0", + "url": "data:%7B%22package%22%3A%20%227f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/hex-0.4.3", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/hmac/hmac-0.10.1.crate", - "sha256": "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15", + "url": "https://static.crates.io/crates/hkdf/hkdf-0.12.3.crate", + "sha256": "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437", "dest": "cargo/vendor", - "dest-filename": "hmac-0.10.1.crate" + "dest-filename": "hkdf-0.12.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/hmac-0.10.1", + "url": "data:%7B%22package%22%3A%20%22791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/hkdf-0.12.3", "dest-filename": ".cargo-checksum.json" }, { @@ -1585,6 +1702,19 @@ "dest": "cargo/vendor/hmac-0.11.0", "dest-filename": ".cargo-checksum.json" }, + { + "type": "file", + "url": "https://static.crates.io/crates/hmac/hmac-0.12.1.crate", + "sha256": "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e", + "dest": "cargo/vendor", + "dest-filename": "hmac-0.12.1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%226c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/hmac-0.12.1", + "dest-filename": ".cargo-checksum.json" + }, { "type": "file", "url": "https://static.crates.io/crates/hostname/hostname-0.3.1.crate", @@ -1600,41 +1730,41 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/http/http-0.2.6.crate", - "sha256": "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03", + "url": "https://static.crates.io/crates/http/http-0.2.8.crate", + "sha256": "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399", "dest": "cargo/vendor", - "dest-filename": "http-0.2.6.crate" + "dest-filename": "http-0.2.8.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2231f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/http-0.2.6", + "url": "data:%7B%22package%22%3A%20%2275f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/http-0.2.8", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/http-body/http-body-0.4.4.crate", - "sha256": "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6", + "url": "https://static.crates.io/crates/http-body/http-body-0.4.5.crate", + "sha256": "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1", "dest": "cargo/vendor", - "dest-filename": "http-body-0.4.4.crate" + "dest-filename": "http-body-0.4.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/http-body-0.4.4", + "url": "data:%7B%22package%22%3A%20%22d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/http-body-0.4.5", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/httparse/httparse-1.5.1.crate", - "sha256": "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503", + "url": "https://static.crates.io/crates/httparse/httparse-1.8.0.crate", + "sha256": "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904", "dest": "cargo/vendor", - "dest-filename": "httparse-1.5.1.crate" + "dest-filename": "httparse-1.8.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/httparse-1.5.1", + "url": "data:%7B%22package%22%3A%20%22d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/httparse-1.8.0", "dest-filename": ".cargo-checksum.json" }, { @@ -1665,15 +1795,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/hyper/hyper-0.14.16.crate", - "sha256": "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55", + "url": "https://static.crates.io/crates/hyper/hyper-0.14.24.crate", + "sha256": "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c", "dest": "cargo/vendor", - "dest-filename": "hyper-0.14.16.crate" + "dest-filename": "hyper-0.14.24.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/hyper-0.14.16", + "url": "data:%7B%22package%22%3A%20%225e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/hyper-0.14.24", "dest-filename": ".cargo-checksum.json" }, { @@ -1691,119 +1821,119 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/ident_case/ident_case-1.0.1.crate", - "sha256": "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39", + "url": "https://static.crates.io/crates/iana-time-zone/iana-time-zone-0.1.53.crate", + "sha256": "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765", "dest": "cargo/vendor", - "dest-filename": "ident_case-1.0.1.crate" + "dest-filename": "iana-time-zone-0.1.53.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/ident_case-1.0.1", + "url": "data:%7B%22package%22%3A%20%2264c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/iana-time-zone-0.1.53", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/idna/idna-0.2.3.crate", - "sha256": "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8", + "url": "https://static.crates.io/crates/iana-time-zone-haiku/iana-time-zone-haiku-0.1.1.crate", + "sha256": "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca", "dest": "cargo/vendor", - "dest-filename": "idna-0.2.3.crate" + "dest-filename": "iana-time-zone-haiku-0.1.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/idna-0.2.3", + "url": "data:%7B%22package%22%3A%20%220703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/iana-time-zone-haiku-0.1.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/if-addrs/if-addrs-0.6.7.crate", - "sha256": "2273e421f7c4f0fc99e1934fe4776f59d8df2972f4199d703fc0da9f2a9f73de", + "url": "https://static.crates.io/crates/ident_case/ident_case-1.0.1.crate", + "sha256": "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39", "dest": "cargo/vendor", - "dest-filename": "if-addrs-0.6.7.crate" + "dest-filename": "ident_case-1.0.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222273e421f7c4f0fc99e1934fe4776f59d8df2972f4199d703fc0da9f2a9f73de%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/if-addrs-0.6.7", + "url": "data:%7B%22package%22%3A%20%22b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/ident_case-1.0.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/if-addrs-sys/if-addrs-sys-0.3.2.crate", - "sha256": "de74b9dd780476e837e5eb5ab7c88b49ed304126e412030a0adba99c8efe79ea", + "url": "https://static.crates.io/crates/idna/idna-0.3.0.crate", + "sha256": "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6", "dest": "cargo/vendor", - "dest-filename": "if-addrs-sys-0.3.2.crate" + "dest-filename": "idna-0.3.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22de74b9dd780476e837e5eb5ab7c88b49ed304126e412030a0adba99c8efe79ea%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/if-addrs-sys-0.3.2", + "url": "data:%7B%22package%22%3A%20%22e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/idna-0.3.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/indexmap/indexmap-1.8.0.crate", - "sha256": "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223", + "url": "https://static.crates.io/crates/if-addrs/if-addrs-0.7.0.crate", + "sha256": "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9", "dest": "cargo/vendor", - "dest-filename": "indexmap-1.8.0.crate" + "dest-filename": "if-addrs-0.7.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/indexmap-1.8.0", + "url": "data:%7B%22package%22%3A%20%22cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/if-addrs-0.7.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/instant/instant-0.1.12.crate", - "sha256": "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c", + "url": "https://static.crates.io/crates/indexmap/indexmap-1.9.2.crate", + "sha256": "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399", "dest": "cargo/vendor", - "dest-filename": "instant-0.1.12.crate" + "dest-filename": "indexmap-1.9.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/instant-0.1.12", + "url": "data:%7B%22package%22%3A%20%221885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/indexmap-1.9.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/isahc/isahc-1.7.0.crate", - "sha256": "437f8808009c031df3c1d532c8fd7e3d73239dfe522ebf0b94b5e34d5d01044b", + "url": "https://static.crates.io/crates/instant/instant-0.1.12.crate", + "sha256": "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c", "dest": "cargo/vendor", - "dest-filename": "isahc-1.7.0.crate" + "dest-filename": "instant-0.1.12.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22437f8808009c031df3c1d532c8fd7e3d73239dfe522ebf0b94b5e34d5d01044b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/isahc-1.7.0", + "url": "data:%7B%22package%22%3A%20%227a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/instant-0.1.12", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/itoa/itoa-0.4.8.crate", - "sha256": "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4", + "url": "https://static.crates.io/crates/isahc/isahc-1.7.2.crate", + "sha256": "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9", "dest": "cargo/vendor", - "dest-filename": "itoa-0.4.8.crate" + "dest-filename": "isahc-1.7.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/itoa-0.4.8", + "url": "data:%7B%22package%22%3A%20%22334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/isahc-1.7.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/itoa/itoa-1.0.1.crate", - "sha256": "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35", + "url": "https://static.crates.io/crates/itoa/itoa-1.0.5.crate", + "sha256": "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440", "dest": "cargo/vendor", - "dest-filename": "itoa-1.0.1.crate" + "dest-filename": "itoa-1.0.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/itoa-1.0.1", + "url": "data:%7B%22package%22%3A%20%22fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/itoa-1.0.5", "dest-filename": ".cargo-checksum.json" }, { @@ -1834,28 +1964,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/jobserver/jobserver-0.1.24.crate", - "sha256": "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa", + "url": "https://static.crates.io/crates/jobserver/jobserver-0.1.25.crate", + "sha256": "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b", "dest": "cargo/vendor", - "dest-filename": "jobserver-0.1.24.crate" + "dest-filename": "jobserver-0.1.25.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/jobserver-0.1.24", + "url": "data:%7B%22package%22%3A%20%22068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/jobserver-0.1.25", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/js-sys/js-sys-0.3.56.crate", - "sha256": "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04", + "url": "https://static.crates.io/crates/js-sys/js-sys-0.3.61.crate", + "sha256": "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730", "dest": "cargo/vendor", - "dest-filename": "js-sys-0.3.56.crate" + "dest-filename": "js-sys-0.3.61.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/js-sys-0.3.56", + "url": "data:%7B%22package%22%3A%20%22445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/js-sys-0.3.61", "dest-filename": ".cargo-checksum.json" }, { @@ -1912,80 +2042,80 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/libadwaita/libadwaita-0.1.0.crate", - "sha256": "0d4b1d54d907dfa5d6663fdf4bdbe46c34747258b85c787adbf66187ccbaac81", + "url": "https://static.crates.io/crates/libadwaita/libadwaita-0.3.0.crate", + "sha256": "674cbf1bd796f3d4f0c24466c15d91180e33e497ae2e07eea3f3d545468dc839", "dest": "cargo/vendor", - "dest-filename": "libadwaita-0.1.0.crate" + "dest-filename": "libadwaita-0.3.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%220d4b1d54d907dfa5d6663fdf4bdbe46c34747258b85c787adbf66187ccbaac81%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libadwaita-0.1.0", + "url": "data:%7B%22package%22%3A%20%22674cbf1bd796f3d4f0c24466c15d91180e33e497ae2e07eea3f3d545468dc839%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libadwaita-0.3.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libadwaita-sys/libadwaita-sys-0.1.0.crate", - "sha256": "f18b6ac4cadd252a89f5cba0a5a4e99836131795d6fad37b859ac79e8cb7d2c8", + "url": "https://static.crates.io/crates/libadwaita-sys/libadwaita-sys-0.3.0.crate", + "sha256": "0727b85b4fe2b1bed5ac90df6343de15cbf8118bfb96d7c3cc1512681a4b34ac", "dest": "cargo/vendor", - "dest-filename": "libadwaita-sys-0.1.0.crate" + "dest-filename": "libadwaita-sys-0.3.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22f18b6ac4cadd252a89f5cba0a5a4e99836131795d6fad37b859ac79e8cb7d2c8%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libadwaita-sys-0.1.0", + "url": "data:%7B%22package%22%3A%20%220727b85b4fe2b1bed5ac90df6343de15cbf8118bfb96d7c3cc1512681a4b34ac%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libadwaita-sys-0.3.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libc/libc-0.2.117.crate", - "sha256": "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c", + "url": "https://static.crates.io/crates/libc/libc-0.2.139.crate", + "sha256": "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79", "dest": "cargo/vendor", - "dest-filename": "libc-0.2.117.crate" + "dest-filename": "libc-0.2.139.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libc-0.2.117", + "url": "data:%7B%22package%22%3A%20%22201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libc-0.2.139", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libloading/libloading-0.7.3.crate", - "sha256": "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd", + "url": "https://static.crates.io/crates/libloading/libloading-0.7.4.crate", + "sha256": "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f", "dest": "cargo/vendor", - "dest-filename": "libloading-0.7.3.crate" + "dest-filename": "libloading-0.7.4.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libloading-0.7.3", + "url": "data:%7B%22package%22%3A%20%22b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libloading-0.7.4", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libm/libm-0.2.2.crate", - "sha256": "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db", + "url": "https://static.crates.io/crates/libm/libm-0.2.6.crate", + "sha256": "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb", "dest": "cargo/vendor", - "dest-filename": "libm-0.2.2.crate" + "dest-filename": "libm-0.2.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2233a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libm-0.2.2", + "url": "data:%7B%22package%22%3A%20%22348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libm-0.2.6", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libmdns/libmdns-0.6.2.crate", - "sha256": "fac185a4d02e873c6d1ead59d674651f8ae5ec23ffe1637bee8de80665562a6a", + "url": "https://static.crates.io/crates/libmdns/libmdns-0.7.4.crate", + "sha256": "6a60d8339ad1ddf68a81335fcafb6c6cf20d5036138a1e4ef86b8ce87f076c92", "dest": "cargo/vendor", - "dest-filename": "libmdns-0.6.2.crate" + "dest-filename": "libmdns-0.7.4.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22fac185a4d02e873c6d1ead59d674651f8ae5ec23ffe1637bee8de80665562a6a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libmdns-0.6.2", + "url": "data:%7B%22package%22%3A%20%226a60d8339ad1ddf68a81335fcafb6c6cf20d5036138a1e4ef86b8ce87f076c92%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libmdns-0.7.4", "dest-filename": ".cargo-checksum.json" }, { @@ -2003,171 +2133,184 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/libpulse-binding/libpulse-binding-2.26.0.crate", - "sha256": "17be42160017e0ae993c03bfdab4ecb6f82ce3f8d515bd8da8fdf18d10703663", + "url": "https://static.crates.io/crates/libpulse-binding/libpulse-binding-2.27.1.crate", + "sha256": "1745b20bfc194ac12ef828f144f0ec2d4a7fe993281fa3567a0bd4969aee6890", + "dest": "cargo/vendor", + "dest-filename": "libpulse-binding-2.27.1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%221745b20bfc194ac12ef828f144f0ec2d4a7fe993281fa3567a0bd4969aee6890%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libpulse-binding-2.27.1", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/libpulse-simple-binding/libpulse-simple-binding-2.27.1.crate", + "sha256": "5ced94199e6e44133431374e4043f34e1f0697ebfb7b7d6c244a65bfaedf0e31", "dest": "cargo/vendor", - "dest-filename": "libpulse-binding-2.26.0.crate" + "dest-filename": "libpulse-simple-binding-2.27.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2217be42160017e0ae993c03bfdab4ecb6f82ce3f8d515bd8da8fdf18d10703663%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libpulse-binding-2.26.0", + "url": "data:%7B%22package%22%3A%20%225ced94199e6e44133431374e4043f34e1f0697ebfb7b7d6c244a65bfaedf0e31%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libpulse-simple-binding-2.27.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libpulse-simple-binding/libpulse-simple-binding-2.25.0.crate", - "sha256": "7cbf1a1dfd69a48cb60906399fa1d17f1b75029ef51c0789597be792dfd0bcd5", + "url": "https://static.crates.io/crates/libpulse-simple-sys/libpulse-simple-sys-1.20.1.crate", + "sha256": "84e423d9c619c908ce9b4916080e65ab586ca55b8c4939379f15e6e72fb43842", "dest": "cargo/vendor", - "dest-filename": "libpulse-simple-binding-2.25.0.crate" + "dest-filename": "libpulse-simple-sys-1.20.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227cbf1a1dfd69a48cb60906399fa1d17f1b75029ef51c0789597be792dfd0bcd5%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libpulse-simple-binding-2.25.0", + "url": "data:%7B%22package%22%3A%20%2284e423d9c619c908ce9b4916080e65ab586ca55b8c4939379f15e6e72fb43842%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libpulse-simple-sys-1.20.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libpulse-simple-sys/libpulse-simple-sys-1.19.2.crate", - "sha256": "7c73f96f9ca34809692c4760cfe421225860aa000de50edab68a16221fd27cc1", + "url": "https://static.crates.io/crates/libpulse-sys/libpulse-sys-1.20.1.crate", + "sha256": "2191e6880818d1df4cf72eac8e91dce7a5a52ba0da4b2a5cdafabc22b937eadb", "dest": "cargo/vendor", - "dest-filename": "libpulse-simple-sys-1.19.2.crate" + "dest-filename": "libpulse-sys-1.20.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227c73f96f9ca34809692c4760cfe421225860aa000de50edab68a16221fd27cc1%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libpulse-simple-sys-1.19.2", + "url": "data:%7B%22package%22%3A%20%222191e6880818d1df4cf72eac8e91dce7a5a52ba0da4b2a5cdafabc22b937eadb%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libpulse-sys-1.20.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libpulse-sys/libpulse-sys-1.19.3.crate", - "sha256": "991e6bd0efe2a36e6534e136e7996925e4c1a8e35b7807fe533f2beffff27c30", + "url": "https://static.crates.io/crates/librespot/librespot-0.4.2.crate", + "sha256": "ea4c9952ef48968f8184a4a87f8576982426ebe623342d5a28f7d9c4978e4a44", "dest": "cargo/vendor", - "dest-filename": "libpulse-sys-1.19.3.crate" + "dest-filename": "librespot-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22991e6bd0efe2a36e6534e136e7996925e4c1a8e35b7807fe533f2beffff27c30%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libpulse-sys-1.19.3", + "url": "data:%7B%22package%22%3A%20%22ea4c9952ef48968f8184a4a87f8576982426ebe623342d5a28f7d9c4978e4a44%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/librespot-0.4.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/librespot/librespot-0.3.1.crate", - "sha256": "5fb49bc466977d940fae6e9219d56e1355a2f3d77a348fe7f708fa8f36905491", + "url": "https://static.crates.io/crates/librespot-audio/librespot-audio-0.4.2.crate", + "sha256": "c176a31355e1ea8e0b9c4ced19df4947bfe4770661c25c142b6fba2365940d9d", "dest": "cargo/vendor", - "dest-filename": "librespot-0.3.1.crate" + "dest-filename": "librespot-audio-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%225fb49bc466977d940fae6e9219d56e1355a2f3d77a348fe7f708fa8f36905491%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/librespot-0.3.1", + "url": "data:%7B%22package%22%3A%20%22c176a31355e1ea8e0b9c4ced19df4947bfe4770661c25c142b6fba2365940d9d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/librespot-audio-0.4.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/librespot-audio/librespot-audio-0.3.1.crate", - "sha256": "e5f7cc7e4d1c2596191be523668c933e07ec8a318d099fd66658258a4fe4a2dc", + "url": "https://static.crates.io/crates/librespot-connect/librespot-connect-0.4.2.crate", + "sha256": "4ffafb6a443e9445ccb3d5d591573b5b1da3c89a9b8846c63ba2c3710210d3ec", "dest": "cargo/vendor", - "dest-filename": "librespot-audio-0.3.1.crate" + "dest-filename": "librespot-connect-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e5f7cc7e4d1c2596191be523668c933e07ec8a318d099fd66658258a4fe4a2dc%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/librespot-audio-0.3.1", + "url": "data:%7B%22package%22%3A%20%224ffafb6a443e9445ccb3d5d591573b5b1da3c89a9b8846c63ba2c3710210d3ec%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/librespot-connect-0.4.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/librespot-connect/librespot-connect-0.3.1.crate", - "sha256": "1e9dbfd8ee475a0874dc284f29c60d214bee43504979b244dd33763979f5ba76", + "url": "https://static.crates.io/crates/librespot-core/librespot-core-0.4.2.crate", + "sha256": "046349f25888e644bf02d9c5de0164b2a493d29aa4ce18e1ad0b756da9b55d6d", "dest": "cargo/vendor", - "dest-filename": "librespot-connect-0.3.1.crate" + "dest-filename": "librespot-core-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221e9dbfd8ee475a0874dc284f29c60d214bee43504979b244dd33763979f5ba76%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/librespot-connect-0.3.1", + "url": "data:%7B%22package%22%3A%20%22046349f25888e644bf02d9c5de0164b2a493d29aa4ce18e1ad0b756da9b55d6d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/librespot-core-0.4.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/librespot-core/librespot-core-0.3.1.crate", - "sha256": "255e8d8d719c020895079d140baf0b0edec8447d39a7e4760708f33b7cafaafb", + "url": "https://static.crates.io/crates/librespot-discovery/librespot-discovery-0.4.2.crate", + "sha256": "2aa877d18f6150364012cb4be5682d62d7c712c88bae2d0d01720fd7c15e2f06", "dest": "cargo/vendor", - "dest-filename": "librespot-core-0.3.1.crate" + "dest-filename": "librespot-discovery-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22255e8d8d719c020895079d140baf0b0edec8447d39a7e4760708f33b7cafaafb%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/librespot-core-0.3.1", + "url": "data:%7B%22package%22%3A%20%222aa877d18f6150364012cb4be5682d62d7c712c88bae2d0d01720fd7c15e2f06%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/librespot-discovery-0.4.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/librespot-discovery/librespot-discovery-0.3.1.crate", - "sha256": "c4adeff34212261a291f6519331f9232699a3b0208116f48cb47a97224ff5b63", + "url": "https://static.crates.io/crates/librespot-metadata/librespot-metadata-0.4.2.crate", + "sha256": "6b80361fcbcb5092056fd47c08c34d5d51b08385d8efb6941c0d3e46d032c21c", "dest": "cargo/vendor", - "dest-filename": "librespot-discovery-0.3.1.crate" + "dest-filename": "librespot-metadata-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c4adeff34212261a291f6519331f9232699a3b0208116f48cb47a97224ff5b63%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/librespot-discovery-0.3.1", + "url": "data:%7B%22package%22%3A%20%226b80361fcbcb5092056fd47c08c34d5d51b08385d8efb6941c0d3e46d032c21c%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/librespot-metadata-0.4.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/librespot-metadata/librespot-metadata-0.3.1.crate", - "sha256": "624ac29bb3ad2e565ef78a049a6c554d94e48b673aaba0bf7e7efd946d0b66cd", + "url": "https://static.crates.io/crates/librespot-playback/librespot-playback-0.4.2.crate", + "sha256": "5190a0b9bcc7f70ee4196a6b4a1c731d405ca130d4a6fcd4c561cfdde8b7cfb7", "dest": "cargo/vendor", - "dest-filename": "librespot-metadata-0.3.1.crate" + "dest-filename": "librespot-playback-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22624ac29bb3ad2e565ef78a049a6c554d94e48b673aaba0bf7e7efd946d0b66cd%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/librespot-metadata-0.3.1", + "url": "data:%7B%22package%22%3A%20%225190a0b9bcc7f70ee4196a6b4a1c731d405ca130d4a6fcd4c561cfdde8b7cfb7%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/librespot-playback-0.4.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/librespot-playback/librespot-playback-0.3.1.crate", - "sha256": "188b252b690ae7387f84a481ff4211df1a5c21eb9bddfc25cbde48793f2e0ef2", + "url": "https://static.crates.io/crates/librespot-protocol/librespot-protocol-0.4.2.crate", + "sha256": "5d6d3ac6196ac0ea67bbe039f56d6730a5d8b31502ef9bce0f504ed729dcb39f", "dest": "cargo/vendor", - "dest-filename": "librespot-playback-0.3.1.crate" + "dest-filename": "librespot-protocol-0.4.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22188b252b690ae7387f84a481ff4211df1a5c21eb9bddfc25cbde48793f2e0ef2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/librespot-playback-0.3.1", + "url": "data:%7B%22package%22%3A%20%225d6d3ac6196ac0ea67bbe039f56d6730a5d8b31502ef9bce0f504ed729dcb39f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/librespot-protocol-0.4.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/librespot-protocol/librespot-protocol-0.3.1.crate", - "sha256": "41b3699b05cb4c50caa5a5b7f5b3aadb928dfcc91cf1aa632c0dabce3ccc3ee4", + "url": "https://static.crates.io/crates/libz-sys/libz-sys-1.1.8.crate", + "sha256": "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf", "dest": "cargo/vendor", - "dest-filename": "librespot-protocol-0.3.1.crate" + "dest-filename": "libz-sys-1.1.8.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2241b3699b05cb4c50caa5a5b7f5b3aadb928dfcc91cf1aa632c0dabce3ccc3ee4%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/librespot-protocol-0.3.1", + "url": "data:%7B%22package%22%3A%20%229702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/libz-sys-1.1.8", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/libz-sys/libz-sys-1.1.3.crate", - "sha256": "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66", + "url": "https://static.crates.io/crates/link-cplusplus/link-cplusplus-1.0.8.crate", + "sha256": "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5", "dest": "cargo/vendor", - "dest-filename": "libz-sys-1.1.3.crate" + "dest-filename": "link-cplusplus-1.0.8.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/libz-sys-1.1.3", + "url": "data:%7B%22package%22%3A%20%22ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/link-cplusplus-1.0.8", "dest-filename": ".cargo-checksum.json" }, { @@ -2185,28 +2328,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/lock_api/lock_api-0.4.6.crate", - "sha256": "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b", + "url": "https://static.crates.io/crates/lock_api/lock_api-0.4.9.crate", + "sha256": "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df", "dest": "cargo/vendor", - "dest-filename": "lock_api-0.4.6.crate" + "dest-filename": "lock_api-0.4.9.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2288943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/lock_api-0.4.6", + "url": "data:%7B%22package%22%3A%20%22435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/lock_api-0.4.9", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/log/log-0.4.14.crate", - "sha256": "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710", + "url": "https://static.crates.io/crates/log/log-0.4.17.crate", + "sha256": "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e", "dest": "cargo/vendor", - "dest-filename": "log-0.4.14.crate" + "dest-filename": "log-0.4.17.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2251b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/log-0.4.14", + "url": "data:%7B%22package%22%3A%20%22abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/log-0.4.17", "dest-filename": ".cargo-checksum.json" }, { @@ -2250,28 +2393,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/matches/matches-0.1.9.crate", - "sha256": "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f", - "dest": "cargo/vendor", - "dest-filename": "matches-0.1.9.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%22a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/matches-0.1.9", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "file", - "url": "https://static.crates.io/crates/memchr/memchr-2.4.1.crate", - "sha256": "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a", + "url": "https://static.crates.io/crates/memchr/memchr-2.5.0.crate", + "sha256": "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d", "dest": "cargo/vendor", - "dest-filename": "memchr-2.4.1.crate" + "dest-filename": "memchr-2.5.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/memchr-2.4.1", + "url": "data:%7B%22package%22%3A%20%222dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/memchr-2.5.0", "dest-filename": ".cargo-checksum.json" }, { @@ -2302,54 +2432,54 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/mio/mio-0.8.0.crate", - "sha256": "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2", + "url": "https://static.crates.io/crates/minimal-lexical/minimal-lexical-0.2.1.crate", + "sha256": "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a", "dest": "cargo/vendor", - "dest-filename": "mio-0.8.0.crate" + "dest-filename": "minimal-lexical-0.2.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/mio-0.8.0", + "url": "data:%7B%22package%22%3A%20%2268354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/minimal-lexical-0.2.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/miow/miow-0.3.7.crate", - "sha256": "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21", + "url": "https://static.crates.io/crates/miniz_oxide/miniz_oxide-0.6.2.crate", + "sha256": "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa", "dest": "cargo/vendor", - "dest-filename": "miow-0.3.7.crate" + "dest-filename": "miniz_oxide-0.6.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/miow-0.3.7", + "url": "data:%7B%22package%22%3A%20%22b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/miniz_oxide-0.6.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/multimap/multimap-0.8.3.crate", - "sha256": "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a", + "url": "https://static.crates.io/crates/mio/mio-0.8.5.crate", + "sha256": "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de", "dest": "cargo/vendor", - "dest-filename": "multimap-0.8.3.crate" + "dest-filename": "mio-0.8.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/multimap-0.8.3", + "url": "data:%7B%22package%22%3A%20%22e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/mio-0.8.5", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/nb-connect/nb-connect-1.2.0.crate", - "sha256": "b1bb540dc6ef51cfe1916ec038ce7a620daf3a111e2502d745197cd53d6bca15", + "url": "https://static.crates.io/crates/multimap/multimap-0.8.3.crate", + "sha256": "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a", "dest": "cargo/vendor", - "dest-filename": "nb-connect-1.2.0.crate" + "dest-filename": "multimap-0.8.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b1bb540dc6ef51cfe1916ec038ce7a620daf3a111e2502d745197cd53d6bca15%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/nb-connect-1.2.0", + "url": "data:%7B%22package%22%3A%20%22e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/multimap-0.8.3", "dest-filename": ".cargo-checksum.json" }, { @@ -2367,15 +2497,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/ndk-glue/ndk-glue-0.6.0.crate", - "sha256": "04c0d14b0858eb9962a5dac30b809b19f19da7e4547d64af2b0bb051d2e55d79", + "url": "https://static.crates.io/crates/ndk-context/ndk-context-0.1.1.crate", + "sha256": "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b", + "dest": "cargo/vendor", + "dest-filename": "ndk-context-0.1.1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%2227b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/ndk-context-0.1.1", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/ndk-glue/ndk-glue-0.6.2.crate", + "sha256": "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f", "dest": "cargo/vendor", - "dest-filename": "ndk-glue-0.6.0.crate" + "dest-filename": "ndk-glue-0.6.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2204c0d14b0858eb9962a5dac30b809b19f19da7e4547d64af2b0bb051d2e55d79%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/ndk-glue-0.6.0", + "url": "data:%7B%22package%22%3A%20%220d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/ndk-glue-0.6.2", "dest-filename": ".cargo-checksum.json" }, { @@ -2406,93 +2549,67 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/nix/nix-0.17.0.crate", - "sha256": "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363", + "url": "https://static.crates.io/crates/nix/nix-0.23.2.crate", + "sha256": "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c", "dest": "cargo/vendor", - "dest-filename": "nix-0.17.0.crate" + "dest-filename": "nix-0.23.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2250e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/nix-0.17.0", + "url": "data:%7B%22package%22%3A%20%228f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/nix-0.23.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/nix/nix-0.20.0.crate", - "sha256": "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a", + "url": "https://static.crates.io/crates/nix/nix-0.25.1.crate", + "sha256": "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4", "dest": "cargo/vendor", - "dest-filename": "nix-0.20.0.crate" + "dest-filename": "nix-0.25.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/nix-0.20.0", + "url": "data:%7B%22package%22%3A%20%22f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/nix-0.25.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/nix/nix-0.23.1.crate", - "sha256": "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6", + "url": "https://static.crates.io/crates/nom/nom-7.1.3.crate", + "sha256": "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a", "dest": "cargo/vendor", - "dest-filename": "nix-0.23.1.crate" + "dest-filename": "nom-7.1.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/nix-0.23.1", + "url": "data:%7B%22package%22%3A%20%22d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/nom-7.1.3", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/nom/nom-5.1.2.crate", - "sha256": "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af", + "url": "https://static.crates.io/crates/nom8/nom8-0.2.0.crate", + "sha256": "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8", "dest": "cargo/vendor", - "dest-filename": "nom-5.1.2.crate" + "dest-filename": "nom8-0.2.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/nom-5.1.2", + "url": "data:%7B%22package%22%3A%20%22ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/nom8-0.2.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/ntapi/ntapi-0.3.6.crate", - "sha256": "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44", + "url": "https://static.crates.io/crates/num/num-0.4.0.crate", + "sha256": "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606", "dest": "cargo/vendor", - "dest-filename": "ntapi-0.3.6.crate" + "dest-filename": "num-0.4.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%223f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/ntapi-0.3.6", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "file", - "url": "https://static.crates.io/crates/num/num-0.3.1.crate", - "sha256": "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f", - "dest": "cargo/vendor", - "dest-filename": "num-0.3.1.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%228b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num-0.3.1", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "file", - "url": "https://static.crates.io/crates/num-bigint/num-bigint-0.3.3.crate", - "sha256": "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3", - "dest": "cargo/vendor", - "dest-filename": "num-bigint-0.3.3.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%225f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num-bigint-0.3.3", + "url": "data:%7B%22package%22%3A%20%2243db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num-0.4.0", "dest-filename": ".cargo-checksum.json" }, { @@ -2510,15 +2627,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/num-complex/num-complex-0.3.1.crate", - "sha256": "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5", + "url": "https://static.crates.io/crates/num-complex/num-complex-0.4.3.crate", + "sha256": "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d", "dest": "cargo/vendor", - "dest-filename": "num-complex-0.3.1.crate" + "dest-filename": "num-complex-0.4.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num-complex-0.3.1", + "url": "data:%7B%22package%22%3A%20%2202e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num-complex-0.4.3", "dest-filename": ".cargo-checksum.json" }, { @@ -2536,93 +2653,93 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/num-integer/num-integer-0.1.44.crate", - "sha256": "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db", + "url": "https://static.crates.io/crates/num-integer/num-integer-0.1.45.crate", + "sha256": "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9", "dest": "cargo/vendor", - "dest-filename": "num-integer-0.1.44.crate" + "dest-filename": "num-integer-0.1.45.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num-integer-0.1.44", + "url": "data:%7B%22package%22%3A%20%22225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num-integer-0.1.45", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/num-iter/num-iter-0.1.42.crate", - "sha256": "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59", + "url": "https://static.crates.io/crates/num-iter/num-iter-0.1.43.crate", + "sha256": "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252", "dest": "cargo/vendor", - "dest-filename": "num-iter-0.1.42.crate" + "dest-filename": "num-iter-0.1.43.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num-iter-0.1.42", + "url": "data:%7B%22package%22%3A%20%227d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num-iter-0.1.43", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/num-rational/num-rational-0.3.2.crate", - "sha256": "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07", + "url": "https://static.crates.io/crates/num-rational/num-rational-0.4.1.crate", + "sha256": "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0", "dest": "cargo/vendor", - "dest-filename": "num-rational-0.3.2.crate" + "dest-filename": "num-rational-0.4.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2212ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num-rational-0.3.2", + "url": "data:%7B%22package%22%3A%20%220638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num-rational-0.4.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/num-traits/num-traits-0.2.14.crate", - "sha256": "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290", + "url": "https://static.crates.io/crates/num-traits/num-traits-0.2.15.crate", + "sha256": "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd", "dest": "cargo/vendor", - "dest-filename": "num-traits-0.2.14.crate" + "dest-filename": "num-traits-0.2.15.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num-traits-0.2.14", + "url": "data:%7B%22package%22%3A%20%22578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num-traits-0.2.15", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/num_cpus/num_cpus-1.13.1.crate", - "sha256": "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1", + "url": "https://static.crates.io/crates/num_cpus/num_cpus-1.15.0.crate", + "sha256": "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b", "dest": "cargo/vendor", - "dest-filename": "num_cpus-1.13.1.crate" + "dest-filename": "num_cpus-1.15.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2219e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num_cpus-1.13.1", + "url": "data:%7B%22package%22%3A%20%220fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num_cpus-1.15.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/num_enum/num_enum-0.5.6.crate", - "sha256": "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad", + "url": "https://static.crates.io/crates/num_enum/num_enum-0.5.9.crate", + "sha256": "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b", "dest": "cargo/vendor", - "dest-filename": "num_enum-0.5.6.crate" + "dest-filename": "num_enum-0.5.9.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num_enum-0.5.6", + "url": "data:%7B%22package%22%3A%20%228d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num_enum-0.5.9", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/num_enum_derive/num_enum_derive-0.5.6.crate", - "sha256": "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21", + "url": "https://static.crates.io/crates/num_enum_derive/num_enum_derive-0.5.9.crate", + "sha256": "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e", "dest": "cargo/vendor", - "dest-filename": "num_enum_derive-0.5.6.crate" + "dest-filename": "num_enum_derive-0.5.9.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%220d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/num_enum_derive-0.5.6", + "url": "data:%7B%22package%22%3A%20%222be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/num_enum_derive-0.5.9", "dest-filename": ".cargo-checksum.json" }, { @@ -2666,15 +2783,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/oboe/oboe-0.4.5.crate", - "sha256": "2463c8f2e19b4e0d0710a21f8e4011501ff28db1c95d7a5482a553b2100502d2", + "url": "https://static.crates.io/crates/object/object-0.30.3.crate", + "sha256": "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439", "dest": "cargo/vendor", - "dest-filename": "oboe-0.4.5.crate" + "dest-filename": "object-0.30.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222463c8f2e19b4e0d0710a21f8e4011501ff28db1c95d7a5482a553b2100502d2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/oboe-0.4.5", + "url": "data:%7B%22package%22%3A%20%22ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/object-0.30.3", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/oboe/oboe-0.4.6.crate", + "sha256": "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1", + "dest": "cargo/vendor", + "dest-filename": "oboe-0.4.6.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%2227f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/oboe-0.4.6", "dest-filename": ".cargo-checksum.json" }, { @@ -2705,15 +2835,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/once_cell/once_cell-1.9.0.crate", - "sha256": "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5", + "url": "https://static.crates.io/crates/once_cell/once_cell-1.17.0.crate", + "sha256": "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66", "dest": "cargo/vendor", - "dest-filename": "once_cell-1.9.0.crate" + "dest-filename": "once_cell-1.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/once_cell-1.9.0", + "url": "data:%7B%22package%22%3A%20%226f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/once_cell-1.17.0", "dest-filename": ".cargo-checksum.json" }, { @@ -2744,54 +2874,54 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/openssl-sys/openssl-sys-0.9.72.crate", - "sha256": "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb", + "url": "https://static.crates.io/crates/openssl-sys/openssl-sys-0.9.80.crate", + "sha256": "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7", "dest": "cargo/vendor", - "dest-filename": "openssl-sys-0.9.72.crate" + "dest-filename": "openssl-sys-0.9.80.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/openssl-sys-0.9.72", + "url": "data:%7B%22package%22%3A%20%2223bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/openssl-sys-0.9.80", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/ordered-stream/ordered-stream-0.0.1.crate", - "sha256": "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1", + "url": "https://static.crates.io/crates/ordered-stream/ordered-stream-0.2.0.crate", + "sha256": "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50", "dest": "cargo/vendor", - "dest-filename": "ordered-stream-0.0.1.crate" + "dest-filename": "ordered-stream-0.2.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2244630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/ordered-stream-0.0.1", + "url": "data:%7B%22package%22%3A%20%229aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/ordered-stream-0.2.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/pango/pango-0.15.2.crate", - "sha256": "79211eff430c29cc38c69e0ab54bc78fa1568121ca9737707eee7f92a8417a94", + "url": "https://static.crates.io/crates/pango/pango-0.17.0.crate", + "sha256": "243c048be90312220fb3bd578176eed8290568274a93c95040289d39349384bc", "dest": "cargo/vendor", - "dest-filename": "pango-0.15.2.crate" + "dest-filename": "pango-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2279211eff430c29cc38c69e0ab54bc78fa1568121ca9737707eee7f92a8417a94%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/pango-0.15.2", + "url": "data:%7B%22package%22%3A%20%22243c048be90312220fb3bd578176eed8290568274a93c95040289d39349384bc%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/pango-0.17.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/pango-sys/pango-sys-0.15.1.crate", - "sha256": "7022c2fb88cd2d9d55e1a708a8c53a3ae8678234c4a54bf623400aeb7f31fac2", + "url": "https://static.crates.io/crates/pango-sys/pango-sys-0.17.0.crate", + "sha256": "4293d0f0b5525eb5c24734d30b0ed02cd02aa734f216883f376b54de49625de8", "dest": "cargo/vendor", - "dest-filename": "pango-sys-0.15.1.crate" + "dest-filename": "pango-sys-0.17.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227022c2fb88cd2d9d55e1a708a8c53a3ae8678234c4a54bf623400aeb7f31fac2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/pango-sys-0.15.1", + "url": "data:%7B%22package%22%3A%20%224293d0f0b5525eb5c24734d30b0ed02cd02aa734f216883f376b54de49625de8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/pango-sys-0.17.0", "dest-filename": ".cargo-checksum.json" }, { @@ -2822,15 +2952,41 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/parking_lot_core/parking_lot_core-0.8.5.crate", - "sha256": "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216", + "url": "https://static.crates.io/crates/parking_lot/parking_lot-0.12.1.crate", + "sha256": "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f", + "dest": "cargo/vendor", + "dest-filename": "parking_lot-0.12.1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%223742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/parking_lot-0.12.1", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/parking_lot_core/parking_lot_core-0.8.6.crate", + "sha256": "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc", + "dest": "cargo/vendor", + "dest-filename": "parking_lot_core-0.8.6.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%2260a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/parking_lot_core-0.8.6", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/parking_lot_core/parking_lot_core-0.9.7.crate", + "sha256": "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521", "dest": "cargo/vendor", - "dest-filename": "parking_lot_core-0.8.5.crate" + "dest-filename": "parking_lot_core-0.9.7.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/parking_lot_core-0.8.5", + "url": "data:%7B%22package%22%3A%20%229069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/parking_lot_core-0.9.7", "dest-filename": ".cargo-checksum.json" }, { @@ -2861,158 +3017,158 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/percent-encoding/percent-encoding-2.1.0.crate", - "sha256": "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e", + "url": "https://static.crates.io/crates/percent-encoding/percent-encoding-2.2.0.crate", + "sha256": "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e", "dest": "cargo/vendor", - "dest-filename": "percent-encoding-2.1.0.crate" + "dest-filename": "percent-encoding-2.2.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/percent-encoding-2.1.0", + "url": "data:%7B%22package%22%3A%20%22478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/percent-encoding-2.2.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/pest/pest-2.1.3.crate", - "sha256": "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53", + "url": "https://static.crates.io/crates/pest/pest-2.5.5.crate", + "sha256": "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660", "dest": "cargo/vendor", - "dest-filename": "pest-2.1.3.crate" + "dest-filename": "pest-2.5.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2210f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/pest-2.1.3", + "url": "data:%7B%22package%22%3A%20%22028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/pest-2.5.5", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/pin-project/pin-project-1.0.10.crate", - "sha256": "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e", + "url": "https://static.crates.io/crates/petgraph/petgraph-0.6.3.crate", + "sha256": "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4", "dest": "cargo/vendor", - "dest-filename": "pin-project-1.0.10.crate" + "dest-filename": "petgraph-0.6.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2258ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/pin-project-1.0.10", + "url": "data:%7B%22package%22%3A%20%224dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/petgraph-0.6.3", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/pin-project-internal/pin-project-internal-1.0.10.crate", - "sha256": "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb", + "url": "https://static.crates.io/crates/pin-project/pin-project-1.0.12.crate", + "sha256": "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc", "dest": "cargo/vendor", - "dest-filename": "pin-project-internal-1.0.10.crate" + "dest-filename": "pin-project-1.0.12.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/pin-project-internal-1.0.10", + "url": "data:%7B%22package%22%3A%20%22ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/pin-project-1.0.12", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/pin-project-lite/pin-project-lite-0.2.8.crate", - "sha256": "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c", + "url": "https://static.crates.io/crates/pin-project-internal/pin-project-internal-1.0.12.crate", + "sha256": "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55", "dest": "cargo/vendor", - "dest-filename": "pin-project-lite-0.2.8.crate" + "dest-filename": "pin-project-internal-1.0.12.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/pin-project-lite-0.2.8", + "url": "data:%7B%22package%22%3A%20%22069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/pin-project-internal-1.0.12", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/pin-utils/pin-utils-0.1.0.crate", - "sha256": "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184", + "url": "https://static.crates.io/crates/pin-project-lite/pin-project-lite-0.2.9.crate", + "sha256": "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116", "dest": "cargo/vendor", - "dest-filename": "pin-utils-0.1.0.crate" + "dest-filename": "pin-project-lite-0.2.9.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/pin-utils-0.1.0", + "url": "data:%7B%22package%22%3A%20%22e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/pin-project-lite-0.2.9", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/pkg-config/pkg-config-0.3.24.crate", - "sha256": "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe", + "url": "https://static.crates.io/crates/pin-utils/pin-utils-0.1.0.crate", + "sha256": "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184", "dest": "cargo/vendor", - "dest-filename": "pkg-config-0.3.24.crate" + "dest-filename": "pin-utils-0.1.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2258893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/pkg-config-0.3.24", + "url": "data:%7B%22package%22%3A%20%228b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/pin-utils-0.1.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/polling/polling-2.2.0.crate", - "sha256": "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259", + "url": "https://static.crates.io/crates/pkg-config/pkg-config-0.3.26.crate", + "sha256": "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160", "dest": "cargo/vendor", - "dest-filename": "polling-2.2.0.crate" + "dest-filename": "pkg-config-0.3.26.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/polling-2.2.0", + "url": "data:%7B%22package%22%3A%20%226ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/pkg-config-0.3.26", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/ppv-lite86/ppv-lite86-0.2.16.crate", - "sha256": "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872", + "url": "https://static.crates.io/crates/polling/polling-2.5.2.crate", + "sha256": "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6", "dest": "cargo/vendor", - "dest-filename": "ppv-lite86-0.2.16.crate" + "dest-filename": "polling-2.5.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/ppv-lite86-0.2.16", + "url": "data:%7B%22package%22%3A%20%2222122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/polling-2.5.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/priority-queue/priority-queue-1.2.1.crate", - "sha256": "00ba480ac08d3cfc40dea10fd466fd2c14dee3ea6fc7873bc4079eda2727caf0", + "url": "https://static.crates.io/crates/ppv-lite86/ppv-lite86-0.2.17.crate", + "sha256": "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de", "dest": "cargo/vendor", - "dest-filename": "priority-queue-1.2.1.crate" + "dest-filename": "ppv-lite86-0.2.17.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2200ba480ac08d3cfc40dea10fd466fd2c14dee3ea6fc7873bc4079eda2727caf0%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/priority-queue-1.2.1", + "url": "data:%7B%22package%22%3A%20%225b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/ppv-lite86-0.2.17", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/proc-macro-crate/proc-macro-crate-0.1.5.crate", - "sha256": "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785", + "url": "https://static.crates.io/crates/priority-queue/priority-queue-1.3.1.crate", + "sha256": "5ca9c6be70d989d21a136eb86c2d83e4b328447fac4a88dace2143c179c86267", "dest": "cargo/vendor", - "dest-filename": "proc-macro-crate-0.1.5.crate" + "dest-filename": "priority-queue-1.3.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/proc-macro-crate-0.1.5", + "url": "data:%7B%22package%22%3A%20%225ca9c6be70d989d21a136eb86c2d83e4b328447fac4a88dace2143c179c86267%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/priority-queue-1.3.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/proc-macro-crate/proc-macro-crate-1.1.0.crate", - "sha256": "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83", + "url": "https://static.crates.io/crates/proc-macro-crate/proc-macro-crate-1.3.0.crate", + "sha256": "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34", "dest": "cargo/vendor", - "dest-filename": "proc-macro-crate-1.1.0.crate" + "dest-filename": "proc-macro-crate-1.3.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/proc-macro-crate-1.1.0", + "url": "data:%7B%22package%22%3A%20%2266618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/proc-macro-crate-1.3.0", "dest-filename": ".cargo-checksum.json" }, { @@ -3043,67 +3199,67 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/proc-macro2/proc-macro2-1.0.36.crate", - "sha256": "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029", + "url": "https://static.crates.io/crates/proc-macro2/proc-macro2-1.0.51.crate", + "sha256": "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6", "dest": "cargo/vendor", - "dest-filename": "proc-macro2-1.0.36.crate" + "dest-filename": "proc-macro2-1.0.51.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/proc-macro2-1.0.36", + "url": "data:%7B%22package%22%3A%20%225d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/proc-macro2-1.0.51", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/protobuf/protobuf-2.27.1.crate", - "sha256": "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96", + "url": "https://static.crates.io/crates/protobuf/protobuf-2.28.0.crate", + "sha256": "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94", "dest": "cargo/vendor", - "dest-filename": "protobuf-2.27.1.crate" + "dest-filename": "protobuf-2.28.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/protobuf-2.27.1", + "url": "data:%7B%22package%22%3A%20%22106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/protobuf-2.28.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/protobuf-codegen/protobuf-codegen-2.27.1.crate", - "sha256": "aec1632b7c8f2e620343439a7dfd1f3c47b18906c4be58982079911482b5d707", + "url": "https://static.crates.io/crates/protobuf-codegen/protobuf-codegen-2.28.0.crate", + "sha256": "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6", "dest": "cargo/vendor", - "dest-filename": "protobuf-codegen-2.27.1.crate" + "dest-filename": "protobuf-codegen-2.28.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22aec1632b7c8f2e620343439a7dfd1f3c47b18906c4be58982079911482b5d707%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/protobuf-codegen-2.27.1", + "url": "data:%7B%22package%22%3A%20%22033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/protobuf-codegen-2.28.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/protobuf-codegen-pure/protobuf-codegen-pure-2.27.1.crate", - "sha256": "9f8122fdb18e55190c796b088a16bdb70cd7acdcd48f7a8b796b58c62e532cc6", + "url": "https://static.crates.io/crates/protobuf-codegen-pure/protobuf-codegen-pure-2.28.0.crate", + "sha256": "95a29399fc94bcd3eeaa951c715f7bea69409b2445356b00519740bcd6ddd865", "dest": "cargo/vendor", - "dest-filename": "protobuf-codegen-pure-2.27.1.crate" + "dest-filename": "protobuf-codegen-pure-2.28.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229f8122fdb18e55190c796b088a16bdb70cd7acdcd48f7a8b796b58c62e532cc6%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/protobuf-codegen-pure-2.27.1", + "url": "data:%7B%22package%22%3A%20%2295a29399fc94bcd3eeaa951c715f7bea69409b2445356b00519740bcd6ddd865%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/protobuf-codegen-pure-2.28.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/quote/quote-1.0.15.crate", - "sha256": "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145", + "url": "https://static.crates.io/crates/quote/quote-1.0.23.crate", + "sha256": "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b", "dest": "cargo/vendor", - "dest-filename": "quote-1.0.15.crate" + "dest-filename": "quote-1.0.23.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/quote-1.0.15", + "url": "data:%7B%22package%22%3A%20%228856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/quote-1.0.23", "dest-filename": ".cargo-checksum.json" }, { @@ -3134,15 +3290,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/rand_core/rand_core-0.6.3.crate", - "sha256": "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7", + "url": "https://static.crates.io/crates/rand_core/rand_core-0.6.4.crate", + "sha256": "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c", "dest": "cargo/vendor", - "dest-filename": "rand_core-0.6.3.crate" + "dest-filename": "rand_core-0.6.4.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/rand_core-0.6.3", + "url": "data:%7B%22package%22%3A%20%22ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/rand_core-0.6.4", "dest-filename": ".cargo-checksum.json" }, { @@ -3160,15 +3316,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/redox_syscall/redox_syscall-0.2.10.crate", - "sha256": "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff", + "url": "https://static.crates.io/crates/redox_syscall/redox_syscall-0.2.16.crate", + "sha256": "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a", "dest": "cargo/vendor", - "dest-filename": "redox_syscall-0.2.10.crate" + "dest-filename": "redox_syscall-0.2.16.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/redox_syscall-0.2.10", + "url": "data:%7B%22package%22%3A%20%22fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/redox_syscall-0.2.16", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/redox_users/redox_users-0.4.3.crate", + "sha256": "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b", + "dest": "cargo/vendor", + "dest-filename": "redox_users-0.4.3.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/redox_users-0.4.3", "dest-filename": ".cargo-checksum.json" }, { @@ -3186,28 +3355,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/regex/regex-1.5.5.crate", - "sha256": "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286", + "url": "https://static.crates.io/crates/regex/regex-1.7.1.crate", + "sha256": "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733", "dest": "cargo/vendor", - "dest-filename": "regex-1.5.5.crate" + "dest-filename": "regex-1.7.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/regex-1.5.5", + "url": "data:%7B%22package%22%3A%20%2248aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/regex-1.7.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/regex-syntax/regex-syntax-0.6.25.crate", - "sha256": "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b", + "url": "https://static.crates.io/crates/regex-syntax/regex-syntax-0.6.28.crate", + "sha256": "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848", "dest": "cargo/vendor", - "dest-filename": "regex-syntax-0.6.25.crate" + "dest-filename": "regex-syntax-0.6.28.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/regex-syntax-0.6.25", + "url": "data:%7B%22package%22%3A%20%22456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/regex-syntax-0.6.28", "dest-filename": ".cargo-checksum.json" }, { @@ -3225,28 +3394,41 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/rodio/rodio-0.14.0.crate", - "sha256": "4d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9", + "url": "https://static.crates.io/crates/rodio/rodio-0.15.0.crate", + "sha256": "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e", + "dest": "cargo/vendor", + "dest-filename": "rodio-0.15.0.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/rodio-0.15.0", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/rpassword/rpassword-6.0.1.crate", + "sha256": "2bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956", "dest": "cargo/vendor", - "dest-filename": "rodio-0.14.0.crate" + "dest-filename": "rpassword-6.0.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%224d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/rodio-0.14.0", + "url": "data:%7B%22package%22%3A%20%222bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/rpassword-6.0.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/rpassword/rpassword-5.0.1.crate", - "sha256": "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb", + "url": "https://static.crates.io/crates/rustc-demangle/rustc-demangle-0.1.21.crate", + "sha256": "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342", "dest": "cargo/vendor", - "dest-filename": "rpassword-5.0.1.crate" + "dest-filename": "rustc-demangle-0.1.21.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/rpassword-5.0.1", + "url": "data:%7B%22package%22%3A%20%227ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/rustc-demangle-0.1.21", "dest-filename": ".cargo-checksum.json" }, { @@ -3290,15 +3472,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/ryu/ryu-1.0.9.crate", - "sha256": "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f", + "url": "https://static.crates.io/crates/ryu/ryu-1.0.12.crate", + "sha256": "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde", "dest": "cargo/vendor", - "dest-filename": "ryu-1.0.9.crate" + "dest-filename": "ryu-1.0.12.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2273b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/ryu-1.0.9", + "url": "data:%7B%22package%22%3A%20%227b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/ryu-1.0.12", "dest-filename": ".cargo-checksum.json" }, { @@ -3316,54 +3498,54 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/schannel/schannel-0.1.19.crate", - "sha256": "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75", + "url": "https://static.crates.io/crates/schannel/schannel-0.1.21.crate", + "sha256": "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3", "dest": "cargo/vendor", - "dest-filename": "schannel-0.1.19.crate" + "dest-filename": "schannel-0.1.21.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/schannel-0.1.19", + "url": "data:%7B%22package%22%3A%20%22713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/schannel-0.1.21", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/scoped-tls/scoped-tls-1.0.0.crate", - "sha256": "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2", + "url": "https://static.crates.io/crates/scopeguard/scopeguard-1.1.0.crate", + "sha256": "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd", "dest": "cargo/vendor", - "dest-filename": "scoped-tls-1.0.0.crate" + "dest-filename": "scopeguard-1.1.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/scoped-tls-1.0.0", + "url": "data:%7B%22package%22%3A%20%22d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/scopeguard-1.1.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/scopeguard/scopeguard-1.1.0.crate", - "sha256": "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd", + "url": "https://static.crates.io/crates/scratch/scratch-1.0.3.crate", + "sha256": "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2", "dest": "cargo/vendor", - "dest-filename": "scopeguard-1.1.0.crate" + "dest-filename": "scratch-1.0.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/scopeguard-1.1.0", + "url": "data:%7B%22package%22%3A%20%22ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/scratch-1.0.3", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/secret-service/secret-service-2.0.1.crate", - "sha256": "2400fb1bf2a87b303ada204946294f932ade4929477e9e2bf66d7b49a66656ec", + "url": "https://static.crates.io/crates/secret-service/secret-service-3.0.1.crate", + "sha256": "5da1a5ad4d28c03536f82f77d9f36603f5e37d8869ac98f0a750d5b5686d8d95", "dest": "cargo/vendor", - "dest-filename": "secret-service-2.0.1.crate" + "dest-filename": "secret-service-3.0.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222400fb1bf2a87b303ada204946294f932ade4929477e9e2bf66d7b49a66656ec%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/secret-service-2.0.1", + "url": "data:%7B%22package%22%3A%20%225da1a5ad4d28c03536f82f77d9f36603f5e37d8869ac98f0a750d5b5686d8d95%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/secret-service-3.0.1", "dest-filename": ".cargo-checksum.json" }, { @@ -3381,15 +3563,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/semver/semver-1.0.5.crate", - "sha256": "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7", + "url": "https://static.crates.io/crates/semver/semver-1.0.16.crate", + "sha256": "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a", "dest": "cargo/vendor", - "dest-filename": "semver-1.0.5.crate" + "dest-filename": "semver-1.0.16.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%220486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/semver-1.0.5", + "url": "data:%7B%22package%22%3A%20%2258bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/semver-1.0.16", "dest-filename": ".cargo-checksum.json" }, { @@ -3407,54 +3589,54 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/serde/serde-1.0.136.crate", - "sha256": "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789", + "url": "https://static.crates.io/crates/serde/serde-1.0.152.crate", + "sha256": "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb", "dest": "cargo/vendor", - "dest-filename": "serde-1.0.136.crate" + "dest-filename": "serde-1.0.152.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/serde-1.0.136", + "url": "data:%7B%22package%22%3A%20%22bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/serde-1.0.152", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/serde_derive/serde_derive-1.0.136.crate", - "sha256": "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9", + "url": "https://static.crates.io/crates/serde_derive/serde_derive-1.0.152.crate", + "sha256": "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e", "dest": "cargo/vendor", - "dest-filename": "serde_derive-1.0.136.crate" + "dest-filename": "serde_derive-1.0.152.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2208597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/serde_derive-1.0.136", + "url": "data:%7B%22package%22%3A%20%22af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/serde_derive-1.0.152", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/serde_json/serde_json-1.0.79.crate", - "sha256": "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95", + "url": "https://static.crates.io/crates/serde_json/serde_json-1.0.93.crate", + "sha256": "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76", "dest": "cargo/vendor", - "dest-filename": "serde_json-1.0.79.crate" + "dest-filename": "serde_json-1.0.93.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/serde_json-1.0.79", + "url": "data:%7B%22package%22%3A%20%22cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/serde_json-1.0.93", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/serde_repr/serde_repr-0.1.7.crate", - "sha256": "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5", + "url": "https://static.crates.io/crates/serde_repr/serde_repr-0.1.10.crate", + "sha256": "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e", "dest": "cargo/vendor", - "dest-filename": "serde_repr-0.1.7.crate" + "dest-filename": "serde_repr-0.1.10.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2298d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/serde_repr-0.1.7", + "url": "data:%7B%22package%22%3A%20%229a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/serde_repr-0.1.10", "dest-filename": ".cargo-checksum.json" }, { @@ -3472,41 +3654,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/sha1/sha1-0.6.1.crate", - "sha256": "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770", - "dest": "cargo/vendor", - "dest-filename": "sha1-0.6.1.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%22c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/sha1-0.6.1", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "file", - "url": "https://static.crates.io/crates/sha1_smol/sha1_smol-1.0.0.crate", - "sha256": "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012", + "url": "https://static.crates.io/crates/sha1/sha1-0.10.5.crate", + "sha256": "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3", "dest": "cargo/vendor", - "dest-filename": "sha1_smol-1.0.0.crate" + "dest-filename": "sha1-0.10.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/sha1_smol-1.0.0", + "url": "data:%7B%22package%22%3A%20%22f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/sha1-0.10.5", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/sha2/sha2-0.9.9.crate", - "sha256": "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800", + "url": "https://static.crates.io/crates/sha2/sha2-0.10.6.crate", + "sha256": "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0", "dest": "cargo/vendor", - "dest-filename": "sha2-0.9.9.crate" + "dest-filename": "sha2-0.10.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%224d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/sha2-0.9.9", + "url": "data:%7B%22package%22%3A%20%2282e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/sha2-0.10.6", "dest-filename": ".cargo-checksum.json" }, { @@ -3537,41 +3706,41 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/shlex/shlex-0.1.1.crate", - "sha256": "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2", + "url": "https://static.crates.io/crates/shlex/shlex-1.1.0.crate", + "sha256": "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3", "dest": "cargo/vendor", - "dest-filename": "shlex-0.1.1.crate" + "dest-filename": "shlex-1.1.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/shlex-0.1.1", + "url": "data:%7B%22package%22%3A%20%2243b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/shlex-1.1.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/signal-hook-registry/signal-hook-registry-1.4.0.crate", - "sha256": "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0", + "url": "https://static.crates.io/crates/signal-hook-registry/signal-hook-registry-1.4.1.crate", + "sha256": "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1", "dest": "cargo/vendor", - "dest-filename": "signal-hook-registry-1.4.0.crate" + "dest-filename": "signal-hook-registry-1.4.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/signal-hook-registry-1.4.0", + "url": "data:%7B%22package%22%3A%20%22d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/signal-hook-registry-1.4.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/slab/slab-0.4.5.crate", - "sha256": "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5", + "url": "https://static.crates.io/crates/slab/slab-0.4.7.crate", + "sha256": "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef", "dest": "cargo/vendor", - "dest-filename": "slab-0.4.5.crate" + "dest-filename": "slab-0.4.7.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/slab-0.4.5", + "url": "data:%7B%22package%22%3A%20%224614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/slab-0.4.7", "dest-filename": ".cargo-checksum.json" }, { @@ -3589,28 +3758,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/smallvec/smallvec-1.8.0.crate", - "sha256": "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83", + "url": "https://static.crates.io/crates/smallvec/smallvec-1.10.0.crate", + "sha256": "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0", "dest": "cargo/vendor", - "dest-filename": "smallvec-1.8.0.crate" + "dest-filename": "smallvec-1.10.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/smallvec-1.8.0", + "url": "data:%7B%22package%22%3A%20%22a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/smallvec-1.10.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/socket2/socket2-0.4.4.crate", - "sha256": "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0", + "url": "https://static.crates.io/crates/socket2/socket2-0.4.7.crate", + "sha256": "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd", "dest": "cargo/vendor", - "dest-filename": "socket2-0.4.4.crate" + "dest-filename": "socket2-0.4.7.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2266d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/socket2-0.4.4", + "url": "data:%7B%22package%22%3A%20%2202e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/socket2-0.4.7", "dest-filename": ".cargo-checksum.json" }, { @@ -3667,41 +3836,28 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/syn/syn-1.0.86.crate", - "sha256": "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b", + "url": "https://static.crates.io/crates/syn/syn-1.0.107.crate", + "sha256": "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5", "dest": "cargo/vendor", - "dest-filename": "syn-1.0.86.crate" + "dest-filename": "syn-1.0.107.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/syn-1.0.86", + "url": "data:%7B%22package%22%3A%20%221f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/syn-1.0.107", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/synstructure/synstructure-0.12.6.crate", - "sha256": "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f", + "url": "https://static.crates.io/crates/system-deps/system-deps-6.0.3.crate", + "sha256": "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff", "dest": "cargo/vendor", - "dest-filename": "synstructure-0.12.6.crate" + "dest-filename": "system-deps-6.0.3.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/synstructure-0.12.6", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "file", - "url": "https://static.crates.io/crates/system-deps/system-deps-6.0.1.crate", - "sha256": "ad3a97fdef3daf935d929b3e97e5a6a680cd4622e40c2941ca0875d6566416f8", - "dest": "cargo/vendor", - "dest-filename": "system-deps-6.0.1.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%22ad3a97fdef3daf935d929b3e97e5a6a680cd4622e40c2941ca0875d6566416f8%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/system-deps-6.0.1", + "url": "data:%7B%22package%22%3A%20%222955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/system-deps-6.0.3", "dest-filename": ".cargo-checksum.json" }, { @@ -3732,197 +3888,236 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/termcolor/termcolor-1.1.2.crate", - "sha256": "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4", + "url": "https://static.crates.io/crates/termcolor/termcolor-1.2.0.crate", + "sha256": "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6", + "dest": "cargo/vendor", + "dest-filename": "termcolor-1.2.0.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/termcolor-1.2.0", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/thiserror/thiserror-1.0.38.crate", + "sha256": "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0", + "dest": "cargo/vendor", + "dest-filename": "thiserror-1.0.38.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%226a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/thiserror-1.0.38", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/thiserror-impl/thiserror-impl-1.0.38.crate", + "sha256": "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f", + "dest": "cargo/vendor", + "dest-filename": "thiserror-impl-1.0.38.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%221fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/thiserror-impl-1.0.38", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/thread-id/thread-id-4.0.0.crate", + "sha256": "5fdfe0627923f7411a43ec9ec9c39c3a9b4151be313e0922042581fb6c9b717f", "dest": "cargo/vendor", - "dest-filename": "termcolor-1.1.2.crate" + "dest-filename": "thread-id-4.0.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/termcolor-1.1.2", + "url": "data:%7B%22package%22%3A%20%225fdfe0627923f7411a43ec9ec9c39c3a9b4151be313e0922042581fb6c9b717f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/thread-id-4.0.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/thiserror/thiserror-1.0.30.crate", - "sha256": "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417", + "url": "https://static.crates.io/crates/time/time-0.1.45.crate", + "sha256": "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a", "dest": "cargo/vendor", - "dest-filename": "thiserror-1.0.30.crate" + "dest-filename": "time-0.1.45.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/thiserror-1.0.30", + "url": "data:%7B%22package%22%3A%20%221b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/time-0.1.45", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/thiserror-impl/thiserror-impl-1.0.30.crate", - "sha256": "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b", + "url": "https://static.crates.io/crates/tinyvec/tinyvec-1.6.0.crate", + "sha256": "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50", "dest": "cargo/vendor", - "dest-filename": "thiserror-impl-1.0.30.crate" + "dest-filename": "tinyvec-1.6.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/thiserror-impl-1.0.30", + "url": "data:%7B%22package%22%3A%20%2287cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tinyvec-1.6.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/time/time-0.1.43.crate", - "sha256": "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438", + "url": "https://static.crates.io/crates/tinyvec_macros/tinyvec_macros-0.1.1.crate", + "sha256": "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20", "dest": "cargo/vendor", - "dest-filename": "time-0.1.43.crate" + "dest-filename": "tinyvec_macros-0.1.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/time-0.1.43", + "url": "data:%7B%22package%22%3A%20%221f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tinyvec_macros-0.1.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tinyvec/tinyvec-1.5.1.crate", - "sha256": "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2", + "url": "https://static.crates.io/crates/tokio/tokio-1.25.0.crate", + "sha256": "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af", "dest": "cargo/vendor", - "dest-filename": "tinyvec-1.5.1.crate" + "dest-filename": "tokio-1.25.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tinyvec-1.5.1", + "url": "data:%7B%22package%22%3A%20%22c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tokio-1.25.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tinyvec_macros/tinyvec_macros-0.1.0.crate", - "sha256": "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c", + "url": "https://static.crates.io/crates/tokio-macros/tokio-macros-1.8.2.crate", + "sha256": "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8", "dest": "cargo/vendor", - "dest-filename": "tinyvec_macros-0.1.0.crate" + "dest-filename": "tokio-macros-1.8.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tinyvec_macros-0.1.0", + "url": "data:%7B%22package%22%3A%20%22d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tokio-macros-1.8.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tokio/tokio-1.17.0.crate", - "sha256": "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee", + "url": "https://static.crates.io/crates/tokio-stream/tokio-stream-0.1.11.crate", + "sha256": "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce", "dest": "cargo/vendor", - "dest-filename": "tokio-1.17.0.crate" + "dest-filename": "tokio-stream-0.1.11.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tokio-1.17.0", + "url": "data:%7B%22package%22%3A%20%22d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tokio-stream-0.1.11", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tokio-macros/tokio-macros-1.7.0.crate", - "sha256": "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7", + "url": "https://static.crates.io/crates/tokio-util/tokio-util-0.7.7.crate", + "sha256": "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2", "dest": "cargo/vendor", - "dest-filename": "tokio-macros-1.7.0.crate" + "dest-filename": "tokio-util-0.7.7.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tokio-macros-1.7.0", + "url": "data:%7B%22package%22%3A%20%225427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tokio-util-0.7.7", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tokio-stream/tokio-stream-0.1.8.crate", - "sha256": "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3", + "url": "https://static.crates.io/crates/toml/toml-0.5.11.crate", + "sha256": "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234", "dest": "cargo/vendor", - "dest-filename": "tokio-stream-0.1.8.crate" + "dest-filename": "toml-0.5.11.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2250145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tokio-stream-0.1.8", + "url": "data:%7B%22package%22%3A%20%22f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/toml-0.5.11", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tokio-util/tokio-util-0.6.9.crate", - "sha256": "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0", + "url": "https://static.crates.io/crates/toml_datetime/toml_datetime-0.5.1.crate", + "sha256": "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5", "dest": "cargo/vendor", - "dest-filename": "tokio-util-0.6.9.crate" + "dest-filename": "toml_datetime-0.5.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%229e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tokio-util-0.6.9", + "url": "data:%7B%22package%22%3A%20%224553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/toml_datetime-0.5.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/toml/toml-0.5.8.crate", - "sha256": "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa", + "url": "https://static.crates.io/crates/toml_edit/toml_edit-0.18.1.crate", + "sha256": "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b", "dest": "cargo/vendor", - "dest-filename": "toml-0.5.8.crate" + "dest-filename": "toml_edit-0.18.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/toml-0.5.8", + "url": "data:%7B%22package%22%3A%20%2256c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/toml_edit-0.18.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tower-service/tower-service-0.3.1.crate", - "sha256": "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6", + "url": "https://static.crates.io/crates/tower-service/tower-service-0.3.2.crate", + "sha256": "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52", "dest": "cargo/vendor", - "dest-filename": "tower-service-0.3.1.crate" + "dest-filename": "tower-service-0.3.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tower-service-0.3.1", + "url": "data:%7B%22package%22%3A%20%22b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tower-service-0.3.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tracing/tracing-0.1.30.crate", - "sha256": "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9", + "url": "https://static.crates.io/crates/tracing/tracing-0.1.37.crate", + "sha256": "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8", "dest": "cargo/vendor", - "dest-filename": "tracing-0.1.30.crate" + "dest-filename": "tracing-0.1.37.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tracing-0.1.30", + "url": "data:%7B%22package%22%3A%20%228ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tracing-0.1.37", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tracing-attributes/tracing-attributes-0.1.19.crate", - "sha256": "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716", + "url": "https://static.crates.io/crates/tracing-attributes/tracing-attributes-0.1.23.crate", + "sha256": "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a", "dest": "cargo/vendor", - "dest-filename": "tracing-attributes-0.1.19.crate" + "dest-filename": "tracing-attributes-0.1.23.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tracing-attributes-0.1.19", + "url": "data:%7B%22package%22%3A%20%224017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tracing-attributes-0.1.23", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/tracing-core/tracing-core-0.1.22.crate", - "sha256": "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23", + "url": "https://static.crates.io/crates/tracing-core/tracing-core-0.1.30.crate", + "sha256": "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a", "dest": "cargo/vendor", - "dest-filename": "tracing-core-0.1.22.crate" + "dest-filename": "tracing-core-0.1.30.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2203cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/tracing-core-0.1.22", + "url": "data:%7B%22package%22%3A%20%2224eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/tracing-core-0.1.30", "dest-filename": ".cargo-checksum.json" }, { @@ -3940,132 +4135,145 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/try-lock/try-lock-0.2.3.crate", - "sha256": "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642", + "url": "https://static.crates.io/crates/try-lock/try-lock-0.2.4.crate", + "sha256": "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed", "dest": "cargo/vendor", - "dest-filename": "try-lock-0.2.3.crate" + "dest-filename": "try-lock-0.2.4.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2259547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/try-lock-0.2.3", + "url": "data:%7B%22package%22%3A%20%223528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/try-lock-0.2.4", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/typenum/typenum-1.15.0.crate", - "sha256": "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987", + "url": "https://static.crates.io/crates/typenum/typenum-1.16.0.crate", + "sha256": "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba", "dest": "cargo/vendor", - "dest-filename": "typenum-1.15.0.crate" + "dest-filename": "typenum-1.16.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/typenum-1.15.0", + "url": "data:%7B%22package%22%3A%20%22497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/typenum-1.16.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/ucd-trie/ucd-trie-0.1.3.crate", - "sha256": "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c", + "url": "https://static.crates.io/crates/ucd-trie/ucd-trie-0.1.5.crate", + "sha256": "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81", "dest": "cargo/vendor", - "dest-filename": "ucd-trie-0.1.3.crate" + "dest-filename": "ucd-trie-0.1.5.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2256dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/ucd-trie-0.1.3", + "url": "data:%7B%22package%22%3A%20%229e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/ucd-trie-0.1.5", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/unicode-bidi/unicode-bidi-0.3.7.crate", - "sha256": "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f", + "url": "https://static.crates.io/crates/uds_windows/uds_windows-1.0.2.crate", + "sha256": "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d", "dest": "cargo/vendor", - "dest-filename": "unicode-bidi-0.3.7.crate" + "dest-filename": "uds_windows-1.0.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%221a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/unicode-bidi-0.3.7", + "url": "data:%7B%22package%22%3A%20%22ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/uds_windows-1.0.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/unicode-normalization/unicode-normalization-0.1.19.crate", - "sha256": "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9", + "url": "https://static.crates.io/crates/unicode-bidi/unicode-bidi-0.3.10.crate", + "sha256": "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58", "dest": "cargo/vendor", - "dest-filename": "unicode-normalization-0.1.19.crate" + "dest-filename": "unicode-bidi-0.3.10.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/unicode-normalization-0.1.19", + "url": "data:%7B%22package%22%3A%20%22d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/unicode-bidi-0.3.10", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/unicode-width/unicode-width-0.1.9.crate", - "sha256": "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973", + "url": "https://static.crates.io/crates/unicode-ident/unicode-ident-1.0.6.crate", + "sha256": "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc", "dest": "cargo/vendor", - "dest-filename": "unicode-width-0.1.9.crate" + "dest-filename": "unicode-ident-1.0.6.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%223ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/unicode-width-0.1.9", + "url": "data:%7B%22package%22%3A%20%2284a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/unicode-ident-1.0.6", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/unicode-xid/unicode-xid-0.2.2.crate", - "sha256": "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3", + "url": "https://static.crates.io/crates/unicode-normalization/unicode-normalization-0.1.22.crate", + "sha256": "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921", "dest": "cargo/vendor", - "dest-filename": "unicode-xid-0.2.2.crate" + "dest-filename": "unicode-normalization-0.1.22.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/unicode-xid-0.2.2", + "url": "data:%7B%22package%22%3A%20%225c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/unicode-normalization-0.1.22", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/url/url-2.2.2.crate", - "sha256": "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c", + "url": "https://static.crates.io/crates/unicode-width/unicode-width-0.1.10.crate", + "sha256": "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b", "dest": "cargo/vendor", - "dest-filename": "url-2.2.2.crate" + "dest-filename": "unicode-width-0.1.10.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/url-2.2.2", + "url": "data:%7B%22package%22%3A%20%22c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/unicode-width-0.1.10", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/uuid/uuid-0.8.2.crate", - "sha256": "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7", + "url": "https://static.crates.io/crates/url/url-2.3.1.crate", + "sha256": "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643", "dest": "cargo/vendor", - "dest-filename": "uuid-0.8.2.crate" + "dest-filename": "url-2.3.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/uuid-0.8.2", + "url": "data:%7B%22package%22%3A%20%220d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/url-2.3.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/value-bag/value-bag-1.0.0-alpha.8.crate", - "sha256": "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f", + "url": "https://static.crates.io/crates/uuid/uuid-1.3.0.crate", + "sha256": "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79", "dest": "cargo/vendor", - "dest-filename": "value-bag-1.0.0-alpha.8.crate" + "dest-filename": "uuid-1.3.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2279923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/value-bag-1.0.0-alpha.8", + "url": "data:%7B%22package%22%3A%20%221674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/uuid-1.3.0", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/value-bag/value-bag-1.0.0-alpha.9.crate", + "sha256": "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55", + "dest": "cargo/vendor", + "dest-filename": "value-bag-1.0.0-alpha.9.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%222209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/value-bag-1.0.0-alpha.9", "dest-filename": ".cargo-checksum.json" }, { @@ -4096,15 +4304,15 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/version-compare/version-compare-0.1.0.crate", - "sha256": "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73", + "url": "https://static.crates.io/crates/version-compare/version-compare-0.1.1.crate", + "sha256": "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29", "dest": "cargo/vendor", - "dest-filename": "version-compare-0.1.0.crate" + "dest-filename": "version-compare-0.1.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/version-compare-0.1.0", + "url": "data:%7B%22package%22%3A%20%22579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/version-compare-0.1.1", "dest-filename": ".cargo-checksum.json" }, { @@ -4120,19 +4328,6 @@ "dest": "cargo/vendor/version_check-0.9.4", "dest-filename": ".cargo-checksum.json" }, - { - "type": "file", - "url": "https://static.crates.io/crates/void/void-1.0.2.crate", - "sha256": "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d", - "dest": "cargo/vendor", - "dest-filename": "void-1.0.2.crate" - }, - { - "type": "file", - "url": "data:%7B%22package%22%3A%20%226a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/void-1.0.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "file", "url": "https://static.crates.io/crates/waker-fn/waker-fn-1.1.0.crate", @@ -4174,106 +4369,119 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/wasi/wasi-0.10.2+wasi-snapshot-preview1.crate", - "sha256": "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6", + "url": "https://static.crates.io/crates/wasi/wasi-0.10.0+wasi-snapshot-preview1.crate", + "sha256": "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f", + "dest": "cargo/vendor", + "dest-filename": "wasi-0.10.0+wasi-snapshot-preview1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%221a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/wasi-0.10.0+wasi-snapshot-preview1", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/wasi/wasi-0.11.0+wasi-snapshot-preview1.crate", + "sha256": "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423", "dest": "cargo/vendor", - "dest-filename": "wasi-0.10.2+wasi-snapshot-preview1.crate" + "dest-filename": "wasi-0.11.0+wasi-snapshot-preview1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/wasi-0.10.2+wasi-snapshot-preview1", + "url": "data:%7B%22package%22%3A%20%229c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/wasi-0.11.0+wasi-snapshot-preview1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/wasm-bindgen/wasm-bindgen-0.2.79.crate", - "sha256": "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06", + "url": "https://static.crates.io/crates/wasm-bindgen/wasm-bindgen-0.2.84.crate", + "sha256": "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b", "dest": "cargo/vendor", - "dest-filename": "wasm-bindgen-0.2.79.crate" + "dest-filename": "wasm-bindgen-0.2.84.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2225f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/wasm-bindgen-0.2.79", + "url": "data:%7B%22package%22%3A%20%2231f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/wasm-bindgen-0.2.84", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/wasm-bindgen-backend/wasm-bindgen-backend-0.2.79.crate", - "sha256": "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca", + "url": "https://static.crates.io/crates/wasm-bindgen-backend/wasm-bindgen-backend-0.2.84.crate", + "sha256": "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9", "dest": "cargo/vendor", - "dest-filename": "wasm-bindgen-backend-0.2.79.crate" + "dest-filename": "wasm-bindgen-backend-0.2.84.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/wasm-bindgen-backend-0.2.79", + "url": "data:%7B%22package%22%3A%20%2295ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/wasm-bindgen-backend-0.2.84", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/wasm-bindgen-futures/wasm-bindgen-futures-0.4.29.crate", - "sha256": "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395", + "url": "https://static.crates.io/crates/wasm-bindgen-futures/wasm-bindgen-futures-0.4.34.crate", + "sha256": "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454", "dest": "cargo/vendor", - "dest-filename": "wasm-bindgen-futures-0.4.29.crate" + "dest-filename": "wasm-bindgen-futures-0.4.34.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/wasm-bindgen-futures-0.4.29", + "url": "data:%7B%22package%22%3A%20%22f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/wasm-bindgen-futures-0.4.34", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/wasm-bindgen-macro/wasm-bindgen-macro-0.2.79.crate", - "sha256": "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01", + "url": "https://static.crates.io/crates/wasm-bindgen-macro/wasm-bindgen-macro-0.2.84.crate", + "sha256": "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5", "dest": "cargo/vendor", - "dest-filename": "wasm-bindgen-macro-0.2.79.crate" + "dest-filename": "wasm-bindgen-macro-0.2.84.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/wasm-bindgen-macro-0.2.79", + "url": "data:%7B%22package%22%3A%20%224c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/wasm-bindgen-macro-0.2.84", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/wasm-bindgen-macro-support/wasm-bindgen-macro-support-0.2.79.crate", - "sha256": "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc", + "url": "https://static.crates.io/crates/wasm-bindgen-macro-support/wasm-bindgen-macro-support-0.2.84.crate", + "sha256": "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6", "dest": "cargo/vendor", - "dest-filename": "wasm-bindgen-macro-support-0.2.79.crate" + "dest-filename": "wasm-bindgen-macro-support-0.2.84.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/wasm-bindgen-macro-support-0.2.79", + "url": "data:%7B%22package%22%3A%20%222aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/wasm-bindgen-macro-support-0.2.84", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/wasm-bindgen-shared/wasm-bindgen-shared-0.2.79.crate", - "sha256": "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2", + "url": "https://static.crates.io/crates/wasm-bindgen-shared/wasm-bindgen-shared-0.2.84.crate", + "sha256": "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d", "dest": "cargo/vendor", - "dest-filename": "wasm-bindgen-shared-0.2.79.crate" + "dest-filename": "wasm-bindgen-shared-0.2.84.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%223d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/wasm-bindgen-shared-0.2.79", + "url": "data:%7B%22package%22%3A%20%220046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/wasm-bindgen-shared-0.2.84", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/web-sys/web-sys-0.3.56.crate", - "sha256": "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb", + "url": "https://static.crates.io/crates/web-sys/web-sys-0.3.61.crate", + "sha256": "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97", "dest": "cargo/vendor", - "dest-filename": "web-sys-0.3.56.crate" + "dest-filename": "web-sys-0.3.61.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/web-sys-0.3.56", + "url": "data:%7B%22package%22%3A%20%22e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/web-sys-0.3.61", "dest-filename": ".cargo-checksum.json" }, { @@ -4343,145 +4551,223 @@ }, { "type": "file", - "url": "https://static.crates.io/crates/zbus/zbus-1.9.1.crate", - "sha256": "2326acc379a3ac4e34b794089f5bdb17086bf29a5fdf619b7b4cc772dc2e9dad", + "url": "https://static.crates.io/crates/windows-sys/windows-sys-0.42.0.crate", + "sha256": "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7", + "dest": "cargo/vendor", + "dest-filename": "windows-sys-0.42.0.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%225a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows-sys-0.42.0", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/windows-sys/windows-sys-0.45.0.crate", + "sha256": "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0", + "dest": "cargo/vendor", + "dest-filename": "windows-sys-0.45.0.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%2275283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows-sys-0.45.0", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/windows-targets/windows-targets-0.42.1.crate", + "sha256": "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7", + "dest": "cargo/vendor", + "dest-filename": "windows-targets-0.42.1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%228e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows-targets-0.42.1", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/windows_aarch64_gnullvm/windows_aarch64_gnullvm-0.42.1.crate", + "sha256": "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608", + "dest": "cargo/vendor", + "dest-filename": "windows_aarch64_gnullvm-0.42.1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%228c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows_aarch64_gnullvm-0.42.1", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/windows_aarch64_msvc/windows_aarch64_msvc-0.42.1.crate", + "sha256": "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7", + "dest": "cargo/vendor", + "dest-filename": "windows_aarch64_msvc-0.42.1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%224c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows_aarch64_msvc-0.42.1", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/windows_i686_gnu/windows_i686_gnu-0.42.1.crate", + "sha256": "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640", + "dest": "cargo/vendor", + "dest-filename": "windows_i686_gnu-0.42.1.crate" + }, + { + "type": "file", + "url": "data:%7B%22package%22%3A%20%22de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows_i686_gnu-0.42.1", + "dest-filename": ".cargo-checksum.json" + }, + { + "type": "file", + "url": "https://static.crates.io/crates/windows_i686_msvc/windows_i686_msvc-0.42.1.crate", + "sha256": "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605", "dest": "cargo/vendor", - "dest-filename": "zbus-1.9.1.crate" + "dest-filename": "windows_i686_msvc-0.42.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%222326acc379a3ac4e34b794089f5bdb17086bf29a5fdf619b7b4cc772dc2e9dad%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zbus-1.9.1", + "url": "data:%7B%22package%22%3A%20%22bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows_i686_msvc-0.42.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zbus/zbus-2.1.1.crate", - "sha256": "7bb86f3d4592e26a48b2719742aec94f8ae6238ebde20d98183ee185d1275e9a", + "url": "https://static.crates.io/crates/windows_x86_64_gnu/windows_x86_64_gnu-0.42.1.crate", + "sha256": "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45", "dest": "cargo/vendor", - "dest-filename": "zbus-2.1.1.crate" + "dest-filename": "windows_x86_64_gnu-0.42.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%227bb86f3d4592e26a48b2719742aec94f8ae6238ebde20d98183ee185d1275e9a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zbus-2.1.1", + "url": "data:%7B%22package%22%3A%20%22c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows_x86_64_gnu-0.42.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zbus_macros/zbus_macros-1.9.1.crate", - "sha256": "a482c56029e48681b89b92b5db3c446db0915e8dd1052c0328a574eda38d5f93", + "url": "https://static.crates.io/crates/windows_x86_64_gnullvm/windows_x86_64_gnullvm-0.42.1.crate", + "sha256": "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463", "dest": "cargo/vendor", - "dest-filename": "zbus_macros-1.9.1.crate" + "dest-filename": "windows_x86_64_gnullvm-0.42.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a482c56029e48681b89b92b5db3c446db0915e8dd1052c0328a574eda38d5f93%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zbus_macros-1.9.1", + "url": "data:%7B%22package%22%3A%20%22628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows_x86_64_gnullvm-0.42.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zbus_macros/zbus_macros-2.1.1.crate", - "sha256": "36823cc10fddc3c6b19f048903262dacaf8274170e9a255784bdd8b4570a8040", + "url": "https://static.crates.io/crates/windows_x86_64_msvc/windows_x86_64_msvc-0.42.1.crate", + "sha256": "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd", "dest": "cargo/vendor", - "dest-filename": "zbus_macros-2.1.1.crate" + "dest-filename": "windows_x86_64_msvc-0.42.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2236823cc10fddc3c6b19f048903262dacaf8274170e9a255784bdd8b4570a8040%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zbus_macros-2.1.1", + "url": "data:%7B%22package%22%3A%20%22447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/windows_x86_64_msvc-0.42.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zbus_names/zbus_names-2.1.0.crate", - "sha256": "45dfcdcf87b71dad505d30cc27b1b7b88a64b6d1c435648f48f9dbc1fdc4b7e1", + "url": "https://static.crates.io/crates/zbus/zbus-3.10.0.crate", + "sha256": "f770930448dd412a4a7131dd968a8e6df0064db4d7916fbbd2d6c3f26b566938", "dest": "cargo/vendor", - "dest-filename": "zbus_names-2.1.0.crate" + "dest-filename": "zbus-3.10.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2245dfcdcf87b71dad505d30cc27b1b7b88a64b6d1c435648f48f9dbc1fdc4b7e1%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zbus_names-2.1.0", + "url": "data:%7B%22package%22%3A%20%22f770930448dd412a4a7131dd968a8e6df0064db4d7916fbbd2d6c3f26b566938%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/zbus-3.10.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zerocopy/zerocopy-0.3.0.crate", - "sha256": "6580539ad917b7c026220c4b3f2c08d52ce54d6ce0dc491e66002e35388fab46", + "url": "https://static.crates.io/crates/zbus_macros/zbus_macros-3.10.0.crate", + "sha256": "4832059b438689017db7340580ebabba07f114eab91bf990c6e55052408b40d8", "dest": "cargo/vendor", - "dest-filename": "zerocopy-0.3.0.crate" + "dest-filename": "zbus_macros-3.10.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%226580539ad917b7c026220c4b3f2c08d52ce54d6ce0dc491e66002e35388fab46%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zerocopy-0.3.0", + "url": "data:%7B%22package%22%3A%20%224832059b438689017db7340580ebabba07f114eab91bf990c6e55052408b40d8%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/zbus_macros-3.10.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zerocopy-derive/zerocopy-derive-0.2.0.crate", - "sha256": "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb", + "url": "https://static.crates.io/crates/zbus_names/zbus_names-2.5.0.crate", + "sha256": "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3", "dest": "cargo/vendor", - "dest-filename": "zerocopy-derive-0.2.0.crate" + "dest-filename": "zbus_names-2.5.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zerocopy-derive-0.2.0", + "url": "data:%7B%22package%22%3A%20%22f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/zbus_names-2.5.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zvariant/zvariant-2.10.0.crate", - "sha256": "a68c7b55f2074489b7e8e07d2d0a6ee6b4f233867a653c664d8020ba53692525", + "url": "https://static.crates.io/crates/zerocopy/zerocopy-0.6.1.crate", + "sha256": "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236", "dest": "cargo/vendor", - "dest-filename": "zvariant-2.10.0.crate" + "dest-filename": "zerocopy-0.6.1.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22a68c7b55f2074489b7e8e07d2d0a6ee6b4f233867a653c664d8020ba53692525%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zvariant-2.10.0", + "url": "data:%7B%22package%22%3A%20%22332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/zerocopy-0.6.1", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zvariant/zvariant-3.1.2.crate", - "sha256": "49ea5dc38b2058fae6a5b79009388143dadce1e91c26a67f984a0fc0381c8033", + "url": "https://static.crates.io/crates/zerocopy-derive/zerocopy-derive-0.3.2.crate", + "sha256": "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3", "dest": "cargo/vendor", - "dest-filename": "zvariant-3.1.2.crate" + "dest-filename": "zerocopy-derive-0.3.2.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%2249ea5dc38b2058fae6a5b79009388143dadce1e91c26a67f984a0fc0381c8033%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zvariant-3.1.2", + "url": "data:%7B%22package%22%3A%20%226505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/zerocopy-derive-0.3.2", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zvariant_derive/zvariant_derive-2.10.0.crate", - "sha256": "e4ca5e22593eb4212382d60d26350065bf2a02c34b85bc850474a74b589a3de9", + "url": "https://static.crates.io/crates/zvariant/zvariant-3.11.0.crate", + "sha256": "903169c05b9ab948ee93fefc9127d08930df4ce031d46c980784274439803e51", "dest": "cargo/vendor", - "dest-filename": "zvariant_derive-2.10.0.crate" + "dest-filename": "zvariant-3.11.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%22e4ca5e22593eb4212382d60d26350065bf2a02c34b85bc850474a74b589a3de9%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zvariant_derive-2.10.0", + "url": "data:%7B%22package%22%3A%20%22903169c05b9ab948ee93fefc9127d08930df4ce031d46c980784274439803e51%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/zvariant-3.11.0", "dest-filename": ".cargo-checksum.json" }, { "type": "file", - "url": "https://static.crates.io/crates/zvariant_derive/zvariant_derive-3.1.2.crate", - "sha256": "8c2cecc5a61c2a053f7f653a24cd15b3b0195d7f7ddb5042c837fb32e161fb7a", + "url": "https://static.crates.io/crates/zvariant_derive/zvariant_derive-3.11.0.crate", + "sha256": "cce76636e8fab7911be67211cf378c252b115ee7f2bae14b18b84821b39260b5", "dest": "cargo/vendor", - "dest-filename": "zvariant_derive-3.1.2.crate" + "dest-filename": "zvariant_derive-3.11.0.crate" }, { "type": "file", - "url": "data:%7B%22package%22%3A%20%228c2cecc5a61c2a053f7f653a24cd15b3b0195d7f7ddb5042c837fb32e161fb7a%22%2C%20%22files%22%3A%20%7B%7D%7D", - "dest": "cargo/vendor/zvariant_derive-3.1.2", + "url": "data:%7B%22package%22%3A%20%22cce76636e8fab7911be67211cf378c252b115ee7f2bae14b18b84821b39260b5%22%2C%20%22files%22%3A%20%7B%7D%7D", + "dest": "cargo/vendor/zvariant_derive-3.11.0", "dest-filename": ".cargo-checksum.json" }, { diff --git a/data/dev.alextren.Spot.appdata.xml b/data/dev.alextren.Spot.appdata.xml index 069cbe4f..df299446 100644 --- a/data/dev.alextren.Spot.appdata.xml +++ b/data/dev.alextren.Spot.appdata.xml @@ -50,6 +50,24 @@ https://raw.githubusercontent.com/xou816/spot/master/data/appstream/3.png + + +

+ It's been a while, hasn't it? I'm back, but please allow everyone some time to work through the issues and pull requests :) +

+ +

+ Thanks to all the contributors who are somehow still around :) If you feel like you've been unjustly forgotten from the AUTHORS or TRANSLATORS file, feel free to open a PR. +

+
+

diff --git a/data/dev.alextren.Spot.desktop b/data/dev.alextren.Spot.desktop index 6f1feed1..e06a59df 100644 --- a/data/dev.alextren.Spot.desktop +++ b/data/dev.alextren.Spot.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -Version=1.0 +Version=1.5 Name=Spot Exec=spot %u GenericName=Music Player @@ -10,3 +10,4 @@ Categories=GTK;GNOME;Music;AudioVideo; MimeType=x-scheme-handler/spotify; StartupNotify=true X-Purism-FormFactor=Workstation;Mobile; +SingleMainWindow=true diff --git a/data/dev.alextren.Spot.gschema.xml b/data/dev.alextren.Spot.gschema.xml index 6a11f4f7..f3fefc0f 100644 --- a/data/dev.alextren.Spot.gschema.xml +++ b/data/dev.alextren.Spot.gschema.xml @@ -9,10 +9,15 @@ + + + + + - - true -

Prefer dark theme + + 'system' + The theme preference 1080 @@ -34,6 +39,10 @@ 'pulseaudio' Audio backend + + true + A flag to enable gap-less playback + 'default' Alsa device (if audio backend is 'alsa') diff --git a/meson.build b/meson.build index 0b45e13c..61774bfa 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'spot', - version: '0.3.3', + version: '0.4.0', meson_version: '>= 0.50.0', default_options: ['warning_level=2', 'buildtype=release'], ) diff --git a/po/LINGUAS b/po/LINGUAS index 96adb403..c687aff0 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1 +1 @@ -en ru fr nl de ca cs pl es pt tr id pt-br fi eu ia nb sl ja ar it uk bn +en ru fr nl de ca cs pl es pt tr id pt-br fi eu ia nb sl ja ar it uk bn bg et diff --git a/po/POTFILES b/po/POTFILES index 7842c63a..d1ce8002 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -4,11 +4,13 @@ src/app/components/labels.rs src/app/components/login/login_model.rs src/app/components/mod.rs src/app/components/navigation/factory.rs -src/app/components/navigation/home.rs +src/app/components/notification/mod.rs src/app/components/now_playing/now_playing_model.rs src/app/components/playback/playback_controls.rs src/app/components/playback/playback_info.rs src/app/components/selection/component.rs +src/app/components/sidebar/sidebar_item.rs +src/app/components/sidebar/sidebar.rs src/app/components/user_menu/user_menu.rs src/app/state/login_state.rs src/main.rs @@ -18,19 +20,23 @@ src/window.ui.in src/app/components/saved_playlists/saved_playlists.ui src/app/components/artist_details/artist_details.ui src/app/components/saved_tracks/saved_tracks.ui -src/app/components/sidebar_listbox/sidebar_icon_widget.ui src/app/components/search/search.ui src/app/components/settings/settings.ui src/app/components/artist/artist.ui src/app/components/user_details/user_details.ui src/app/components/selection/selection_toolbar.ui +src/app/components/scrolling_header/scrolling_header.ui src/app/components/details/album_header.ui src/app/components/details/release_details.ui src/app/components/details/details.ui src/app/components/now_playing/now_playing.ui src/app/components/login/login.ui +src/app/components/playlist_details/playlist_headerbar.ui +src/app/components/playlist_details/playlist_header.ui src/app/components/playlist_details/playlist_details.ui src/app/components/headerbar/headerbar.ui +src/app/components/sidebar/create_playlist.ui +src/app/components/sidebar/sidebar_row.ui src/app/components/album/album.ui src/app/components/playlist/song.ui src/app/components/playback/playback_widget.ui diff --git a/po/ar.po b/po/ar.po index 8ebf7ccd..19dc33ca 100644 --- a/po/ar.po +++ b/po/ar.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "لايمكن حفظ كلمة المرور. تحقق من أن ال Session Keyring مفتوح." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "حدث خطأ. تحقق من الlog لمزيد التفاصيل!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "مكتبة" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "قائمة أغاني" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "يشتغل الأن" @@ -84,7 +84,7 @@ msgstr "غادر" msgid "Log out" msgstr "تسجيل الخروج" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "إعادة الاتصال" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "قم بتسجيل الدخول إلى Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "أسم المستخدم" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "كلمة السر" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "فشل عملىة التحقق!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "تسجيل دخول" @@ -133,16 +133,11 @@ msgstr "ألبومات" msgid "Artists" msgstr "الفنانين" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "أغاني محفوظة" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lock مفعل" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "أوقف" @@ -218,6 +213,7 @@ msgid "Add to playlist..." msgstr "أضف إلى قائمة التشغيل..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "ألغاء" @@ -229,7 +225,6 @@ msgstr "اختر الكل" #. translators: This is part of a contextual menu attached to a single track; the full text is "More from ". #: src/app/components/labels.rs:39 -#, fuzzy msgid "More from {}" msgstr "{} المزيد من" @@ -262,12 +257,12 @@ msgstr "حقوق النشر" msgid "{} by {}" msgstr "{}بواسطة {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -280,7 +275,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -322,35 +317,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -358,3 +353,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/bg.po b/po/bg.po new file mode 100644 index 00000000..182f7668 --- /dev/null +++ b/po/bg.po @@ -0,0 +1,389 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: POEditor.com\n" +"Project-Id-Version: Spot\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. translators: This is part of a contextual menu attached to a single track; this entry allows viewing the album containing a specific track. +#: src/app/components/labels.rs:5 +msgid "View album" +msgstr "" + +#. translators: This is part of a contextual menu attached to a single track; the intent is to copy the link (public URL) to a specific track. +#: src/app/components/labels.rs:8 +msgid "Copy link" +msgstr "" + +#. translators: This is part of a contextual menu attached to a single track; this entry adds a track at the end of the play queue. +#: src/app/components/labels.rs:11 +#: src/app/components/selection/selection_toolbar.ui:39 +msgid "Add to queue" +msgstr "" + +#. translators: This is part of a contextual menu attached to a single track; this entry removes a track from the play queue. +#: src/app/components/labels.rs:14 +msgid "Remove from queue" +msgstr "" + +#. translators: This is part of a larger text that says "Add to ". This text should be as short as possible. +#: src/app/components/labels.rs:21 +msgid "Add to {}" +msgstr "" + +#. translators: This notification shows up right after login if the password could not be stored in the keyring (that is, GNOME's keyring aka seahorse, or any other libsecret compliant secret store). +#: src/app/components/login/login_model.rs:56 +msgid "Could not save password. Make sure the session keyring is unlocked." +msgstr "" + +#. translators: This notification is the default message for unhandled errors. Logs refer to console output. +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 +msgid "An error occured. Check logs for details!" +msgstr "" + +#. translators: This is a sidebar entry to browse to saved albums. +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 +msgid "Library" +msgstr "" + +#. translators: This is a sidebar entry to browse to saved playlists. +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 +msgid "Playlists" +msgstr "" + +#. This is the visible name for the play queue. It appears in the sidebar as well. +#: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 +msgid "Now playing" +msgstr "" + +#. translators: Short text displayed instead of a song title when nothing plays +#. Short text displayed instead of a song title when nothing plays +#: src/app/components/playback/playback_info.rs:58 +#: src/app/components/playback/playback_info.ui:32 +msgid "No song playing" +msgstr "" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:67 +msgid "About" +msgstr "" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:69 +msgid "Quit" +msgstr "" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:74 +msgid "Log out" +msgstr "" + +#: src/app/state/login_state.rs:112 +msgid "Connection restored" +msgstr "" + +#. Title of the section that shows 5 of the top tracks for an artist, as defined by Spotify. +#: src/app/components/artist_details/artist_details.ui:26 +msgid "Top tracks" +msgstr "" + +#. Title of the sections that contains all releases from an artist (both singles and albums). +#: src/app/components/artist_details/artist_details.ui:53 +msgid "Releases" +msgstr "" + +#. Login window title -- shouldn't be too long, but must mention Premium (a premium account is required). +#: src/app/components/login/login.ui:45 +msgid "Login to Spotify Premium" +msgstr "" + +#. Placeholder for the username field +#: src/app/components/login/login.ui:72 +msgid "Username" +msgstr "" + +#. Placeholder for the password field +#: src/app/components/login/login.ui:89 +msgid "Password" +msgstr "" + +#. This error is shown when authentication fails. +#: src/app/components/login/login.ui:114 +msgid "Authentication failed!" +msgstr "" + +#. Log in button label +#: src/app/components/login/login.ui:129 +msgid "Log in" +msgstr "" + +#. This is the title of a section of the search results +#: src/app/components/search/search.ui:72 +msgid "Albums" +msgstr "" + +#. This is the title of a section of the search results +#: src/app/components/search/search.ui:105 +msgid "Artists" +msgstr "" + +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 +msgid "Saved tracks" +msgstr "" + +#: src/app/components/playback/playback_controls.rs:64 +msgid "Pause" +msgstr "" + +#: src/app/components/playback/playback_controls.rs:66 +msgid "Play" +msgstr "" + +#: src/app/components/playback/playback_controls.ui:17 +msgid "Shuffle" +msgstr "" + +#: src/app/components/playback/playback_controls.ui:27 +msgid "Previous" +msgstr "" + +#: src/app/components/playback/playback_controls.ui:50 +msgid "Next" +msgstr "" + +#: src/app/components/playback/playback_controls.ui:60 +msgid "Repeat" +msgstr "" + +#. A title that is shown when the user has not saved any playlists. +#: src/app/components/saved_playlists/saved_playlists.ui:26 +msgid "You have no saved playlists." +msgstr "" + +#. A description of what happens when the user has saved playlists. +#: src/app/components/saved_playlists/saved_playlists.ui:27 +msgid "Your playlists will be shown here." +msgstr "" + +#. A title that is shown when the user has not saved any albums. +#: src/app/components/library/library.ui:26 +msgid "You have no saved albums." +msgstr "" + +#. A description of what happens when the user has saved albums. +#: src/app/components/library/library.ui:27 +msgid "Your library will be shown here." +msgstr "" + +#. translators: This shows up when in selection mode. This text should be as short as possible. +#: src/app/components/labels.rs:30 +msgid "{} song selected" +msgid_plural "{} songs selected" +msgstr[0] "" +msgstr[1] "" + +#. Title for the empty search page (initial state). +#: src/app/components/search/search.ui:116 +msgid "Search Spotify." +msgstr "" + +#. Subtitle for the empty search page (initial state). +#: src/app/components/search/search.ui:117 +msgid "Type to search." +msgstr "" + +#: src/app/components/selection/selection_toolbar.ui:69 +msgid "Remove" +msgstr "" + +#. playlist2-symbolic +#: src/app/components/selection/selection_toolbar.ui:56 +msgid "Add to playlist..." +msgstr "" + +#. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 +#: src/app/components/headerbar/headerbar.ui:47 +msgid "Cancel" +msgstr "" + +#. Button label. Selects all visible songs. +#: src/app/components/headerbar/headerbar.ui:58 +msgid "Select all" +msgstr "" + +#. translators: This is part of a contextual menu attached to a single track; the full text is "More from ". +#: src/app/components/labels.rs:39 +msgid "More from {}" +msgstr "" + +#. This refers to a music label +#: src/app/components/details/release_details.ui:38 +msgid "Label" +msgstr "" + +#. This refers to a release date +#: src/app/components/details/release_details.ui:48 +msgid "Released" +msgstr "" + +#. This refers to a number of tracks +#: src/app/components/details/release_details.ui:58 +msgid "Tracks" +msgstr "" + +#. This refers to the duration of a release +#: src/app/components/details/release_details.ui:68 +msgid "Duration" +msgstr "" + +#: src/app/components/details/release_details.ui:68 +msgid "Copyright" +msgstr "" + +#. translators: This is part of a larger label that reads " by " +#: src/app/components/labels.rs:48 +msgid "{} by {}" +msgstr "" + +#: src/app/components/sidebar/sidebar.rs:48 +msgid "Unnamed playlist" +msgstr "" + +#. translators: This is a sidebar entry to browse to saved playlists. +#: src/app/components/sidebar/sidebar_item.rs:81 +msgid "All Playlists" +msgstr "" + +#: src/app/components/selection/component.rs:66 +msgid "Tracks saved!" +msgstr "" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:65 +msgid "Preferences" +msgstr "" + +#: src/main.rs:80 +msgid "Failed to open link!" +msgstr "" + +#. Header for a group of preference items regarding audio +#: src/app/components/settings/settings.ui:13 +msgid "Audio" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:16 +msgid "Audio Backend" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:29 +msgid "ALSA Device" +msgstr "" + +#. Description for the item (ALSA Device) in preferences +#: src/app/components/settings/settings.ui:30 +msgid "Applied only if audio backend is ALSA" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:40 +msgid "Audio Quality" +msgstr "" + +#: src/app/components/settings/settings.ui:44 +msgid "Normal" +msgstr "" + +#: src/app/components/settings/settings.ui:45 +msgid "High" +msgstr "" + +#: src/app/components/settings/settings.ui:46 +msgid "Very high" +msgstr "" + +#. Header for a group of preference items regarding the application's appearance +#: src/app/components/settings/settings.ui:70 +msgid "Appearance" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:73 +msgid "Theme" +msgstr "" + +#: src/app/components/settings/settings.ui:77 +msgid "Light" +msgstr "" + +#: src/app/components/settings/settings.ui:78 +msgid "Dark" +msgstr "" + +#. Header for a group of preference items regarding network +#: src/app/components/settings/settings.ui:89 +msgid "Network" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:92 +msgid "Access Point Port" +msgstr "" + +#. Longer description for an item (Access Point Port) in preferences +#: src/app/components/settings/settings.ui:93 +msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." +msgstr "" + +#: src/app/components/selection/selection_toolbar.ui:90 +msgid "Save to library" +msgstr "" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/bn.po b/po/bn.po index d0632f42..899b8233 100644 --- a/po/bn.po +++ b/po/bn.po @@ -46,28 +46,28 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "পাসওয়ার্ড সেভ করা যায়নি। সেশন কীরিং আনলক করা আছে কিনা নিশ্চিত করুন।" #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 #, fuzzy msgid "An error occured. Check logs for details!" msgstr "একটি ত্রুটি ঘটেছে। বিস্তারিত জানতে লগ চেক করুন!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 #, fuzzy msgid "Library" msgstr "লাইব্রেরী" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 #, fuzzy msgid "Playlists" msgstr "প্লেলিস্ট" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 #, fuzzy msgid "Now playing" msgstr "এখন প্লে হচ্ছে" @@ -98,7 +98,7 @@ msgstr "প্রস্থান করুন" msgid "Log out" msgstr "লগ আউট" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 #, fuzzy msgid "Connection restored" msgstr "সংযোগ পুনরুদ্ধার করা হয়েছে" @@ -122,25 +122,25 @@ msgid "Login to Spotify Premium" msgstr "স্পটিফাই প্রিমিয়ামে লগইন করুন" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 #, fuzzy msgid "Username" msgstr "ইউজারনেম" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 #, fuzzy msgid "Password" msgstr "পাসওয়ার্ড" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 #, fuzzy msgid "Authentication failed!" msgstr "অথেন্টিকেশন ব্যর্থ হয়েছে!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 #, fuzzy msgid "Log in" msgstr "লগ ইন" @@ -157,18 +157,12 @@ msgstr "অ্যালবাম" msgid "Artists" msgstr "আর্টিস্ট" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 #, fuzzy msgid "Saved tracks" msgstr "সেভ করা ট্র্যাকগুলি" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -#, fuzzy -msgid "Caps Lock is enabled!" -msgstr "ক্যাপস লক সক্রিয় আছে!" - #: src/app/components/playback/playback_controls.rs:64 #, fuzzy msgid "Pause" @@ -255,6 +249,7 @@ msgid "Add to playlist..." msgstr "প্লেলিস্টে যোগ করুন..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 #, fuzzy msgid "Cancel" @@ -307,12 +302,12 @@ msgstr "কপিরাইট" msgid "{} by {}" msgstr "{} বাই {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -325,7 +320,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -367,35 +362,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -403,3 +398,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/ca.po b/po/ca.po index b04a788b..65666603 100644 --- a/po/ca.po +++ b/po/ca.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "No s'ha pogut desar la sessió. Assegura't que l'anell de claus de la sessió està desbloquejat." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Ha ocorregut un error. Comprova els registres per més detalls!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Biblioteca" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Llistes de reproducció" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "S'està reproduïnt" @@ -84,7 +84,7 @@ msgstr "Surt" msgid "Log out" msgstr "Tanca la sessió" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Connexió restablerta" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Inicia la sessió a Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Nom d'usuari" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Contrasenya" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "L'autenticació ha fallat!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Inicia sessió" @@ -133,16 +133,11 @@ msgstr "Àlbums" msgid "Artists" msgstr "Artistes" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Pistes desades" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Bloq Maj està habilitat!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pausa" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Afegeix a la llista..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Cancel·la" @@ -235,13 +231,11 @@ msgstr "Etiqueta" #. This refers to a release date #: src/app/components/details/release_details.ui:48 -#, fuzzy msgid "Released" msgstr "Llançaments" #. This refers to a number of tracks #: src/app/components/details/release_details.ui:58 -#, fuzzy msgid "Tracks" msgstr "Millors pistes" @@ -259,99 +253,139 @@ msgstr "Copyright" msgid "{} by {}" msgstr "{} per {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" -msgstr "" +msgstr "Llista sense nom" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" -msgstr "" +msgstr "Totes les llistes" #: src/app/components/selection/component.rs:66 msgid "Tracks saved!" -msgstr "" +msgstr "Cançons desades!" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:65 msgid "Preferences" -msgstr "" +msgstr "Preferències" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" -msgstr "" +msgstr "No s'ha pogut obrir l'enllaç!" #. Header for a group of preference items regarding audio #: src/app/components/settings/settings.ui:13 msgid "Audio" -msgstr "" +msgstr "Àudio" #. Title for an item in preferences #: src/app/components/settings/settings.ui:16 msgid "Audio Backend" -msgstr "" +msgstr "Sistema d'àudio" #. Title for an item in preferences #: src/app/components/settings/settings.ui:29 msgid "ALSA Device" -msgstr "" +msgstr "Dispositiu ALSA" #. Description for the item (ALSA Device) in preferences #: src/app/components/settings/settings.ui:30 msgid "Applied only if audio backend is ALSA" -msgstr "" +msgstr "Usat només si el sistema d'àudio és l'ALSA" #. Title for an item in preferences #: src/app/components/settings/settings.ui:40 msgid "Audio Quality" -msgstr "" +msgstr "Qualitat de l'àudio" #: src/app/components/settings/settings.ui:44 msgid "Normal" -msgstr "" +msgstr "Normal" +#. Qualitat d'àudio -> femení, la qualitat #: src/app/components/settings/settings.ui:45 msgid "High" -msgstr "" +msgstr "Alta" +#. El mateix que amb "High". Cal usar el femení #: src/app/components/settings/settings.ui:46 msgid "Very high" -msgstr "" +msgstr "Molt alta" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" -msgstr "" +msgstr "Aparença" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" -msgstr "" +msgstr "Tema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" -msgstr "" +msgstr "Clar" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" -msgstr "" +msgstr "Fosc" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" -msgstr "" +msgstr "Xarxa" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" -msgstr "" +msgstr "Port del punt d'accés" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." -msgstr "" +msgstr "El port usat per les connexions al punt d'accés de l'Spotify. Establiu-ho a 0 si qualsevol port és correcte." #: src/app/components/selection/selection_toolbar.ui:90 msgid "Save to library" +msgstr "Desa-ho a la llibreria" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" msgstr "" diff --git a/po/cs.po b/po/cs.po index 52e70fe0..a5d48d96 100644 --- a/po/cs.po +++ b/po/cs.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Heslo nelze uložit. Zkontrolujte, že je klíčenka (session keyring) odemčená." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Došlo k chybě. Podrobnosti najdete v protokolu." #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Knihovna" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Playlisty" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Právě hraje" @@ -84,7 +84,7 @@ msgstr "Konec" msgid "Log out" msgstr "Odhlásit se" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Připojení obnoveno" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Přihlásit se ke Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Uživatelské jméno" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Heslo" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Chyba autentizace!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Přihlásit se" @@ -136,16 +136,11 @@ msgstr "Umělci" #. Where is this text displayed? #. I see it is supposed to be in `src/app/components/navigation/home.rs:47`, but that does not seem to be the case: https://github.com/xou816/spot/blob/1b96cd07129f27c7f3f3a2e66299c44a52e489d4/src/app/components/navigation/home.rs #. Maybe it is something that has not been commited yet (2021-10-02T10:42:52+02:00), but @xou816 has it locally and has generated pot / po files from it in https://github.com/xou816/spot/commit/86414c03d207cdf4e2c1cbddd47c7ca5629d1303 -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Uložené skladby" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Máte zapnutý Caps Lock!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pozastavit" @@ -218,6 +213,7 @@ msgid "Add to playlist..." msgstr "Přidat do playlistu..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Zrušit" @@ -261,12 +257,12 @@ msgstr "Copyright" msgid "{} by {}" msgstr "{} od {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "Playlist bez názvu" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "Všechny playlisty" @@ -279,7 +275,7 @@ msgstr "Skladby uloženy!" msgid "Preferences" msgstr "Nastavení" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "Nepodařilo se otevřít odkaz!" @@ -321,35 +317,35 @@ msgid "Very high" msgstr "Velmi vysoká" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "Vzhled" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "Téma" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "Světlé" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "Tmavé" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "Síť" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "Port Access Pointu" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "Port používaný pro připojení ke Spotify Access Point. Nastavte na 0 pokud lze použít libovolný port." @@ -357,3 +353,41 @@ msgstr "Port používaný pro připojení ke Spotify Access Point. Nastavte na 0 msgid "Save to library" msgstr "Uložit do knihovny" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Playlist byl vytvořen." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Zobrazit" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Přidat playlist" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Přehrávání bez mezer" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Systém" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Hotovo" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Název" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Vytvořit" + diff --git a/po/de.po b/po/de.po index 86f0cd5a..f1df6bf7 100644 --- a/po/de.po +++ b/po/de.po @@ -40,34 +40,34 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Das Passwort konnte nicht gespeichert werden. Stellen Sie sicher, dass der Sitzungs-Schlüsselbund entsperrt ist." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Es ist ein Fehler aufgetreten. Überprüfen Sie die Protokolle für Details!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Bibliothek" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Playlists" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" -msgstr "Es läuft" +msgstr "Wiedergabe" #. translators: Short text displayed instead of a song title when nothing plays #. Short text displayed instead of a song title when nothing plays #: src/app/components/playback/playback_info.rs:58 #: src/app/components/playback/playback_info.ui:32 msgid "No song playing" -msgstr "Es wird kein Titel gespielt" +msgstr "Keine Wiedergabe" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:67 @@ -84,7 +84,7 @@ msgstr "Beenden" msgid "Log out" msgstr "Abmelden" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Verbindung wiederhergestellt" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Bei Spotify Premium anmelden" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Benutzername" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Passwort" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Anmeldung fehlgeschlagen!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Anmelden" @@ -133,16 +133,11 @@ msgstr "Alben" msgid "Artists" msgstr "Künstler" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Gespeicherte Titel" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Feststelltaste ist aktiviert!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pause" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Zur Playlist hinzufügen..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Abbrechen" @@ -257,14 +253,14 @@ msgstr "Copyright" msgid "{} by {}" msgstr "{} von {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "Unbenannte Playlist" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" -msgstr "Alle Playlist" +msgstr "Alle Playlists" #: src/app/components/selection/component.rs:66 msgid "Tracks saved!" @@ -275,9 +271,9 @@ msgstr "Titel gespeichert!" msgid "Preferences" msgstr "Einstellungen" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" -msgstr "Öffnen des Links fehlgschlagen!" +msgstr "Öffnen des Links fehlgeschlagen!" #. Header for a group of preference items regarding audio #: src/app/components/settings/settings.ui:13 @@ -302,7 +298,7 @@ msgstr "Wird nur angewendet, wenn das Audio-Backend ALSA ist" #. Title for an item in preferences #: src/app/components/settings/settings.ui:40 msgid "Audio Quality" -msgstr "Audio Qualität" +msgstr "Audioqualität" #: src/app/components/settings/settings.ui:44 msgid "Normal" @@ -317,39 +313,77 @@ msgid "Very high" msgstr "Sehr hoch" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "Aussehen" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "Thema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "Hell" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "Dunkel" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "Netzwerk" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "Access Point Port" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "Port, der für Verbindungen mit dem Spotify Access Point verwendet wird. Setze den Wert auf 0 für einen beliebigen Port." #: src/app/components/selection/selection_toolbar.ui:90 msgid "Save to library" -msgstr "Speichere in Bibliothek" +msgstr "In Bibliothek speichern" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Neue Playlist erstellt." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Anzeigen" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Neue Playlist" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Lückenlose Wiedergabe" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "System" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Fertig" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Name" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Erstellen" diff --git a/po/en.po b/po/en.po index 5fe7d6c2..87549455 100644 --- a/po/en.po +++ b/po/en.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Could not save password. Make sure the session keyring is unlocked." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "An error occured. Check logs for details!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Library" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Playlists" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Now playing" @@ -84,7 +84,7 @@ msgstr "Quit" msgid "Log out" msgstr "Log out" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Connection restored" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Login to Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Username" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Password" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Authentication failed!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Log in" @@ -133,16 +133,11 @@ msgstr "Albums" msgid "Artists" msgstr "Artists" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Saved Tracks" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lock is enabled!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pause" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Add to playlist..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Cancel" @@ -257,12 +253,12 @@ msgstr "Copyright" msgid "{} by {}" msgstr "{} by {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" -msgstr "" +msgstr "Unnamed playlist" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -275,7 +271,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -317,35 +313,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -353,3 +349,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/es.po b/po/es.po index d029224c..a47ce127 100644 --- a/po/es.po +++ b/po/es.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "No se pudo guardar la contraseña. Asegúrate de que el anillo de claves esta desbloqueado." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Ha ocurrido un error. ¡Revisa los logs para más detalles!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Biblioteca" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Lista de reproducción" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Reproduciendo ahora" @@ -84,7 +84,7 @@ msgstr "Salir" msgid "Log out" msgstr "Cerrar sesión" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Conexión restaurada" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Iniciar sesión en Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Usuario" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Contraseña" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "¡Autenticación fallida!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Iniciar sesión" @@ -133,16 +133,11 @@ msgstr "Álbumes" msgid "Artists" msgstr "Artistas" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Pistas guardadas" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "¡El bloqueo de mayúsculas está activado!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pausa" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Añadir a la lista de reproducción..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Cancelar" @@ -257,12 +253,12 @@ msgstr "Copyright" msgid "{} by {}" msgstr "{} de {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "Lista de reproducción sin nombre" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "Todas las listas de reproducción" @@ -275,7 +271,7 @@ msgstr "¡Pistas guardadas!" msgid "Preferences" msgstr "Preferencias" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "¡No se ha podido abrir el enlace!" @@ -317,35 +313,35 @@ msgid "Very high" msgstr "Muy alta" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "Apariencia" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "Tema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "Claro" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "Oscuro" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "Red" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "Puerto del punto de acceso" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "Puerto utilizado para las conexiones con el punto de acceso de Spotify. Poner a 0 si cualquier puerto está bien." @@ -353,3 +349,41 @@ msgstr "Puerto utilizado para las conexiones con el punto de acceso de Spotify. msgid "Save to library" msgstr "Guardar en la biblioteca" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/et.po b/po/et.po new file mode 100644 index 00000000..a8d92d46 --- /dev/null +++ b/po/et.po @@ -0,0 +1,389 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: POEditor.com\n" +"Project-Id-Version: Spot\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. translators: This is part of a contextual menu attached to a single track; this entry allows viewing the album containing a specific track. +#: src/app/components/labels.rs:5 +msgid "View album" +msgstr "Vaata albumit" + +#. translators: This is part of a contextual menu attached to a single track; the intent is to copy the link (public URL) to a specific track. +#: src/app/components/labels.rs:8 +msgid "Copy link" +msgstr "Kopeeri link" + +#. translators: This is part of a contextual menu attached to a single track; this entry adds a track at the end of the play queue. +#: src/app/components/labels.rs:11 +#: src/app/components/selection/selection_toolbar.ui:39 +msgid "Add to queue" +msgstr "Lisa järjekorda" + +#. translators: This is part of a contextual menu attached to a single track; this entry removes a track from the play queue. +#: src/app/components/labels.rs:14 +msgid "Remove from queue" +msgstr "Eemalda järjekorrast" + +#. translators: This is part of a larger text that says "Add to ". This text should be as short as possible. +#: src/app/components/labels.rs:21 +msgid "Add to {}" +msgstr "Lisa {}" + +#. translators: This notification shows up right after login if the password could not be stored in the keyring (that is, GNOME's keyring aka seahorse, or any other libsecret compliant secret store). +#: src/app/components/login/login_model.rs:56 +msgid "Could not save password. Make sure the session keyring is unlocked." +msgstr "Salasõna salvestamine ebaõnnestus. Kindel, et sessiooni võtmering on lukust lahti?" + +#. translators: This notification is the default message for unhandled errors. Logs refer to console output. +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 +msgid "An error occured. Check logs for details!" +msgstr "Tekkis viga. Rohkem infot logides." + +#. translators: This is a sidebar entry to browse to saved albums. +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 +msgid "Library" +msgstr "Teek" + +#. translators: This is a sidebar entry to browse to saved playlists. +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 +msgid "Playlists" +msgstr "Esitusloendid" + +#. This is the visible name for the play queue. It appears in the sidebar as well. +#: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 +msgid "Now playing" +msgstr "Praegu mängib" + +#. translators: Short text displayed instead of a song title when nothing plays +#. Short text displayed instead of a song title when nothing plays +#: src/app/components/playback/playback_info.rs:58 +#: src/app/components/playback/playback_info.ui:32 +msgid "No song playing" +msgstr "Ükski laul ei mängi" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:67 +msgid "About" +msgstr "Teave" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:69 +msgid "Quit" +msgstr "Sulge" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:74 +msgid "Log out" +msgstr "Logi välja" + +#: src/app/state/login_state.rs:112 +msgid "Connection restored" +msgstr "Ühendus taastatud" + +#. Title of the section that shows 5 of the top tracks for an artist, as defined by Spotify. +#: src/app/components/artist_details/artist_details.ui:26 +msgid "Top tracks" +msgstr "Populaarsemad lood" + +#. Title of the sections that contains all releases from an artist (both singles and albums). +#: src/app/components/artist_details/artist_details.ui:53 +msgid "Releases" +msgstr "Diskograafia" + +#. Login window title -- shouldn't be too long, but must mention Premium (a premium account is required). +#: src/app/components/login/login.ui:45 +msgid "Login to Spotify Premium" +msgstr "Logi sisse Spotify Premiumisse" + +#. Placeholder for the username field +#: src/app/components/login/login.ui:72 +msgid "Username" +msgstr "Kasutajanimi" + +#. Placeholder for the password field +#: src/app/components/login/login.ui:89 +msgid "Password" +msgstr "Salasõna" + +#. This error is shown when authentication fails. +#: src/app/components/login/login.ui:114 +msgid "Authentication failed!" +msgstr "Autentimine ebaõnnestus!" + +#. Log in button label +#: src/app/components/login/login.ui:129 +msgid "Log in" +msgstr "Logi sisse" + +#. This is the title of a section of the search results +#: src/app/components/search/search.ui:72 +msgid "Albums" +msgstr "Albumid" + +#. This is the title of a section of the search results +#: src/app/components/search/search.ui:105 +msgid "Artists" +msgstr "Esitajad" + +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 +msgid "Saved tracks" +msgstr "Salvestatud lood" + +#: src/app/components/playback/playback_controls.rs:64 +msgid "Pause" +msgstr "Peata" + +#: src/app/components/playback/playback_controls.rs:66 +msgid "Play" +msgstr "Esita" + +#: src/app/components/playback/playback_controls.ui:17 +msgid "Shuffle" +msgstr "Juhuesitus" + +#: src/app/components/playback/playback_controls.ui:27 +msgid "Previous" +msgstr "Eelmine" + +#: src/app/components/playback/playback_controls.ui:50 +msgid "Next" +msgstr "Järgmine" + +#: src/app/components/playback/playback_controls.ui:60 +msgid "Repeat" +msgstr "Korda" + +#. A title that is shown when the user has not saved any playlists. +#: src/app/components/saved_playlists/saved_playlists.ui:26 +msgid "You have no saved playlists." +msgstr "Sul pole ühtegi salvestatud esitusloendit." + +#. A description of what happens when the user has saved playlists. +#: src/app/components/saved_playlists/saved_playlists.ui:27 +msgid "Your playlists will be shown here." +msgstr "Sinu esitusloendid näidatakse siin." + +#. A title that is shown when the user has not saved any albums. +#: src/app/components/library/library.ui:26 +msgid "You have no saved albums." +msgstr "Sul pole ühtegi salvestatud albumit." + +#. A description of what happens when the user has saved albums. +#: src/app/components/library/library.ui:27 +msgid "Your library will be shown here." +msgstr "Sinu teeki näidatakse siin." + +#. translators: This shows up when in selection mode. This text should be as short as possible. +#: src/app/components/labels.rs:30 +msgid "{} song selected" +msgid_plural "{} songs selected" +msgstr[0] "{} lugu valitud" +msgstr[1] "{} lugu valitud" + +#. Title for the empty search page (initial state). +#: src/app/components/search/search.ui:116 +msgid "Search Spotify." +msgstr "Otsi Spotify'st." + +#. Subtitle for the empty search page (initial state). +#: src/app/components/search/search.ui:117 +msgid "Type to search." +msgstr "Tipi, et otsida." + +#: src/app/components/selection/selection_toolbar.ui:69 +msgid "Remove" +msgstr "Eemalda" + +#. playlist2-symbolic +#: src/app/components/selection/selection_toolbar.ui:56 +msgid "Add to playlist..." +msgstr "Lisa esitusloendisse..." + +#. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 +#: src/app/components/headerbar/headerbar.ui:47 +msgid "Cancel" +msgstr "Loobu" + +#. Button label. Selects all visible songs. +#: src/app/components/headerbar/headerbar.ui:58 +msgid "Select all" +msgstr "Vali kõik" + +#. translators: This is part of a contextual menu attached to a single track; the full text is "More from ". +#: src/app/components/labels.rs:39 +msgid "More from {}" +msgstr "Rohkem esitajast {}" + +#. This refers to a music label +#: src/app/components/details/release_details.ui:38 +msgid "Label" +msgstr "Väljaandja" + +#. This refers to a release date +#: src/app/components/details/release_details.ui:48 +msgid "Released" +msgstr "Välja antud" + +#. This refers to a number of tracks +#: src/app/components/details/release_details.ui:58 +msgid "Tracks" +msgstr "Lood" + +#. This refers to the duration of a release +#: src/app/components/details/release_details.ui:68 +msgid "Duration" +msgstr "Pikkus" + +#: src/app/components/details/release_details.ui:68 +msgid "Copyright" +msgstr "Autoriõigused" + +#. translators: This is part of a larger label that reads " by " +#: src/app/components/labels.rs:48 +msgid "{} by {}" +msgstr "{} - {}" + +#: src/app/components/sidebar/sidebar.rs:48 +msgid "Unnamed playlist" +msgstr "Nimetamata esitusloend" + +#. translators: This is a sidebar entry to browse to saved playlists. +#: src/app/components/sidebar/sidebar_item.rs:81 +msgid "All Playlists" +msgstr "Kõik esitusloendid" + +#: src/app/components/selection/component.rs:66 +msgid "Tracks saved!" +msgstr "Lugu salvestatud!" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:65 +msgid "Preferences" +msgstr "Eelistused" + +#: src/main.rs:80 +msgid "Failed to open link!" +msgstr "Lingi avamine ebaõnnestus!" + +#. Header for a group of preference items regarding audio +#: src/app/components/settings/settings.ui:13 +msgid "Audio" +msgstr "Heli" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:16 +msgid "Audio Backend" +msgstr "Heli sisend" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:29 +msgid "ALSA Device" +msgstr "ALSA heliseade" + +#. Description for the item (ALSA Device) in preferences +#: src/app/components/settings/settings.ui:30 +msgid "Applied only if audio backend is ALSA" +msgstr "Kehtib ainult, kui heli sisend on ALSA" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:40 +msgid "Audio Quality" +msgstr "Heli kvaliteet" + +#: src/app/components/settings/settings.ui:44 +msgid "Normal" +msgstr "Keskmine" + +#: src/app/components/settings/settings.ui:45 +msgid "High" +msgstr "Kõrge" + +#: src/app/components/settings/settings.ui:46 +msgid "Very high" +msgstr "Väga kõrge" + +#. Header for a group of preference items regarding the application's appearance +#: src/app/components/settings/settings.ui:70 +msgid "Appearance" +msgstr "Välimus" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:73 +msgid "Theme" +msgstr "Teema" + +#: src/app/components/settings/settings.ui:77 +msgid "Light" +msgstr "Hele teema" + +#: src/app/components/settings/settings.ui:78 +msgid "Dark" +msgstr "Tume teema" + +#. Header for a group of preference items regarding network +#: src/app/components/settings/settings.ui:89 +msgid "Network" +msgstr "Võrk" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:92 +msgid "Access Point Port" +msgstr "Sissepääsu port" + +#. Longer description for an item (Access Point Port) in preferences +#: src/app/components/settings/settings.ui:93 +msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." +msgstr "Port Spotify ühendamiseks. Säti 0, et lubada iga port." + +#: src/app/components/selection/selection_toolbar.ui:90 +msgid "Save to library" +msgstr "Salvesta teeki" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/eu.po b/po/eu.po index 0e081bb1..5596c2c9 100644 --- a/po/eu.po +++ b/po/eu.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Ezin izan da pasahitza gorde. Ziurtatu saioko giltzatakoa desblokeatuta dagoela." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Errore bat gertatu da. Egiaztatu xehetasunak erregistroetan!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Biblioteka" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Erreprodukzio-zerrendak" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Orain erreproduzitzen" @@ -84,7 +84,7 @@ msgstr "Utzi" msgid "Log out" msgstr "Saioa itxi" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Konexioa leheneratu da" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Saioa hasi Spotify Premiumen" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Erabiltzailearen izena" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Pasahitza" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Autentifikazioak huts egin du!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Hasi saioa" @@ -133,16 +133,11 @@ msgstr "Albumak" msgid "Artists" msgstr "Artistak" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Gordetako pistak" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Letra larrien blokeoa aktibatuta dago!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Gelditu" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Erreprodukzio-zerrendara gehitu..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Ezeztatu" @@ -257,12 +253,12 @@ msgstr "Egile-eskubideak" msgid "{} by {}" msgstr "{} {} -ek eginda" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -275,7 +271,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -317,35 +313,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -353,3 +349,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/fi.po b/po/fi.po index 4cd28e5d..8213168a 100644 --- a/po/fi.po +++ b/po/fi.po @@ -37,28 +37,28 @@ msgstr "Lisää kohteeseen {}" #. translators: This notification shows up right after login if the password could not be stored in the keyring (that is, GNOME's keyring aka seahorse, or any other libsecret compliant secret store). #: src/app/components/login/login_model.rs:56 msgid "Could not save password. Make sure the session keyring is unlocked." -msgstr "Salasanaa ei voitu tallentaa. Varmista että avainnippua ei ole lukittu." +msgstr "Salasanaa ei voitu tallentaa. Varmista, että avainnippua ei ole lukittu." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" -msgstr "Tapahti virhe. Katso lisätiedot lokista!" +msgstr "Tapahtui virhe. Katso lisätiedot lokista!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Kirjasto" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Soittolistat" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Nyt toistetaan" @@ -84,7 +84,7 @@ msgstr "Lopeta" msgid "Log out" msgstr "Kirjaudu ulos" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Yhteys palautunut" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Kirjaudu Spotify Premiumiin" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Käyttäjätunnus" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Salasana" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Tunnistautuminen epäonnistui!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Kirjaudu sisään" @@ -133,16 +133,11 @@ msgstr "Albumit" msgid "Artists" msgstr "Esittäjät" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Tallennetut kappaleet" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lock on päällä!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Keskeytä" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Lisää soittolistaan..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Peru" @@ -257,12 +253,12 @@ msgstr "Tekijänoikeus" msgid "{} by {}" msgstr "{} tehnyt {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "Nimetön soittolista" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "Kaikki soittolistat" @@ -275,7 +271,7 @@ msgstr "Kappaleet tallennettu!" msgid "Preferences" msgstr "Asetukset" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "Linkin avaaminen epäonnistui!" @@ -317,35 +313,35 @@ msgid "Very high" msgstr "Hyvin korkea" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "Ulkoasu" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "Teema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "Vaalea" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "Tumma" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "Verkko" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "Access Pointin portti" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "Spotifyn Access Pointiin tuleviin yhteyksiin käytettävä portti. Aseta arvoksi 0, jos mikä tahansa portti kelpaa." @@ -353,3 +349,41 @@ msgstr "Spotifyn Access Pointiin tuleviin yhteyksiin käytettävä portti. Aseta msgid "Save to library" msgstr "Tallenna kirjastoon" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Uusi soittolista luotu." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Näytä" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Uusi soittolista" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Keskeytyksetön toisto" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Järjestelmä" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Valmis" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Nimi" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Luo" + diff --git a/po/fr.po b/po/fr.po index 79c00644..b38527d0 100644 --- a/po/fr.po +++ b/po/fr.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Le mot de passe n'a pu être enregistré, assurez-vous que le Trousseau de session est déverouillé." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Une erreur est survenue. Consultez les journaux de débogage pour plus d'information." #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Bibliothèque" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Listes de lecture" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "En cours de lecture" @@ -84,7 +84,7 @@ msgstr "Quitter" msgid "Log out" msgstr "Déconnexion" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Connexion rétablie" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Connexion à Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Nom d'utilisateur" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Mot de passe" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "L'authentification a échoué !" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Connexion" @@ -133,16 +133,11 @@ msgstr "Albums" msgid "Artists" msgstr "Artistes" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Titres aimés" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Verr. Maj. est actif !" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pause" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Ajouter à..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Annuler" @@ -257,12 +253,12 @@ msgstr "Copyright" msgid "{} by {}" msgstr "{} de {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "Liste de lecture sans titre" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "Toutes les listes de lecture" @@ -275,7 +271,7 @@ msgstr "Pistes enregistrées !" msgid "Preferences" msgstr "Préférences" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "Échec de l'ouverture du lien." @@ -317,35 +313,35 @@ msgid "Very high" msgstr "Très élevée" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "Apparence" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "Thème" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "Clair" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "Sombre" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "Réseau" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "Port du point d'accès" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "Port utilisé pour se connecter au point d'accès de Spotify. Laisser la valeur à 0 pour gérer ce paramètre automatiquement. " @@ -353,3 +349,41 @@ msgstr "Port utilisé pour se connecter au point d'accès de Spotify. Laisser la msgid "Save to library" msgstr "Enregistrer dans la bibliothèque" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Liste de lecture créée." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Voir" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Nouvelle liste de lecture" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Lecture continue" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Valeur système" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Terminé" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Nom" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Créer" + diff --git a/po/ia.po b/po/ia.po index e0cbded5..178e36e7 100644 --- a/po/ia.po +++ b/po/ia.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Non poteva salvar le contrasigno. Assecura te qui le magazin de claves es disblocate." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Ocurreva un error. Verifica le registros pro detalios!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Bibliotheca" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Listas de reproduction" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Ora in reproduction" @@ -84,7 +84,7 @@ msgstr "Quitar" msgid "Log out" msgstr "Clauder le session" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Connexion restabilite" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Initiar session in Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Nomine de usator" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Contrasigno" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Falleva le authentication!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Initiar session" @@ -133,16 +133,11 @@ msgstr "Albumes" msgid "Artists" msgstr "Artistas" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Tracias salvate" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Serratura de majusculas es activate!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pausar" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Adder al lista de reproduction..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Cancellar" @@ -257,27 +253,27 @@ msgstr "Copyright" msgid "{} by {}" msgstr "{} per {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" -msgstr "" +msgstr "Lista de reproduction sin nomine" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" -msgstr "" +msgstr "Tote le listas de reproduction" #: src/app/components/selection/component.rs:66 msgid "Tracks saved!" -msgstr "" +msgstr "Tracias salvate!" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:65 msgid "Preferences" -msgstr "" +msgstr "Preferentias" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" -msgstr "" +msgstr "Falleva in aperir ligamine!" #. Header for a group of preference items regarding audio #: src/app/components/settings/settings.ui:13 @@ -317,35 +313,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" -msgstr "" +msgstr "Apparentia" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" -msgstr "" +msgstr "Thema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" -msgstr "" +msgstr "Clar" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" -msgstr "" +msgstr "Obscur" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" -msgstr "" +msgstr "Rete" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -353,3 +349,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/id.po b/po/id.po index 51745116..eba1f435 100644 --- a/po/id.po +++ b/po/id.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Tak bisa menyimpan sandi. Pastikan bahwa kunci sesi tidak terkunci." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Timbul galat. Periksa log untuk detailnya!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Pustaka" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Daftar putar" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Sedang memutar" @@ -84,7 +84,7 @@ msgstr "Keluar" msgid "Log out" msgstr "Log keluar" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Sambungan dipulihkan" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Masuk ke Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Nama Pengguna" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Kata Sandi" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Autentikasi gagal!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Log masuk" @@ -133,16 +133,11 @@ msgstr "Album" msgid "Artists" msgstr "Artis" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Trek yang disimpan" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lock diaktifkan!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Jeda" @@ -213,6 +208,7 @@ msgid "Add to playlist..." msgstr "Tambah ke daftar putar…" #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Batal" @@ -256,99 +252,137 @@ msgstr "Hak Cipta" msgid "{} by {}" msgstr "{} oleh {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" -msgstr "" +msgstr "Daftar putar tanpa nama" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" -msgstr "" +msgstr "Semua Daftar Putar" #: src/app/components/selection/component.rs:66 msgid "Tracks saved!" -msgstr "" +msgstr "Trek disimpan!" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:65 msgid "Preferences" -msgstr "" +msgstr "Preferensi" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" -msgstr "" +msgstr "Gagal membuka tautan!" #. Header for a group of preference items regarding audio #: src/app/components/settings/settings.ui:13 msgid "Audio" -msgstr "" +msgstr "Audio" #. Title for an item in preferences #: src/app/components/settings/settings.ui:16 msgid "Audio Backend" -msgstr "" +msgstr "Backend Audio" #. Title for an item in preferences #: src/app/components/settings/settings.ui:29 msgid "ALSA Device" -msgstr "" +msgstr "Perangkat ALSA" #. Description for the item (ALSA Device) in preferences #: src/app/components/settings/settings.ui:30 msgid "Applied only if audio backend is ALSA" -msgstr "" +msgstr "Diterapkan hanya jika backend audio adalah ALSA" #. Title for an item in preferences #: src/app/components/settings/settings.ui:40 msgid "Audio Quality" -msgstr "" +msgstr "Kualitas Audio" #: src/app/components/settings/settings.ui:44 msgid "Normal" -msgstr "" +msgstr "Normal" #: src/app/components/settings/settings.ui:45 msgid "High" -msgstr "" +msgstr "Tinggi" #: src/app/components/settings/settings.ui:46 msgid "Very high" -msgstr "" +msgstr "Sangat tinggi" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" -msgstr "" +msgstr "Penampilan" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" -msgstr "" +msgstr "Tema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" -msgstr "" +msgstr "Terang" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" -msgstr "" +msgstr "Gelap" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" -msgstr "" +msgstr "Jaringan" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" -msgstr "" +msgstr "Port Titik Akses" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." -msgstr "" +msgstr "Port yang digunakan untuk koneksi ke Titik Akses Spotify. Atur ke 0 jika ada port yang baik-baik saja." #: src/app/components/selection/selection_toolbar.ui:90 msgid "Save to library" -msgstr "" +msgstr "Simpan ke pustaka" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Daftar putar baru dibuat." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Tilik" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Daftar Putar Baru" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Pemutaran tanpa celah" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Sistem" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Selesai" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Nama" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Mencipta" diff --git a/po/it.po b/po/it.po index 0b4f3abe..7fa76261 100644 --- a/po/it.po +++ b/po/it.po @@ -1,20 +1,13 @@ msgid "" msgstr "" -"Project-Id-Version: Spot\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-01-19 19:46-0500\n" -"Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" +"Project-Id-Version: Spot\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:117 -msgid "An error occured. Check logs for details!" -msgstr "C'è stato un errore. Controlla i log per i dettagli!" - #. translators: This is part of a contextual menu attached to a single track; this entry allows viewing the album containing a specific track. #: src/app/components/labels.rs:5 msgid "View album" @@ -27,7 +20,7 @@ msgstr "Copia link" #. translators: This is part of a contextual menu attached to a single track; this entry adds a track at the end of the play queue. #: src/app/components/labels.rs:11 -#: src/app/components/selection/selection_toolbar.ui:37 +#: src/app/components/selection/selection_toolbar.ui:39 msgid "Add to queue" msgstr "Aggiungi alla coda di riproduzione" @@ -41,61 +34,34 @@ msgstr "Rimuovi dalla coda di riproduzione" msgid "Add to {}" msgstr "Aggiungi a {}" -#. translators: This shows up when in selection mode. This text should be as short as possible. -#: src/app/components/labels.rs:30 -msgid "{} song selected" -msgid_plural "{} songs selected" -msgstr[0] "{} brano selezionato" -msgstr[1] "{} brani selezionati" - -#. translators: This is part of a contextual menu attached to a single track; the full text is "More from ". -#: src/app/components/labels.rs:39 -msgid "More from {}" -msgstr "Di più da {}" - -#. translators: This is part of a larger label that reads " by " -#: src/app/components/labels.rs:48 -msgid "{} by {}" -msgstr "{} di {}" - #. translators: This notification shows up right after login if the password could not be stored in the keyring (that is, GNOME's keyring aka seahorse, or any other libsecret compliant secret store). #: src/app/components/login/login_model.rs:56 msgid "Could not save password. Make sure the session keyring is unlocked." -msgstr "" -"Impossibile salvare la password. Controlla che la session keyring sia " -"sbloccata." +msgstr "Impossibile salvare la password. Controlla che la session keyring sia sbloccata." + +#. translators: This notification is the default message for unhandled errors. Logs refer to console output. +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 +msgid "An error occured. Check logs for details!" +msgstr "C'è stato un errore. Controlla i log per i dettagli!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:29 -#: src/app/components/navigation/home.rs:36 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Raccolta" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:44 -#: src/app/components/navigation/home.rs:42 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Playlist" -#. translators: This is a sidebar entry to browse to saved tracks. -#: src/app/components/navigation/factory.rs:73 -#: src/app/components/navigation/home.rs:48 -msgid "Saved tracks" -msgstr "Tracce salvate" - -#: src/app/components/navigation/home.rs:53 -#: src/app/components/now_playing/now_playing_model.rs:152 +#. This is the visible name for the play queue. It appears in the sidebar as well. +#: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "In riproduzione" -#: src/app/components/playback/playback_controls.rs:64 -msgid "Pause" -msgstr "Pausa" - -#: src/app/components/playback/playback_controls.rs:66 -msgid "Play" -msgstr "Riproduci" - #. translators: Short text displayed instead of a song title when nothing plays #. Short text displayed instead of a song title when nothing plays #: src/app/components/playback/playback_info.rs:58 @@ -104,136 +70,81 @@ msgid "No song playing" msgstr "Nessun brano in riproduzione" #. translators: This is a menu entry. -#: src/app/components/user_menu/user_menu.rs:56 +#: src/app/components/user_menu/user_menu.rs:67 msgid "About" msgstr "Informazioni su" #. translators: This is a menu entry. -#: src/app/components/user_menu/user_menu.rs:58 +#: src/app/components/user_menu/user_menu.rs:69 msgid "Quit" msgstr "Esci" #. translators: This is a menu entry. -#: src/app/components/user_menu/user_menu.rs:63 +#: src/app/components/user_menu/user_menu.rs:74 msgid "Log out" msgstr "Log out" -#: src/app/state/login_state.rs:117 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Connessione ripristinata" -#. A title that is shown when the user has not saved any playlists. -#: src/app/components/saved_playlists/saved_playlists.ui:26 -msgid "You have no saved playlists." -msgstr "Non hai playlist salvate." - -#. A description of what happens when the user has saved playlists. -#: src/app/components/saved_playlists/saved_playlists.ui:27 -msgid "Your playlists will be shown here." -msgstr "Le tue playlist verranno mostrate qui." - #. Title of the section that shows 5 of the top tracks for an artist, as defined by Spotify. #: src/app/components/artist_details/artist_details.ui:26 msgid "Top tracks" msgstr "Brani più popolari" #. Title of the sections that contains all releases from an artist (both singles and albums). -#: src/app/components/artist_details/artist_details.ui:55 +#: src/app/components/artist_details/artist_details.ui:53 msgid "Releases" msgstr "Releases" -#. This is the title of a section of the search results -#: src/app/components/search/search.ui:70 -msgid "Albums" -msgstr "Album" - -#. This is the title of a section of the search results -#: src/app/components/search/search.ui:103 -msgid "Artists" -msgstr "Artisti" - -#. Title for the empty search page (initial state). -#: src/app/components/search/search.ui:114 -msgid "Search Spotify." -msgstr "Cerca Spotify." - -#. Subtitle for the empty search page (initial state). -#: src/app/components/search/search.ui:115 -msgid "Type to search." -msgstr "Digita per cercare." - -#. playlist2-symbolic -#: src/app/components/selection/selection_toolbar.ui:47 -msgid "Add to playlist..." -msgstr "Aggiungi alla playlist..." - -#: src/app/components/selection/selection_toolbar.ui:58 -msgid "Remove" -msgstr "Rimuovi" - -#. This refers to a music label -#: src/app/components/details/release_details.ui:38 -msgid "Label" -msgstr "Etichetta discografica" - -#. This refers to a release date -#: src/app/components/details/release_details.ui:48 -msgid "Released" -msgstr "Data di uscita" - -#. This refers to a number of tracks -#: src/app/components/details/release_details.ui:58 -msgid "Tracks" -msgstr "Traccia" - -#. This refers to the duration of a release -#: src/app/components/details/release_details.ui:68 -msgid "Duration" -msgstr "Durata" - -#: src/app/components/details/release_details.ui:78 -msgid "Copyright" -msgstr "Copyright" - #. Login window title -- shouldn't be too long, but must mention Premium (a premium account is required). #: src/app/components/login/login.ui:45 msgid "Login to Spotify Premium" msgstr "Login su Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Username" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Password" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Il blocco maiuscole è abilitato!" - #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Autenticazione fallita!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Log in" -#. Button label. Exits selection mode. -#: src/app/components/headerbar/headerbar.ui:46 -msgid "Cancel" -msgstr "Annulla" +#. This is the title of a section of the search results +#: src/app/components/search/search.ui:72 +msgid "Albums" +msgstr "Album" -#. Button label. Selects all visible songs. -#: src/app/components/headerbar/headerbar.ui:57 -msgid "Select all" -msgstr "Seleziona tutto" +#. This is the title of a section of the search results +#: src/app/components/search/search.ui:105 +msgid "Artists" +msgstr "Artisti" + +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 +msgid "Saved tracks" +msgstr "Tracce salvate" + +#: src/app/components/playback/playback_controls.rs:64 +msgid "Pause" +msgstr "Pausa" + +#: src/app/components/playback/playback_controls.rs:66 +msgid "Play" +msgstr "Riproduci" #: src/app/components/playback/playback_controls.ui:17 msgid "Shuffle" @@ -251,6 +162,16 @@ msgstr "Successivo" msgid "Repeat" msgstr "Ripeti" +#. A title that is shown when the user has not saved any playlists. +#: src/app/components/saved_playlists/saved_playlists.ui:26 +msgid "You have no saved playlists." +msgstr "Non hai playlist salvate." + +#. A description of what happens when the user has saved playlists. +#: src/app/components/saved_playlists/saved_playlists.ui:27 +msgid "Your playlists will be shown here." +msgstr "Le tue playlist verranno mostrate qui." + #. A title that is shown when the user has not saved any albums. #: src/app/components/library/library.ui:26 msgid "You have no saved albums." @@ -261,5 +182,209 @@ msgstr "Non hai album salvati." msgid "Your library will be shown here." msgstr "La tua libreria verrà mostrata qui." -#~ msgid "by" -#~ msgstr "by" +#. translators: This shows up when in selection mode. This text should be as short as possible. +#: src/app/components/labels.rs:30 +msgid "{} song selected" +msgid_plural "{} songs selected" +msgstr[0] "{} brano selezionato" +msgstr[1] "{} brani selezionati" + +#. Title for the empty search page (initial state). +#: src/app/components/search/search.ui:116 +msgid "Search Spotify." +msgstr "Cerca Spotify." + +#. Subtitle for the empty search page (initial state). +#: src/app/components/search/search.ui:117 +msgid "Type to search." +msgstr "Digita per cercare." + +#: src/app/components/selection/selection_toolbar.ui:69 +msgid "Remove" +msgstr "Rimuovi" + +#. playlist2-symbolic +#: src/app/components/selection/selection_toolbar.ui:56 +msgid "Add to playlist..." +msgstr "Aggiungi alla playlist..." + +#. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 +#: src/app/components/headerbar/headerbar.ui:47 +msgid "Cancel" +msgstr "Annulla" + +#. Button label. Selects all visible songs. +#: src/app/components/headerbar/headerbar.ui:58 +msgid "Select all" +msgstr "Seleziona tutto" + +#. translators: This is part of a contextual menu attached to a single track; the full text is "More from ". +#: src/app/components/labels.rs:39 +msgid "More from {}" +msgstr "Di più da {}" + +#. This refers to a music label +#: src/app/components/details/release_details.ui:38 +msgid "Label" +msgstr "Etichetta discografica" + +#. This refers to a release date +#: src/app/components/details/release_details.ui:48 +msgid "Released" +msgstr "Data di uscita" + +#. This refers to a number of tracks +#: src/app/components/details/release_details.ui:58 +msgid "Tracks" +msgstr "Tracce" + +#. This refers to the duration of a release +#: src/app/components/details/release_details.ui:68 +msgid "Duration" +msgstr "Durata" + +#: src/app/components/details/release_details.ui:68 +msgid "Copyright" +msgstr "Copyright" + +#. translators: This is part of a larger label that reads " by " +#: src/app/components/labels.rs:48 +msgid "{} by {}" +msgstr "{} di {}" + +#: src/app/components/sidebar/sidebar.rs:48 +msgid "Unnamed playlist" +msgstr "Playlist senza nome" + +#. translators: This is a sidebar entry to browse to saved playlists. +#: src/app/components/sidebar/sidebar_item.rs:81 +msgid "All Playlists" +msgstr "Tutte le playlist" + +#: src/app/components/selection/component.rs:66 +msgid "Tracks saved!" +msgstr "Tracce salvate!" + +#. translators: This is a menu entry. +#: src/app/components/user_menu/user_menu.rs:65 +msgid "Preferences" +msgstr "Preferenze" + +#: src/main.rs:80 +msgid "Failed to open link!" +msgstr "Apertura del link fallita!" + +#. Header for a group of preference items regarding audio +#: src/app/components/settings/settings.ui:13 +msgid "Audio" +msgstr "Audio" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:16 +msgid "Audio Backend" +msgstr "Backend Audio" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:29 +msgid "ALSA Device" +msgstr "Device ALSA" + +#. Description for the item (ALSA Device) in preferences +#: src/app/components/settings/settings.ui:30 +msgid "Applied only if audio backend is ALSA" +msgstr "Applicato solo se il backend audio è ALSA" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:40 +msgid "Audio Quality" +msgstr "Qualità Audio" + +#: src/app/components/settings/settings.ui:44 +msgid "Normal" +msgstr "Normale" + +#: src/app/components/settings/settings.ui:45 +#, fuzzy +msgid "High" +msgstr "Alta" + +#: src/app/components/settings/settings.ui:46 +msgid "Very high" +msgstr "Molto alta" + +#. Header for a group of preference items regarding the application's appearance +#: src/app/components/settings/settings.ui:70 +msgid "Appearance" +msgstr "Aspetto" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:73 +msgid "Theme" +msgstr "Tema" + +#: src/app/components/settings/settings.ui:77 +msgid "Light" +msgstr "Chiaro" + +#: src/app/components/settings/settings.ui:78 +msgid "Dark" +msgstr "Scuro" + +#. Header for a group of preference items regarding network +#: src/app/components/settings/settings.ui:89 +msgid "Network" +msgstr "Rete" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:92 +msgid "Access Point Port" +msgstr "Porta Access Point" + +#. Longer description for an item (Access Point Port) in preferences +#: src/app/components/settings/settings.ui:93 +msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." +msgstr "Porta usata per le connessioni all'Access Point Spotify. Impostala a 0 se qualsiasi valore va bene." + +#: src/app/components/selection/selection_toolbar.ui:90 +msgid "Save to library" +msgstr "Salva nella libreria" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Creata nuova playlist." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Visualizza" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Nuova Playlist" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Riproduzione gapless" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Sistema" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Fatto" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Nome" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Crea" + diff --git a/po/ja.po b/po/ja.po index 8d14b9c3..b1b16950 100644 --- a/po/ja.po +++ b/po/ja.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "パスワードを保存できませんでした。セッションキーリングのロックを解除してください。" #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "エラーが発生しました。詳細はログを確認してください。" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "ライブラリ" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "プレイリスト" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "再生中" @@ -84,7 +84,7 @@ msgstr "終了" msgid "Log out" msgstr "ログアウト" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "再接続しました" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Spotifyプレミアムにログイン" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "ユーザー名" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "パスワード" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "認証に失敗しました。" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "ログイン" @@ -133,16 +133,11 @@ msgstr "アルバム" msgid "Artists" msgstr "アーティスト" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "お気に入り" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lockが有効になっています。" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "一時停止" @@ -213,6 +208,7 @@ msgid "Add to playlist..." msgstr "プレイリストに追加…" #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "選択解除" @@ -226,7 +222,7 @@ msgstr "すべて選択" #: src/app/components/labels.rs:39 #, fuzzy msgid "More from {}" -msgstr "詳細" +msgstr "" #. This refers to a music label #: src/app/components/details/release_details.ui:38 @@ -257,12 +253,12 @@ msgstr "著作権表示" msgid "{} by {}" msgstr "{} から {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -275,7 +271,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -317,35 +313,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -353,3 +349,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/nb.po b/po/nb.po index 28c509c4..0f0a7813 100644 --- a/po/nb.po +++ b/po/nb.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Kunne ikke lagre passordet. Sørg for at nøkkelringen til sesjonen er låst opp." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "En feil oppstod. Sjekk logger for detaljer!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Bibliotek" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Spillelister" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Nå spiller" @@ -84,7 +84,7 @@ msgstr "Avslutt" msgid "Log out" msgstr "Logg ut" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Tilkoblingen er gjenopprettet" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Logg på Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Brukernavn" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Passord" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Autentiseringen mislyktes!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Logg inn" @@ -133,16 +133,11 @@ msgstr "Album" msgid "Artists" msgstr "Artister" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Lagrede spor" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lock er aktivert!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pause" @@ -215,6 +210,7 @@ msgid "Add to playlist..." msgstr "Legg til spilleliste..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Avbryt" @@ -258,99 +254,137 @@ msgstr "Opphavsrett" msgid "{} by {}" msgstr "{} av {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" -msgstr "" +msgstr "Navnløs spilleliste" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" -msgstr "" +msgstr "Alle Spillelister" #: src/app/components/selection/component.rs:66 msgid "Tracks saved!" -msgstr "" +msgstr "Spor lagret!" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:65 msgid "Preferences" -msgstr "" +msgstr "Innstillinger" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" -msgstr "" +msgstr "Kunne ikke åpne linken!" #. Header for a group of preference items regarding audio #: src/app/components/settings/settings.ui:13 msgid "Audio" -msgstr "" +msgstr "Lyd" #. Title for an item in preferences #: src/app/components/settings/settings.ui:16 msgid "Audio Backend" -msgstr "" +msgstr "Lyd Backend" #. Title for an item in preferences #: src/app/components/settings/settings.ui:29 msgid "ALSA Device" -msgstr "" +msgstr "ALSA Enhet" #. Description for the item (ALSA Device) in preferences #: src/app/components/settings/settings.ui:30 msgid "Applied only if audio backend is ALSA" -msgstr "" +msgstr "Brukes bare hvis lyd backend er ALSA" #. Title for an item in preferences #: src/app/components/settings/settings.ui:40 msgid "Audio Quality" -msgstr "" +msgstr "Lyd Kvalitet" #: src/app/components/settings/settings.ui:44 msgid "Normal" -msgstr "" +msgstr "Normal" #: src/app/components/settings/settings.ui:45 msgid "High" -msgstr "" +msgstr "Høy" #: src/app/components/settings/settings.ui:46 msgid "Very high" -msgstr "" +msgstr "Veldig høy" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" -msgstr "" +msgstr "Utseende" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" -msgstr "" +msgstr "Tema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" -msgstr "" +msgstr "Lys" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" -msgstr "" +msgstr "Mørk" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" -msgstr "" +msgstr "Nettverk" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" -msgstr "" +msgstr "Aksesspunkt Port" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." -msgstr "" +msgstr "Port som brukes for tilkoblinger til Spotify sitt aksesspunkt. Sett til 0 hvis tilfeldig port er greit." #: src/app/components/selection/selection_toolbar.ui:90 msgid "Save to library" +msgstr "Lagre til bibliotek" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" msgstr "" diff --git a/po/nl.po b/po/nl.po index d94a3cf8..fdc4ae68 100644 --- a/po/nl.po +++ b/po/nl.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Het wachtwoord kan niet worden opgeslagen - zorg dat de sessiesleutelhanger ontgrendeld is." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Er is een fout opgetreden - bekijk het logboek!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Verzameling" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Afspeellijsten" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Je luistert naar" @@ -84,7 +84,7 @@ msgstr "Afsluiten" msgid "Log out" msgstr "Uitloggen" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "De verbinding is hersteld" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Inloggen op Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Gebruikersnaam" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Wachtwoord" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Het inloggen is mislukt." #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Inloggen" @@ -133,16 +133,11 @@ msgstr "Albums" msgid "Artists" msgstr "Artiesten" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Opgeslagen nummers" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lock is ingeschakeld!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Pauzeren" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "Toevoegen aan afspeellijst…" #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Annuleren" @@ -257,12 +253,12 @@ msgstr "Copyright" msgid "{} by {}" msgstr "{} van {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "Naamloze afspeellijst" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "Alle afspeellijsten" @@ -275,7 +271,7 @@ msgstr "De nummers zijn opgeslagen!" msgid "Preferences" msgstr "Voorkeuren" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "De link kan niet worden geopend!" @@ -317,35 +313,35 @@ msgid "Very high" msgstr "Hoogst" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "Vormgeving" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "Thema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "Licht" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "Donker" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "Netwerk" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "Poort van toegangspunt" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "De poort die wordt gebruikt om verbinding te maken met Spotify's toegangspunt. 0 = elke poort." @@ -353,3 +349,41 @@ msgstr "De poort die wordt gebruikt om verbinding te maken met Spotify's toegang msgid "Save to library" msgstr "Opslaan in verzameling" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "De afspeellijst is aangemaakt." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Bekijken" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Nieuwe afspeellijst" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Afspelen zonder pauzes" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Systeem" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Klaar" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Naam" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Aanmaken" + diff --git a/po/pl.po b/po/pl.po index 46a8aba1..f1dd1115 100644 --- a/po/pl.po +++ b/po/pl.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Nie można zapisać hasła. Upewnij się że narzędzie zarządzające kluczami jest odblokowane." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Wystąpił błąd. Sprawdź logi po więcej informacji!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Biblioteka" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Playlisty" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Aktualnie odtwarzane" @@ -84,7 +84,7 @@ msgstr "Wyjdź" msgid "Log out" msgstr "Wyloguj się" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Odzyskano połączenie" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Zaloguj się do Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Nazwa użytkownika" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Hasło" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Błąd autoryzacji!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Zaloguj" @@ -133,16 +133,11 @@ msgstr "Albumy" msgid "Artists" msgstr "Artyści" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Zachowane piosenki" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lock jest włączony!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "" @@ -216,6 +211,7 @@ msgid "Add to playlist..." msgstr "" #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "" @@ -259,12 +255,12 @@ msgstr "Prawa autorskie" msgid "{} by {}" msgstr "" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -277,7 +273,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -319,35 +315,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -355,3 +351,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/pt-br.po b/po/pt-br.po index 6529d167..eda99ce8 100644 --- a/po/pt-br.po +++ b/po/pt-br.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Não foi possível salvar a senha. Verifique se o seu chaveiro de sessão está desbloqueado." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Ocorreu um erro. Verifique os logs para mais detalhes!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Biblioteca" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Listas de reprodução" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Tocando agora" @@ -84,7 +84,7 @@ msgstr "Fechar" msgid "Log out" msgstr "Sair" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Conexão reestabelecida" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Entrar no Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Nome de usuário" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Senha" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "A autenticação falhou!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Entrar" @@ -133,16 +133,11 @@ msgstr "Álbuns" msgid "Artists" msgstr "Artistas" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "" @@ -214,6 +209,7 @@ msgid "Add to playlist..." msgstr "" #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "" @@ -257,12 +253,12 @@ msgstr "Copyright" msgid "{} by {}" msgstr "" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -275,7 +271,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -317,35 +313,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -353,3 +349,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/pt.po b/po/pt.po index 9173087c..502e5590 100644 --- a/po/pt.po +++ b/po/pt.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Não foi possível guardar a palavra-passe. Garanta que o chaveiro da sessão está desbloqueado." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Ocorreu um erro! Verifique os logs para mais detalhes!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Biblioteca" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Listas de reprodução" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "A reproduzir" @@ -84,7 +84,7 @@ msgstr "Sair" msgid "Log out" msgstr "Terminar sessão" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Conexão restaurada" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Autenticar-se no Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Utilizador" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Palavra-passe" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Autenticação falhou!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Autenticar" @@ -133,59 +133,54 @@ msgstr "Álbums" msgid "Artists" msgstr "Artistas" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" -msgstr "" - -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "" +msgstr "Músicas salvas" #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" -msgstr "" +msgstr "Pausar" #: src/app/components/playback/playback_controls.rs:66 msgid "Play" -msgstr "" +msgstr "Tocar" #: src/app/components/playback/playback_controls.ui:17 msgid "Shuffle" -msgstr "" +msgstr "Misturar" #: src/app/components/playback/playback_controls.ui:27 msgid "Previous" -msgstr "" +msgstr "Anterior" #: src/app/components/playback/playback_controls.ui:50 msgid "Next" -msgstr "" +msgstr "Próximo" #: src/app/components/playback/playback_controls.ui:60 msgid "Repeat" -msgstr "" +msgstr "Repetir" #. A title that is shown when the user has not saved any playlists. #: src/app/components/saved_playlists/saved_playlists.ui:26 msgid "You have no saved playlists." -msgstr "" +msgstr "Não tem listas de reprodução salvas." #. A description of what happens when the user has saved playlists. #: src/app/components/saved_playlists/saved_playlists.ui:27 msgid "Your playlists will be shown here." -msgstr "" +msgstr "As tuas listas de reprodução aparecerão aqui." #. A title that is shown when the user has not saved any albums. #: src/app/components/library/library.ui:26 msgid "You have no saved albums." -msgstr "" +msgstr "Não tens albúns salvos." #. A description of what happens when the user has saved albums. #: src/app/components/library/library.ui:27 msgid "Your library will be shown here." -msgstr "" +msgstr "A tua biblioteca vai aparecer aqui." #. translators: This shows up when in selection mode. This text should be as short as possible. #: src/app/components/labels.rs:30 @@ -197,31 +192,32 @@ msgstr[1] "{} canções selecionadas" #. Title for the empty search page (initial state). #: src/app/components/search/search.ui:116 msgid "Search Spotify." -msgstr "" +msgstr "Procurar no Spotify." #. Subtitle for the empty search page (initial state). #: src/app/components/search/search.ui:117 msgid "Type to search." -msgstr "" +msgstr "Escrever para pesquisar." #: src/app/components/selection/selection_toolbar.ui:69 msgid "Remove" -msgstr "" +msgstr "Remover" #. playlist2-symbolic #: src/app/components/selection/selection_toolbar.ui:56 msgid "Add to playlist..." -msgstr "" +msgstr "Adicionar à lista de reprodução..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" -msgstr "" +msgstr "Cancelar" #. Button label. Selects all visible songs. #: src/app/components/headerbar/headerbar.ui:58 msgid "Select all" -msgstr "" +msgstr "Selecionar todos" #. translators: This is part of a contextual menu attached to a single track; the full text is "More from ". #: src/app/components/labels.rs:39 @@ -255,101 +251,139 @@ msgstr "Copyright" #. translators: This is part of a larger label that reads " by " #: src/app/components/labels.rs:48 msgid "{} by {}" -msgstr "" +msgstr "{} por {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" -msgstr "" +msgstr "Lista de reprodução sem nome" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" -msgstr "" +msgstr "Todas as listas de reprodução" #: src/app/components/selection/component.rs:66 msgid "Tracks saved!" -msgstr "" +msgstr "Músicas salvas!" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:65 msgid "Preferences" -msgstr "" +msgstr "Preferências" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" -msgstr "" +msgstr "Falha ao abrir a ligação!" #. Header for a group of preference items regarding audio #: src/app/components/settings/settings.ui:13 msgid "Audio" -msgstr "" +msgstr "Áudio" #. Title for an item in preferences #: src/app/components/settings/settings.ui:16 msgid "Audio Backend" -msgstr "" +msgstr "Back-end de Áudio" #. Title for an item in preferences #: src/app/components/settings/settings.ui:29 msgid "ALSA Device" -msgstr "" +msgstr "Dispositivo ALSA" #. Description for the item (ALSA Device) in preferences #: src/app/components/settings/settings.ui:30 msgid "Applied only if audio backend is ALSA" -msgstr "" +msgstr "Aplicado apenas se back-end do áudio é ALSA" #. Title for an item in preferences #: src/app/components/settings/settings.ui:40 msgid "Audio Quality" -msgstr "" +msgstr "Qualidade do Áudio" #: src/app/components/settings/settings.ui:44 msgid "Normal" -msgstr "" +msgstr "Normal" #: src/app/components/settings/settings.ui:45 msgid "High" -msgstr "" +msgstr "Alta" #: src/app/components/settings/settings.ui:46 msgid "Very high" -msgstr "" +msgstr "Muito Alta" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" -msgstr "" +msgstr "Aparência" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" -msgstr "" +msgstr "Tema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" -msgstr "" +msgstr "Claro" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" -msgstr "" +msgstr "Escuro" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" -msgstr "" +msgstr "Rede" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" -msgstr "" +msgstr "Porta do Ponto de Acesso" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." -msgstr "" +msgstr "Porta usada para conexões ao Ponto de Acesso do Spotify. Definir para 0 se qualquer porta servir." #: src/app/components/selection/selection_toolbar.ui:90 msgid "Save to library" -msgstr "" +msgstr "Salvar na biblioteca" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Nova lista de reprodução criada." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Ver" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Nova lista de reprodução" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Reprodução sem intervalos" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Sistema" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Feito" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Nome" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Criar" diff --git a/po/ru.po b/po/ru.po index 140c34fe..d1141f09 100644 --- a/po/ru.po +++ b/po/ru.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Не удалось сохранить пароль. Убедитесь, что связка ключей сеанса разблокирована." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Произошла ошибка. Смотрите подробности в логах!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Фонотека" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Плейлисты" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Воспроизводится сейчас" @@ -84,7 +84,7 @@ msgstr "Выйти из программы" msgid "Log out" msgstr "Выйти из аккаунта" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Подключение восстановлено" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Войти в Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Имя аккаунта" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Пароль" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Вход не удался!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Войти" @@ -133,16 +133,11 @@ msgstr "Альбомы" msgid "Artists" msgstr "Исполнители" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Сохраненные треки" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Caps Lock включен!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Пауза" @@ -216,6 +211,7 @@ msgid "Add to playlist..." msgstr "Добавить в плейлист..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Отменить" @@ -259,99 +255,137 @@ msgstr "Авторское право" msgid "{} by {}" msgstr "{} в исполнении {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" -msgstr "" +msgstr "Безымянный плейлист" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" -msgstr "" +msgstr "Все плейлисты" #: src/app/components/selection/component.rs:66 msgid "Tracks saved!" -msgstr "" +msgstr "Треки сохранены!" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:65 msgid "Preferences" -msgstr "" +msgstr "Настройки" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" -msgstr "" +msgstr "Не удалось открыть ссылку!" #. Header for a group of preference items regarding audio #: src/app/components/settings/settings.ui:13 msgid "Audio" -msgstr "" +msgstr "Аудио" #. Title for an item in preferences #: src/app/components/settings/settings.ui:16 msgid "Audio Backend" -msgstr "" +msgstr "Аудио Бэкэнд" #. Title for an item in preferences #: src/app/components/settings/settings.ui:29 msgid "ALSA Device" -msgstr "" +msgstr "ALSA Device" #. Description for the item (ALSA Device) in preferences #: src/app/components/settings/settings.ui:30 msgid "Applied only if audio backend is ALSA" -msgstr "" +msgstr "Применяется, только если звуковой бэкэнд ALSA" #. Title for an item in preferences #: src/app/components/settings/settings.ui:40 msgid "Audio Quality" -msgstr "" +msgstr "Качество звука" #: src/app/components/settings/settings.ui:44 msgid "Normal" -msgstr "" +msgstr "Нормальное" #: src/app/components/settings/settings.ui:45 msgid "High" -msgstr "" +msgstr "Высокое" #: src/app/components/settings/settings.ui:46 msgid "Very high" -msgstr "" +msgstr "Очень высокое" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" -msgstr "" +msgstr "Внешний вид" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" -msgstr "" +msgstr "Тема" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" -msgstr "" +msgstr "Светлая" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" -msgstr "" +msgstr "Темная" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" -msgstr "" +msgstr "Сеть" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" -msgstr "" +msgstr "Порт точки доступа" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." -msgstr "" +msgstr "Порт, используемый для подключения к точке доступа Spotify. Установите на 0, если все порты в порядке." #: src/app/components/selection/selection_toolbar.ui:90 msgid "Save to library" -msgstr "" +msgstr "Сохранить в библиотеку" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Создан новый плейлист." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Вид" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Новый плейлист" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Непрерывное воспроизведение" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Система" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Сделано" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Имя" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Создать" diff --git a/po/sl.po b/po/sl.po index fa55a402..ff90a559 100644 --- a/po/sl.po +++ b/po/sl.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Gesla ni bilo mogoče shraniti. Preveri, da je session keyring odklenjen." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Napaka! Poglej v dnevnik od programa za podrobnosti." #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Moja zbirka" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Seznami predvajanja" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Se predvaja" @@ -84,7 +84,7 @@ msgstr "Izhod" msgid "Log out" msgstr "Odjava" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Povezava ponovno vzpovstavljena" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Prijava v Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Uporabniško ime" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Geslo" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Preverjanje pristnosti ni bilo uspešno!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Prijava" @@ -133,16 +133,11 @@ msgstr "Albumi" msgid "Artists" msgstr "Izvajalci" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "Shranjene skladbe" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "Velike črke so vklopljene!" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "Premor" @@ -216,6 +211,7 @@ msgid "Add to playlist..." msgstr "Dodaj na seznam predvajanja..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "Prekliči" @@ -259,12 +255,12 @@ msgstr "Avtorska pravica" msgid "{} by {}" msgstr "{} od {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -277,7 +273,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -319,35 +315,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -355,3 +351,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/po/spot.pot b/po/spot.pot index b9fd689b..aeb5a665 100644 --- a/po/spot.pot +++ b/po/spot.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: spot\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-03-28 00:21+0200\n" +"POT-Creation-Date: 2023-02-19 17:27-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -19,7 +19,7 @@ msgstr "" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "" @@ -72,35 +72,37 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "" #. translators: This is a sidebar entry that marks that the entries below are playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "" #. translators: This is a sidebar entry to browse to saved tracks. -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "" -#: src/app/components/navigation/home.rs:32 -msgid "Unnamed playlist" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." msgstr "" -#: src/app/components/navigation/home.rs:87 -#: src/app/components/now_playing/now_playing_model.rs:134 -msgid "Now playing" +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 -msgid "All Playlists" +#: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 +msgid "Now playing" msgstr "" #: src/app/components/playback/playback_controls.rs:64 @@ -122,6 +124,18 @@ msgstr "" msgid "Tracks saved!" msgstr "" +#: src/app/components/sidebar/sidebar_item.rs:81 +msgid "All Playlists" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#: src/app/components/sidebar/sidebar.rs:48 +msgid "Unnamed playlist" +msgstr "" + #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:65 msgid "Preferences" @@ -142,11 +156,11 @@ msgstr "" msgid "Log out" msgstr "" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -227,36 +241,45 @@ msgstr "" msgid "Very high" msgstr "" +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "" "Port used for connections to Spotify's Access Point. Set to 0 if any port is " "fine." @@ -319,16 +342,33 @@ msgstr "" msgid "Log in" msgstr "" +#. Exit playlist edition #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "" +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + #. Button label. Selects all visible songs. #: src/app/components/headerbar/headerbar.ui:58 msgid "Select all" msgstr "" +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + #: src/app/components/playback/playback_controls.ui:17 msgid "Shuffle" msgstr "" diff --git a/po/tr.po b/po/tr.po index 5637788d..34796801 100644 --- a/po/tr.po +++ b/po/tr.po @@ -37,28 +37,28 @@ msgstr "{} listesine ekle" #. translators: This notification shows up right after login if the password could not be stored in the keyring (that is, GNOME's keyring aka seahorse, or any other libsecret compliant secret store). #: src/app/components/login/login_model.rs:56 msgid "Could not save password. Make sure the session keyring is unlocked." -msgstr "Şifreniz kaydedilemedi. Oturum anahtarlığınızın kilidinin açık olduğundan emin olun." +msgstr "Parola kaydedilemedi. Oturum anahtarlığınızın kilidinin açık olduğundan emin olun." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Bir hata meydana geldi. Günlükleri kontrol edin." #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Kütüphane" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Oynatma listesi" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Şu an oynatılıyor" @@ -77,14 +77,14 @@ msgstr "Hakkında" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:69 msgid "Quit" -msgstr "Çıkış" +msgstr "Çık" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:74 msgid "Log out" msgstr "Oturumdan çık" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "Bağlantı geri yüklendi." @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Spotify Premium'a giriş yap" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Kullanıcı adı" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" -msgstr "Şifre" +msgstr "Parola" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Kimlik doğrulama başarısız." #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Giriş yap" @@ -133,59 +133,54 @@ msgstr "Albümler" msgid "Artists" msgstr "Sanatçılar" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" -msgstr "" - -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "" +msgstr "Kaydedilen parçalar" #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" -msgstr "" +msgstr "Durdur" #: src/app/components/playback/playback_controls.rs:66 msgid "Play" -msgstr "" +msgstr "Oynat" #: src/app/components/playback/playback_controls.ui:17 msgid "Shuffle" -msgstr "" +msgstr "Karıştır" #: src/app/components/playback/playback_controls.ui:27 msgid "Previous" -msgstr "" +msgstr "Önceki" #: src/app/components/playback/playback_controls.ui:50 msgid "Next" -msgstr "" +msgstr "Sonraki" #: src/app/components/playback/playback_controls.ui:60 msgid "Repeat" -msgstr "" +msgstr "Yinele" #. A title that is shown when the user has not saved any playlists. #: src/app/components/saved_playlists/saved_playlists.ui:26 msgid "You have no saved playlists." -msgstr "" +msgstr "Kaydedilmiş oynatma listeniz yok." #. A description of what happens when the user has saved playlists. #: src/app/components/saved_playlists/saved_playlists.ui:27 msgid "Your playlists will be shown here." -msgstr "" +msgstr "Oynatma listeniz burada gösterilir." #. A title that is shown when the user has not saved any albums. #: src/app/components/library/library.ui:26 msgid "You have no saved albums." -msgstr "" +msgstr "Kaydedilmiş ablümünüz yok." #. A description of what happens when the user has saved albums. #: src/app/components/library/library.ui:27 msgid "Your library will be shown here." -msgstr "" +msgstr "Kütüphaneniz burada gösterilir." #. translators: This shows up when in selection mode. This text should be as short as possible. #: src/app/components/labels.rs:30 @@ -197,31 +192,32 @@ msgstr[1] "{} seçildi" #. Title for the empty search page (initial state). #: src/app/components/search/search.ui:116 msgid "Search Spotify." -msgstr "" +msgstr "Spotify'da Ara." #. Subtitle for the empty search page (initial state). #: src/app/components/search/search.ui:117 msgid "Type to search." -msgstr "" +msgstr "Aramak için yazın." #: src/app/components/selection/selection_toolbar.ui:69 msgid "Remove" -msgstr "" +msgstr "Kaldır" #. playlist2-symbolic #: src/app/components/selection/selection_toolbar.ui:56 msgid "Add to playlist..." -msgstr "" +msgstr "Oynatma listesine ekle..." #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" -msgstr "" +msgstr "İptal Et" #. Button label. Selects all visible songs. #: src/app/components/headerbar/headerbar.ui:58 msgid "Select all" -msgstr "" +msgstr "Tümünü seç" #. translators: This is part of a contextual menu attached to a single track; the full text is "More from ". #: src/app/components/labels.rs:39 @@ -231,127 +227,163 @@ msgstr "Daha fazla {}" #. This refers to a music label #: src/app/components/details/release_details.ui:38 msgid "Label" -msgstr "" +msgstr "Yayıncı" #. This refers to a release date #: src/app/components/details/release_details.ui:48 -#, fuzzy msgid "Released" -msgstr "Parçalar" +msgstr "Yayın tarihi" #. This refers to a number of tracks #: src/app/components/details/release_details.ui:58 -#, fuzzy msgid "Tracks" -msgstr "En çok dinlenenler" +msgstr "Parça" #. This refers to the duration of a release #: src/app/components/details/release_details.ui:68 msgid "Duration" -msgstr "" +msgstr "Süre" #: src/app/components/details/release_details.ui:68 msgid "Copyright" -msgstr "" +msgstr "Telif hakkı" #. translators: This is part of a larger label that reads " by " #: src/app/components/labels.rs:48 msgid "{} by {}" -msgstr "" +msgstr "{}, {}" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" -msgstr "" +msgstr "Adsız oynatma listesi" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" -msgstr "" +msgstr "Tüm Oynatma Listeleri" #: src/app/components/selection/component.rs:66 msgid "Tracks saved!" -msgstr "" +msgstr "Parçalar kaydedildi!" #. translators: This is a menu entry. #: src/app/components/user_menu/user_menu.rs:65 msgid "Preferences" -msgstr "" +msgstr "Tercihler" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" -msgstr "" +msgstr "Bağlantı açılamadı!" #. Header for a group of preference items regarding audio #: src/app/components/settings/settings.ui:13 msgid "Audio" -msgstr "" +msgstr "Ses" #. Title for an item in preferences #: src/app/components/settings/settings.ui:16 msgid "Audio Backend" -msgstr "" +msgstr "Ses Arka Ucu" #. Title for an item in preferences #: src/app/components/settings/settings.ui:29 msgid "ALSA Device" -msgstr "" +msgstr "ALSA Aygıtı" #. Description for the item (ALSA Device) in preferences #: src/app/components/settings/settings.ui:30 msgid "Applied only if audio backend is ALSA" -msgstr "" +msgstr "Sadece, ses arka ucu ALSA ise uygulanır" #. Title for an item in preferences #: src/app/components/settings/settings.ui:40 msgid "Audio Quality" -msgstr "" +msgstr "Ses Kalitesi" #: src/app/components/settings/settings.ui:44 msgid "Normal" -msgstr "" +msgstr "Normal" #: src/app/components/settings/settings.ui:45 msgid "High" -msgstr "" +msgstr "Yüksek" #: src/app/components/settings/settings.ui:46 msgid "Very high" -msgstr "" +msgstr "Çok yüksek" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" -msgstr "" +msgstr "Görünüm" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" -msgstr "" +msgstr "Tema" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" -msgstr "" +msgstr "Açık" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" -msgstr "" +msgstr "Koyu" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" -msgstr "" +msgstr "Ağ" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" -msgstr "" +msgstr "Erişim Noktası Bağlantı Noktası" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." -msgstr "" +msgstr "Spotify Erişim Noktasına bağlanmak için kullanılan bağlantı noktası. Herhangi bir bağlantı noktası iyiyse 0'a ayarlayın." #: src/app/components/selection/selection_toolbar.ui:90 msgid "Save to library" -msgstr "" +msgstr "Kütüphaneye kaydet" + +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "Yeni çalma listesi oluşturuldu." + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "Görünüm" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "Yeni Çalma Listesi" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "Kesintisiz çalma" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "Sistem" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "Bitti" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "Ad" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "Oluştur" diff --git a/po/uk.po b/po/uk.po index ec336439..fef57652 100644 --- a/po/uk.po +++ b/po/uk.po @@ -40,25 +40,25 @@ msgid "Could not save password. Make sure the session keyring is unlocked." msgstr "Не вдалося зберегти пароль. Переконайтесь, що зв'язка ключів сеансу розблокована." #. translators: This notification is the default message for unhandled errors. Logs refer to console output. -#: src/app/batch_loader.rs:91 src/app/components/mod.rs:122 +#: src/app/batch_loader.rs:91 src/app/components/mod.rs:128 msgid "An error occured. Check logs for details!" msgstr "Сталася помилка. Перевірте журнал для детальної інформації!" #. translators: This is a sidebar entry to browse to saved albums. -#: src/app/components/navigation/factory.rs:32 -#: src/app/components/navigation/home.rs:68 +#: src/app/components/navigation/factory.rs:33 +#: src/app/components/sidebar/sidebar_item.rs:39 msgid "Library" msgstr "Бібліотека" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/factory.rs:51 -#: src/app/components/navigation/home.rs:94 +#: src/app/components/navigation/factory.rs:54 +#: src/app/components/sidebar/sidebar_item.rs:45 msgid "Playlists" msgstr "Плейлисти" #. This is the visible name for the play queue. It appears in the sidebar as well. -#: src/app/components/navigation/home.rs:87 #: src/app/components/now_playing/now_playing_model.rs:134 +#: src/app/components/sidebar/sidebar_item.rs:43 msgid "Now playing" msgstr "Відтворюється зараз" @@ -84,7 +84,7 @@ msgstr "Вийти з програми" msgid "Log out" msgstr "Вийти з аккаунту" -#: src/app/state/login_state.rs:110 +#: src/app/state/login_state.rs:112 msgid "Connection restored" msgstr "З'єднання відновлено" @@ -104,22 +104,22 @@ msgid "Login to Spotify Premium" msgstr "Увійти в Spotify Premium" #. Placeholder for the username field -#: src/app/components/login/login.ui:64 +#: src/app/components/login/login.ui:72 msgid "Username" msgstr "Логін" #. Placeholder for the password field -#: src/app/components/login/login.ui:72 +#: src/app/components/login/login.ui:89 msgid "Password" msgstr "Пароль" #. This error is shown when authentication fails. -#: src/app/components/login/login.ui:126 +#: src/app/components/login/login.ui:114 msgid "Authentication failed!" msgstr "Помилка входу!" #. Log in button label -#: src/app/components/login/login.ui:141 +#: src/app/components/login/login.ui:129 msgid "Log in" msgstr "Увійти" @@ -133,16 +133,11 @@ msgstr "Альбоми" msgid "Artists" msgstr "Виконавці" -#: src/app/components/navigation/factory.rs:82 -#: src/app/components/navigation/home.rs:78 +#: src/app/components/navigation/factory.rs:85 +#: src/app/components/sidebar/sidebar_item.rs:41 msgid "Saved tracks" msgstr "" -#. This information is shown when Caps Lock is enabled. -#: src/app/components/login/login.ui:95 -msgid "Caps Lock is enabled!" -msgstr "" - #: src/app/components/playback/playback_controls.rs:64 msgid "Pause" msgstr "" @@ -216,6 +211,7 @@ msgid "Add to playlist..." msgstr "" #. Button label. Exits selection mode. +#: src/app/components/playlist_details/playlist_headerbar.ui:50 #: src/app/components/headerbar/headerbar.ui:47 msgid "Cancel" msgstr "" @@ -259,12 +255,12 @@ msgstr "" msgid "{} by {}" msgstr "" -#: src/app/components/navigation/home.rs:32 +#: src/app/components/sidebar/sidebar.rs:48 msgid "Unnamed playlist" msgstr "" #. translators: This is a sidebar entry to browse to saved playlists. -#: src/app/components/navigation/home.rs:104 +#: src/app/components/sidebar/sidebar_item.rs:81 msgid "All Playlists" msgstr "" @@ -277,7 +273,7 @@ msgstr "" msgid "Preferences" msgstr "" -#: src/main.rs:81 +#: src/main.rs:80 msgid "Failed to open link!" msgstr "" @@ -319,35 +315,35 @@ msgid "Very high" msgstr "" #. Header for a group of preference items regarding the application's appearance -#: src/app/components/settings/settings.ui:56 +#: src/app/components/settings/settings.ui:70 msgid "Appearance" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:59 +#: src/app/components/settings/settings.ui:73 msgid "Theme" msgstr "" -#: src/app/components/settings/settings.ui:63 +#: src/app/components/settings/settings.ui:77 msgid "Light" msgstr "" -#: src/app/components/settings/settings.ui:64 +#: src/app/components/settings/settings.ui:78 msgid "Dark" msgstr "" #. Header for a group of preference items regarding network -#: src/app/components/settings/settings.ui:74 +#: src/app/components/settings/settings.ui:89 msgid "Network" msgstr "" #. Title for an item in preferences -#: src/app/components/settings/settings.ui:77 +#: src/app/components/settings/settings.ui:92 msgid "Access Point Port" msgstr "" #. Longer description for an item (Access Point Port) in preferences -#: src/app/components/settings/settings.ui:78 +#: src/app/components/settings/settings.ui:93 msgid "Port used for connections to Spotify's Access Point. Set to 0 if any port is fine." msgstr "" @@ -355,3 +351,41 @@ msgstr "" msgid "Save to library" msgstr "" +#. translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. +#: src/app/components/notification/mod.rs:25 +msgid "New playlist created." +msgstr "" + +#. translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. +#: src/app/components/notification/mod.rs:27 +msgid "View" +msgstr "" + +#: src/app/components/sidebar/sidebar_item.rs:90 +msgid "New Playlist" +msgstr "" + +#. Title for an item in preferences +#: src/app/components/settings/settings.ui:54 +msgid "Gapless playback" +msgstr "" + +#: src/app/components/settings/settings.ui:79 +msgid "System" +msgstr "" + +#. Finish playlist edition +#: src/app/components/playlist_details/playlist_headerbar.ui:63 +msgid "Done" +msgstr "" + +#. label for the entry containing the name of a new playlist +#: src/app/components/sidebar/create_playlist.ui:10 +msgid "Name" +msgstr "" + +#. Button that creates a new playlist +#: src/app/components/sidebar/create_playlist.ui:33 +msgid "Create" +msgstr "" + diff --git a/src/api/api_models.rs b/src/api/api_models.rs index b96f1592..8dbbb6b1 100644 --- a/src/api/api_models.rs +++ b/src/api/api_models.rs @@ -8,6 +8,11 @@ use std::{ use crate::app::models::*; +#[derive(Serialize)] +pub struct PlaylistDetails { + pub name: String, +} + #[derive(Serialize)] pub struct Uris { pub uris: Vec, @@ -18,6 +23,11 @@ pub struct Ids { pub ids: Vec, } +#[derive(Serialize)] +pub struct Name<'a> { + pub name: &'a str, +} + pub enum SearchType { Artist, Album, diff --git a/src/api/cache.rs b/src/api/cache.rs index e2359a7a..fd2fd54d 100644 --- a/src/api/cache.rs +++ b/src/api/cache.rs @@ -99,7 +99,7 @@ impl CacheManager { fn cache_meta_path(&self, resource: &str) -> PathBuf { let full = resource.to_string() + EXPIRY_FILE_EXT; - self.root.join(&full) + self.root.join(full) } } @@ -118,7 +118,7 @@ impl CacheManager { duration.copy_from_slice(&buffer[..OFFSET]); let duration = Duration::from_secs(u64::from_be_bytes(duration)); - let etag = String::from_utf8((&buffer[OFFSET..]).to_vec()).ok(); + let etag = String::from_utf8(buffer[OFFSET..].to_vec()).ok(); Ok(CacheExpiry::AtUnixTimestamp(duration, etag)) } diff --git a/src/api/cached_client.rs b/src/api/cached_client.rs index c7702cd8..e975099f 100644 --- a/src/api/cached_client.rs +++ b/src/api/cached_client.rs @@ -57,8 +57,16 @@ pub trait SpotifyApiClient { fn add_to_playlist(&self, id: &str, uris: Vec) -> BoxFuture>; + fn create_new_playlist( + &self, + name: &str, + user_id: &str, + ) -> BoxFuture>; + fn remove_from_playlist(&self, id: &str, uris: Vec) -> BoxFuture>; + fn update_playlist_details(&self, id: &str, name: String) -> BoxFuture>; + fn search( &self, query: &str, @@ -311,6 +319,27 @@ impl SpotifyApiClient for CachedSpotifyClient { }) } + fn create_new_playlist( + &self, + name: &str, + user_id: &str, + ) -> BoxFuture> { + let name = name.to_owned(); + let user_id = user_id.to_owned(); + + Box::pin(async move { + let playlist = self + .client + .create_new_playlist(&name, &user_id) + .send() + .await? + .deserialize() + .unwrap(); + + Ok(playlist.into()) + }) + } + fn remove_from_playlist(&self, id: &str, uris: Vec) -> BoxFuture> { let id = id.to_owned(); @@ -328,6 +357,24 @@ impl SpotifyApiClient for CachedSpotifyClient { }) } + fn update_playlist_details(&self, id: &str, name: String) -> BoxFuture> { + let id = id.to_owned(); + + Box::pin(async move { + self.cache + .set_expired_pattern(&playlist_cache_key(&id)) + .await + .unwrap_or(()); + + self.client + .update_playlist_details(&id, name) + .send_no_response() + .await?; + + Ok(()) + }) + } + fn get_album(&self, id: &str) -> BoxFuture> { let id = id.to_owned(); @@ -359,7 +406,7 @@ impl SpotifyApiClient for CachedSpotifyClient { let id = id.to_owned(); Box::pin(async move { - let _ = self.cache.set_expired_pattern(&*ME_ALBUMS_CACHE).await; + let _ = self.cache.set_expired_pattern(&ME_ALBUMS_CACHE).await; self.client.save_album(&id).send_no_response().await?; self.get_album(&id[..]).await.map(|a| a.description) }) @@ -367,7 +414,7 @@ impl SpotifyApiClient for CachedSpotifyClient { fn save_tracks(&self, ids: Vec) -> BoxFuture> { Box::pin(async move { - let _ = self.cache.set_expired_pattern(&*ME_TRACKS_CACHE).await; + let _ = self.cache.set_expired_pattern(&ME_TRACKS_CACHE).await; self.client.save_tracks(ids).send_no_response().await?; Ok(()) }) @@ -377,14 +424,14 @@ impl SpotifyApiClient for CachedSpotifyClient { let id = id.to_owned(); Box::pin(async move { - let _ = self.cache.set_expired_pattern(&*ME_ALBUMS_CACHE).await; + let _ = self.cache.set_expired_pattern(&ME_ALBUMS_CACHE).await; self.client.remove_saved_album(&id).send_no_response().await }) } fn remove_saved_tracks(&self, ids: Vec) -> BoxFuture> { Box::pin(async move { - let _ = self.cache.set_expired_pattern(&*ME_TRACKS_CACHE).await; + let _ = self.cache.set_expired_pattern(&ME_TRACKS_CACHE).await; self.client .remove_saved_tracks(ids) .send_no_response() diff --git a/src/api/client.rs b/src/api/client.rs index 13022f50..70b9c8ba 100644 --- a/src/api/client.rs +++ b/src/api/client.rs @@ -417,6 +417,17 @@ impl SpotifyClient { .json_body(Uris { uris }) } + pub(crate) fn create_new_playlist( + &self, + name: &str, + user_id: &str, + ) -> SpotifyRequest<'_, Vec, Playlist> { + self.request() + .method(Method::POST) + .uri(format!("/v1/users/{}/playlists", user_id), None) + .json_body(Name { name }) + } + pub(crate) fn remove_from_playlist( &self, playlist: &str, @@ -428,6 +439,17 @@ impl SpotifyClient { .json_body(Uris { uris }) } + pub(crate) fn update_playlist_details( + &self, + playlist: &str, + name: String, + ) -> SpotifyRequest<'_, Vec, ()> { + self.request() + .method(Method::PUT) + .uri(format!("/v1/playlists/{}", playlist), None) + .json_body(PlaylistDetails { name }) + } + pub(crate) fn get_saved_albums( &self, offset: usize, diff --git a/src/api/mod.rs b/src/api/mod.rs index 8d986401..bfd03a51 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -9,7 +9,7 @@ pub use client::SpotifyApiError; pub async fn clear_user_cache() -> Option<()> { cache::CacheManager::for_dir("spot/net")? - .clear_cache_pattern(&*cached_client::USER_CACHE) + .clear_cache_pattern(&cached_client::USER_CACHE) .await .ok() } diff --git a/src/app.css b/src/app.css index 762abf36..dd23e94d 100644 --- a/src/app.css +++ b/src/app.css @@ -8,4 +8,8 @@ .container--loaded { opacity: 1; +} + +.playlist__title-entry--ro { + background: none; } \ No newline at end of file diff --git a/src/app/components/album/album.rs b/src/app/components/album/album.rs index 014eb858..77dd80f9 100644 --- a/src/app/components/album/album.rs +++ b/src/app/components/album/album.rs @@ -38,7 +38,7 @@ mod imp { type ParentType = libadwaita::Bin; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -58,7 +58,7 @@ glib::wrapper! { impl AlbumWidget { pub fn new() -> Self { display_add_css_provider(resource!("/components/album.css")); - glib::Object::new(&[]).expect("Failed to create an instance of AlbumWidget") + glib::Object::new() } pub fn for_model(album_model: &AlbumModel, worker: Worker) -> Self { @@ -73,21 +73,19 @@ impl AlbumWidget { } fn set_image(&self, pixbuf: Option<&gdk_pixbuf::Pixbuf>) { - imp::AlbumWidget::from_instance(self) - .cover_image - .set_from_pixbuf(pixbuf); + self.imp().cover_image.set_from_pixbuf(pixbuf); } fn bind(&self, album_model: &AlbumModel, worker: Worker) { - let widget = imp::AlbumWidget::from_instance(self); + let widget = self.imp(); widget.cover_image.set_overflow(gtk::Overflow::Hidden); - if let Some(url) = album_model.cover_url() { + if let Some(cover_art) = album_model.cover() { let _self = self.downgrade(); worker.send_local_task(async move { if let Some(_self) = _self.upgrade() { let loader = ImageLoader::new(); - let result = loader.load_remote(&url, "jpg", 200, 200).await; + let result = loader.load_remote(&cover_art, "jpg", 200, 200).await; _self.set_image(result.as_ref()); _self.set_loaded(); } @@ -106,21 +104,18 @@ impl AlbumWidget { .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) .build(); - match album_model.year() { - Some(_) => { - album_model - .bind_property("year", &*widget.year_label, "label") - .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) - .build(); - } - None => { - widget.year_label.hide(); - } + if album_model.year() > 0 { + album_model + .bind_property("year", &*widget.year_label, "label") + .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) + .build(); + } else { + widget.year_label.hide(); } } pub fn connect_album_pressed(&self, f: F) { - imp::AlbumWidget::from_instance(self) + self.imp() .cover_btn .connect_clicked(clone!(@weak self as _self => move |_| { f(&_self); diff --git a/src/app/components/artist/mod.rs b/src/app/components/artist/mod.rs index 3d3cac04..46dd29c3 100644 --- a/src/app/components/artist/mod.rs +++ b/src/app/components/artist/mod.rs @@ -30,7 +30,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -49,7 +49,7 @@ glib::wrapper! { impl ArtistWidget { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of ArtistWidget") + glib::Object::new() } pub fn for_model(model: &ArtistModel, worker: Worker) -> Self { @@ -59,7 +59,7 @@ impl ArtistWidget { } pub fn connect_artist_pressed(&self, f: F) { - imp::ArtistWidget::from_instance(self) + self.imp() .avatar_btn .connect_clicked(clone!(@weak self as _self => move |_| { f(&_self); @@ -67,9 +67,9 @@ impl ArtistWidget { } fn bind(&self, model: &ArtistModel, worker: Worker) { - let widget = imp::ArtistWidget::from_instance(self); + let widget = self.imp(); - if let Some(url) = model.image_url() { + if let Some(url) = model.image() { let avatar = widget.avatar.downgrade(); worker.send_local_task(async move { if let Some(avatar) = avatar.upgrade() { diff --git a/src/app/components/artist_details/artist_details.rs b/src/app/components/artist_details/artist_details.rs index 729a81f1..3d3fdd78 100644 --- a/src/app/components/artist_details/artist_details.rs +++ b/src/app/components/artist_details/artist_details.rs @@ -35,7 +35,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -55,15 +55,11 @@ glib::wrapper! { impl ArtistDetailsWidget { fn new() -> Self { display_add_css_provider(resource!("/components/artist_details.css")); - glib::Object::new(&[]).expect("Failed to create an instance of ArtistDetailsWidget") - } - - fn widget(&self) -> &imp::ArtistDetailsWidget { - imp::ArtistDetailsWidget::from_instance(self) + glib::Object::new() } fn top_tracks_widget(&self) -> >k::ListView { - self.widget().top_tracks.as_ref() + self.imp().top_tracks.as_ref() } fn set_loaded(&self) { @@ -75,7 +71,7 @@ impl ArtistDetailsWidget { where F: Fn() + 'static, { - self.widget() + self.imp() .scrolled_window .connect_edge_reached(move |_, pos| { if let gtk::PositionType::Bottom = pos { @@ -92,7 +88,7 @@ impl ArtistDetailsWidget { ) where F: Fn(String) + Clone + 'static, { - self.widget() + self.imp() .artist_releases .bind_model(Some(store.unsafe_store()), move |item| { let item = item.downcast_ref::().unwrap(); @@ -127,7 +123,7 @@ impl ArtistDetails { if let Some(store) = model.get_list_store() { widget.bind_artist_releases( worker.clone(), - &*store, + &store, clone!(@weak model => move |id| { model.open_album(id); }), diff --git a/src/app/components/details/album_header.css b/src/app/components/details/album_header.css index 4b209498..8bbf5924 100644 --- a/src/app/components/details/album_header.css +++ b/src/app/components/details/album_header.css @@ -1,15 +1,11 @@ -.album__header .title-4 label, .header__mobile .title-4 label { +.album__header .title-4 label { color: @window_fg_color; font-weight: bold; text-decoration: none; } -.album__header .title-4, .header__mobile .title-4 { - padding: 0; -} - -.album__header .title-4:hover, .header__mobile .title-4:hover { +.album__header .title-4:hover { border-radius: 6px; background-image: image(alpha(currentColor, 0.08)); } @@ -28,16 +24,13 @@ margin-bottom: 6px; } -.header__mobile .card { - margin-top: 12px; -} + clamp.details__clamp { background-color: @view_bg_color; box-shadow: inset 0px -1px 0px @borders; } headerbar.details__headerbar { - box-shadow: none; transition: background-color .3s ease; } @@ -52,5 +45,4 @@ headerbar.details__headerbar windowtitle { .details__headerbar.flat { background-color: @view_bg_color; -} - +} \ No newline at end of file diff --git a/src/app/components/details/album_header.rs b/src/app/components/details/album_header.rs index cf74daf4..f4bbb606 100644 --- a/src/app/components/details/album_header.rs +++ b/src/app/components/details/album_header.rs @@ -42,7 +42,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -62,39 +62,35 @@ glib::wrapper! { impl AlbumHeaderWidget { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of AlbumHeaderWidget") - } - - pub fn widget(&self) -> &imp::AlbumHeaderWidget { - imp::AlbumHeaderWidget::from_instance(self) + glib::Object::new() } pub fn connect_liked(&self, f: F) where F: Fn() + 'static, { - self.widget().like_button.connect_clicked(move |_| f()); + self.imp().like_button.connect_clicked(move |_| f()); } pub fn connect_info(&self, f: F) where F: Fn() + 'static, { - self.widget().info_button.connect_clicked(move |_| f()); + self.imp().info_button.connect_clicked(move |_| f()); } pub fn connect_artist_clicked(&self, f: F) where F: Fn() + 'static, { - self.widget().artist_button.connect_activate_link(move |_| { + self.imp().artist_button.connect_activate_link(move |_| { f(); glib::signal::Inhibit(true) }); } pub fn set_liked(&self, is_liked: bool) { - self.widget().like_button.set_icon_name(if is_liked { + self.imp().like_button.set_icon_name(if is_liked { "starred-symbolic" } else { "non-starred-symbolic" @@ -102,11 +98,11 @@ impl AlbumHeaderWidget { } pub fn set_artwork(&self, art: &gdk_pixbuf::Pixbuf) { - self.widget().album_art.set_from_pixbuf(Some(art)); + self.imp().album_art.set_from_pixbuf(Some(art)); } pub fn set_album_and_artist_and_year(&self, album: &str, artist: &str, year: Option) { - let widget = self.widget(); + let widget = self.imp(); widget.album_label.set_label(album); widget.artist_button_label.set_label(artist); match year { @@ -116,15 +112,10 @@ impl AlbumHeaderWidget { } pub fn set_centered(&self) { - let widget = self.widget(); + let widget = self.imp(); widget.album_label.set_halign(gtk::Align::Center); widget.album_label.set_justify(gtk::Justification::Center); widget.artist_button.set_halign(gtk::Align::Center); widget.year_label.set_halign(gtk::Align::Center); } - - pub fn hide_actions(&self) { - self.widget().like_button.set_visible(false); - self.widget().info_button.set_visible(false); - } } diff --git a/src/app/components/details/album_header.ui b/src/app/components/details/album_header.ui index b23f3f9c..e246ea41 100644 --- a/src/app/components/details/album_header.ui +++ b/src/app/components/details/album_header.ui @@ -10,8 +10,8 @@ 6 - hidden - center + hidden + center 160 @@ -36,7 +36,7 @@ @@ -45,7 +45,7 @@ 1 center vertical - 6 + 6 0 @@ -89,7 +89,7 @@ 1 0 @@ -107,5 +107,8 @@ + - + \ No newline at end of file diff --git a/src/app/components/details/details.rs b/src/app/components/details/details.rs index fcb36c33..46fe19b1 100644 --- a/src/app/components/details/details.rs +++ b/src/app/components/details/details.rs @@ -8,7 +8,7 @@ use super::release_details::ReleaseDetailsWindow; use super::DetailsModel; use crate::app::components::{ - Component, EventListener, HeaderBarComponent, HeaderBarWidget, Playlist, + Component, EventListener, HeaderBarComponent, HeaderBarWidget, Playlist, ScrollingHeaderWidget, }; use crate::app::dispatch::Worker; use crate::app::loader::ImageLoader; @@ -24,14 +24,11 @@ mod imp { #[template(resource = "/dev/alextren/Spot/components/details.ui")] pub struct AlbumDetailsWidget { #[template_child] - pub scrolled_window: TemplateChild, + pub scrolling_header: TemplateChild, #[template_child] pub headerbar: TemplateChild, - #[template_child] - pub header_revealer: TemplateChild, - #[template_child] pub header_widget: TemplateChild, @@ -49,7 +46,7 @@ mod imp { type ParentType = libadwaita::Bin; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -58,8 +55,8 @@ mod imp { } impl ObjectImpl for AlbumDetailsWidget { - fn constructed(&self, obj: &Self::Type) { - self.parent_constructed(obj); + fn constructed(&self) { + self.parent_constructed(); self.header_mobile.set_centered(); self.headerbar.add_classes(&["details__headerbar"]); } @@ -75,77 +72,45 @@ glib::wrapper! { impl AlbumDetailsWidget { fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of AlbumDetailsWidget") - } - - fn widget(&self) -> &imp::AlbumDetailsWidget { - imp::AlbumDetailsWidget::from_instance(self) + glib::Object::new() } - fn set_header_visible(&self, visible: bool) -> bool { - let widget = self.widget(); - let is_up_to_date = widget.header_revealer.reveals_child() == visible; - if !is_up_to_date { - widget.header_revealer.set_reveal_child(visible); - widget.headerbar.set_title_visible(true); - if visible { - widget.headerbar.add_classes(&["flat"]); - } else { - widget.headerbar.remove_classes(&["flat"]); - } + fn set_header_visible(&self, visible: bool) { + let widget = self.imp(); + widget.headerbar.set_title_visible(true); + if visible { + widget.headerbar.add_classes(&["flat"]); + } else { + widget.headerbar.remove_classes(&["flat"]); } - is_up_to_date } - fn connect_header_visibility(&self) { - self.set_header_visible(true); - - let scroll_controller = - gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::VERTICAL); - scroll_controller.connect_scroll( - clone!(@weak self as _self => @default-return gtk::Inhibit(false), move |_, _, dy| { - let visible = dy < 0f64; - gtk::Inhibit(!_self.set_header_visible(visible)) + fn connect_header(&self) { + self.set_header_visible(false); + self.imp().scrolling_header.connect_header_visibility( + clone!(@weak self as _self => move |visible| { + _self.set_header_visible(visible); }), ); - - let swipe_controller = gtk::GestureSwipe::new(); - swipe_controller.set_touch_only(true); - swipe_controller.set_propagation_phase(gtk::PropagationPhase::Capture); - swipe_controller.connect_swipe(clone!(@weak self as _self => move |_, _, dy| { - let visible = dy >= 0f64; - _self.set_header_visible(visible); - })); - - self.widget() - .scrolled_window - .add_controller(&scroll_controller); - self.add_controller(&swipe_controller); } fn connect_bottom_edge(&self, f: F) where F: Fn() + 'static, { - self.widget() - .scrolled_window - .connect_edge_reached(move |_, pos| { - if let gtk::PositionType::Bottom = pos { - f() - } - }); + self.imp().scrolling_header.connect_bottom_edge(f); } fn headerbar_widget(&self) -> &HeaderBarWidget { - self.widget().headerbar.as_ref() + self.imp().headerbar.as_ref() } fn album_tracks_widget(&self) -> >k::ListView { - self.widget().album_tracks.as_ref() + self.imp().album_tracks.as_ref() } fn set_loaded(&self) { - let context = self.style_context(); + let context = self.imp().scrolling_header.style_context(); context.add_class("container--loaded"); } @@ -153,48 +118,44 @@ impl AlbumDetailsWidget { where F: Fn() + Clone + 'static, { - self.widget().header_widget.connect_liked(f.clone()); - self.widget().header_mobile.connect_liked(f); + self.imp().header_widget.connect_liked(f.clone()); + self.imp().header_mobile.connect_liked(f); } fn connect_info(&self, f: F) where F: Fn() + Clone + 'static, { - self.widget().header_widget.connect_info(f.clone()); - self.widget().header_mobile.connect_info(f); + self.imp().header_widget.connect_info(f.clone()); + self.imp().header_mobile.connect_info(f); } fn set_liked(&self, is_liked: bool) { - self.widget().header_widget.set_liked(is_liked); - self.widget().header_mobile.set_liked(is_liked); + self.imp().header_widget.set_liked(is_liked); + self.imp().header_mobile.set_liked(is_liked); } fn set_album_and_artist_and_year(&self, album: &str, artist: &str, year: Option) { - self.widget() + self.imp() .header_widget .set_album_and_artist_and_year(album, artist, year); - self.widget() + self.imp() .header_mobile .set_album_and_artist_and_year(album, artist, year); - self.widget() - .headerbar - .set_title_and_subtitle(album, artist); + self.imp().headerbar.set_title_and_subtitle(album, artist); } fn set_artwork(&self, art: &gdk_pixbuf::Pixbuf) { - self.widget().header_widget.set_artwork(art); - self.widget().header_mobile.set_artwork(art); + self.imp().header_widget.set_artwork(art); + self.imp().header_mobile.set_artwork(art); } fn connect_artist_clicked(&self, f: F) where F: Fn() + Clone + 'static, { - self.widget() - .header_widget - .connect_artist_clicked(f.clone()); - self.widget().header_mobile.connect_artist_clicked(f); + self.imp().header_widget.connect_artist_clicked(f.clone()); + self.imp().header_mobile.connect_artist_clicked(f); } } @@ -231,7 +192,7 @@ impl Details { widget.connect_liked(clone!(@weak model => move || model.toggle_save_album())); - widget.connect_header_visibility(); + widget.connect_header(); widget.connect_bottom_edge(clone!(@weak model => move || { model.load_more(); diff --git a/src/app/components/details/details.ui b/src/app/components/details/details.ui index 02e92dad..55e1d491 100644 --- a/src/app/components/details/details.ui +++ b/src/app/components/details/details.ui @@ -12,13 +12,12 @@ - - - - 900 + + + - - slide-up + + 900 natural @@ -26,38 +25,23 @@ 0 crossfade - - - + vertical 12 - + - - - - - - never - 1 - 1 - 1 900 @@ -70,12 +54,12 @@ + - - + \ No newline at end of file diff --git a/src/app/components/details/mod.rs b/src/app/components/details/mod.rs index ae36dd5a..5c7f36ef 100644 --- a/src/app/components/details/mod.rs +++ b/src/app/components/details/mod.rs @@ -1,8 +1,7 @@ mod album_header; mod details; mod details_model; +mod release_details; -pub use album_header::AlbumHeaderWidget; pub use details::Details; pub use details_model::DetailsModel; -mod release_details; diff --git a/src/app/components/details/release_details.rs b/src/app/components/details/release_details.rs index 4226a433..ee54aea0 100644 --- a/src/app/components/details/release_details.rs +++ b/src/app/components/details/release_details.rs @@ -1,4 +1,3 @@ -use gtk::prelude::*; use gtk::subclass::prelude::*; use gtk::CompositeTemplate; use libadwaita::subclass::prelude::*; @@ -35,7 +34,7 @@ mod imp { type ParentType = libadwaita::Window; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -44,8 +43,8 @@ mod imp { } impl ObjectImpl for ReleaseDetailsWindow { - fn constructed(&self, obj: &Self::Type) { - self.parent_constructed(obj); + fn constructed(&self) { + self.parent_constructed(); } } @@ -60,11 +59,7 @@ glib::wrapper! { impl ReleaseDetailsWindow { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of ReleaseDetailsWindow") - } - - fn widget(&self) -> &imp::ReleaseDetailsWindow { - imp::ReleaseDetailsWindow::from_instance(self) + glib::Object::new() } #[allow(clippy::too_many_arguments)] @@ -77,7 +72,7 @@ impl ReleaseDetailsWindow { track_count: usize, copyright: &str, ) { - let widget = self.widget(); + let widget = self.imp(); widget .album_artist diff --git a/src/app/components/headerbar/widget.rs b/src/app/components/headerbar/widget.rs index 2b90a0b6..7ce34197 100644 --- a/src/app/components/headerbar/widget.rs +++ b/src/app/components/headerbar/widget.rs @@ -48,7 +48,7 @@ mod imp { type Interfaces = (gtk::Buildable,); fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -59,15 +59,9 @@ mod imp { impl ObjectImpl for HeaderBarWidget {} impl BuildableImpl for HeaderBarWidget { - fn add_child( - &self, - buildable: &Self::Type, - builder: >k::Builder, - child: &glib::Object, - type_: Option<&str>, - ) { + fn add_child(&self, builder: >k::Builder, child: &glib::Object, type_: Option<&str>) { if Some("root") == type_ { - self.parent_add_child(buildable, builder, child, type_); + self.parent_add_child(builder, child, type_); } else { self.main_header .set_title_widget(child.downcast_ref::()); @@ -86,46 +80,42 @@ glib::wrapper! { impl HeaderBarWidget { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of HeaderBarWidget") - } - - fn widget(&self) -> &imp::HeaderBarWidget { - imp::HeaderBarWidget::from_instance(self) + glib::Object::new() } pub fn connect_selection_start(&self, f: F) where F: Fn() + 'static, { - self.widget().start_selection.connect_clicked(move |_| f()); + self.imp().start_selection.connect_clicked(move |_| f()); } pub fn connect_select_all(&self, f: F) where F: Fn() + 'static, { - self.widget().select_all.connect_clicked(move |_| f()); + self.imp().select_all.connect_clicked(move |_| f()); } pub fn connect_selection_cancel(&self, f: F) where F: Fn() + 'static, { - self.widget().cancel.connect_clicked(move |_| f()); + self.imp().cancel.connect_clicked(move |_| f()); } pub fn connect_go_back(&self, f: F) where F: Fn() + 'static, { - self.widget().go_back.connect_clicked(move |_| f()); + self.imp().go_back.connect_clicked(move |_| f()); } pub fn bind_to_leaflet(&self, leaflet: &libadwaita::Leaflet) { leaflet .bind_property( "folded", - &*self.widget().main_header, + &*self.imp().main_header, "show-start-title-buttons", ) .build(); @@ -133,63 +123,63 @@ impl HeaderBarWidget { } pub fn set_can_go_back(&self, can_go_back: bool) { - self.widget().go_back.set_visible(can_go_back); + self.imp().go_back.set_visible(can_go_back); } pub fn set_selection_possible(&self, possible: bool) { - self.widget().start_selection.set_visible(possible); + self.imp().start_selection.set_visible(possible); } pub fn set_select_all_possible(&self, possible: bool) { - self.widget().select_all.set_visible(possible); + self.imp().select_all.set_visible(possible); } pub fn set_selection_active(&self, active: bool) { if active { - self.widget() + self.imp() .selection_title .set_title(&labels::n_songs_selected_label(0)); - self.widget().selection_title.show(); - self.widget().selection_header.show(); + self.imp().selection_title.show(); + self.imp().selection_header.show(); } else { - self.widget().selection_title.hide(); - self.widget().selection_header.hide(); + self.imp().selection_title.hide(); + self.imp().selection_header.hide(); } } pub fn set_selection_count(&self, count: usize) { - self.widget() + self.imp() .selection_title .set_title(&labels::n_songs_selected_label(count)); } pub fn add_classes(&self, classes: &[&str]) { - let context = self.widget().main_header.style_context(); + let context = self.imp().main_header.style_context(); for &class in classes { context.add_class(class); } } pub fn remove_classes(&self, classes: &[&str]) { - let context = self.widget().main_header.style_context(); + let context = self.imp().main_header.style_context(); for &class in classes { context.remove_class(class); } } pub fn set_title_visible(&self, visible: bool) { - self.widget().title.set_visible(visible); + self.imp().title.set_visible(visible); } pub fn set_title_and_subtitle(&self, title: &str, subtitle: &str) { - self.widget().title.set_title(title); - self.widget().title.set_subtitle(subtitle); + self.imp().title.set_title(title); + self.imp().title.set_subtitle(subtitle); } pub fn set_title(&self, title: Option<&str>) { - self.widget().title.set_visible(title.is_some()); + self.imp().title.set_visible(title.is_some()); if let Some(title) = title { - self.widget().title.set_title(title); + self.imp().title.set_title(title); } } } diff --git a/src/app/components/library/library.rs b/src/app/components/library/library.rs index cf97f578..74923a54 100644 --- a/src/app/components/library/library.rs +++ b/src/app/components/library/library.rs @@ -35,7 +35,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -54,14 +54,14 @@ glib::wrapper! { impl LibraryWidget { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of LibraryWidget") + glib::Object::new() } fn connect_bottom_edge(&self, f: F) where F: Fn() + 'static, { - imp::LibraryWidget::from_instance(self) + self.imp() .scrolled_window .connect_edge_reached(move |_, pos| { if let gtk::PositionType::Bottom = pos { @@ -74,9 +74,9 @@ impl LibraryWidget { where F: Fn(String) + Clone + 'static, { - imp::LibraryWidget::from_instance(self).flowbox.bind_model( - Some(store.unsafe_store()), - move |item| { + self.imp() + .flowbox + .bind_model(Some(store.unsafe_store()), move |item| { wrap_flowbox_item(item, |album_model| { let f = on_album_pressed.clone(); let album = AlbumWidget::for_model(album_model, worker.clone()); @@ -85,12 +85,11 @@ impl LibraryWidget { })); album }) - }, - ); + }); } pub fn status_page(&self) -> &libadwaita::StatusPage { - &imp::LibraryWidget::from_instance(self).status_page + &self.imp().status_page } } @@ -118,7 +117,7 @@ impl Library { fn bind_flowbox(&self) { self.widget.bind_albums( self.worker.clone(), - &*self.model.get_list_store().unwrap(), + &self.model.get_list_store().unwrap(), clone!(@weak self.model as model => move |id| { model.open_album(id); }), diff --git a/src/app/components/login/login.rs b/src/app/components/login/login.rs index ae6e4a29..62cc1af3 100644 --- a/src/app/components/login/login.rs +++ b/src/app/components/login/login.rs @@ -22,7 +22,7 @@ mod imp { pub username: TemplateChild, #[template_child] - pub password: TemplateChild, + pub password: TemplateChild, #[template_child] pub close_button: TemplateChild, @@ -41,7 +41,7 @@ mod imp { type ParentType = libadwaita::Window; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -61,15 +61,14 @@ glib::wrapper! { impl LoginWindow { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of LoginWindow") + glib::Object::new() } fn connect_close(&self, on_close: F) where F: Fn() + 'static, { - let widget = imp::LoginWindow::from_instance(self); - widget.close_button.connect_clicked(move |_| { + self.imp().close_button.connect_clicked(move |_| { on_close(); }); } @@ -78,8 +77,6 @@ impl LoginWindow { where SubmitFn: Fn(&str, &str) + Clone + 'static, { - let widget = imp::LoginWindow::from_instance(self); - let on_submit_clone = on_submit.clone(); let controller = gtk::EventControllerKey::new(); controller.set_propagation_phase(gtk::PropagationPhase::Capture); @@ -93,9 +90,9 @@ impl LoginWindow { } }), ); - self.add_controller(&controller); + self.add_controller(controller); - widget + self.imp() .login_button .connect_clicked(clone!(@weak self as _self => move |_| { _self.submit(&on_submit); @@ -103,7 +100,7 @@ impl LoginWindow { } fn show_auth_error(&self, shown: bool) { - let widget = imp::LoginWindow::from_instance(self); + let widget = self.imp(); widget.auth_error_container.set_reveal_child(shown); } @@ -111,7 +108,7 @@ impl LoginWindow { where SubmitFn: Fn(&str, &str), { - let widget = imp::LoginWindow::from_instance(self); + let widget = self.imp(); self.show_auth_error(false); @@ -161,14 +158,6 @@ impl Login { self.login_window.upcast_ref::() } - fn show_self_if_needed(&self) { - if self.model.try_autologin() { - self.window().close(); - } else { - self.show_self(); - } - } - fn show_self(&self) { self.window().set_transient_for(Some(&self.parent)); self.window().set_modal(true); @@ -198,9 +187,9 @@ impl EventListener for Login { self.reveal_error(); } AppEvent::Started => { - self.show_self_if_needed(); + self.model.try_autologin(); } - AppEvent::LoginEvent(LoginEvent::LogoutCompleted) => { + AppEvent::LoginEvent(LoginEvent::LogoutCompleted | LoginEvent::LoginShown) => { self.show_self(); } AppEvent::LoginEvent(LoginEvent::RefreshTokenCompleted { diff --git a/src/app/components/login/login.ui b/src/app/components/login/login.ui index 9175b67d..c106c229 100644 --- a/src/app/components/login/login.ui +++ b/src/app/components/login/login.ui @@ -1,7 +1,7 @@ - - + + - + \ No newline at end of file diff --git a/src/app/components/login/login_model.rs b/src/app/components/login/login_model.rs index cd3e73a9..033468f4 100644 --- a/src/app/components/login/login_model.rs +++ b/src/app/components/login/login_model.rs @@ -4,58 +4,70 @@ use gettextrs::*; use crate::app::credentials::Credentials; use crate::app::state::{LoginAction, TryLoginAction}; -use crate::app::{ActionDispatcher, AppAction}; +use crate::app::{ActionDispatcher, AppAction, Worker}; pub struct LoginModel { dispatcher: Box, + worker: Worker, } impl LoginModel { - pub fn new(dispatcher: Box) -> Self { - Self { dispatcher } + pub fn new(dispatcher: Box, worker: Worker) -> Self { + Self { dispatcher, worker } } - pub fn try_autologin(&self) -> bool { - if let Ok(creds) = Credentials::retrieve() { - let try_login_action = if creds.token_expired() { - TryLoginAction::Password { - username: creds.username, - password: creds.password, - } - } else { - TryLoginAction::Token { - username: creds.username, - token: creds.token, + pub fn try_autologin(&self) { + self.dispatcher.dispatch_async(Box::pin(async { + let action = match Credentials::retrieve().await { + Ok(creds) => LoginAction::TryLogin(if creds.token_expired() { + TryLoginAction::Password { + username: creds.username, + password: creds.password, + } + } else { + TryLoginAction::Token { + username: creds.username, + token: creds.token, + } + }), + Err(err) => { + warn!("Could not retrieve credentials: {}", err); + LoginAction::ShowLogin } }; - self.dispatcher - .dispatch(LoginAction::TryLogin(try_login_action).into()); - true - } else { - false - } + Some(action.into()) + })); } pub fn clear_saved_credentials(&self) { - let _ = Credentials::logout(); + self.worker.send_task(async { + let _ = Credentials::logout().await; + }); } pub fn save_token(&self, token: String, token_expiry_time: SystemTime) { - if let Ok(mut credentials) = Credentials::retrieve() { - credentials.token = token; - credentials.token_expiry_time = Some(token_expiry_time); - self.save_for_autologin(credentials); - } + self.worker.send_task(async move { + if let Ok(mut credentials) = Credentials::retrieve().await { + credentials.token = token; + credentials.token_expiry_time = Some(token_expiry_time); + if let Err(err) = credentials.save().await { + warn!("Could not save credentials: {}", err); + } + } + }); } pub fn save_for_autologin(&self, credentials: Credentials) { - if credentials.save().is_err() { - self.dispatcher - .dispatch(AppAction::ShowNotification(gettext( - // translators: This notification shows up right after login if the password could not be stored in the keyring (that is, GNOME's keyring aka seahorse, or any other libsecret compliant secret store). - "Could not save password. Make sure the session keyring is unlocked.", - ))); - } + self.dispatcher.dispatch_async(Box::pin(async move { + let Err(err) = credentials.save().await else { + return None; + }; + warn!("Could not save credentials: {}", err); + Some(AppAction::ShowNotification(gettext( + // translators: This notification shows up right after login if the password could not be stored in the keyring (that is, GNOME's keyring aka seahorse, or any other libsecret compliant secret store). + "Could not save password. Make sure the session keyring is unlocked.", + ))) + })); } pub fn login(&self, username: String, password: String) { diff --git a/src/app/components/mod.rs b/src/app/components/mod.rs index 86d4809e..148425e9 100644 --- a/src/app/components/mod.rs +++ b/src/app/components/mod.rs @@ -79,15 +79,21 @@ pub use selection::*; mod headerbar; pub use headerbar::*; +mod scrolling_header; +pub use scrolling_header::*; + pub mod utils; pub mod labels; -pub mod sidebar_listbox; + +pub mod sidebar; pub fn expose_widgets() { playback::expose_widgets(); selection::expose_widgets(); headerbar::expose_widgets(); + playlist_details::expose_widgets(); + scrolling_header::expose_widgets(); } impl dyn ActionDispatcher { @@ -112,7 +118,7 @@ impl dyn ActionDispatcher { Err(SpotifyApiError::NoToken) => vec![], Err(SpotifyApiError::InvalidToken) => { let mut retried = call().await.unwrap_or_else(|_| Vec::new()); - retried.push(LoginAction::RefreshToken.into()); + retried.insert(0, LoginAction::RefreshToken.into()); retried } Err(err) => { diff --git a/src/app/components/navigation/factory.rs b/src/app/components/navigation/factory.rs index 7d7cbc7b..d8f6564f 100644 --- a/src/app/components/navigation/factory.rs +++ b/src/app/components/navigation/factory.rs @@ -1,5 +1,6 @@ use std::rc::Rc; +use crate::app::components::sidebar::{Sidebar, SidebarModel}; use crate::app::components::*; use crate::app::state::SelectionContext; use crate::app::{ActionDispatcher, AppModel, Worker}; @@ -41,12 +42,14 @@ impl ScreenFactory { ) } - pub fn make_saved_playlists_model(&self) -> SavedPlaylistsModel { - SavedPlaylistsModel::new(Rc::clone(&self.app_model), self.dispatcher.box_clone()) + pub fn make_sidebar(&self, listbox: gtk::ListBox) -> impl ListenerComponent { + let model = SidebarModel::new(Rc::clone(&self.app_model), self.dispatcher.box_clone()); + Sidebar::new(listbox, Rc::new(model)) } pub fn make_saved_playlists(&self) -> impl ListenerComponent { - let model = self.make_saved_playlists_model(); + let model = + SavedPlaylistsModel::new(Rc::clone(&self.app_model), self.dispatcher.box_clone()); let screen_model = DefaultHeaderBarModel::new( Some(gettext("Playlists")), None, @@ -134,16 +137,7 @@ impl ScreenFactory { Rc::clone(&self.app_model), self.dispatcher.box_clone(), )); - let screen_model = SimpleHeaderBarModelWrapper::new( - Rc::clone(&model), - Rc::clone(&self.app_model), - self.dispatcher.box_clone(), - ); - StandardScreen::new( - PlaylistDetails::new(model, self.worker.clone()), - &self.leaflet, - Rc::new(screen_model), - ) + PlaylistDetails::new(model, self.worker.clone()) } pub fn make_user_details(&self, id: String) -> impl ListenerComponent { diff --git a/src/app/components/navigation/home.rs b/src/app/components/navigation/home.rs index 313404e2..1c2e62f3 100644 --- a/src/app/components/navigation/home.rs +++ b/src/app/components/navigation/home.rs @@ -1,153 +1,64 @@ -use gettextrs::*; use gtk::prelude::*; -use crate::app::components::sidebar_listbox::{SideBarItem, SideBarRow}; -use crate::app::components::{Component, EventListener, SavedPlaylistsModel, ScreenFactory}; -use crate::app::models::AlbumModel; +use crate::app::components::sidebar::SidebarDestination; +use crate::app::components::{Component, EventListener, ScreenFactory}; use crate::app::{AppEvent, BrowserEvent}; -const LIBRARY: &str = "library"; -const SAVED_TRACKS: &str = "saved_tracks"; -const NOW_PLAYING: &str = "now_playing"; -const SAVED_PLAYLISTS: &str = "saved_playlists"; -const NUM_FIXED_ENTRIES: u32 = 5; -const NUM_PLAYLISTS: usize = 20; - -fn add_to_stack_and_listbox( - stack: >k::Stack, - list_store: &gio::ListStore, - widget: >k::Widget, - name: &str, - title: &str, - icon_name: &str, - grayed_out: bool, -) { - stack.add_titled(widget, Option::from(name), title); - list_store.append(&SideBarItem::new(name, title, icon_name, grayed_out)) -} - -fn make_playlist_item(playlist_item: AlbumModel) -> SideBarItem { - let mut title = playlist_item.album_title(); - if title.is_empty() { - title = gettext("Unnamed playlist"); - } - - let id = playlist_item.uri(); - - SideBarItem::new(id.as_str(), &title, "playlist2-symbolic", false) -} - pub struct HomePane { stack: gtk::Stack, - listbox: gtk::ListBox, - list_store: gio::ListStore, components: Vec>, - saved_playlists_model: SavedPlaylistsModel, } impl HomePane { - pub fn new( - listbox: gtk::ListBox, - screen_factory: &ScreenFactory, - list_store: gio::ListStore, - ) -> Self { + pub fn new(listbox: gtk::ListBox, screen_factory: &ScreenFactory) -> Self { let library = screen_factory.make_library(); let saved_playlists = screen_factory.make_saved_playlists(); let saved_tracks = screen_factory.make_saved_tracks(); let now_playing = screen_factory.make_now_playing(); + let sidebar = screen_factory.make_sidebar(listbox); - let saved_playlists_model = screen_factory.make_saved_playlists_model(); let stack = gtk::Stack::new(); stack.set_transition_type(gtk::StackTransitionType::Crossfade); - add_to_stack_and_listbox( - &stack, - &list_store, + + let dest = SidebarDestination::Library; + stack.add_titled( library.get_root_widget(), - LIBRARY, - // translators: This is a sidebar entry to browse to saved albums. - &gettext("Library"), - "library-music-symbolic", - false, + Option::from(dest.id()), + &dest.title(), ); - add_to_stack_and_listbox( - &stack, - &list_store, + + let dest = SidebarDestination::SavedTracks; + stack.add_titled( saved_tracks.get_root_widget(), - SAVED_TRACKS, - // translators: This is a sidebar entry to browse to saved tracks. - &gettext("Saved tracks"), - "starred-symbolic", - false, + Option::from(dest.id()), + &dest.title(), ); - add_to_stack_and_listbox( - &stack, - &list_store, - now_playing.get_root_widget(), - NOW_PLAYING, - &gettext("Now playing"), - "music-queue-symbolic", - false, - ); - list_store.append(&SideBarItem::new( - SAVED_PLAYLISTS, - // translators: This is a sidebar entry that marks that the entries below are playlists. - &gettext("Playlists"), - "", - true, - )); - add_to_stack_and_listbox( - &stack, - &list_store, + + let dest = SidebarDestination::SavedPlaylists; + stack.add_titled( saved_playlists.get_root_widget(), - SAVED_PLAYLISTS, - // translators: This is a sidebar entry to browse to saved playlists. - &gettext("All Playlists"), - "view-app-grid-symbolic", - false, + Option::from(dest.id()), + &dest.title(), + ); + + let dest = SidebarDestination::NowPlaying; + stack.add_titled( + now_playing.get_root_widget(), + Option::from(dest.id()), + &dest.title(), ); Self { stack, - listbox, - list_store, components: vec![ + Box::new(sidebar), Box::new(library), Box::new(saved_playlists), Box::new(saved_tracks), Box::new(now_playing), ], - saved_playlists_model, } } - - pub fn connect_navigated(&self, f: F) { - let model = self.saved_playlists_model.clone(); - self.listbox - .connect_row_activated(clone!(@weak self.stack as stack => move |_, row| { - let id = row.downcast_ref::().unwrap().id(); - match id.as_str() { - LIBRARY | SAVED_TRACKS | NOW_PLAYING | SAVED_PLAYLISTS => { - stack.set_visible_child_name(&id); - f(); - }, - _ => model.open_playlist(id), - } - })); - } - - fn update_playlists_in_sidebar(&mut self) { - let playlists = self.saved_playlists_model.get_playlists(); - let vec: Vec = playlists - .iter() - .take(NUM_PLAYLISTS) - .map(make_playlist_item) - .collect(); - self.list_store.splice( - NUM_FIXED_ENTRIES, - self.list_store.n_items() - NUM_FIXED_ENTRIES, - vec.as_slice(), - ); - } } impl Component for HomePane { @@ -164,10 +75,11 @@ impl EventListener for HomePane { fn on_event(&mut self, event: &AppEvent) { match event { AppEvent::NowPlayingShown => { - self.stack.set_visible_child_name("now_playing"); + self.stack + .set_visible_child_name(SidebarDestination::NowPlaying.id()); } - AppEvent::BrowserEvent(BrowserEvent::SavedPlaylistsUpdated) => { - self.update_playlists_in_sidebar(); + AppEvent::BrowserEvent(BrowserEvent::HomeVisiblePageChanged(page)) => { + self.stack.set_visible_child_name(page); } _ => {} } diff --git a/src/app/components/navigation/navigation.rs b/src/app/components/navigation/navigation.rs index 44b95d5f..879350c5 100644 --- a/src/app/components/navigation/navigation.rs +++ b/src/app/components/navigation/navigation.rs @@ -13,7 +13,6 @@ pub struct Navigation { leaflet: libadwaita::Leaflet, navigation_stack: gtk::Stack, home_listbox: gtk::ListBox, - home_list_store: gio::ListStore, screen_factory: ScreenFactory, children: Vec>, } @@ -24,7 +23,6 @@ impl Navigation { leaflet: libadwaita::Leaflet, navigation_stack: gtk::Stack, home_listbox: gtk::ListBox, - home_list_store: gio::ListStore, screen_factory: ScreenFactory, ) -> Self { let model = Rc::new(model); @@ -50,33 +48,27 @@ impl Navigation { leaflet, navigation_stack, home_listbox, - home_list_store, screen_factory, children: vec![], } } fn make_home(&self) -> Box { - let home = HomePane::new( + Box::new(HomePane::new( self.home_listbox.clone(), &self.screen_factory, - self.home_list_store.clone(), - ); - - home.connect_navigated( - clone!(@weak self.model as model, @weak self.leaflet as leaflet => move || { - leaflet.navigate(NavigationDirection::Forward); - model.go_home(); - }), - ); - - Box::new(home) + )) } fn show_navigation(&self) { self.leaflet.navigate(NavigationDirection::Back); } + fn pop_to_home(&mut self) { + self.leaflet.navigate(NavigationDirection::Forward); + self.pop_to(&ScreenName::Home); + } + fn push_screen(&mut self, name: &ScreenName) { let component: Box = match name { ScreenName::Home => self.make_home(), @@ -148,6 +140,9 @@ impl EventListener for Navigation { AppEvent::BrowserEvent(BrowserEvent::NavigationPoppedTo(name)) => { self.pop_to(name); } + AppEvent::BrowserEvent(BrowserEvent::HomeVisiblePageChanged(_)) => { + self.pop_to_home(); + } _ => {} }; for child in self.children.iter_mut() { diff --git a/src/app/components/navigation/navigation_model.rs b/src/app/components/navigation/navigation_model.rs index 761327a5..0051787d 100644 --- a/src/app/components/navigation/navigation_model.rs +++ b/src/app/components/navigation/navigation_model.rs @@ -16,11 +16,6 @@ impl NavigationModel { } } - pub fn go_home(&self) { - self.dispatcher - .dispatch(BrowserAction::NavigationPopTo(ScreenName::Home).into()) - } - pub fn visible_child_name(&self) -> impl Deref + '_ { self.app_model.map_state(|s| s.browser.current_screen()) } diff --git a/src/app/components/notification/mod.rs b/src/app/components/notification/mod.rs index becb9848..a0f67bb2 100644 --- a/src/app/components/notification/mod.rs +++ b/src/app/components/notification/mod.rs @@ -1,5 +1,7 @@ use crate::app::components::EventListener; use crate::app::AppEvent; +use gettextrs::*; +use glib::ToVariant; pub struct Notification { toast_overlay: libadwaita::ToastOverlay, @@ -15,7 +17,22 @@ impl Notification { .title(content) .timeout(4) .build(); - self.toast_overlay.add_toast(&toast); + self.toast_overlay.add_toast(toast); + } + + fn show_playlist_created(&self, id: &str) { + // translators: This is a notification that pop ups when a new playlist is created. It includes the name of that playlist. + let message = gettext("New playlist created."); + // translators: This is a label in the notification shown after creating a new playlist. If it is clicked, the new playlist will be opened. + let label = gettext("View"); + let toast = libadwaita::Toast::builder() + .title(message) + .timeout(4) + .action_name("app.open_playlist") + .button_label(label) + .action_target(&id.to_variant()) + .build(); + self.toast_overlay.add_toast(toast); } } @@ -23,6 +40,8 @@ impl EventListener for Notification { fn on_event(&mut self, event: &AppEvent) { if let AppEvent::NotificationShown(content) = event { self.show(content) + } else if let AppEvent::PlaylistCreatedNotificationShown(id) = event { + self.show_playlist_created(id) } } } diff --git a/src/app/components/now_playing/now_playing.rs b/src/app/components/now_playing/now_playing.rs index 17f119da..c487983e 100644 --- a/src/app/components/now_playing/now_playing.rs +++ b/src/app/components/now_playing/now_playing.rs @@ -29,7 +29,7 @@ mod imp { type ParentType = libadwaita::Bin; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -48,14 +48,14 @@ glib::wrapper! { impl NowPlayingWidget { fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of NowPlayingWidget") + glib::Object::new() } fn connect_bottom_edge(&self, f: F) where F: Fn() + 'static, { - imp::NowPlayingWidget::from_instance(self) + self.imp() .scrolled_window .connect_edge_reached(move |_, pos| { if let gtk::PositionType::Bottom = pos { @@ -65,9 +65,7 @@ impl NowPlayingWidget { } fn song_list_widget(&self) -> >k::ListView { - imp::NowPlayingWidget::from_instance(self) - .song_list - .as_ref() + self.imp().song_list.as_ref() } } diff --git a/src/app/components/playback/playback_controls.rs b/src/app/components/playback/playback_controls.rs index 6038f99a..613626bc 100644 --- a/src/app/components/playback/playback_controls.rs +++ b/src/app/components/playback/playback_controls.rs @@ -35,7 +35,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -67,16 +67,13 @@ impl PlaybackControlsWidget { }; let tooltip_text = Some(translated_tooltip.as_str()); - let playback_control = imp::PlaybackControlsWidget::from_instance(self); - + let playback_control = self.imp(); playback_control.play_pause.set_icon_name(playback_icon); playback_control.play_pause.set_tooltip_text(tooltip_text); } pub fn set_shuffled(&self, shuffled: bool) { - imp::PlaybackControlsWidget::from_instance(self) - .shuffle - .set_active(shuffled); + self.imp().shuffle.set_active(shuffled); } pub fn set_repeat_mode(&self, mode: RepeatMode) { @@ -86,53 +83,41 @@ impl PlaybackControlsWidget { RepeatMode::None => "media-playlist-consecutive-symbolic", }; - imp::PlaybackControlsWidget::from_instance(self) - .repeat - .set_icon_name(repeat_mode_icon); + self.imp().repeat.set_icon_name(repeat_mode_icon); } pub fn connect_play_pause(&self, f: F) where F: Fn() + 'static, { - imp::PlaybackControlsWidget::from_instance(self) - .play_pause - .connect_clicked(move |_| f()); + self.imp().play_pause.connect_clicked(move |_| f()); } pub fn connect_prev(&self, f: F) where F: Fn() + 'static, { - imp::PlaybackControlsWidget::from_instance(self) - .prev - .connect_clicked(move |_| f()); + self.imp().prev.connect_clicked(move |_| f()); } pub fn connect_next(&self, f: F) where F: Fn() + 'static, { - imp::PlaybackControlsWidget::from_instance(self) - .next - .connect_clicked(move |_| f()); + self.imp().next.connect_clicked(move |_| f()); } pub fn connect_shuffle(&self, f: F) where F: Fn() + 'static, { - imp::PlaybackControlsWidget::from_instance(self) - .shuffle - .connect_clicked(move |_| f()); + self.imp().shuffle.connect_clicked(move |_| f()); } pub fn connect_repeat(&self, f: F) where F: Fn() + 'static, { - imp::PlaybackControlsWidget::from_instance(self) - .repeat - .connect_clicked(move |_| f()); + self.imp().repeat.connect_clicked(move |_| f()); } } diff --git a/src/app/components/playback/playback_info.rs b/src/app/components/playback/playback_info.rs index a6d4dff6..f18e8813 100644 --- a/src/app/components/playback/playback_info.rs +++ b/src/app/components/playback/playback_info.rs @@ -24,7 +24,7 @@ mod imp { type ParentType = gtk::Button; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -43,7 +43,7 @@ glib::wrapper! { impl PlaybackInfoWidget { pub fn set_title_and_artist(&self, title: &str, artist: &str) { - let widget = imp::PlaybackInfoWidget::from_instance(self); + let widget = self.imp(); let title = glib::markup_escape_text(title); let artist = glib::markup_escape_text(artist); let label = format!("{}\n{}", title.as_str(), artist.as_str()); @@ -51,7 +51,7 @@ impl PlaybackInfoWidget { } pub fn reset_info(&self) { - let widget = imp::PlaybackInfoWidget::from_instance(self); + let widget = self.imp(); widget .current_song_info // translators: Short text displayed instead of a song title when nothing plays @@ -65,14 +65,10 @@ impl PlaybackInfoWidget { } pub fn set_info_visible(&self, visible: bool) { - imp::PlaybackInfoWidget::from_instance(self) - .current_song_info - .set_visible(visible); + self.imp().current_song_info.set_visible(visible); } pub fn set_artwork(&self, art: &gdk_pixbuf::Pixbuf) { - imp::PlaybackInfoWidget::from_instance(self) - .playing_image - .set_from_pixbuf(Some(art)); + self.imp().playing_image.set_from_pixbuf(Some(art)); } } diff --git a/src/app/components/playback/playback_widget.rs b/src/app/components/playback/playback_widget.rs index 073b1431..ff2410aa 100644 --- a/src/app/components/playback/playback_widget.rs +++ b/src/app/components/playback/playback_widget.rs @@ -49,7 +49,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -58,8 +58,8 @@ mod imp { } impl ObjectImpl for PlaybackWidget { - fn constructed(&self, obj: &Self::Type) { - self.parent_constructed(obj); + fn constructed(&self) { + self.parent_constructed(); self.now_playing_mobile.set_info_visible(false); self.now_playing.set_info_visible(true); display_add_css_provider(resource!("/components/playback.css")); @@ -76,19 +76,19 @@ glib::wrapper! { impl PlaybackWidget { pub fn set_title_and_artist(&self, title: &str, artist: &str) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.now_playing.set_title_and_artist(title, artist); } pub fn reset_info(&self) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.now_playing.reset_info(); widget.now_playing_mobile.reset_info(); self.set_song_duration(None); } fn set_artwork(&self, image: &gdk_pixbuf::Pixbuf) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.now_playing.set_artwork(image); widget.now_playing_mobile.set_artwork(image); } @@ -105,7 +105,7 @@ impl PlaybackWidget { } pub fn set_song_duration(&self, duration: Option) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); let class = "seek-bar--active"; let style_context = widget.seek_bar.style_context(); if let Some(duration) = duration { @@ -127,13 +127,13 @@ impl PlaybackWidget { } pub fn set_seek_position(&self, pos: f64) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.seek_bar.set_value(pos); widget.track_position.set_text(&format_duration(pos)); } pub fn increment_seek_position(&self) { - let value = imp::PlaybackWidget::from_instance(self).seek_bar.value() + 1_000.0; + let value = self.imp().seek_bar.value() + 1_000.0; self.set_seek_position(value); } @@ -141,7 +141,7 @@ impl PlaybackWidget { where F: Fn() + Clone + 'static, { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); let f_clone = f.clone(); widget.now_playing.connect_clicked(move |_| f_clone()); widget.now_playing_mobile.connect_clicked(move |_| f()); @@ -152,11 +152,11 @@ impl PlaybackWidget { Seek: Fn(u32) + Clone + 'static, { let debouncer = Debouncer::new(); - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.seek_bar.set_increments(5_000.0, 10_000.0); widget.seek_bar.connect_change_value( clone!(@weak self as _self => @default-return glib::signal::Inhibit(false), move |_, _, requested| { - imp::PlaybackWidget::from_instance(&_self) + _self.imp() .track_position .set_text(&format_duration(requested)); let seek = seek.clone(); @@ -167,7 +167,7 @@ impl PlaybackWidget { } pub fn set_playing(&self, is_playing: bool) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.controls.set_playing(is_playing); widget.controls_mobile.set_playing(is_playing); if is_playing { @@ -180,19 +180,19 @@ impl PlaybackWidget { } pub fn set_repeat_mode(&self, mode: RepeatMode) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.controls.set_repeat_mode(mode); widget.controls_mobile.set_repeat_mode(mode); } pub fn set_shuffled(&self, shuffled: bool) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.controls.set_shuffled(shuffled); widget.controls_mobile.set_shuffled(shuffled); } pub fn set_seekbar_visible(&self, visible: bool) { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.seek_bar.set_visible(visible); } @@ -200,7 +200,7 @@ impl PlaybackWidget { where F: Fn() + Clone + 'static, { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.controls.connect_play_pause(f.clone()); widget.controls_mobile.connect_play_pause(f); } @@ -209,7 +209,7 @@ impl PlaybackWidget { where F: Fn() + Clone + 'static, { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.controls.connect_prev(f.clone()); widget.controls_mobile.connect_prev(f); } @@ -218,7 +218,7 @@ impl PlaybackWidget { where F: Fn() + Clone + 'static, { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.controls.connect_next(f.clone()); widget.controls_mobile.connect_next(f); } @@ -227,7 +227,7 @@ impl PlaybackWidget { where F: Fn() + Clone + 'static, { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.controls.connect_shuffle(f.clone()); widget.controls_mobile.connect_shuffle(f); } @@ -236,7 +236,7 @@ impl PlaybackWidget { where F: Fn() + Clone + 'static, { - let widget = imp::PlaybackWidget::from_instance(self); + let widget = self.imp(); widget.controls.connect_repeat(f.clone()); widget.controls_mobile.connect_repeat(f); } diff --git a/src/app/components/player_notifier.rs b/src/app/components/player_notifier.rs index e2e5aa35..7b67dbec 100644 --- a/src/app/components/player_notifier.rs +++ b/src/app/components/player_notifier.rs @@ -35,6 +35,9 @@ impl EventListener for PlayerNotifier { AppEvent::PlaybackEvent(PlaybackEvent::TrackChanged(id)) => { SpotifyId::from_base62(id).ok().map(Command::PlayerLoad) } + AppEvent::PlaybackEvent(PlaybackEvent::Preload(id)) => { + SpotifyId::from_base62(id).ok().map(Command::PlayerPreload) + } AppEvent::PlaybackEvent(PlaybackEvent::TrackSeeked(position)) => { Some(Command::PlayerSeek(*position)) } diff --git a/src/app/components/playlist/playlist.rs b/src/app/components/playlist/playlist.rs index 6e7434d2..e6e7a12c 100644 --- a/src/app/components/playlist/playlist.rs +++ b/src/app/components/playlist/playlist.rs @@ -73,7 +73,6 @@ pub trait PlaylistModel { pub struct Playlist { animator: AnimatorDefault, listview: gtk::ListView, - _press_gesture: gtk::GestureLongPress, model: Rc, } @@ -83,7 +82,7 @@ where { pub fn new(listview: gtk::ListView, model: Rc, worker: Worker) -> Self { let list_model = model.song_list_model(); - let selection_model = gtk::NoSelection::new(Some(&list_model)); + let selection_model = gtk::NoSelection::new(Some(list_model.clone())); let factory = gtk::SignalListItemFactory::new(); let style_context = listview.style_context(); @@ -129,17 +128,16 @@ where })); let press_gesture = gtk::GestureLongPress::new(); - listview.add_controller(&press_gesture); press_gesture.set_touch_only(false); press_gesture.set_propagation_phase(gtk::PropagationPhase::Capture); press_gesture.connect_pressed(clone!(@weak model => move |_, _, _| { model.enable_selection(); })); + listview.add_controller(press_gesture); Self { animator: AnimatorDefault::ease_in_out_animator(), listview, - _press_gesture: press_gesture, model, } } diff --git a/src/app/components/playlist/song.rs b/src/app/components/playlist/song.rs index c37a8f96..bbf19c52 100644 --- a/src/app/components/playlist/song.rs +++ b/src/app/components/playlist/song.rs @@ -4,6 +4,8 @@ use crate::app::models::SongModel; use crate::app::Worker; use gio::MenuModel; +use glib::subclass::InitializingObject; + use gtk::prelude::*; use gtk::subclass::prelude::*; use gtk::CompositeTemplate; @@ -49,30 +51,18 @@ mod imp { type ParentType = gtk::Grid; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } - fn instance_init(obj: &glib::subclass::InitializingObject) { + fn instance_init(obj: &InitializingObject) { obj.init_template(); } } lazy_static! { static ref PROPERTIES: [glib::ParamSpec; 2] = [ - glib::ParamSpecBoolean::new( - "playing", - "Playing", - "", - false, - glib::ParamFlags::READWRITE - ), - glib::ParamSpecBoolean::new( - "selected", - "Selected", - "", - false, - glib::ParamFlags::READWRITE, - ), + glib::ParamSpecBoolean::builder("playing").build(), + glib::ParamSpecBoolean::builder("selected").build() ]; } @@ -81,19 +71,13 @@ mod imp { &*PROPERTIES } - fn set_property( - &self, - obj: &Self::Type, - _id: usize, - value: &glib::Value, - pspec: &glib::ParamSpec, - ) { + fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { match pspec.name() { "playing" => { let is_playing = value .get() .expect("type conformity checked by `Object::set_property`"); - let context = obj.style_context(); + let context = self.obj().style_context(); if is_playing { context.add_class(SONG_CLASS); } else { @@ -110,21 +94,21 @@ mod imp { } } - fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { + fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { match pspec.name() { - "playing" => obj.style_context().has_class(SONG_CLASS).to_value(), + "playing" => self.obj().style_context().has_class(SONG_CLASS).to_value(), "selected" => self.song_checkbox.is_active().to_value(), _ => unimplemented!(), } } - fn constructed(&self, obj: &Self::Type) { - self.parent_constructed(obj); + fn constructed(&self) { + self.parent_constructed(); self.song_checkbox.set_sensitive(false); } - fn dispose(&self, obj: &Self::Type) { - while let Some(child) = obj.first_child() { + fn dispose(&self) { + while let Some(child) = self.obj().first_child() { child.unparent(); } } @@ -141,11 +125,7 @@ glib::wrapper! { impl SongWidget { pub fn new() -> Self { display_add_css_provider(resource!("/components/song.css")); - glib::Object::new(&[]).expect("Failed to create an instance of SongWidget") - } - - fn widget(&self) -> &imp::SongWidget { - imp::SongWidget::from_instance(self) + glib::Object::new() } pub fn set_actions(&self, actions: Option<&gio::ActionGroup>) { @@ -154,7 +134,7 @@ impl SongWidget { pub fn set_menu(&self, menu: Option<&MenuModel>) { if menu.is_some() { - let widget = self.widget(); + let widget = self.imp(); widget.menu_btn.set_menu_model(menu); widget .menu_btn @@ -174,7 +154,7 @@ impl SongWidget { } fn set_image(&self, pixbuf: Option<&gdk_pixbuf::Pixbuf>) { - self.widget().song_cover.set_from_pixbuf(pixbuf); + self.imp().song_cover.set_from_pixbuf(pixbuf); } pub fn set_art(&self, model: &SongModel, worker: Worker) { @@ -191,7 +171,7 @@ impl SongWidget { } pub fn bind(&self, model: &SongModel, worker: Worker, show_cover: bool) { - let widget = self.widget(); + let widget = self.imp(); model.bind_title(&*widget.song_title, "label"); model.bind_artist(&*widget.song_artist, "label"); diff --git a/src/app/components/playlist/song.ui b/src/app/components/playlist/song.ui index 341f93a5..87b0818d 100644 --- a/src/app/components/playlist/song.ui +++ b/src/app/components/playlist/song.ui @@ -67,7 +67,7 @@ 1 1 - 3 + 2 1 0 diff --git a/src/app/components/playlist_details/mod.rs b/src/app/components/playlist_details/mod.rs index 741938a0..9680fa6c 100644 --- a/src/app/components/playlist_details/mod.rs +++ b/src/app/components/playlist_details/mod.rs @@ -1,5 +1,13 @@ mod playlist_details; mod playlist_details_model; +mod playlist_header; +mod playlist_headerbar; pub use playlist_details::*; pub use playlist_details_model::*; + +use glib::StaticType; + +pub fn expose_widgets() { + playlist_headerbar::PlaylistHeaderBarWidget::static_type(); +} diff --git a/src/app/components/playlist_details/playlist_details.rs b/src/app/components/playlist_details/playlist_details.rs index ad78c4f5..c40e5073 100644 --- a/src/app/components/playlist_details/playlist_details.rs +++ b/src/app/components/playlist_details/playlist_details.rs @@ -3,12 +3,16 @@ use gtk::subclass::prelude::*; use gtk::CompositeTemplate; use std::rc::Rc; +use super::playlist_header::PlaylistHeaderWidget; +use super::playlist_headerbar::PlaylistHeaderBarWidget; use super::PlaylistDetailsModel; -use crate::app::components::AlbumHeaderWidget; -use crate::app::components::{Component, EventListener, Playlist}; +use crate::app::components::{ + Component, EventListener, Playlist, PlaylistModel, ScrollingHeaderWidget, +}; use crate::app::dispatch::Worker; use crate::app::loader::ImageLoader; +use crate::app::state::SelectionEvent; use crate::app::{AppEvent, BrowserEvent}; use libadwaita::subclass::prelude::BinImpl; @@ -20,16 +24,16 @@ mod imp { #[template(resource = "/dev/alextren/Spot/components/playlist_details.ui")] pub struct PlaylistDetailsWidget { #[template_child] - pub scrolled_window: TemplateChild, + pub headerbar: TemplateChild, #[template_child] - pub header_revealer: TemplateChild, + pub scrolling_header: TemplateChild, #[template_child] - pub header_widget: TemplateChild, + pub header_widget: TemplateChild, #[template_child] - pub header_mobile: TemplateChild, + pub header_mobile: TemplateChild, #[template_child] pub tracks: TemplateChild, @@ -42,7 +46,7 @@ mod imp { type ParentType = libadwaita::Bin; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -51,11 +55,15 @@ mod imp { } impl ObjectImpl for PlaylistDetailsWidget { - fn constructed(&self, obj: &Self::Type) { - self.parent_constructed(obj); + fn constructed(&self) { + self.parent_constructed(); self.header_mobile.set_centered(); - self.header_mobile.hide_actions(); - self.header_widget.hide_actions(); + self.header_widget.set_grows_automatically(); + self.header_widget + .entry() + .bind_property("text", self.header_mobile.entry(), "text") + .flags(glib::BindingFlags::BIDIRECTIONAL) + .build(); } } @@ -69,81 +77,110 @@ glib::wrapper! { impl PlaylistDetailsWidget { fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of PlaylistDetailsWidget") - } - - fn widget(&self) -> &imp::PlaylistDetailsWidget { - imp::PlaylistDetailsWidget::from_instance(self) + glib::Object::new() } fn playlist_tracks_widget(&self) -> >k::ListView { - self.widget().tracks.as_ref() + self.imp().tracks.as_ref() } fn connect_bottom_edge(&self, f: F) where F: Fn() + 'static, { - self.widget() - .scrolled_window - .connect_edge_reached(move |_, pos| { - if let gtk::PositionType::Bottom = pos { - f() - } - }); - } - - fn set_header_visible(&self, visible: bool) -> bool { - let widget = self.widget(); - let is_up_to_date = widget.header_revealer.reveals_child() == visible; - if !is_up_to_date { - widget.header_revealer.set_reveal_child(visible); + self.imp().scrolling_header.connect_bottom_edge(f); + } + + fn set_header_visible(&self, visible: bool) { + let widget = self.imp(); + widget.headerbar.set_title_visible(true); + if visible { + widget.headerbar.add_classes(&["flat"]); + } else { + widget.headerbar.remove_classes(&["flat"]); } - is_up_to_date } fn connect_header(&self) { - self.set_header_visible(true); - - let scroll_controller = - gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::VERTICAL); - scroll_controller.connect_scroll( - clone!(@weak self as _self => @default-return gtk::Inhibit(false), move |_, _, dy| { - gtk::Inhibit(!_self.set_header_visible(dy < 0f64)) + self.set_header_visible(false); + self.imp().scrolling_header.connect_header_visibility( + clone!(@weak self as _self => move |visible| { + _self.set_header_visible(visible); }), ); - - let widget = self.widget(); - widget.scrolled_window.add_controller(&scroll_controller); } fn set_loaded(&self) { - let context = self.style_context(); + let context = self.imp().scrolling_header.style_context(); context.add_class("container--loaded"); } - fn set_album_and_artist(&self, album: &str, artist: &str) { - self.widget() - .header_widget - .set_album_and_artist_and_year(album, artist, None); - self.widget() - .header_mobile - .set_album_and_artist_and_year(album, artist, None); + fn set_editing(&self, editing: bool) { + self.imp().header_widget.set_editing(editing); + self.imp().header_mobile.set_editing(editing); + self.imp().headerbar.set_editing(editing); + } + + fn set_editable(&self, editing: bool) { + self.imp().headerbar.set_editable(editing); + } + + fn set_info(&self, playlist: &str, owner: &str) { + self.imp().header_widget.set_info(playlist, owner); + self.imp().header_mobile.set_info(playlist, owner); + self.imp().headerbar.set_title(Some(playlist)); } fn set_artwork(&self, art: &gdk_pixbuf::Pixbuf) { - self.widget().header_widget.set_artwork(art); - self.widget().header_mobile.set_artwork(art); + self.imp().header_widget.set_artwork(art); + self.imp().header_mobile.set_artwork(art); } - fn connect_artist_clicked(&self, f: F) + fn connect_owner_clicked(&self, f: F) where F: Fn() + Clone + 'static, { - self.widget() - .header_widget - .connect_artist_clicked(f.clone()); - self.widget().header_mobile.connect_artist_clicked(f); + self.imp().header_widget.connect_owner_clicked(f.clone()); + self.imp().header_mobile.connect_owner_clicked(f); + } + + pub fn connect_edit(&self, f: F) + where + F: Fn() + 'static, + { + self.imp().headerbar.connect_edit(f); + } + + pub fn connect_cancel(&self, f: F) + where + F: Fn() + 'static, + { + self.imp() + .headerbar + .connect_cancel(clone!(@weak self as _self => move || { + _self.imp().header_widget.reset_playlist_name(); + _self.imp().header_mobile.reset_playlist_name(); + f(); + })); + } + + pub fn connect_done(&self, f: F) + where + F: Fn(String) + 'static, + { + self.imp() + .headerbar + .connect_ok(clone!(@weak self as _self => move || { + let s = _self.imp().header_widget.get_edited_playlist_name(); + f(s); + })); + } + + pub fn connect_go_back(&self, f: F) + where + F: Fn() + 'static, + { + self.imp().headerbar.connect_go_back(f); } } @@ -159,6 +196,7 @@ impl PlaylistDetails { if model.get_playlist_info().is_none() { model.load_playlist_info(); } + let widget = PlaylistDetailsWidget::new(); let playlist = Box::new(Playlist::new( widget.playlist_tracks_widget().clone(), @@ -166,16 +204,28 @@ impl PlaylistDetails { worker.clone(), )); + widget.set_editable(model.is_playlist_editable()); + widget.connect_header(); widget.connect_bottom_edge(clone!(@weak model => move || { model.load_more_tracks(); })); - widget.connect_artist_clicked(clone!(@weak model => move || { - model.view_owner(); + widget.connect_owner_clicked(clone!(@weak model => move || model.view_owner())); + + widget.connect_edit(clone!(@weak model => move || { + model.enable_selection(); })); + widget.connect_cancel(clone!(@weak model => move || model.disable_selection())); + widget.connect_done(clone!(@weak model => move |n| { + model.disable_selection(); + model.update_playlist_details(n); + })); + + widget.connect_go_back(clone!(@weak model => move || model.go_back())); + Self { model, worker, @@ -190,7 +240,7 @@ impl PlaylistDetails { let owner = &info.owner.display_name[..]; let art_url = info.art.as_ref(); - self.widget.set_album_and_artist(title, owner); + self.widget.set_info(title, owner); if let Some(art_url) = art_url.cloned() { let widget = self.widget.downgrade(); @@ -208,6 +258,13 @@ impl PlaylistDetails { } } } + + fn set_editing(&self, editable: bool) { + if !self.model.is_playlist_editable() { + return; + } + self.widget.set_editing(editable); + } } impl Component for PlaylistDetails { @@ -228,6 +285,9 @@ impl EventListener for PlaylistDetails { { self.update_details() } + AppEvent::SelectionEvent(SelectionEvent::SelectionModeChanged(editing)) => { + self.set_editing(*editing); + } _ => {} } self.broadcast_event(event); diff --git a/src/app/components/playlist_details/playlist_details.ui b/src/app/components/playlist_details/playlist_details.ui index f5851aee..99d7e83f 100644 --- a/src/app/components/playlist_details/playlist_details.ui +++ b/src/app/components/playlist_details/playlist_details.ui @@ -9,13 +9,15 @@ 1 1 - - - - 900 + + + + + + - - slide-up + + 900 center @@ -23,38 +25,23 @@ crossfade natural - - - + - + vertical 12 - + - - - - - - never - 1 - 1 - 1 900 @@ -63,12 +50,12 @@ + - \ No newline at end of file diff --git a/src/app/components/playlist_details/playlist_details_model.rs b/src/app/components/playlist_details/playlist_details_model.rs index 9349f8a1..f6903686 100644 --- a/src/app/components/playlist_details/playlist_details_model.rs +++ b/src/app/components/playlist_details/playlist_details_model.rs @@ -4,16 +4,14 @@ use std::ops::Deref; use std::rc::Rc; use crate::api::SpotifyApiError; -use crate::app::components::SimpleHeaderBarModel; use crate::app::components::{labels, PlaylistModel}; use crate::app::models::*; use crate::app::state::SelectionContext; use crate::app::state::{BrowserAction, PlaybackAction, SelectionAction, SelectionState}; -use crate::app::{ActionDispatcher, AppAction, AppEvent, AppModel, BatchQuery, SongsSource}; +use crate::app::{ActionDispatcher, AppAction, AppModel, BatchQuery, SongsSource}; pub struct PlaylistDetailsModel { pub id: String, - _editable_selection_context: SelectionContext, app_model: Rc, dispatcher: Box, } @@ -21,14 +19,13 @@ pub struct PlaylistDetailsModel { impl PlaylistDetailsModel { pub fn new(id: String, app_model: Rc, dispatcher: Box) -> Self { Self { - id: id.clone(), - _editable_selection_context: SelectionContext::EditablePlaylist(id), + id, app_model, dispatcher, } } - fn is_playlist_editable(&self) -> bool { + pub fn is_playlist_editable(&self) -> bool { let state = self.app_model.get_state(); state.logged_user.playlists.iter().any(|p| p.id == self.id) } @@ -85,6 +82,19 @@ impl PlaylistDetailsModel { Some(()) } + pub fn update_playlist_details(&self, title: String) { + let api = self.app_model.get_spotify(); + let id = self.id.clone(); + self.dispatcher + .call_spotify_and_dispatch(move || async move { + let playlist = api.update_playlist_details(&id, title.clone()).await; + match playlist { + Ok(_) => Ok(AppAction::UpdatePlaylistName(PlaylistSummary { id, title })), + Err(e) => Err(e), + } + }); + } + pub fn view_owner(&self) { if let Some(playlist) = self.get_playlist_info() { let owner = &playlist.owner.id; @@ -92,6 +102,15 @@ impl PlaylistDetailsModel { .dispatch(AppAction::ViewUser(owner.to_owned())); } } + + pub fn disable_selection(&self) { + self.dispatcher.dispatch(AppAction::CancelSelection); + } + + pub fn go_back(&self) { + self.dispatcher + .dispatch(BrowserAction::NavigationPop.into()); + } } impl PlaylistModel for PlaylistDetailsModel { @@ -169,9 +188,12 @@ impl PlaylistModel for PlaylistDetailsModel { } fn enable_selection(&self) -> bool { - self.dispatcher.dispatch(AppAction::EnableSelection( - self.selection_context().unwrap().clone(), - )); + self.dispatcher + .dispatch(AppAction::EnableSelection(if self.is_playlist_editable() { + SelectionContext::EditablePlaylist(self.id.clone()) + } else { + SelectionContext::Playlist + })); true } @@ -179,27 +201,3 @@ impl PlaylistModel for PlaylistDetailsModel { Some(Box::new(self.app_model.map_state(|s| &s.selection))) } } - -impl SimpleHeaderBarModel for PlaylistDetailsModel { - fn title(&self) -> Option { - None - } - - fn title_updated(&self, _: &AppEvent) -> bool { - false - } - - fn selection_context(&self) -> Option<&SelectionContext> { - Some(if self.is_playlist_editable() { - &self._editable_selection_context - } else { - &SelectionContext::Playlist - }) - } - - fn select_all(&self) { - let songs: Vec = self.song_list_model().collect(); - self.dispatcher - .dispatch(SelectionAction::Select(songs).into()); - } -} diff --git a/src/app/components/playlist_details/playlist_header.css b/src/app/components/playlist_details/playlist_header.css new file mode 100644 index 00000000..2df9145f --- /dev/null +++ b/src/app/components/playlist_details/playlist_header.css @@ -0,0 +1,46 @@ +.playlist__header .title-4 label { + color: @window_fg_color; + font-weight: bold; + text-decoration: none; +} + +.playlist__header .title-4:hover { + border-radius: 6px; + background-image: image(alpha(currentColor, 0.08)); +} + +.playlist__header .like__button { + margin-right: 6px; +} + +.playlist__header .vertical { + margin-left: 18px; +} + +.playlist__header .card { + margin-top: 18px; + margin-left: 6px; + margin-bottom: 6px; +} + +clamp.playlist_details__clamp { + background-color: @view_bg_color; + box-shadow: inset 0px -1px 0px @borders; +} + +headerbar.playlist_details__headerbar { + transition: background-color .3s ease; +} + +headerbar.flat.playlist_details__headerbar windowtitle { + opacity: 0; +} + +headerbar.playlist_details__headerbar windowtitle { + transition: opacity .3s ease; + opacity: 1; +} + +.playlist_details__headerbar.flat { + background-color: @view_bg_color; +} \ No newline at end of file diff --git a/src/app/components/playlist_details/playlist_header.rs b/src/app/components/playlist_details/playlist_header.rs new file mode 100644 index 00000000..cb3f560c --- /dev/null +++ b/src/app/components/playlist_details/playlist_header.rs @@ -0,0 +1,149 @@ +use crate::app::components::display_add_css_provider; +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::{glib, CompositeTemplate}; + +const CSS_RO_ENTRY: &str = "playlist__title-entry--ro"; + +mod imp { + + use std::cell::RefCell; + use std::convert::TryFrom; + + use glib::{ParamSpec, Properties}; + + use super::*; + + #[derive(Debug, Default, CompositeTemplate, Properties)] + #[template(resource = "/dev/alextren/Spot/components/playlist_header.ui")] + #[properties(wrapper_type = super::PlaylistHeaderWidget)] + pub struct PlaylistHeaderWidget { + #[template_child] + pub playlist_label_entry: TemplateChild, + + #[template_child] + pub playlist_art: TemplateChild, + + #[template_child] + pub playlist_info: TemplateChild, + + #[template_child] + pub author_button: TemplateChild, + + #[template_child] + pub author_button_label: TemplateChild, + + #[property(get, set, name = "original-entry-text")] + pub original_entry_text: RefCell, + } + + #[glib::object_subclass] + impl ObjectSubclass for PlaylistHeaderWidget { + const NAME: &'static str = "PlaylistHeaderWidget"; + type Type = super::PlaylistHeaderWidget; + type ParentType = gtk::Box; + + fn class_init(klass: &mut Self::Class) { + Self::bind_template(klass); + } + + fn instance_init(obj: &glib::subclass::InitializingObject) { + display_add_css_provider(resource!("/components/playlist_header.css")); + obj.init_template(); + } + } + + impl ObjectImpl for PlaylistHeaderWidget { + fn properties() -> &'static [ParamSpec] { + Self::derived_properties() + } + + fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { + self.derived_set_property(id, value, pspec); + } + + fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value { + self.derived_property(id, pspec) + } + + fn constructed(&self) { + self.parent_constructed(); + } + } + + impl WidgetImpl for PlaylistHeaderWidget {} + impl BoxImpl for PlaylistHeaderWidget {} +} + +glib::wrapper! { + pub struct PlaylistHeaderWidget(ObjectSubclass) @extends gtk::Widget, gtk::Box; +} + +impl PlaylistHeaderWidget { + pub fn new() -> Self { + glib::Object::new() + } + + pub fn connect_owner_clicked(&self, f: F) + where + F: Fn() + 'static, + { + self.imp().author_button.connect_activate_link(move |_| { + f(); + glib::signal::Inhibit(true) + }); + } + + pub fn reset_playlist_name(&self) { + self.imp() + .playlist_label_entry + .set_text(&self.original_entry_text()); + } + + pub fn get_edited_playlist_name(&self) -> String { + self.imp().playlist_label_entry.text().to_string() + } + + pub fn set_artwork(&self, art: &gdk_pixbuf::Pixbuf) { + self.imp().playlist_art.set_from_pixbuf(Some(art)); + } + + pub fn set_info(&self, playlist: &str, owner: &str) { + let widget = self.imp(); + self.set_original_entry_text(playlist); + widget.playlist_label_entry.set_text(playlist); + widget + .playlist_label_entry + .set_placeholder_text(Some(playlist)); + widget.author_button_label.set_label(owner); + } + + pub fn set_centered(&self) { + let widget = self.imp(); + widget.playlist_info.set_halign(gtk::Align::Center); + } + + pub fn set_editing(&self, editing: bool) { + let widget = self.imp(); + widget.playlist_label_entry.set_can_focus(editing); + widget.playlist_label_entry.set_editable(editing); + if editing { + widget.playlist_label_entry.remove_css_class(CSS_RO_ENTRY); + } else { + widget.playlist_label_entry.add_css_class(CSS_RO_ENTRY); + } + } + + pub fn entry(&self) -> >k::Entry { + self.imp().playlist_label_entry.as_ref() + } + + pub fn set_grows_automatically(&self) { + let entry: >k::Entry = &self.imp().playlist_label_entry; + entry + .bind_property("text", entry, "width-chars") + .transform_to(|_, text: &str| Some(text.len() as i32)) + .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) + .build(); + } +} diff --git a/src/app/components/playlist_details/playlist_header.ui b/src/app/components/playlist_details/playlist_header.ui new file mode 100644 index 00000000..ad0f6245 --- /dev/null +++ b/src/app/components/playlist_details/playlist_header.ui @@ -0,0 +1,72 @@ + + + + + + \ No newline at end of file diff --git a/src/app/components/playlist_details/playlist_headerbar.rs b/src/app/components/playlist_details/playlist_headerbar.rs new file mode 100644 index 00000000..f727a555 --- /dev/null +++ b/src/app/components/playlist_details/playlist_headerbar.rs @@ -0,0 +1,160 @@ +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::CompositeTemplate; +use libadwaita::subclass::prelude::BinImpl; + +mod imp { + + use super::*; + + #[derive(Debug, Default, CompositeTemplate)] + #[template(resource = "/dev/alextren/Spot/components/playlist_headerbar.ui")] + pub struct PlaylistHeaderBarWidget { + #[template_child] + pub main_header: TemplateChild, + + #[template_child] + pub edition_header: TemplateChild, + + #[template_child] + pub go_back: TemplateChild, + + #[template_child] + pub title: TemplateChild, + + #[template_child] + pub edit: TemplateChild, + + #[template_child] + pub ok: TemplateChild, + + #[template_child] + pub cancel: TemplateChild, + + #[template_child] + pub overlay: TemplateChild, + } + + #[glib::object_subclass] + impl ObjectSubclass for PlaylistHeaderBarWidget { + const NAME: &'static str = "PlaylistHeaderBarWidget"; + type Type = super::PlaylistHeaderBarWidget; + type ParentType = libadwaita::Bin; + type Interfaces = (gtk::Buildable,); + + fn class_init(klass: &mut Self::Class) { + Self::bind_template(klass); + } + + fn instance_init(obj: &glib::subclass::InitializingObject) { + obj.init_template(); + } + } + + impl ObjectImpl for PlaylistHeaderBarWidget {} + + impl BuildableImpl for PlaylistHeaderBarWidget { + fn add_child(&self, builder: >k::Builder, child: &glib::Object, type_: Option<&str>) { + if Some("root") == type_ { + self.parent_add_child(builder, child, type_); + } else { + self.main_header + .set_title_widget(child.downcast_ref::()); + } + } + } + + impl WidgetImpl for PlaylistHeaderBarWidget {} + impl BinImpl for PlaylistHeaderBarWidget {} + impl WindowImpl for PlaylistHeaderBarWidget {} +} + +glib::wrapper! { + pub struct PlaylistHeaderBarWidget(ObjectSubclass) @extends gtk::Widget, libadwaita::Bin; +} + +impl PlaylistHeaderBarWidget { + pub fn new() -> Self { + glib::Object::new() + } + + pub fn connect_edit(&self, f: F) + where + F: Fn() + 'static, + { + self.imp().edit.connect_clicked(move |_| f()); + } + + pub fn connect_ok(&self, f: F) + where + F: Fn() + 'static, + { + self.imp().ok.connect_clicked(move |_| f()); + } + + pub fn connect_cancel(&self, f: F) + where + F: Fn() + 'static, + { + self.imp().cancel.connect_clicked(move |_| f()); + } + + pub fn connect_go_back(&self, f: F) + where + F: Fn() + 'static, + { + self.imp().go_back.connect_clicked(move |_| f()); + } + + pub fn bind_to_leaflet(&self, leaflet: &libadwaita::Leaflet) { + leaflet + .bind_property( + "folded", + &*self.imp().main_header, + "show-start-title-buttons", + ) + .build(); + leaflet.notify("folded"); + } + + pub fn set_can_go_back(&self, can_go_back: bool) { + self.imp().go_back.set_visible(can_go_back); + } + + pub fn set_editable(&self, editable: bool) { + self.imp().edit.set_visible(editable); + } + + pub fn set_editing(&self, editing: bool) { + if editing { + self.imp().edition_header.show(); + } else { + self.imp().edition_header.hide(); + } + } + + pub fn add_classes(&self, classes: &[&str]) { + let context = self.imp().main_header.style_context(); + for &class in classes { + context.add_class(class); + } + } + + pub fn remove_classes(&self, classes: &[&str]) { + let context = self.imp().main_header.style_context(); + for &class in classes { + context.remove_class(class); + } + } + + pub fn set_title_visible(&self, visible: bool) { + self.imp().title.set_visible(visible); + } + + pub fn set_title(&self, title: Option<&str>) { + self.imp().title.set_visible(title.is_some()); + if let Some(title) = title { + self.imp().title.set_title(title); + } + } +} diff --git a/src/app/components/playlist_details/playlist_headerbar.ui b/src/app/components/playlist_details/playlist_headerbar.ui new file mode 100644 index 00000000..331ced0f --- /dev/null +++ b/src/app/components/playlist_details/playlist_headerbar.ui @@ -0,0 +1,74 @@ + + + + + + \ No newline at end of file diff --git a/src/app/components/saved_playlists/saved_playlists.rs b/src/app/components/saved_playlists/saved_playlists.rs index 3016c44e..6b5fdcde 100644 --- a/src/app/components/saved_playlists/saved_playlists.rs +++ b/src/app/components/saved_playlists/saved_playlists.rs @@ -33,7 +33,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -52,14 +52,14 @@ glib::wrapper! { impl SavedPlaylistsWidget { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of SavedPlaylistsWidget") + glib::Object::new() } fn connect_bottom_edge(&self, f: F) where F: Fn() + 'static, { - imp::SavedPlaylistsWidget::from_instance(self) + self.imp() .scrolled_window .connect_edge_reached(move |_, pos| { if let gtk::PositionType::Bottom = pos { @@ -72,7 +72,7 @@ impl SavedPlaylistsWidget { where F: Fn(String) + Clone + 'static, { - imp::SavedPlaylistsWidget::from_instance(self) + self.imp() .flowbox .bind_model(Some(store.unsafe_store()), move |item| { let album_model = item.downcast_ref::().unwrap(); @@ -89,7 +89,7 @@ impl SavedPlaylistsWidget { }); } pub fn get_status_page(&self) -> &libadwaita::StatusPage { - &imp::SavedPlaylistsWidget::from_instance(self).status_page + &self.imp().status_page } } @@ -119,7 +119,7 @@ impl SavedPlaylists { fn bind_flowbox(&self) { self.widget.bind_albums( self.worker.clone(), - &*self.model.get_list_store().unwrap(), + &self.model.get_list_store().unwrap(), clone!(@weak self.model as model => move |id| { model.open_playlist(id); }), diff --git a/src/app/components/saved_playlists/saved_playlists_model.rs b/src/app/components/saved_playlists/saved_playlists_model.rs index 0140c150..062aadff 100644 --- a/src/app/components/saved_playlists/saved_playlists_model.rs +++ b/src/app/components/saved_playlists/saved_playlists_model.rs @@ -23,10 +23,6 @@ impl SavedPlaylistsModel { self.app_model.map_state_opt(|s| s.browser.home_state()) } - pub fn get_playlists(&self) -> ListStore { - self.state().unwrap().playlists.clone() - } - pub fn get_list_store(&self) -> Option> + '_> { Some(Ref::map(self.state()?, |s| &s.playlists)) } @@ -71,8 +67,4 @@ impl SavedPlaylistsModel { pub fn open_playlist(&self, id: String) { self.dispatcher.dispatch(AppAction::ViewPlaylist(id)); } - - pub fn clone(&self) -> SavedPlaylistsModel { - SavedPlaylistsModel::new(self.app_model.clone(), self.dispatcher.box_clone()) - } } diff --git a/src/app/components/saved_tracks/saved_tracks.rs b/src/app/components/saved_tracks/saved_tracks.rs index 76f8881a..715ac28b 100644 --- a/src/app/components/saved_tracks/saved_tracks.rs +++ b/src/app/components/saved_tracks/saved_tracks.rs @@ -30,7 +30,7 @@ mod imp { type ParentType = libadwaita::Bin; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -49,14 +49,14 @@ glib::wrapper! { impl SavedTracksWidget { fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of SavedTracksWidget") + glib::Object::new() } fn connect_bottom_edge(&self, f: F) where F: Fn() + 'static, { - imp::SavedTracksWidget::from_instance(self) + self.imp() .scrolled_window .connect_edge_reached(move |_, pos| { if let gtk::PositionType::Bottom = pos { @@ -66,9 +66,7 @@ impl SavedTracksWidget { } fn song_list_widget(&self) -> >k::ListView { - imp::SavedTracksWidget::from_instance(self) - .song_list - .as_ref() + self.imp().song_list.as_ref() } } diff --git a/src/app/components/scrolling_header/mod.rs b/src/app/components/scrolling_header/mod.rs new file mode 100644 index 00000000..1f8c390c --- /dev/null +++ b/src/app/components/scrolling_header/mod.rs @@ -0,0 +1,7 @@ +mod scrolling_header_widget; +use glib::StaticType; +pub use scrolling_header_widget::*; + +pub fn expose_widgets() { + scrolling_header_widget::ScrollingHeaderWidget::static_type(); +} diff --git a/src/app/components/scrolling_header/scrolling_header.ui b/src/app/components/scrolling_header/scrolling_header.ui new file mode 100644 index 00000000..04a65c31 --- /dev/null +++ b/src/app/components/scrolling_header/scrolling_header.ui @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/src/app/components/scrolling_header/scrolling_header_widget.rs b/src/app/components/scrolling_header/scrolling_header_widget.rs new file mode 100644 index 00000000..85be0059 --- /dev/null +++ b/src/app/components/scrolling_header/scrolling_header_widget.rs @@ -0,0 +1,117 @@ +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::CompositeTemplate; + +mod imp { + + use super::*; + + #[derive(Debug, Default, CompositeTemplate)] + #[template(resource = "/dev/alextren/Spot/components/scrolling_header.ui")] + pub struct ScrollingHeaderWidget { + #[template_child] + pub scrolled_window: TemplateChild, + + #[template_child] + pub revealer: TemplateChild, + } + + #[glib::object_subclass] + impl ObjectSubclass for ScrollingHeaderWidget { + const NAME: &'static str = "ScrollingHeaderWidget"; + type Type = super::ScrollingHeaderWidget; + type ParentType = gtk::Box; + type Interfaces = (gtk::Buildable,); + + fn class_init(klass: &mut Self::Class) { + klass.bind_template(); + } + + fn instance_init(obj: &glib::subclass::InitializingObject) { + obj.init_template(); + } + } + + impl ObjectImpl for ScrollingHeaderWidget { + fn constructed(&self) { + self.parent_constructed(); + } + } + + impl BuildableImpl for ScrollingHeaderWidget { + fn add_child(&self, builder: >k::Builder, child: &glib::Object, type_: Option<&str>) { + let child_widget = child.downcast_ref::(); + match type_ { + Some("internal") => self.parent_add_child(builder, child, type_), + Some("header") => self.revealer.set_child(child_widget), + _ => self.scrolled_window.set_child(child_widget), + } + } + } + + impl WidgetImpl for ScrollingHeaderWidget {} + impl BoxImpl for ScrollingHeaderWidget {} +} + +glib::wrapper! { + pub struct ScrollingHeaderWidget(ObjectSubclass) @extends gtk::Widget, gtk::Box; +} + +impl ScrollingHeaderWidget { + fn set_header_visible(&self, visible: bool) -> bool { + let widget = self.imp(); + let is_up_to_date = widget.revealer.reveals_child() == visible; + if !is_up_to_date { + widget.revealer.set_reveal_child(visible); + } + is_up_to_date + } + + fn is_scrolled_to_top(&self) -> bool { + self.imp().scrolled_window.vadjustment().value() <= f64::EPSILON + || self.imp().revealer.reveals_child() + } + + pub fn connect_header_visibility(&self, f: F) + where + F: Fn(bool) + Clone + 'static, + { + self.set_header_visible(true); + f(true); + + let scroll_controller = + gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::VERTICAL); + scroll_controller.connect_scroll( + clone!(@strong f, @weak self as _self => @default-return gtk::Inhibit(false), move |_, _, dy| { + let visible = dy < 0f64 && _self.is_scrolled_to_top(); + f(visible); + gtk::Inhibit(!_self.set_header_visible(visible)) + }), + ); + + let swipe_controller = gtk::GestureSwipe::new(); + swipe_controller.set_touch_only(true); + swipe_controller.set_propagation_phase(gtk::PropagationPhase::Capture); + swipe_controller.connect_swipe(clone!(@weak self as _self => move |_, _, dy| { + let visible = dy >= 0f64 && _self.is_scrolled_to_top(); + f(visible); + _self.set_header_visible(visible); + })); + + self.imp().scrolled_window.add_controller(scroll_controller); + self.add_controller(swipe_controller); + } + + pub fn connect_bottom_edge(&self, f: F) + where + F: Fn() + 'static, + { + self.imp() + .scrolled_window + .connect_edge_reached(move |_, pos| { + if let gtk::PositionType::Bottom = pos { + f() + } + }); + } +} diff --git a/src/app/components/search/search.rs b/src/app/components/search/search.rs index 46d516e4..7f2c6671 100644 --- a/src/app/components/search/search.rs +++ b/src/app/components/search/search.rs @@ -46,7 +46,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -58,7 +58,7 @@ mod imp { impl BoxImpl for SearchResultsWidget {} impl WidgetImpl for SearchResultsWidget { - fn grab_focus(&self, _: &Self::Type) -> bool { + fn grab_focus(&self) -> bool { self.search_entry.grab_focus() } } @@ -70,18 +70,14 @@ glib::wrapper! { impl SearchResultsWidget { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create an instance of SearchResultsWidget") - } - - fn widget(&self) -> &imp::SearchResultsWidget { - imp::SearchResultsWidget::from_instance(self) + glib::Object::new() } pub fn bind_to_leaflet(&self, leaflet: &libadwaita::Leaflet) { leaflet .bind_property( "folded", - &*self.widget().main_header, + &*self.imp().main_header, "show-start-title-buttons", ) .build(); @@ -92,20 +88,20 @@ impl SearchResultsWidget { where F: Fn() + 'static, { - self.widget().go_back.connect_clicked(move |_| f()); + self.imp().go_back.connect_clicked(move |_| f()); } pub fn connect_search_updated(&self, f: F) where F: Fn(String) + 'static, { - self.widget() + self.imp() .search_entry .connect_changed(clone!(@weak self as _self => move |s| { let query = s.text(); let query = query.as_str(); - _self.widget().status_page.set_visible(query.is_empty()); - _self.widget().search_results.set_visible(!query.is_empty()); + _self.imp().status_page.set_visible(query.is_empty()); + _self.imp().search_results.set_visible(!query.is_empty()); if !query.is_empty() { f(query.to_string()); } @@ -116,7 +112,7 @@ impl SearchResultsWidget { where F: Fn(String) + Clone + 'static, { - self.widget() + self.imp() .albums_results .bind_model(Some(store), move |item| { wrap_flowbox_item(item, |album_model| { @@ -134,7 +130,7 @@ impl SearchResultsWidget { where F: Fn(String) + Clone + 'static, { - self.widget() + self.imp() .artist_results .bind_model(Some(store), move |item| { wrap_flowbox_item(item, |artist_model| { diff --git a/src/app/components/selection/component.rs b/src/app/components/selection/component.rs index 9fa467af..78da39b3 100644 --- a/src/app/components/selection/component.rs +++ b/src/app/components/selection/component.rs @@ -216,7 +216,7 @@ impl EventListener for SelectionToolbar { AppEvent::LoginEvent(LoginEvent::UserPlaylistsLoaded) => { let model = &self.model; self.widget.connect_playlists( - &*model.user_playlists(), + &model.user_playlists(), clone!(@weak model => move |s| model.add_to_playlist(s)), ); } diff --git a/src/app/components/selection/widget.rs b/src/app/components/selection/widget.rs index 7f3c9f66..9a1ae8dc 100644 --- a/src/app/components/selection/widget.rs +++ b/src/app/components/selection/widget.rs @@ -43,7 +43,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -52,8 +52,8 @@ mod imp { } impl ObjectImpl for SelectionToolbarWidget { - fn constructed(&self, obj: &Self::Type) { - self.parent_constructed(obj); + fn constructed(&self) { + self.parent_constructed(); display_add_css_provider(resource!("/components/selection_toolbar.css")); } } @@ -83,75 +83,71 @@ impl SelectionToolState { } impl SelectionToolbarWidget { - fn widget(&self) -> &imp::SelectionToolbarWidget { - imp::SelectionToolbarWidget::from_instance(self) - } - pub fn connect_move_down(&self, f: F) where F: Fn() + 'static, { - self.widget().move_down.connect_clicked(move |_| f()); + self.imp().move_down.connect_clicked(move |_| f()); } pub fn connect_move_up(&self, f: F) where F: Fn() + 'static, { - self.widget().move_up.connect_clicked(move |_| f()); + self.imp().move_up.connect_clicked(move |_| f()); } pub fn connect_queue(&self, f: F) where F: Fn() + 'static, { - self.widget().queue.connect_clicked(move |_| f()); + self.imp().queue.connect_clicked(move |_| f()); } pub fn connect_save(&self, f: F) where F: Fn() + 'static, { - self.widget().save.connect_clicked(move |_| f()); + self.imp().save.connect_clicked(move |_| f()); } pub fn connect_remove(&self, f: F) where F: Fn() + 'static, { - self.widget().remove.connect_clicked(move |_| f()); + self.imp().remove.connect_clicked(move |_| f()); } pub fn set_move(&self, state: SelectionToolState) { - self.widget().move_up.set_sensitive(state.sensitive()); - self.widget().move_up.set_visible(state.visible()); - self.widget().move_down.set_sensitive(state.sensitive()); - self.widget().move_down.set_visible(state.visible()); + self.imp().move_up.set_sensitive(state.sensitive()); + self.imp().move_up.set_visible(state.visible()); + self.imp().move_down.set_sensitive(state.sensitive()); + self.imp().move_down.set_visible(state.visible()); } pub fn set_queue(&self, state: SelectionToolState) { - self.widget().queue.set_sensitive(state.sensitive()); - self.widget().queue.set_visible(state.visible()); + self.imp().queue.set_sensitive(state.sensitive()); + self.imp().queue.set_visible(state.visible()); } pub fn set_add(&self, state: SelectionToolState) { - self.widget().add.set_sensitive(state.sensitive()); - self.widget().add.set_visible(state.visible()); + self.imp().add.set_sensitive(state.sensitive()); + self.imp().add.set_visible(state.visible()); } pub fn set_remove(&self, state: SelectionToolState) { - self.widget().remove.set_sensitive(state.sensitive()); - self.widget().remove.set_visible(state.visible()); + self.imp().remove.set_sensitive(state.sensitive()); + self.imp().remove.set_visible(state.visible()); } pub fn set_save(&self, state: SelectionToolState) { - self.widget().save.set_sensitive(state.sensitive()); - self.widget().save.set_visible(state.visible()); + self.imp().save.set_sensitive(state.sensitive()); + self.imp().save.set_visible(state.visible()); } pub fn set_visible(&self, visible: bool) { gtk::Widget::set_visible(self.upcast_ref(), visible); - self.widget().action_bar.set_revealed(visible); + self.imp().action_bar.set_revealed(visible); } pub fn connect_playlists(&self, playlists: &[PlaylistSummary], on_playlist_selected: F) @@ -179,8 +175,8 @@ impl SelectionToolbarWidget { } let popover = gtk::PopoverMenu::from_model(Some(&menu)); - self.widget().add.set_popover(Some(&popover)); - self.widget() + self.imp().add.set_popover(Some(&popover)); + self.imp() .add .insert_action_group("add_to", Some(&action_group)); } diff --git a/src/app/components/settings/settings.rs b/src/app/components/settings/settings.rs index 63eb0644..76df8375 100644 --- a/src/app/components/settings/settings.rs +++ b/src/app/components/settings/settings.rs @@ -31,6 +31,9 @@ mod imp { #[template_child] pub audio_backend: TemplateChild, + #[template_child] + pub gapless_playback: TemplateChild, + #[template_child] pub ap_port: TemplateChild, @@ -45,7 +48,7 @@ mod imp { type ParentType = libadwaita::PreferencesWindow; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -66,8 +69,7 @@ glib::wrapper! { impl SettingsWindow { pub fn new() -> Self { - let window: Self = - glib::Object::new(&[]).expect("Failed to create an instance of SettingsWindow"); + let window: Self = glib::Object::new(); window.bind_backend_and_device(); window.bind_settings(); @@ -76,7 +78,7 @@ impl SettingsWindow { } fn bind_backend_and_device(&self) { - let widget = imp::SettingsWindow::from_instance(self); + let widget = self.imp(); let audio_backend = widget .audio_backend @@ -89,7 +91,7 @@ impl SettingsWindow { audio_backend .bind_property("selected", alsa_device_row, "visible") - .transform_to(|_, value| value.get::().ok().map(|u| (u == 1).to_value())) + .transform_to(|_, value: u32| Some(value == 1)) .build(); if audio_backend.selected() == 0 { @@ -98,7 +100,7 @@ impl SettingsWindow { } fn bind_settings(&self) { - let widget = imp::SettingsWindow::from_instance(self); + let widget = self.imp(); let settings = gio::Settings::new(SETTINGS); let player_bitrate = widget @@ -162,6 +164,18 @@ impl SettingsWindow { }) .build(); + let gapless_playback = widget + .gapless_playback + .downcast_ref::() + .unwrap(); + settings + .bind( + "gapless-playback", + &gapless_playback.activatable_widget().unwrap(), + "active", + ) + .build(); + let ap_port = widget.ap_port.downcast_ref::().unwrap(); settings .bind("ap-port", ap_port, "text") @@ -171,28 +185,46 @@ impl SettingsWindow { let theme = widget.theme.downcast_ref::().unwrap(); settings - .bind("prefers-dark-theme", theme, "selected") + .bind("theme-preference", theme, "selected") .mapping(|variant, _| { - variant - .get::() - .map(|prefer_dark| if prefer_dark { 1 } else { 0 }.to_value()) + variant.str().map(|s| { + match s { + "light" => 0, + "dark" => 1, + "system" => 2, + _ => unreachable!(), + } + .to_value() + }) + }) + .set_mapping(|value, _| { + value.get::().ok().map(|u| { + match u { + 0 => "light", + 1 => "dark", + 2 => "system", + _ => unreachable!(), + } + .to_variant() + }) }) - .set_mapping(|value, _| value.get::().ok().map(|u| (u == 1).to_variant())) .build(); } fn connect_theme_select(&self) { - let widget = imp::SettingsWindow::from_instance(self); + let widget = self.imp(); let theme = widget.theme.downcast_ref::().unwrap(); theme.connect_selected_notify(|theme| { - let prefers_dark_theme = theme.selected() == 1; + debug!("Theme switched! --> value: {}", theme.selected()); let manager = libadwaita::StyleManager::default(); - manager.set_color_scheme(if prefers_dark_theme { - libadwaita::ColorScheme::PreferDark - } else { - libadwaita::ColorScheme::PreferLight - }); + let pref = match theme.selected() { + 0 => libadwaita::ColorScheme::ForceLight, + 1 => libadwaita::ColorScheme::ForceDark, + _ => libadwaita::ColorScheme::Default, + }; + + manager.set_color_scheme(pref); }); } diff --git a/src/app/components/settings/settings.ui b/src/app/components/settings/settings.ui index 10487e72..1dc69a1e 100644 --- a/src/app/components/settings/settings.ui +++ b/src/app/components/settings/settings.ui @@ -49,6 +49,20 @@ + + + Gapless playback + gapless_playback_row + gapless_playback_switch + True + + + 12 + 12 + + + + @@ -62,6 +76,7 @@ Light Dark + System diff --git a/src/app/components/sidebar/create_playlist.rs b/src/app/components/sidebar/create_playlist.rs new file mode 100644 index 00000000..9829c465 --- /dev/null +++ b/src/app/components/sidebar/create_playlist.rs @@ -0,0 +1,61 @@ +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::CompositeTemplate; + +mod imp { + use super::*; + + #[derive(Debug, Default, CompositeTemplate)] + #[template(resource = "/dev/alextren/Spot/components/create_playlist.ui")] + pub struct CreatePlaylistPopover { + #[template_child] + pub label: TemplateChild, + + #[template_child] + pub entry: TemplateChild, + + #[template_child] + pub button: TemplateChild, + } + + #[glib::object_subclass] + impl ObjectSubclass for CreatePlaylistPopover { + const NAME: &'static str = "CreatePlaylistPopover"; + type Type = super::CreatePlaylistPopover; + type ParentType = gtk::Popover; + + fn class_init(klass: &mut Self::Class) { + Self::bind_template(klass); + } + + fn instance_init(obj: &glib::subclass::InitializingObject) { + obj.init_template(); + } + } + + impl ObjectImpl for CreatePlaylistPopover {} + impl WidgetImpl for CreatePlaylistPopover {} + impl PopoverImpl for CreatePlaylistPopover {} +} + +glib::wrapper! { + pub struct CreatePlaylistPopover(ObjectSubclass) @extends gtk::Widget, gtk::Popover; +} + +impl CreatePlaylistPopover { + pub fn new() -> Self { + glib::Object::new() + } + + pub fn connect_create(&self, create_fun: F) { + let entry = self.imp().entry.get(); + let closure = clone!(@weak self as popover, @weak entry, @strong create_fun => move || { + create_fun(entry.text().to_string()); + popover.popdown(); + entry.buffer().delete_text(0, None); + }); + let closure_clone = closure.clone(); + entry.connect_activate(move |_| closure()); + self.imp().button.connect_clicked(move |_| closure_clone()); + } +} diff --git a/src/app/components/sidebar/create_playlist.ui b/src/app/components/sidebar/create_playlist.ui new file mode 100644 index 00000000..5cbe8113 --- /dev/null +++ b/src/app/components/sidebar/create_playlist.ui @@ -0,0 +1,45 @@ + + + + + \ No newline at end of file diff --git a/src/app/components/sidebar_listbox/icons/library-music-symbolic.svg b/src/app/components/sidebar/icons/library-music-symbolic.svg similarity index 100% rename from src/app/components/sidebar_listbox/icons/library-music-symbolic.svg rename to src/app/components/sidebar/icons/library-music-symbolic.svg diff --git a/src/app/components/sidebar/mod.rs b/src/app/components/sidebar/mod.rs new file mode 100644 index 00000000..5cbd4dbd --- /dev/null +++ b/src/app/components/sidebar/mod.rs @@ -0,0 +1,8 @@ +mod sidebar; +pub use sidebar::*; + +mod sidebar_item; +pub use sidebar_item::*; + +mod create_playlist; +mod sidebar_row; diff --git a/src/app/components/sidebar/sidebar.rs b/src/app/components/sidebar/sidebar.rs new file mode 100644 index 00000000..78dd2a28 --- /dev/null +++ b/src/app/components/sidebar/sidebar.rs @@ -0,0 +1,197 @@ +use gettextrs::gettext; +use gtk::prelude::*; +use std::rc::Rc; + +use super::create_playlist::CreatePlaylistPopover; +use super::{ + sidebar_row::SidebarRow, SidebarDestination, SidebarItem, CREATE_PLAYLIST_ITEM, + SAVED_PLAYLISTS_SECTION, +}; +use crate::app::models::{AlbumModel, PlaylistSummary}; +use crate::app::{ + ActionDispatcher, AppAction, AppEvent, AppModel, BrowserAction, BrowserEvent, Component, + EventListener, +}; + +const NUM_FIXED_ENTRIES: u32 = 6; +const NUM_PLAYLISTS: usize = 20; + +pub struct SidebarModel { + app_model: Rc, + dispatcher: Box, +} + +impl SidebarModel { + pub fn new(app_model: Rc, dispatcher: Box) -> Self { + Self { + app_model, + dispatcher, + } + } + + fn get_playlists(&self) -> Vec { + self.app_model + .get_state() + .browser + .home_state() + .expect("expected HomeState to be available") + .playlists + .iter() + .take(NUM_PLAYLISTS) + .map(Self::map_to_destination) + .collect() + } + + fn map_to_destination(a: AlbumModel) -> SidebarDestination { + let title = Some(a.album()) + .filter(|s| !s.is_empty()) + .unwrap_or_else(|| gettext("Unnamed playlist")); + let id = a.uri(); + SidebarDestination::Playlist(PlaylistSummary { id, title }) + } + + fn create_new_playlist(&self, name: String) { + let user_id = self.app_model.get_state().logged_user.user.clone().unwrap(); + let api = self.app_model.get_spotify(); + self.dispatcher + .call_spotify_and_dispatch(move || async move { + api.create_new_playlist(name.as_str(), user_id.as_str()) + .await + .map(AppAction::CreatePlaylist) + }) + } + + fn navigate(&self, dest: SidebarDestination) { + let actions = match dest { + SidebarDestination::Library + | SidebarDestination::SavedTracks + | SidebarDestination::NowPlaying + | SidebarDestination::SavedPlaylists => { + vec![BrowserAction::SetHomeVisiblePage(dest.id()).into()] + } + SidebarDestination::Playlist(PlaylistSummary { id, .. }) => vec![ + BrowserAction::SetHomeVisiblePage(SidebarDestination::SavedPlaylists.id()).into(), + AppAction::ViewPlaylist(id), + ], + }; + self.dispatcher.dispatch_many(actions); + } +} + +pub struct Sidebar { + listbox: gtk::ListBox, + list_store: gio::ListStore, + model: Rc, +} + +impl Sidebar { + pub fn new(listbox: gtk::ListBox, model: Rc) -> Self { + let popover = CreatePlaylistPopover::new(); + popover.connect_create(clone!(@weak model => move |t| model.create_new_playlist(t))); + + let list_store = gio::ListStore::new(SidebarItem::static_type()); + + list_store.append(&SidebarItem::from_destination(SidebarDestination::Library)); + list_store.append(&SidebarItem::from_destination( + SidebarDestination::SavedTracks, + )); + list_store.append(&SidebarItem::from_destination( + SidebarDestination::NowPlaying, + )); + list_store.append(&SidebarItem::playlists_section()); + list_store.append(&SidebarItem::create_playlist_item()); + list_store.append(&SidebarItem::from_destination( + SidebarDestination::SavedPlaylists, + )); + + listbox.bind_model( + Some(&list_store), + clone!(@weak popover => @default-panic, move |obj| { + let item = obj.downcast_ref::().unwrap(); + if item.navigatable() { + Self::make_navigatable(item) + } else { + match item.id().as_str() { + SAVED_PLAYLISTS_SECTION => Self::make_section_label(item), + CREATE_PLAYLIST_ITEM => Self::make_create_playlist(item, popover), + _ => unimplemented!(), + } + } + }), + ); + + listbox.connect_row_activated(clone!(@weak popover, @weak model => move |_, row| { + if let Some(row) = row.downcast_ref::() { + if let Some(dest) = row.item().destination() { + model.navigate(dest); + } else { + match row.item().id().as_str() { + CREATE_PLAYLIST_ITEM => popover.popup(), + _ => unimplemented!() + } + } + } + })); + + Self { + listbox, + list_store, + model, + } + } + + fn make_navigatable(item: &SidebarItem) -> gtk::Widget { + let row = SidebarRow::new(item.clone()); + row.set_selectable(false); + row.upcast() + } + + fn make_section_label(item: &SidebarItem) -> gtk::Widget { + let label = gtk::Label::new(Some(item.title().as_str())); + label.add_css_class("caption-heading"); + let row = gtk::ListBoxRow::builder() + .activatable(false) + .selectable(false) + .sensitive(false) + .child(&label) + .build(); + row.upcast() + } + + fn make_create_playlist(item: &SidebarItem, popover: CreatePlaylistPopover) -> gtk::Widget { + let row = SidebarRow::new(item.clone()); + row.set_activatable(true); + row.set_selectable(false); + row.set_sensitive(true); + popover.set_parent(&row); + row.upcast() + } + + fn update_playlists_in_sidebar(&self) { + let playlists: Vec = self + .model + .get_playlists() + .into_iter() + .map(SidebarItem::from_destination) + .collect(); + self.list_store.splice( + NUM_FIXED_ENTRIES, + self.list_store.n_items() - NUM_FIXED_ENTRIES, + playlists.as_slice(), + ); + } +} + +impl Component for Sidebar { + fn get_root_widget(&self) -> >k::Widget { + self.listbox.upcast_ref() + } +} + +impl EventListener for Sidebar { + fn on_event(&mut self, event: &AppEvent) { + if let AppEvent::BrowserEvent(BrowserEvent::SavedPlaylistsUpdated) = event { + self.update_playlists_in_sidebar(); + } + } +} diff --git a/src/app/components/sidebar/sidebar_item.rs b/src/app/components/sidebar/sidebar_item.rs new file mode 100644 index 00000000..7213ae16 --- /dev/null +++ b/src/app/components/sidebar/sidebar_item.rs @@ -0,0 +1,168 @@ +use gettextrs::gettext; +use glib::Properties; +use gtk::prelude::*; +use gtk::subclass::prelude::*; + +use crate::app::models::PlaylistSummary; + +const LIBRARY: &str = "library"; +const SAVED_TRACKS: &str = "saved_tracks"; +const NOW_PLAYING: &str = "now_playing"; +const SAVED_PLAYLISTS: &str = "saved_playlists"; +const PLAYLIST: &str = "playlist"; +pub const SAVED_PLAYLISTS_SECTION: &str = "saved_playlists_section"; +pub const CREATE_PLAYLIST_ITEM: &str = "create_playlist"; + +#[derive(Debug)] +pub enum SidebarDestination { + Library, + SavedTracks, + NowPlaying, + SavedPlaylists, + Playlist(PlaylistSummary), +} + +impl SidebarDestination { + pub fn id(&self) -> &'static str { + match self { + Self::Library => LIBRARY, + Self::SavedTracks => SAVED_TRACKS, + Self::NowPlaying => NOW_PLAYING, + Self::SavedPlaylists => SAVED_PLAYLISTS, + Self::Playlist(_) => PLAYLIST, + } + } + + pub fn title(&self) -> String { + match self { + // translators: This is a sidebar entry to browse to saved albums. + Self::Library => gettext("Library"), + // translators: This is a sidebar entry to browse to saved tracks. + Self::SavedTracks => gettext("Saved tracks"), + // translators: This is a sidebar entry to browse to saved playlists. + Self::NowPlaying => gettext("Now playing"), + // translators: This is a sidebar entry that marks that the entries below are playlists. + Self::SavedPlaylists => gettext("Playlists"), + Self::Playlist(PlaylistSummary { title, .. }) => title.clone(), + } + } + + pub fn icon(&self) -> &'static str { + match self { + Self::Library => "library-music-symbolic", + Self::SavedTracks => "starred-symbolic", + Self::NowPlaying => "music-queue-symbolic", + Self::SavedPlaylists => "view-app-grid-symbolic", + Self::Playlist(_) => "playlist2-symbolic", + } + } +} + +impl SidebarItem { + pub fn from_destination(dest: SidebarDestination) -> Self { + let (id, data, title) = match dest { + SidebarDestination::Playlist(PlaylistSummary { id, title }) => { + (PLAYLIST, Some(id), title) + } + _ => (dest.id(), None, dest.title()), + }; + glib::Object::builder() + .property("id", &id) + .property("data", &data.unwrap_or_default()) + .property("title", &title) + .property("navigatable", &true) + .build() + } + + pub fn playlists_section() -> Self { + glib::Object::builder() + .property("id", &SAVED_PLAYLISTS_SECTION) + .property("data", &String::new()) + .property("title", &gettext("All Playlists")) + .property("navigatable", &false) + .build() + } + + pub fn create_playlist_item() -> Self { + glib::Object::builder() + .property("id", &CREATE_PLAYLIST_ITEM) + .property("data", &String::new()) + .property("title", &gettext("New Playlist")) + .property("navigatable", &false) + .build() + } + + pub fn destination(&self) -> Option { + let navigatable = self.property::("navigatable"); + if navigatable { + let id = self.id(); + let data = self.property::("data"); + let title = self.title(); + match id.as_str() { + LIBRARY => Some(SidebarDestination::Library), + SAVED_TRACKS => Some(SidebarDestination::SavedTracks), + NOW_PLAYING => Some(SidebarDestination::NowPlaying), + SAVED_PLAYLISTS => Some(SidebarDestination::SavedPlaylists), + PLAYLIST => Some(SidebarDestination::Playlist(PlaylistSummary { + id: data, + title, + })), + _ => None, + } + } else { + None + } + } + + pub fn icon(&self) -> Option<&str> { + match self.id().as_str() { + CREATE_PLAYLIST_ITEM => Some("list-add-symbolic"), + _ => self.destination().map(|d| d.icon()), + } + } +} + +mod imp { + use super::*; + use gdk::cairo::glib::ParamSpec; + use std::cell::{Cell, RefCell}; + use std::convert::TryFrom; + + #[derive(Debug, Default, Properties)] + #[properties(wrapper_type = super::SidebarItem)] + pub struct SidebarItem { + #[property(get, set)] + pub id: RefCell, + #[property(get, set)] + pub data: RefCell, + #[property(get, set)] + pub title: RefCell, + #[property(get, set)] + pub navigatable: Cell, + } + + #[glib::object_subclass] + impl ObjectSubclass for SidebarItem { + const NAME: &'static str = "SideBarItem"; + type Type = super::SidebarItem; + type ParentType = glib::Object; + } + + impl ObjectImpl for SidebarItem { + fn properties() -> &'static [ParamSpec] { + Self::derived_properties() + } + + fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { + self.derived_set_property(id, value, pspec); + } + + fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value { + self.derived_property(id, pspec) + } + } +} + +glib::wrapper! { + pub struct SidebarItem(ObjectSubclass); +} diff --git a/src/app/components/sidebar/sidebar_row.rs b/src/app/components/sidebar/sidebar_row.rs new file mode 100644 index 00000000..516a9415 --- /dev/null +++ b/src/app/components/sidebar/sidebar_row.rs @@ -0,0 +1,85 @@ +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::CompositeTemplate; + +use super::SidebarItem; + +impl SidebarRow { + pub fn new(item: SidebarItem) -> Self { + glib::Object::builder().property("item", item).build() + } +} + +mod imp { + use super::*; + use glib::{ParamSpec, Properties}; + use std::cell::RefCell; + use std::convert::TryFrom; + + #[derive(Debug, CompositeTemplate, Properties)] + #[template(resource = "/dev/alextren/Spot/sidebar/sidebar_row.ui")] + #[properties(wrapper_type = super::SidebarRow)] + pub struct SidebarRow { + #[template_child] + pub icon: TemplateChild, + + #[template_child] + pub title: TemplateChild, + + #[property(get, set = Self::set_item)] + pub item: RefCell, + } + + impl SidebarRow { + fn set_item(&self, item: SidebarItem) { + self.title.set_text(item.title().as_str()); + self.icon.set_icon_name(item.icon()); + self.obj().set_tooltip_text(Some(item.title().as_str())); + self.item.replace(item); + } + } + + #[glib::object_subclass] + impl ObjectSubclass for SidebarRow { + const NAME: &'static str = "SidebarRow"; + type Type = super::SidebarRow; + type ParentType = gtk::ListBoxRow; + + fn class_init(klass: &mut Self::Class) { + klass.bind_template(); + } + + fn instance_init(obj: &glib::subclass::InitializingObject) { + obj.init_template(); + } + + fn new() -> Self { + Self { + icon: Default::default(), + title: Default::default(), + item: RefCell::new(glib::Object::new()), + } + } + } + + impl ObjectImpl for SidebarRow { + fn properties() -> &'static [ParamSpec] { + Self::derived_properties() + } + + fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { + self.derived_set_property(id, value, pspec); + } + + fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value { + self.derived_property(id, pspec) + } + } + + impl WidgetImpl for SidebarRow {} + impl ListBoxRowImpl for SidebarRow {} +} + +glib::wrapper! { + pub struct SidebarRow(ObjectSubclass) @extends gtk::Widget, gtk::ListBoxRow; +} diff --git a/src/app/components/sidebar/sidebar_row.ui b/src/app/components/sidebar/sidebar_row.ui new file mode 100644 index 00000000..da15c989 --- /dev/null +++ b/src/app/components/sidebar/sidebar_row.ui @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/src/app/components/sidebar_listbox/mod.rs b/src/app/components/sidebar_listbox/mod.rs deleted file mode 100644 index 960fe346..00000000 --- a/src/app/components/sidebar_listbox/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -mod sidebar_icon_widget; -mod sidebar_item; -mod sidebar_row; - -use crate::app::components::display_add_css_provider; -use gtk::prelude::*; -use gtk::ListBox; -pub use sidebar_item::*; -pub use sidebar_row::*; - -pub fn build_sidebar_listbox(builder: >k::Builder, list_store: &gio::ListStore) -> ListBox { - display_add_css_provider(resource!("/sidebar_listbox/sidebar.css")); - let listbox: gtk::ListBox = builder.object("home_listbox").unwrap(); - listbox.bind_model(Some(list_store), move |obj| { - let item = obj.downcast_ref::().unwrap(); - let row = SideBarRow::new(item); - row.upcast::() - }); - listbox.add_css_class("navigation-sidebar"); - listbox.add_css_class("listbox_sidebar"); - listbox -} diff --git a/src/app/components/sidebar_listbox/sidebar.css b/src/app/components/sidebar_listbox/sidebar.css deleted file mode 100644 index bab390e3..00000000 --- a/src/app/components/sidebar_listbox/sidebar.css +++ /dev/null @@ -1,7 +0,0 @@ -.item_sidebar { - margin: 12px 6px; -} - -.listbox_sidebar { - background-color: @view_bg_color; -} \ No newline at end of file diff --git a/src/app/components/sidebar_listbox/sidebar_icon_widget.rs b/src/app/components/sidebar_listbox/sidebar_icon_widget.rs deleted file mode 100644 index 6be73f5b..00000000 --- a/src/app/components/sidebar_listbox/sidebar_icon_widget.rs +++ /dev/null @@ -1,63 +0,0 @@ -use gtk::prelude::*; -use gtk::subclass::prelude::*; -use gtk::CompositeTemplate; - -mod imp { - - use super::*; - - #[derive(Debug, Default, CompositeTemplate)] - #[template(resource = "/dev/alextren/Spot/sidebar_listbox/sidebar_icon_widget.ui")] - pub struct SideBarItemWidgetIcon { - #[template_child] - pub icon: TemplateChild, - - #[template_child] - pub title: TemplateChild, - } - - #[glib::object_subclass] - impl ObjectSubclass for SideBarItemWidgetIcon { - const NAME: &'static str = "SideBarItemWidgetIcon"; - type Type = super::SideBarItemWidgetIcon; - type ParentType = gtk::Box; - - fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); - } - - fn instance_init(obj: &glib::subclass::InitializingObject) { - obj.init_template(); - } - } - - impl ObjectImpl for SideBarItemWidgetIcon { - fn dispose(&self, obj: &Self::Type) { - while let Some(child) = obj.first_child() { - child.unparent(); - } - } - } - - impl WidgetImpl for SideBarItemWidgetIcon {} - impl BoxImpl for SideBarItemWidgetIcon {} -} - -glib::wrapper! { - pub struct SideBarItemWidgetIcon(ObjectSubclass) @extends gtk::Widget, gtk::Box; -} - -impl SideBarItemWidgetIcon { - pub fn new(title: &str, iconname: Option<&str>) -> Self { - let s: SideBarItemWidgetIcon = - glib::Object::new(&[]).expect("Failed to create an instance of SideBarItemWidgetIcon"); - s.widget().title.set_text(title); - s.widget().icon.set_icon_name(iconname); - s.set_tooltip_text(Option::from(title)); - s - } - - pub fn widget(&self) -> &imp::SideBarItemWidgetIcon { - imp::SideBarItemWidgetIcon::from_instance(self) - } -} diff --git a/src/app/components/sidebar_listbox/sidebar_icon_widget.ui b/src/app/components/sidebar_listbox/sidebar_icon_widget.ui deleted file mode 100644 index cdab7115..00000000 --- a/src/app/components/sidebar_listbox/sidebar_icon_widget.ui +++ /dev/null @@ -1,22 +0,0 @@ - - - - - diff --git a/src/app/components/sidebar_listbox/sidebar_item.rs b/src/app/components/sidebar_listbox/sidebar_item.rs deleted file mode 100644 index 270fa0d1..00000000 --- a/src/app/components/sidebar_listbox/sidebar_item.rs +++ /dev/null @@ -1,137 +0,0 @@ -use gtk::prelude::*; -use gtk::subclass::prelude::*; - -impl SideBarItem { - pub fn new(id: &str, title: &str, iconname: &str, grayedout: bool) -> SideBarItem { - glib::Object::new::(&[ - ("id", &id), - ("title", &title), - ("iconname", &iconname), - ("grayedout", &grayedout), - ]) - .expect("Failed to create") - } - - pub(crate) fn id(&self) -> String { - self.property::("id") - } - - pub(crate) fn title(&self) -> String { - self.property::("title") - } - - pub(crate) fn iconname(&self) -> String { - self.property::("iconname") - } - - pub(crate) fn grayedout(&self) -> bool { - self.property::("grayedout") - } -} - -mod imp { - use super::*; - use gdk::cairo::glib::ParamSpec; - use std::cell::RefCell; - - #[derive(Debug, Default)] - pub struct SideBarItem { - pub id: RefCell>, - pub title: RefCell>, - pub iconname: RefCell>, - pub grayedout: RefCell, - } - - #[glib::object_subclass] - impl ObjectSubclass for SideBarItem { - const NAME: &'static str = "SideBarItem"; - type Type = super::SideBarItem; - type ParentType = glib::Object; - - fn new() -> Self { - Self { - id: RefCell::new(None), - title: RefCell::new(None), - iconname: RefCell::new(None), - grayedout: RefCell::new(false), - } - } - } - - lazy_static! { - static ref PROPERTIES: [glib::ParamSpec; 4] = [ - glib::ParamSpecString::new("id", "ID", "", None, glib::ParamFlags::READWRITE), - glib::ParamSpecString::new("title", "Title", "", None, glib::ParamFlags::READWRITE), - glib::ParamSpecString::new( - "iconname", - "IconName", - "", - None, - glib::ParamFlags::READWRITE - ), - glib::ParamSpecBoolean::new( - "grayedout", - "GrayedOut", - "", - false, - glib::ParamFlags::READWRITE - ), - ]; - } - - impl ObjectImpl for SideBarItem { - fn properties() -> &'static [ParamSpec] { - &*PROPERTIES - } - - fn set_property( - &self, - _obj: &Self::Type, - _id: usize, - value: &glib::Value, - pspec: &glib::ParamSpec, - ) { - match pspec.name() { - "id" => { - let id = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.id.replace(id); - } - "title" => { - let title = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.title.replace(title); - } - "iconname" => { - let iconname = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.iconname.replace(iconname); - } - "grayedout" => { - let grayedout = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.grayedout.replace(grayedout); - } - _ => unimplemented!(), - } - } - - fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { - match pspec.name() { - "id" => self.id.borrow().to_value(), - "title" => self.title.borrow().to_value(), - "iconname" => self.iconname.borrow().to_value(), - "grayedout" => self.grayedout.borrow().to_value(), - _ => unimplemented!(), - } - } - } -} - -glib::wrapper! { - pub struct SideBarItem(ObjectSubclass); -} diff --git a/src/app/components/sidebar_listbox/sidebar_row.rs b/src/app/components/sidebar_listbox/sidebar_row.rs deleted file mode 100644 index c7d6d5c5..00000000 --- a/src/app/components/sidebar_listbox/sidebar_row.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crate::app::components::display_add_css_provider; -use crate::app::components::sidebar_listbox::sidebar_icon_widget::SideBarItemWidgetIcon; -use crate::app::components::sidebar_listbox::SideBarItem; -use gtk::prelude::*; -use gtk::subclass::prelude::*; - -impl SideBarRow { - pub fn new(item: &SideBarItem) -> SideBarRow { - display_add_css_provider(resource!("/sidebar_listbox/sidebar.css")); - let id = item.id(); - let t = item.title(); - let row = - glib::Object::new::(&[("id", &id.as_str())]).expect("Failed to create"); - if item.grayedout() { - let label = gtk::Label::new(Option::from(t.as_str())); - let gtk_box = gtk::Box::new(gtk::Orientation::Horizontal, 12); - gtk_box.append(&label); - row.set_child(Option::from(>k_box)); - row.set_activatable(false); - row.set_selectable(false); - row.set_sensitive(false); - label.add_css_class("caption-heading"); - label.add_css_class("item_sidebar"); - } else { - let widget = SideBarItemWidgetIcon::new(t.as_str(), Some(item.iconname().as_str())); - row.set_child(Option::from(&widget)); - } - row - } - - pub fn id(&self) -> String { - self.property::("id") - } -} - -mod imp { - use super::*; - use gdk::cairo::glib::ParamSpec; - use std::cell::RefCell; - - #[derive(Debug, Default)] - pub struct SideBarRow { - pub id: RefCell>, - } - - #[glib::object_subclass] - impl ObjectSubclass for SideBarRow { - const NAME: &'static str = "SideBarRow"; - type Type = super::SideBarRow; - type ParentType = gtk::ListBoxRow; - - fn new() -> Self { - Self { - id: RefCell::new(None), - } - } - } - - lazy_static! { - static ref PROPERTIES: [glib::ParamSpec; 1] = [glib::ParamSpecString::new( - "id", - "ID", - "", - None, - glib::ParamFlags::READWRITE - ),]; - } - - impl ObjectImpl for SideBarRow { - fn properties() -> &'static [ParamSpec] { - &*PROPERTIES - } - - fn set_property( - &self, - _obj: &Self::Type, - _id: usize, - value: &glib::Value, - pspec: &glib::ParamSpec, - ) { - match pspec.name() { - "id" => { - let id = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.id.replace(id); - } - _ => unimplemented!(), - } - } - - fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { - match pspec.name() { - "id" => self.id.borrow().to_value(), - _ => unimplemented!(), - } - } - } - - impl WidgetImpl for SideBarRow {} - - impl ListBoxRowImpl for SideBarRow {} -} -glib::wrapper! { - pub struct SideBarRow(ObjectSubclass) @extends gtk::Widget, gtk::ListBoxRow; -} diff --git a/src/app/components/user_details/user_details.rs b/src/app/components/user_details/user_details.rs index 671ae894..392684c5 100644 --- a/src/app/components/user_details/user_details.rs +++ b/src/app/components/user_details/user_details.rs @@ -34,7 +34,7 @@ mod imp { type ParentType = gtk::Box; fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); + klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { @@ -54,24 +54,20 @@ glib::wrapper! { impl UserDetailsWidget { fn new() -> Self { display_add_css_provider(resource!("/components/user_details.css")); - glib::Object::new(&[]).expect("Failed to create an instance of UserDetailsWidget") - } - - fn widget(&self) -> &imp::UserDetailsWidget { - imp::UserDetailsWidget::from_instance(self) + glib::Object::new() } fn set_user_name(&self, name: &str) { let context = self.style_context(); context.add_class("user__loaded"); - self.widget().user_name.set_text(name); + self.imp().user_name.set_text(name); } fn connect_bottom_edge(&self, f: F) where F: Fn() + 'static, { - self.widget() + self.imp() .scrolled_window .connect_edge_reached(move |_, pos| { if let gtk::PositionType::Bottom = pos { @@ -84,7 +80,7 @@ impl UserDetailsWidget { where F: Fn(String) + Clone + 'static, { - self.widget() + self.imp() .user_playlists .bind_model(Some(store.unsafe_store()), move |item| { wrap_flowbox_item(item, |item: &AlbumModel| { @@ -118,7 +114,7 @@ impl UserDetails { if let Some(store) = model.get_list_store() { widget.bind_user_playlists( worker, - &*store, + &store, clone!(@weak model => move |uri| { model.open_playlist(uri); }), diff --git a/src/app/components/user_menu/user_menu_model.rs b/src/app/components/user_menu/user_menu_model.rs index c6b2f9b8..99dd39e3 100644 --- a/src/app/components/user_menu/user_menu_model.rs +++ b/src/app/components/user_menu/user_menu_model.rs @@ -1,6 +1,5 @@ use crate::api::clear_user_cache; use crate::app::credentials::Credentials; -use crate::app::models::{PlaylistDescription, PlaylistSummary}; use crate::app::state::{LoginAction, PlaybackAction}; use crate::app::{ActionDispatcher, AppModel}; use std::ops::Deref; @@ -27,7 +26,7 @@ impl UserMenuModel { pub fn logout(&self) { self.dispatcher.dispatch(PlaybackAction::Stop.into()); self.dispatcher.dispatch_async(Box::pin(async { - let _ = Credentials::logout(); + let _ = Credentials::logout().await; let _ = clear_user_cache().await; Some(LoginAction::Logout.into()) })); @@ -43,10 +42,7 @@ impl UserMenuModel { let summaries = playlists .into_iter() .filter(|p| p.owner.id == current_user) - .map(|PlaylistDescription { id, title, .. }| PlaylistSummary { - id, - title, - }) + .map(|p| p.into()) .collect(); LoginAction::SetUserPlaylists(summaries).into() }) diff --git a/src/app/credentials.rs b/src/app/credentials.rs index abba1344..50867f82 100644 --- a/src/app/credentials.rs +++ b/src/app/credentials.rs @@ -27,33 +27,46 @@ impl Credentials { } } - pub fn retrieve() -> Result { - let service = SecretService::new(EncryptionType::Dh)?; - let collection = service.get_default_collection()?; - let items = collection.search_items(make_attributes())?; - let item = items.get(0).ok_or(Error::NoResult)?.get_secret()?; - serde_json::from_slice(&item).map_err(|_| Error::Parse) + pub async fn retrieve() -> Result { + let service = SecretService::connect(EncryptionType::Dh).await?; + let collection = service.get_default_collection().await?; + if collection.is_locked().await? { + collection.unlock().await?; + } + let items = collection.search_items(make_attributes()).await?; + let item = items.get(0).ok_or(Error::NoResult)?.get_secret().await?; + serde_json::from_slice(&item).map_err(|_| Error::Unavailable) } - pub fn logout() -> Result<(), Error> { - let service = SecretService::new(EncryptionType::Dh)?; - let collection = service.get_default_collection()?; - let result = collection.search_items(make_attributes())?; - let item = result.get(0).ok_or(Error::NoResult)?; - item.delete() + pub async fn logout() -> Result<(), Error> { + let service = SecretService::connect(EncryptionType::Dh).await?; + let collection = service.get_default_collection().await?; + if !collection.is_locked().await? { + let result = collection.search_items(make_attributes()).await?; + let item = result.get(0).ok_or(Error::NoResult)?; + item.delete().await + } else { + warn!("Keyring is locked -- not clearing credentials"); + Ok(()) + } } - pub fn save(&self) -> Result<(), Error> { - let service = SecretService::new(EncryptionType::Dh)?; - let collection = service.get_default_collection()?; + pub async fn save(&self) -> Result<(), Error> { + let service = SecretService::connect(EncryptionType::Dh).await?; + let collection = service.get_default_collection().await?; + if collection.is_locked().await? { + collection.unlock().await?; + } let encoded = serde_json::to_vec(&self).unwrap(); - collection.create_item( - "Spotify Credentials", - make_attributes(), - &encoded, - true, - "text/plain", - )?; + collection + .create_item( + "Spotify Credentials", + make_attributes(), + &encoded, + true, + "text/plain", + ) + .await?; Ok(()) } } diff --git a/src/app/dispatch.rs b/src/app/dispatch.rs index d22290af..c54774b7 100644 --- a/src/app/dispatch.rs +++ b/src/app/dispatch.rs @@ -8,6 +8,7 @@ use super::AppAction; pub trait ActionDispatcher { fn dispatch(&self, action: AppAction); + fn dispatch_many(&self, actions: Vec); fn dispatch_local_async(&self, action: LocalBoxFuture<'static, Option>); fn dispatch_async(&self, action: BoxFuture<'static, Option>); fn dispatch_many_async(&self, actions: BoxFuture<'static, Vec>); @@ -31,6 +32,12 @@ impl ActionDispatcher for ActionDispatcherImpl { self.sender.unbounded_send(action).unwrap(); } + fn dispatch_many(&self, actions: Vec) { + for action in actions.into_iter() { + self.sender.unbounded_send(action).unwrap(); + } + } + fn dispatch_local_async(&self, action: LocalBoxFuture<'static, Option>) { let clone = self.sender.clone(); self.worker.send_local_task(async move { @@ -81,8 +88,8 @@ impl DispatchLoop { pub async fn attach(self, mut handler: impl FnMut(AppAction)) { self.receiver .for_each(|action| { - let result = handler(action); - async move { result } + handler(action); + async {} }) .await; } diff --git a/src/app/list_store.rs b/src/app/list_store.rs index 2dce499b..6b4aa929 100644 --- a/src/app/list_store.rs +++ b/src/app/list_store.rs @@ -28,6 +28,11 @@ where &self.store } + pub fn prepend(&mut self, elements: impl Iterator) { + let upcast_vec: Vec = elements.map(|e| e.upcast::()).collect(); + self.store.splice(0, 0, &upcast_vec[..]); + } + pub fn extend(&mut self, elements: impl Iterator) { let upcast_vec: Vec = elements.map(|e| e.upcast::()).collect(); self.store.splice(self.store.n_items(), 0, &upcast_vec[..]); diff --git a/src/app/mod.rs b/src/app/mod.rs index db0cefa3..01b5ef1f 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,6 +1,4 @@ use crate::api::CachedSpotifyClient; -use crate::app::components::sidebar_listbox::{build_sidebar_listbox, SideBarItem}; -use crate::glib::StaticType; use crate::settings::SpotSettings; use futures::channel::mpsc::UnboundedSender; use std::rc::Rc; @@ -80,7 +78,7 @@ impl App { dispatcher.box_clone(), worker.clone(), ), - App::make_login(builder, dispatcher.box_clone()), + App::make_login(builder, dispatcher.box_clone(), worker.clone()), App::make_navigation( builder, Rc::clone(model), @@ -129,8 +127,7 @@ impl App { ) -> Box { let leaflet: libadwaita::Leaflet = builder.object("leaflet").unwrap(); let navigation_stack: gtk::Stack = builder.object("navigation_stack").unwrap(); - let home_list_store = gio::ListStore::new(SideBarItem::static_type()); - let home_listbox = build_sidebar_listbox(builder, &home_list_store); + let home_listbox: gtk::ListBox = builder.object("home_listbox").unwrap(); let model = NavigationModel::new(Rc::clone(&app_model), dispatcher.box_clone()); let screen_factory = ScreenFactory::new( Rc::clone(&app_model), @@ -143,14 +140,17 @@ impl App { leaflet, navigation_stack, home_listbox, - home_list_store, screen_factory, )) } - fn make_login(builder: >k::Builder, dispatcher: Box) -> Box { + fn make_login( + builder: >k::Builder, + dispatcher: Box, + worker: Worker, + ) -> Box { let parent: gtk::Window = builder.object("window").unwrap(); - let model = LoginModel::new(dispatcher); + let model = LoginModel::new(dispatcher, worker); Box::new(Login::new(parent, model)) } diff --git a/src/app/models/album_model.rs b/src/app/models/album_model.rs index d7b932ff..9ebbd55a 100644 --- a/src/app/models/album_model.rs +++ b/src/app/models/album_model.rs @@ -2,13 +2,12 @@ use gio::prelude::*; use glib::subclass::prelude::*; +use glib::Properties; glib::wrapper! { pub struct AlbumModel(ObjectSubclass); } -// Constructor for new instances. This simply calls glib::Object::new() with -// initial values for our two properties and then returns the new instance impl AlbumModel { pub fn new( artist: &String, @@ -18,33 +17,13 @@ impl AlbumModel { uri: &String, ) -> AlbumModel { let year = &year.unwrap_or(0); - glib::Object::new::(&[ - ("artist", artist), - ("album", album), - ("year", year), - ("cover", &cover), - ("uri", uri), - ]) - .expect("Failed to create") - } - - pub fn year(&self) -> Option { - match self.property::("year") { - 0 => None, - year => Some(year), - } - } - - pub fn cover_url(&self) -> Option { - self.property("cover") - } - - pub fn uri(&self) -> String { - self.property("uri") - } - - pub fn album_title(&self) -> String { - self.property("album") + glib::Object::builder() + .property("artist", artist) + .property("album", album) + .property("year", year) + .property("cover", &cover) + .property("uri", uri) + .build() } } @@ -53,105 +32,41 @@ mod imp { use super::*; use std::cell::{Cell, RefCell}; + use std::convert::TryFrom; - // Static array for defining the properties of the new type. - lazy_static! { - static ref PROPERTIES: [glib::ParamSpec; 5] = [ - glib::ParamSpecString::new("artist", "Artist", "", None, glib::ParamFlags::READWRITE), - glib::ParamSpecString::new("album", "Album", "", None, glib::ParamFlags::READWRITE), - glib::ParamSpecUInt::new("year", "Year", "", 0, 9999, 0, glib::ParamFlags::READWRITE), - glib::ParamSpecString::new("cover", "Cover", "", None, glib::ParamFlags::READWRITE), - glib::ParamSpecString::new("uri", "URI", "", None, glib::ParamFlags::READWRITE), - ]; - } - - // This is the struct containing all state carried with - // the new type. Generally this has to make use of - // interior mutability. - #[derive(Default)] + #[derive(Default, Properties)] + #[properties(wrapper_type = super::AlbumModel)] pub struct AlbumModel { + #[property(get, set)] album: RefCell, + #[property(get, set)] artist: RefCell, + #[property(get, set)] year: Cell, + #[property(get, set)] cover: RefCell>, + #[property(get, set)] uri: RefCell, } - // ObjectSubclass is the trait that defines the new type and - // contains all information needed by the GObject type system, - // including the new type's name, parent type, etc. #[glib::object_subclass] impl ObjectSubclass for AlbumModel { - // This type name must be unique per process. const NAME: &'static str = "AlbumModel"; - type Type = super::AlbumModel; - - // The parent type this one is inheriting from. type ParentType = glib::Object; } - // Trait that is used to override virtual methods of glib::Object. impl ObjectImpl for AlbumModel { fn properties() -> &'static [glib::ParamSpec] { - &*PROPERTIES + Self::derived_properties() } - // Called whenever a property is set on this instance. The id - // is the same as the index of the property in the PROPERTIES array. - fn set_property( - &self, - _obj: &Self::Type, - _id: usize, - value: &glib::Value, - pspec: &glib::ParamSpec, - ) { - match pspec.name() { - "album" => { - let album = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.album.replace(album); - } - "artist" => { - let artist = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.artist.replace(artist); - } - "year" => { - let year = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.year.replace(year); - } - "cover" => { - let cover: Option = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.cover.replace(cover); - } - "uri" => { - let uri = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.uri.replace(uri); - } - _ => unimplemented!(), - } + fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { + self.derived_set_property(id, value, pspec) } - // Called whenever a property is retrieved from this instance. The id - // is the same as the index of the property in the PROPERTIES array. - fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { - match pspec.name() { - "album" => self.album.borrow().to_value(), - "artist" => self.artist.borrow().to_value(), - "year" => self.year.get().to_value(), - "cover" => self.cover.borrow().to_value(), - "uri" => self.uri.borrow().to_value(), - _ => unimplemented!(), - } + fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value { + self.derived_property(id, pspec) } } } diff --git a/src/app/models/artist_model.rs b/src/app/models/artist_model.rs index 0cf7fcb7..61d42d0c 100644 --- a/src/app/models/artist_model.rs +++ b/src/app/models/artist_model.rs @@ -2,25 +2,19 @@ use gio::prelude::*; use glib::subclass::prelude::*; +use glib::Properties; glib::wrapper! { pub struct ArtistModel(ObjectSubclass); } -// Constructor for new instances. This simply calls glib::Object::new() with -// initial values for our two properties and then returns the new instance impl ArtistModel { pub fn new(artist: &str, image: &Option, id: &str) -> ArtistModel { - glib::Object::new::(&[("artist", &artist), ("image", image), ("id", &id)]) - .expect("Failed to create") - } - - pub fn image_url(&self) -> Option { - self.property("image") - } - - pub fn id(&self) -> String { - self.property("id") + glib::Object::builder() + .property("artist", &artist) + .property("image", image) + .property("id", &id) + .build() } } @@ -28,87 +22,37 @@ mod imp { use super::*; use std::cell::RefCell; + use std::convert::TryFrom; - // Static array for defining the properties of the new type. - lazy_static! { - static ref PROPERTIES: [glib::ParamSpec; 3] = [ - glib::ParamSpecString::new("artist", "Artist", "", None, glib::ParamFlags::READWRITE), - glib::ParamSpecString::new("image", "Image", "", None, glib::ParamFlags::READWRITE), - glib::ParamSpecString::new("id", "id", "", None, glib::ParamFlags::READWRITE), - ]; - } - - // This is the struct containing all state carried with - // the new type. Generally this has to make use of - // interior mutability. - #[derive(Default)] + #[derive(Default, Properties)] + #[properties(wrapper_type = super::ArtistModel)] pub struct ArtistModel { + #[property(get, set)] artist: RefCell, + #[property(get, set)] image: RefCell>, + #[property(get, set)] id: RefCell, } - // ObjectSubclass is the trait that defines the new type and - // contains all information needed by the GObject type system, - // including the new type's name, parent type, etc. #[glib::object_subclass] impl ObjectSubclass for ArtistModel { - // This type name must be unique per process. const NAME: &'static str = "ArtistModel"; - type Type = super::ArtistModel; - - // The parent type this one is inheriting from. type ParentType = glib::Object; } - // Trait that is used to override virtual methods of glib::Object. impl ObjectImpl for ArtistModel { fn properties() -> &'static [glib::ParamSpec] { - &*PROPERTIES + Self::derived_properties() } - // Called whenever a property is set on this instance. The id - // is the same as the index of the property in the PROPERTIES array. - fn set_property( - &self, - _obj: &Self::Type, - _id: usize, - value: &glib::Value, - pspec: &glib::ParamSpec, - ) { - match pspec.name() { - "artist" => { - let artist = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.artist.replace(artist); - } - "image" => { - let image = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.image.replace(image); - } - "id" => { - let id = value - .get() - .expect("type conformity checked by `Object::set_property`"); - self.id.replace(id); - } - _ => unimplemented!(), - } + fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { + self.derived_set_property(id, value, pspec) } - // Called whenever a property is retrieved from this instance. The id - // is the same as the index of the property in the PROPERTIES array. - fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { - match pspec.name() { - "artist" => self.artist.borrow().to_value(), - "image" => self.image.borrow().to_value(), - "id" => self.id.borrow().to_value(), - _ => unimplemented!(), - } + fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value { + self.derived_property(id, pspec) } } } diff --git a/src/app/models/mod.rs b/src/app/models/mod.rs index b7b2f6d2..d6328b15 100644 --- a/src/app/models/mod.rs +++ b/src/app/models/mod.rs @@ -41,6 +41,12 @@ impl From<&PlaylistDescription> for AlbumModel { } } +impl From for PlaylistSummary { + fn from(PlaylistDescription { id, title, .. }: PlaylistDescription) -> Self { + Self { id, title } + } +} + impl From for AlbumModel { fn from(playlist: PlaylistDescription) -> Self { Self::from(&playlist) diff --git a/src/app/models/songs/song_list_model.rs b/src/app/models/songs/song_list_model.rs index d1d5f1cf..2c56751a 100644 --- a/src/app/models/songs/song_list_model.rs +++ b/src/app/models/songs/song_list_model.rs @@ -1,8 +1,9 @@ use gio::prelude::*; use gio::ListModel; +use glib::Properties; use glib::StaticType; use gtk::subclass::prelude::*; -use std::cell::{Ref, RefCell, RefMut}; +use std::cell::{Cell, Ref, RefCell, RefMut}; use super::support::*; use crate::app::models::*; @@ -60,15 +61,17 @@ glib::wrapper! { impl SongListModel { pub fn new(batch_size: u32) -> Self { - glib::Object::new(&[("batch-size", &batch_size)]).unwrap() + glib::Object::builder() + .property("batch-size", batch_size) + .build() } fn inner_mut(&mut self) -> RefMut { - imp::SongListModel::from_instance(self).get_mut() + self.imp().get_mut() } fn inner(&self) -> Ref { - imp::SongListModel::from_instance(self).get() + self.imp().get() } fn notify_changes(&self, changes: impl IntoIterator + 'static) { @@ -170,74 +173,56 @@ impl SongListModel { mod imp { use super::*; + use std::convert::TryFrom; - pub struct SongListModel(RefCell>); + #[derive(Default, Properties)] + #[properties(wrapper_type = super::SongListModel)] + pub struct SongListModel { + #[property(get, set = Self::set_batch_size, name = "batch-size")] + batch_size: Cell, + song_list: RefCell>, + } + + impl SongListModel { + fn set_batch_size(&self, batch_size: u32) { + self.batch_size.set(batch_size); + self.song_list + .replace(Some(SongList::new_sized(batch_size as usize))); + } + } #[glib::object_subclass] impl ObjectSubclass for SongListModel { const NAME: &'static str = "SongList"; - type Type = super::SongListModel; type ParentType = glib::Object; type Interfaces = (ListModel,); - - fn new() -> Self { - Self(RefCell::new(None)) - } - } - - lazy_static! { - static ref PROPERTIES: [glib::ParamSpec; 1] = [glib::ParamSpecUInt::new( - "batch-size", - "Size of the batches", - "", - 1, - u32::MAX, - 1, - glib::ParamFlags::READWRITE, - )]; } impl ObjectImpl for SongListModel { fn properties() -> &'static [glib::ParamSpec] { - &*PROPERTIES + Self::derived_properties() } - fn set_property( - &self, - _obj: &Self::Type, - _id: usize, - value: &glib::Value, - pspec: &glib::ParamSpec, - ) { - if "batch-size" == pspec.name() { - let batch_size = value.get::().unwrap(); - *self.0.borrow_mut() = Some(SongList::new_sized(batch_size as usize)) - } else { - unimplemented!() - } + fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { + self.derived_set_property(id, value, pspec); } - fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { - if "batch-size" == pspec.name() { - let size = self.get().batch_size() as u32; - size.to_value() - } else { - unimplemented!() - } + fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value { + self.derived_property(id, pspec) } } impl ListModelImpl for SongListModel { - fn item_type(&self, _: &Self::Type) -> glib::Type { + fn item_type(&self) -> glib::Type { SongModel::static_type() } - fn n_items(&self, _: &Self::Type) -> u32 { + fn n_items(&self) -> u32 { self.get().partial_len() as u32 } - fn item(&self, _: &Self::Type, position: u32) -> Option { + fn item(&self, position: u32) -> Option { self.get() .index_continuous(position as usize) .map(|m| m.clone().upcast()) @@ -246,13 +231,13 @@ mod imp { impl SongListModel { pub fn get_mut(&self) -> RefMut { - RefMut::map(self.0.borrow_mut(), |s| { + RefMut::map(self.song_list.borrow_mut(), |s| { s.as_mut().expect("set at construction") }) } pub fn get(&self) -> Ref { - Ref::map(self.0.borrow(), |s| { + Ref::map(self.song_list.borrow(), |s| { s.as_ref().expect("set at construction") }) } diff --git a/src/app/models/songs/song_model.rs b/src/app/models/songs/song_model.rs index 3141dbe2..e83c1ba0 100644 --- a/src/app/models/songs/song_model.rs +++ b/src/app/models/songs/song_model.rs @@ -13,8 +13,8 @@ glib::wrapper! { impl SongModel { pub fn new(song: SongDescription) -> Self { - let o: Self = glib::Object::new(&[]).unwrap(); - imp::SongModel::from_instance(&o).song.replace(Some(song)); + let o: Self = glib::Object::new(); + o.imp().song.replace(Some(song)); o } @@ -39,7 +39,7 @@ impl SongModel { } pub fn bind_index(&self, o: &impl ObjectType, property: &str) { - imp::SongModel::from_instance(self).push_binding( + self.imp().push_binding( self.bind_property("index", o, property) .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) .build(), @@ -47,7 +47,7 @@ impl SongModel { } pub fn bind_artist(&self, o: &impl ObjectType, property: &str) { - imp::SongModel::from_instance(self).push_binding( + self.imp().push_binding( self.bind_property("artist", o, property) .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) .build(), @@ -55,7 +55,7 @@ impl SongModel { } pub fn bind_title(&self, o: &impl ObjectType, property: &str) { - imp::SongModel::from_instance(self).push_binding( + self.imp().push_binding( self.bind_property("title", o, property) .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) .build(), @@ -63,7 +63,7 @@ impl SongModel { } pub fn bind_duration(&self, o: &impl ObjectType, property: &str) { - imp::SongModel::from_instance(self).push_binding( + self.imp().push_binding( self.bind_property("duration", o, property) .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) .build(), @@ -71,7 +71,7 @@ impl SongModel { } pub fn bind_playing(&self, o: &impl ObjectType, property: &str) { - imp::SongModel::from_instance(self).push_binding( + self.imp().push_binding( self.bind_property("playing", o, property) .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) .build(), @@ -79,7 +79,7 @@ impl SongModel { } pub fn bind_selected(&self, o: &impl ObjectType, property: &str) { - imp::SongModel::from_instance(self).push_binding( + self.imp().push_binding( self.bind_property("selected", o, property) .flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE) .build(), @@ -87,17 +87,17 @@ impl SongModel { } pub fn unbind_all(&self) { - imp::SongModel::from_instance(self).unbind_all(self); + self.imp().unbind_all(self); } pub fn description(&self) -> impl Deref + '_ { - Ref::map(imp::SongModel::from_instance(self).song.borrow(), |s| { + Ref::map(self.imp().song.borrow(), |s| { s.as_ref().expect("song set at constructor") }) } pub fn into_description(&self) -> SongDescription { - imp::SongModel::from_instance(&self) + self.imp() .song .borrow() .as_ref() @@ -139,6 +139,7 @@ mod imp { bindings.bindings.drain(..).for_each(|b| b.unbind()); } } + #[glib::object_subclass] impl ObjectSubclass for SongModel { const NAME: &'static str = "SongModel"; @@ -148,64 +149,20 @@ mod imp { lazy_static! { static ref PROPERTIES: [glib::ParamSpec; 8] = [ - glib::ParamSpecString::new( - "id", - "Spotify identifier", - "", - None, - glib::ParamFlags::READABLE - ), - glib::ParamSpecUInt::new( - "index", - "Track number within an album", - "", - 1, - u32::MAX, - 1, - glib::ParamFlags::READABLE, - ), - glib::ParamSpecString::new( - "title", - "Title of the track", - "", - None, - glib::ParamFlags::READABLE - ), - glib::ParamSpecString::new( - "artist", - "Artists, comma separated", - "", - None, - glib::ParamFlags::READABLE - ), - glib::ParamSpecString::new( - "duration", - "Duration (formatted)", - "", - None, - glib::ParamFlags::READABLE, - ), - glib::ParamSpecString::new( - "art", - "URL to the cover art", - "", - None, - glib::ParamFlags::READABLE, - ), - glib::ParamSpecBoolean::new( - "playing", - "Playing", - "", - false, - glib::ParamFlags::READWRITE - ), - glib::ParamSpecBoolean::new( - "selected", - "Selected", - "", - false, - glib::ParamFlags::READWRITE, - ), + glib::ParamSpecString::builder("id").read_only().build(), + glib::ParamSpecUInt::builder("index").read_only().build(), + glib::ParamSpecString::builder("title").read_only().build(), + glib::ParamSpecString::builder("artist").read_only().build(), + glib::ParamSpecString::builder("duration") + .read_only() + .build(), + glib::ParamSpecString::builder("art").read_only().build(), + glib::ParamSpecBoolean::builder("playing") + .readwrite() + .build(), + glib::ParamSpecBoolean::builder("selected") + .readwrite() + .build(), ]; } @@ -214,13 +171,7 @@ mod imp { &*PROPERTIES } - fn set_property( - &self, - _obj: &Self::Type, - _id: usize, - value: &glib::Value, - pspec: &glib::ParamSpec, - ) { + fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { match pspec.name() { "playing" => { let is_playing = value @@ -246,7 +197,7 @@ mod imp { } } - fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { + fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { match pspec.name() { "index" => self .song diff --git a/src/app/state/app_state.rs b/src/app/state/app_state.rs index cfa72e26..addb2f9e 100644 --- a/src/app/state/app_state.rs +++ b/src/app/state/app_state.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; +use crate::app::models::{PlaylistDescription, PlaylistSummary}; use crate::app::state::{ browser_state::{BrowserAction, BrowserEvent, BrowserState}, login_state::{LoginAction, LoginEvent, LoginState}, @@ -29,6 +30,8 @@ pub enum AppAction { UnsaveSelection, EnableSelection(SelectionContext), CancelSelection, + CreatePlaylist(PlaylistDescription), + UpdatePlaylistName(PlaylistSummary), } impl AppAction { @@ -91,6 +94,7 @@ pub enum AppEvent { Started, Raised, NotificationShown(String), + PlaylistCreatedNotificationShown(String), NowPlayingShown, SettingsEvent(SettingsEvent), } @@ -201,6 +205,30 @@ impl AppState { vec![] } } + AppAction::CreatePlaylist(playlist) => { + let id = playlist.id.clone(); + let mut events = forward_action( + LoginAction::PrependUserPlaylist(vec![playlist.clone().into()]), + &mut self.logged_user, + ); + let mut more_events = forward_action( + BrowserAction::PrependPlaylistsContent(vec![playlist]), + &mut self.browser, + ); + events.append(&mut more_events); + events.push(AppEvent::PlaylistCreatedNotificationShown(id)); + events + } + AppAction::UpdatePlaylistName(s) => { + let mut events = forward_action( + LoginAction::UpdateUserPlaylist(s.clone()), + &mut self.logged_user, + ); + let mut more_events = + forward_action(BrowserAction::UpdatePlaylistName(s), &mut self.browser); + events.append(&mut more_events); + events + } AppAction::PlaybackAction(a) => forward_action(a, &mut self.playback), AppAction::BrowserAction(a) => forward_action(a, &mut self.browser), AppAction::SelectionAction(a) => forward_action(a, &mut self.selection), diff --git a/src/app/state/browser_state.rs b/src/app/state/browser_state.rs index 4a008bbf..aa78f7f5 100644 --- a/src/app/state/browser_state.rs +++ b/src/app/state/browser_state.rs @@ -1,16 +1,17 @@ use super::{ - AppEvent, ArtistState, DetailsState, HomeState, PlaylistDetailsState, ScreenName, SearchState, - UpdatableState, UserState, + AppAction, AppEvent, ArtistState, DetailsState, HomeState, PlaylistDetailsState, ScreenName, + SearchState, UpdatableState, UserState, }; use crate::app::models::*; -use crate::app::state::AppAction; use std::borrow::Cow; use std::iter::Iterator; #[derive(Clone, Debug)] pub enum BrowserAction { SetNavigationHidden(bool), + SetHomeVisiblePage(&'static str), SetLibraryContent(Vec), + PrependPlaylistsContent(Vec), AppendLibraryContent(Vec), SetPlaylistsContent(Vec), AppendPlaylistsContent(Vec), @@ -18,6 +19,7 @@ pub enum BrowserAction { SetAlbumDetails(Box), AppendAlbumTracks(String, Box), SetPlaylistDetails(Box), + UpdatePlaylistName(PlaylistSummary), AppendPlaylistTracks(String, Box), Search(String), SetSearchResults(Box), @@ -45,6 +47,7 @@ impl From for AppAction { #[derive(Eq, PartialEq, Clone, Debug)] pub enum BrowserEvent { NavigationHidden(bool), + HomeVisiblePageChanged(&'static str), LibraryUpdated, SavedPlaylistsUpdated, AlbumDetailsLoaded(String), diff --git a/src/app/state/login_state.rs b/src/app/state/login_state.rs index ca609128..39eb93a2 100644 --- a/src/app/state/login_state.rs +++ b/src/app/state/login_state.rs @@ -20,9 +20,12 @@ pub enum SetLoginSuccessAction { #[derive(Clone, Debug)] pub enum LoginAction { + ShowLogin, TryLogin(TryLoginAction), SetLoginSuccess(SetLoginSuccessAction), SetUserPlaylists(Vec), + UpdateUserPlaylist(PlaylistSummary), + PrependUserPlaylist(Vec), SetLoginFailure, RefreshToken, SetRefreshedToken { @@ -52,6 +55,7 @@ pub enum LoginCompletedEvent { #[derive(Clone, Debug)] pub enum LoginEvent { + LoginShown, LoginStarted(LoginStartedEvent), LoginCompleted(LoginCompletedEvent), UserPlaylistsLoaded, @@ -82,6 +86,7 @@ impl UpdatableState for LoginState { fn update_with(&mut self, action: Cow) -> Vec { match action.into_owned() { + LoginAction::ShowLogin => vec![LoginEvent::LoginShown.into()], LoginAction::TryLogin(TryLoginAction::Password { username, password }) => { vec![ LoginEvent::LoginStarted(LoginStartedEvent::Password { username, password }) @@ -123,6 +128,17 @@ impl UpdatableState for LoginState { self.playlists = playlists; vec![LoginEvent::UserPlaylistsLoaded.into()] } + LoginAction::UpdateUserPlaylist(PlaylistSummary { id, title }) => { + if let Some(p) = self.playlists.iter_mut().find(|p| p.id == id) { + p.title = title; + } + vec![LoginEvent::UserPlaylistsLoaded.into()] + } + LoginAction::PrependUserPlaylist(mut summaries) => { + summaries.append(&mut self.playlists); + self.playlists = summaries; + vec![LoginEvent::UserPlaylistsLoaded.into()] + } } } } diff --git a/src/app/state/playback_state.rs b/src/app/state/playback_state.rs index b17974e4..a4c23339 100644 --- a/src/app/state/playback_state.rs +++ b/src/app/state/playback_state.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::time::Instant; use crate::app::models::{SongBatch, SongDescription, SongListModel, SongListModelPending}; use crate::app::state::{AppAction, AppEvent, UpdatableState}; @@ -8,7 +9,8 @@ use crate::app::{BatchQuery, LazyRandomIndex, SongsSource}; pub struct PlaybackState { index: LazyRandomIndex, songs: SongListModel, - position: Option, + list_position: Option, + seek_position: PositionMillis, source: Option, repeat: RepeatMode, is_playing: bool, @@ -21,7 +23,7 @@ impl PlaybackState { } pub fn is_playing(&self) -> bool { - self.is_playing && self.position.is_some() + self.is_playing && self.list_position.is_some() } pub fn is_shuffled(&self) -> bool { @@ -58,17 +60,22 @@ impl PlaybackState { } pub fn current_song_id(&self) -> Option { - Some(self.index(self.position?)?.id) + Some(self.index(self.list_position?)?.id) } pub fn current_song(&self) -> Option { - self.index(self.position?) + self.index(self.list_position?) + } + + fn next_id(&self) -> Option { + self.next_index() + .and_then(|i| Some(self.songs().index(i)?.description().id.clone())) } fn clear(&mut self, source: Option) -> SongListModelPending { self.source = source; self.index = Default::default(); - self.position = None; + self.list_position = None; self.songs.clear() } @@ -98,14 +105,14 @@ impl PlaybackState { pub fn dequeue(&mut self, ids: &[String]) { let current_id = self.current_song_id(); self.songs.remove(ids).commit(); - self.position = current_id.and_then(|id| self.songs.find_index(&id)); + self.list_position = current_id.and_then(|id| self.songs.find_index(&id)); self.index.shrink(self.songs.len()); } fn swap_pos(&mut self, index: usize, other_index: usize) { let len = self.songs.len(); - self.position = self - .position + self.list_position = self + .list_position .map(|position| match position { i if i == index => other_index, i if i == other_index => index, @@ -149,24 +156,29 @@ impl PlaybackState { } fn stop(&mut self) { - self.position = None; + self.list_position = None; self.is_playing = false; + self.seek_position.set(0, false); } fn play_index(&mut self, index: usize) -> Option { self.is_playing = true; - self.position.replace(index); + self.list_position.replace(index); + self.seek_position.set(0, true); self.index.next_until(index + 1); self.current_song_id() } fn play_next(&mut self) -> Option { - self.next_index().and_then(move |i| self.play_index(i)) + self.next_index().and_then(move |i| { + self.seek_position.set(0, true); + self.play_index(i) + }) } pub fn next_index(&self) -> Option { let len = self.songs.len(); - self.position.and_then(|p| match self.repeat { + self.list_position.and_then(|p| match self.repeat { RepeatMode::Song => Some(p), RepeatMode::Playlist if len != 0 => Some((p + 1) % len), RepeatMode::None => Some(p + 1).filter(|&i| i < len), @@ -175,12 +187,23 @@ impl PlaybackState { } fn play_prev(&mut self) -> Option { - self.prev_index().and_then(move |i| self.play_index(i)) + self.prev_index().and_then(move |i| { + // Only jump to the previous track if we aren't more than 2 seconds (2,000 ms) into the current track. + // Otherwise, seek to the start of the current track. + // (This replicates the behavior of official Spotify clients.) + if self.seek_position.current() <= 2000 { + self.seek_position.set(0, true); + self.play_index(i) + } else { + self.seek_position.set(0, true); + None + } + }) } pub fn prev_index(&self) -> Option { let len = self.songs.len(); - self.position.and_then(|p| match self.repeat { + self.list_position.and_then(|p| match self.repeat { RepeatMode::Song => Some(p), RepeatMode::Playlist if len != 0 => Some((if p == 0 { len } else { p }) - 1), RepeatMode::None => Some(p).filter(|&i| i > 0).map(|i| i - 1), @@ -189,8 +212,14 @@ impl PlaybackState { } fn toggle_play(&mut self) -> Option { - if self.position.is_some() { + if self.list_position.is_some() { self.is_playing = !self.is_playing; + + match self.is_playing { + false => self.seek_position.pause(), + true => self.seek_position.resume(), + }; + Some(self.is_playing) } else { None @@ -199,7 +228,7 @@ impl PlaybackState { fn toggle_shuffle(&mut self) { self.is_shuffled = !self.is_shuffled; - let old = self.position.replace(0).unwrap_or(0); + let old = self.list_position.replace(0).unwrap_or(0); self.index.reset_picking_first(old); } } @@ -209,7 +238,8 @@ impl Default for PlaybackState { Self { index: LazyRandomIndex::default(), songs: SongListModel::new(50), - position: None, + list_position: None, + seek_position: PositionMillis::new(1.0), source: None, repeat: RepeatMode::None, is_playing: false, @@ -235,6 +265,7 @@ pub enum PlaybackAction { SetVolume(f64), Next, Previous, + Preload, Queue(Vec), Dequeue(String), } @@ -254,6 +285,7 @@ pub enum PlaybackEvent { SeekSynced(u32), VolumeSet(f64), TrackChanged(String), + Preload(String), ShuffleChanged, PlaylistChanged, PlaybackStopped, @@ -345,7 +377,7 @@ impl UpdatableState for PlaybackState { Some(PlaybackEvent::PlaybackResumed), ]) } else { - vec![] + make_events(vec![Some(PlaybackEvent::TrackSeeked(0))]) } } PlaybackAction::Load(id) => { @@ -358,6 +390,13 @@ impl UpdatableState for PlaybackState { vec![] } } + PlaybackAction::Preload => { + if let Some(id) = self.next_id() { + vec![PlaybackEvent::Preload(id)] + } else { + vec![] + } + } PlaybackAction::LoadPagedSongs(source, batch) if Some(&source) == self.source.as_ref() => { @@ -385,14 +424,60 @@ impl UpdatableState for PlaybackState { self.dequeue(&[id]); vec![PlaybackEvent::PlaylistChanged] } - PlaybackAction::Seek(pos) => vec![PlaybackEvent::TrackSeeked(pos)], - PlaybackAction::SyncSeek(pos) => vec![PlaybackEvent::SeekSynced(pos)], + PlaybackAction::Seek(pos) => { + self.seek_position.set(pos as u64 * 1000, true); + vec![PlaybackEvent::TrackSeeked(pos)] + } + PlaybackAction::SyncSeek(pos) => { + self.seek_position.set(pos as u64 * 1000, true); + vec![PlaybackEvent::SeekSynced(pos)] + } PlaybackAction::SetVolume(volume) => vec![PlaybackEvent::VolumeSet(volume)], _ => vec![], } } } +#[derive(Debug)] +struct PositionMillis { + last_known_position: u64, + last_resume_instant: Option, + rate: f32, +} + +impl PositionMillis { + fn new(rate: f32) -> Self { + Self { + last_known_position: 0, + last_resume_instant: None, + rate, + } + } + + fn current(&self) -> u64 { + let current_progress = self.last_resume_instant.map(|ri| { + let elapsed = ri.elapsed().as_millis() as f32; + let real_elapsed = self.rate * elapsed; + real_elapsed.ceil() as u64 + }); + self.last_known_position + current_progress.unwrap_or(0) + } + + fn set(&mut self, position: u64, playing: bool) { + self.last_known_position = position; + self.last_resume_instant = if playing { Some(Instant::now()) } else { None } + } + + fn pause(&mut self) { + self.last_known_position = self.current(); + self.last_resume_instant = None; + } + + fn resume(&mut self) { + self.last_resume_instant = Some(Instant::now()); + } +} + #[cfg(test)] mod tests { @@ -417,7 +502,7 @@ mod tests { impl PlaybackState { fn current_position(&self) -> Option { - self.position + self.list_position } fn prev_id(&self) -> Option { @@ -425,11 +510,6 @@ mod tests { .and_then(|i| Some(self.songs().index(i)?.description().id.clone())) } - fn next_id(&self) -> Option { - self.next_index() - .and_then(|i| Some(self.songs().index(i)?.description().id.clone())) - } - fn song_ids(&self) -> Vec { self.songs() .collect() diff --git a/src/app/state/screen_states.rs b/src/app/state/screen_states.rs index 7adf66a8..56b98bdd 100644 --- a/src/app/state/screen_states.rs +++ b/src/app/state/screen_states.rs @@ -122,6 +122,12 @@ impl UpdatableState for PlaylistDetailsState { self.playlist = Some(*playlist.clone()); vec![BrowserEvent::PlaylistDetailsLoaded(id)] } + BrowserAction::UpdatePlaylistName(PlaylistSummary { id, title }) if id == &self.id => { + if let Some(p) = self.playlist.as_mut() { + p.title = title.clone(); + } + vec![BrowserEvent::PlaylistDetailsLoaded(self.id.clone())] + } BrowserAction::AppendPlaylistTracks(id, song_batch) if id == &self.id => { self.songs.add(*song_batch.clone()).commit(); vec![BrowserEvent::PlaylistTracksAppended(id.clone())] @@ -192,6 +198,7 @@ impl UpdatableState for ArtistState { pub struct HomeState { pub name: ScreenName, + pub visible_page: &'static str, pub next_albums_page: Pagination<()>, pub albums: ListStore, pub next_playlists_page: Pagination<()>, @@ -203,6 +210,7 @@ impl Default for HomeState { fn default() -> Self { Self { name: ScreenName::Home, + visible_page: "library", next_albums_page: Pagination::new((), 30), albums: ListStore::new(), next_playlists_page: Pagination::new((), 30), @@ -218,6 +226,10 @@ impl UpdatableState for HomeState { fn update_with(&mut self, action: Cow) -> Vec { match action.as_ref() { + BrowserAction::SetHomeVisiblePage(page) => { + self.visible_page = *page; + vec![BrowserEvent::HomeVisiblePageChanged(page)] + } BrowserAction::SetLibraryContent(content) => { if !self.albums.eq(content, |a, b| a.uri() == b.id) { self.albums.replace_all(content.iter().map(|a| a.into())); @@ -227,6 +239,10 @@ impl UpdatableState for HomeState { vec![] } } + BrowserAction::PrependPlaylistsContent(content) => { + self.playlists.prepend(content.iter().map(|a| a.into())); + vec![BrowserEvent::SavedPlaylistsUpdated] + } BrowserAction::AppendLibraryContent(content) => { self.next_albums_page.set_loaded_count(content.len()); self.albums.extend(content.iter().map(|a| a.into())); @@ -267,6 +283,12 @@ impl UpdatableState for HomeState { self.playlists.extend(content.iter().map(|p| p.into())); vec![BrowserEvent::SavedPlaylistsUpdated] } + BrowserAction::UpdatePlaylistName(PlaylistSummary { id, title }) => { + if let Some(p) = self.playlists.iter().find(|p| &p.uri() == id) { + p.set_album(title.to_owned()); + } + vec![BrowserEvent::SavedPlaylistsUpdated] + } BrowserAction::AppendSavedTracks(song_batch) => { if self.saved_tracks.add(*song_batch.clone()).commit() { vec![BrowserEvent::SavedTracksUpdated] diff --git a/src/dbus/types.rs b/src/dbus/types.rs index aea0429b..5594081f 100644 --- a/src/dbus/types.rs +++ b/src/dbus/types.rs @@ -20,17 +20,15 @@ impl Type for LoopStatus { } } -impl TryFrom<&Value<'_>> for LoopStatus { - type Error = zvariant::Error; - - fn try_from(value: &Value<'_>) -> Result { - let s = String::try_from(value)?; - let s = s.as_str(); - Ok(match s { - "Track" => LoopStatus::Track, - "Playlist" => LoopStatus::Playlist, - _ => LoopStatus::None, - }) +impl From> for LoopStatus { + fn from(value: Value<'_>) -> Self { + String::try_from(value) + .map(|s| match s.as_str() { + "Track" => LoopStatus::Track, + "Playlist" => LoopStatus::Playlist, + _ => LoopStatus::None, + }) + .unwrap_or(LoopStatus::None) } } diff --git a/src/main.rs b/src/main.rs index d93633f7..089438ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,6 @@ use gio::prelude::*; use gio::ApplicationFlags; use gio::SimpleAction; use gtk::prelude::*; -use libadwaita::ColorScheme; mod api; mod app; @@ -91,18 +90,14 @@ fn main() { fn startup(settings: &settings::SpotSettings) { gtk::init().unwrap_or_else(|_| panic!("Failed to initialize GTK")); - libadwaita::init(); + libadwaita::init().unwrap_or_else(|_| panic!("Failed to initialize libadwaita")); let manager = libadwaita::StyleManager::default(); let res = gio::Resource::load(config::PKGDATADIR.to_owned() + "/spot.gresource") .expect("Could not load resources"); gio::resources_register(&res); - manager.set_color_scheme(if settings.prefers_dark_theme { - ColorScheme::PreferDark - } else { - ColorScheme::PreferLight - }); + manager.set_color_scheme(settings.theme_preference); let provider = gtk::CssProvider::new(); provider.load_from_resource("/dev/alextren/Spot/app.css"); @@ -151,8 +146,21 @@ fn register_actions(app: >k::Application, sender: UnboundedSender) app.add_action(&make_action( "search", AppAction::BrowserAction(BrowserAction::NavigationPush(ScreenName::Search)), - sender, + sender.clone(), )); + + app.add_action(&{ + let action = SimpleAction::new("open_playlist", Some(glib::VariantTy::STRING)); + action.set_enabled(true); + action.connect_activate(move |_, playlist_id| { + if let Some(id) = playlist_id.and_then(|s| s.str()) { + sender + .unbounded_send(AppAction::ViewPlaylist(id.to_owned())) + .unwrap(); + } + }); + action + }); } fn make_action( diff --git a/src/meson.build b/src/meson.build index 61339caf..e1bf1338 100644 --- a/src/meson.build +++ b/src/meson.build @@ -102,14 +102,13 @@ sources = files( './app/components/saved_tracks/saved_tracks.rs', './app/components/saved_tracks/saved_tracks_model.rs', './app/components/saved_tracks/mod.rs', -'./app/components/sidebar_listbox/sidebar_item.rs', -'./app/components/sidebar_listbox/sidebar_row.rs', -'./app/components/sidebar_listbox/mod.rs', -'./app/components/sidebar_listbox/sidebar_icon_widget.rs', './app/components/search/search_model.rs', './app/components/search/search_button.rs', './app/components/search/mod.rs', './app/components/search/search.rs', +'./app/components/settings/settings_model.rs', +'./app/components/settings/settings.rs', +'./app/components/settings/mod.rs', './app/components/artist/mod.rs', './app/components/player_notifier.rs', './app/components/window/mod.rs', @@ -124,6 +123,8 @@ sources = files( './app/components/selection/widget.rs', './app/components/selection/component.rs', './app/components/selection/mod.rs', +'./app/components/scrolling_header/scrolling_header_widget.rs', +'./app/components/scrolling_header/mod.rs', './app/components/mod.rs', './app/components/details/album_header.rs', './app/components/details/release_details.rs', @@ -137,15 +138,19 @@ sources = files( './app/components/login/login.rs', './app/components/login/mod.rs', './app/components/login/login_model.rs', -'./app/components/settings/mod.rs', -'./app/components/settings/settings_model.rs', -'./app/components/settings/settings.rs', './app/components/playlist_details/playlist_details_model.rs', './app/components/playlist_details/mod.rs', './app/components/playlist_details/playlist_details.rs', +'./app/components/playlist_details/playlist_headerbar.rs', +'./app/components/playlist_details/playlist_header.rs', './app/components/headerbar/widget.rs', './app/components/headerbar/component.rs', './app/components/headerbar/mod.rs', +'./app/components/sidebar/sidebar_item.rs', +'./app/components/sidebar/sidebar_row.rs', +'./app/components/sidebar/create_playlist.rs', +'./app/components/sidebar/sidebar.rs', +'./app/components/sidebar/mod.rs', './app/components/album/album.rs', './app/components/album/mod.rs', './app/components/labels.rs', diff --git a/src/player/mod.rs b/src/player/mod.rs index 8d64551f..72ed45ba 100644 --- a/src/player/mod.rs +++ b/src/player/mod.rs @@ -23,6 +23,7 @@ pub enum Command { PlayerStop, PlayerSeek(u32), PlayerSetVolume(f64), + PlayerPreload(SpotifyId), RefreshToken, ReloadSettings, } @@ -94,6 +95,13 @@ impl SpotifyPlayerDelegate for AppPlayerDelegate { .unbounded_send(PlaybackAction::SyncSeek(position).into()) .unwrap(); } + + fn preload_next_track(&self) { + self.sender + .borrow_mut() + .unbounded_send(PlaybackAction::Preload.into()) + .unwrap(); + } } #[tokio::main] diff --git a/src/player/player.rs b/src/player/player.rs index 81894130..8480b9db 100644 --- a/src/player/player.rs +++ b/src/player/player.rs @@ -2,6 +2,7 @@ use futures::channel::mpsc::UnboundedReceiver; use futures::stream::StreamExt; use librespot::core::authentication::Credentials; +use librespot::core::cache::Cache; use librespot::core::config::SessionConfig; use librespot::core::keymaster; use librespot::core::session::{Session, SessionError}; @@ -29,6 +30,7 @@ pub enum SpotifyError { LoginFailed, TokenFailed, PlayerNotReady, + TechnicalError, } impl Error for SpotifyError {} @@ -39,6 +41,9 @@ impl fmt::Display for SpotifyError { Self::LoginFailed => write!(f, "Login failed!"), Self::TokenFailed => write!(f, "Token retrieval failed!"), Self::PlayerNotReady => write!(f, "Player is not responding."), + Self::TechnicalError => { + write!(f, "A technical error occured. Check your connectivity.") + } } } } @@ -50,6 +55,7 @@ pub trait SpotifyPlayerDelegate { fn refresh_successful(&self, token: String, token_expiry_time: SystemTime); fn report_error(&self, error: SpotifyError); fn notify_playback_state(&self, position: u32); + fn preload_next_track(&self); } #[derive(Debug, Clone, PartialEq, Eq)] @@ -62,6 +68,7 @@ pub enum AudioBackend { pub struct SpotifyPlayerSettings { pub bitrate: Bitrate, pub backend: AudioBackend, + pub gapless: bool, pub ap_port: Option, } @@ -69,6 +76,7 @@ impl Default for SpotifyPlayerSettings { fn default() -> Self { Self { bitrate: Bitrate::Bitrate160, + gapless: true, backend: AudioBackend::PulseAudio, ap_port: None, } @@ -76,77 +84,91 @@ impl Default for SpotifyPlayerSettings { } pub struct SpotifyPlayer { - settings: RefCell, - player: RefCell>, - mixer: RefCell>>, - session: RefCell>, + settings: SpotifyPlayerSettings, + player: Option, + mixer: Option>, + session: Option, delegate: Rc, } impl SpotifyPlayer { pub fn new(settings: SpotifyPlayerSettings, delegate: Rc) -> Self { Self { - settings: RefCell::new(settings), - mixer: RefCell::new(None), - player: RefCell::new(None), - session: RefCell::new(None), + settings, + mixer: None, + player: None, + session: None, delegate, } } - async fn handle(&self, action: Command) -> Result<(), SpotifyError> { - let mut player = self.player.borrow_mut(); - let mut session = self.session.borrow_mut(); + async fn handle(&mut self, action: Command) -> Result<(), SpotifyError> { match action { Command::PlayerSetVolume(volume) => { - if let Some(mixer) = self.mixer.borrow_mut().as_mut() { + if let Some(mixer) = self.mixer.as_mut() { mixer.set_volume((VolumeCtrl::MAX_VOLUME as f64 * volume) as u16); } Ok(()) } Command::PlayerResume => { - let player = player.as_ref().ok_or(SpotifyError::PlayerNotReady)?; - player.play(); + self.player + .as_ref() + .ok_or(SpotifyError::PlayerNotReady)? + .play(); Ok(()) } Command::PlayerPause => { - let player = player.as_ref().ok_or(SpotifyError::PlayerNotReady)?; - player.pause(); + self.player + .as_ref() + .ok_or(SpotifyError::PlayerNotReady)? + .pause(); Ok(()) } Command::PlayerStop => { - let player = player.as_ref().ok_or(SpotifyError::PlayerNotReady)?; - player.stop(); + self.player + .as_ref() + .ok_or(SpotifyError::PlayerNotReady)? + .stop(); Ok(()) } Command::PlayerSeek(position) => { - let player = player.as_ref().ok_or(SpotifyError::PlayerNotReady)?; - player.seek(position); + self.player + .as_ref() + .ok_or(SpotifyError::PlayerNotReady)? + .seek(position); Ok(()) } Command::PlayerLoad(track) => { - let player = player.as_mut().ok_or(SpotifyError::PlayerNotReady)?; - player.load(track, true, 0); + self.player + .as_mut() + .ok_or(SpotifyError::PlayerNotReady)? + .load(track, true, 0); + Ok(()) + } + Command::PlayerPreload(track) => { + self.player + .as_mut() + .ok_or(SpotifyError::PlayerNotReady)? + .preload(track); Ok(()) } Command::RefreshToken => { - let session = session.as_ref().ok_or(SpotifyError::PlayerNotReady)?; + let session = self.session.as_ref().ok_or(SpotifyError::PlayerNotReady)?; let (token, token_expiry_time) = get_access_token_and_expiry_time(session).await?; self.delegate.refresh_successful(token, token_expiry_time); Ok(()) } Command::Logout => { - session + self.session .take() .ok_or(SpotifyError::PlayerNotReady)? .shutdown(); - let _ = player.take(); + let _ = self.player.take(); Ok(()) } Command::PasswordLogin { username, password } => { let credentials = Credentials::with_password(username, password.clone()); - let new_session = - create_session(credentials, self.settings.borrow().ap_port).await?; + let new_session = create_session(&credentials, self.settings.ap_port).await?; let (token, token_expiry_time) = get_access_token_and_expiry_time(&new_session).await?; let credentials = credentials::Credentials { @@ -160,8 +182,8 @@ impl SpotifyPlayer { let (new_player, channel) = self.create_player(new_session.clone()); tokio::task::spawn_local(player_setup_delegate(channel, Rc::clone(&self.delegate))); - player.replace(new_player); - session.replace(new_session); + self.player.replace(new_player); + self.session.replace(new_session); Ok(()) } @@ -171,45 +193,43 @@ impl SpotifyPlayer { auth_type: AuthenticationType::AUTHENTICATION_SPOTIFY_TOKEN, auth_data: token.clone().into_bytes(), }; - let new_session = - create_session(credentials, self.settings.borrow().ap_port).await?; + let new_session = create_session(&credentials, self.settings.ap_port).await?; self.delegate .token_login_successful(new_session.username(), token); let (new_player, channel) = self.create_player(new_session.clone()); tokio::task::spawn_local(player_setup_delegate(channel, Rc::clone(&self.delegate))); - player.replace(new_player); - session.replace(new_session); + self.player.replace(new_player); + self.session.replace(new_session); Ok(()) } Command::ReloadSettings => { let settings = SpotSettings::new_from_gsettings().unwrap_or_default(); - self.settings.replace(settings.player_settings); + self.settings = settings.player_settings; - let session = session.as_ref().ok_or(SpotifyError::PlayerNotReady)?; - let (new_player, channel) = self.create_player(session.clone()); + let session = self.session.take().ok_or(SpotifyError::PlayerNotReady)?; + let (new_player, channel) = self.create_player(session); tokio::task::spawn_local(player_setup_delegate(channel, Rc::clone(&self.delegate))); - player.replace(new_player); + self.player.replace(new_player); Ok(()) } } } - fn create_player(&self, session: Session) -> (Player, PlayerEventChannel) { - let settings = self.settings.borrow(); - let backend = settings.backend.clone(); + fn create_player(&mut self, session: Session) -> (Player, PlayerEventChannel) { + let backend = self.settings.backend.clone(); let player_config = PlayerConfig { - bitrate: settings.bitrate, + gapless: self.settings.gapless, + bitrate: self.settings.bitrate, ..Default::default() }; info!("bitrate: {:?}", &player_config.bitrate); - let filter = self + let soft_volume = self .mixer - .borrow_mut() .get_or_insert_with(|| { let mix = Box::new(SoftMixer::open(MixerConfig { // This value feels reasonable to me. Feel free to change it @@ -221,8 +241,8 @@ impl SpotifyPlayer { mix.set_volume(VolumeCtrl::MAX_VOLUME); mix }) - .get_audio_filter(); - Player::new(player_config, session, filter, move || match backend { + .get_soft_volume(); + Player::new(player_config, session, soft_volume, move || match backend { AudioBackend::PulseAudio => { info!("using pulseaudio"); let backend = audio_backend::find(Some("pulseaudio".to_string())).unwrap(); @@ -237,9 +257,10 @@ impl SpotifyPlayer { } pub async fn start(self, receiver: UnboundedReceiver) -> Result<(), ()> { - let _self = &self; + let _self = RefCell::new(self); receiver - .for_each(|action| async move { + .for_each(|action| async { + let mut _self = _self.borrow_mut(); match _self.handle(action).await { Ok(_) => {} Err(err) => _self.delegate.report_error(err), @@ -261,7 +282,8 @@ user-top-read,\ user-read-recently-played,\ playlist-modify-public,\ playlist-modify-private,\ -streaming"; +streaming,\ +playlist-modify-public"; const KNOWN_AP_PORTS: [Option; 4] = [None, Some(80), Some(443), Some(4070)]; @@ -270,48 +292,57 @@ async fn get_access_token_and_expiry_time( ) -> Result<(String, SystemTime), SpotifyError> { let token = keymaster::get_token(session, CLIENT_ID, SCOPES) .await - .map_err(|e| { - dbg!(e); - SpotifyError::TokenFailed - })?; + .map_err(|_e| SpotifyError::TokenFailed)?; let expiry_time = SystemTime::now() + Duration::from_secs(token.expires_in.into()); Ok((token.access_token, expiry_time)) } +async fn create_session_with_port( + credentials: &Credentials, + ap_port: Option, +) -> Result { + let session_config = SessionConfig { + ap_port, + ..Default::default() + }; + let root = glib::user_cache_dir().join("spot").join("librespot"); + let cache = Cache::new( + Some(root.join("credentials")), + Some(root.join("volume")), + Some(root.join("audio")), + None, + ) + .map_err(|e| dbg!(e)) + .ok(); + match Session::connect(session_config, credentials.clone(), cache, true).await { + Ok(r) => Ok(r.0), + Err(SessionError::IoError(_)) => Err(SpotifyError::TechnicalError), + Err(SessionError::AuthenticationError(err)) => { + warn!("Login failure: {}", err); + Err(SpotifyError::LoginFailed) + } + } +} + async fn create_session( - credentials: Credentials, + credentials: &Credentials, ap_port: Option, ) -> Result { match ap_port { - Some(ap_port) => { - let session_config = SessionConfig { - ap_port: Some(ap_port), - ..Default::default() - }; - let result = Session::connect(session_config, credentials, None).await; - result.map_err(|e| { - dbg!(e); - SpotifyError::LoginFailed - }) - } + Some(_) => create_session_with_port(credentials, ap_port).await, None => { - for port in KNOWN_AP_PORTS { - let session_config = SessionConfig { - ap_port: port, - ..Default::default() - }; - let result = Session::connect(session_config, credentials.clone(), None).await; - - match result { - Ok(session) => return Ok(session), - Err(SessionError::IoError(_)) => {} - Err(SessionError::AuthenticationError(_)) => { - return Err(SpotifyError::LoginFailed) + let mut ports_to_try = KNOWN_AP_PORTS.iter(); + loop { + if let Some(next_port) = ports_to_try.next() { + let res = create_session_with_port(credentials, *next_port).await; + match res { + Err(SpotifyError::TechnicalError) => continue, + _ => break res, } + } else { + break Err(SpotifyError::TechnicalError); } } - - Err(SpotifyError::LoginFailed) } } } @@ -328,6 +359,10 @@ async fn player_setup_delegate( PlayerEvent::Playing { position_ms, .. } => { delegate.notify_playback_state(position_ms); } + PlayerEvent::TimeToPreloadNextTrack { .. } => { + debug!("Requestiong next track to be preloaded..."); + delegate.preload_next_track(); + } _ => {} } } diff --git a/src/settings.rs b/src/settings.rs index a29621e2..fe7d3f47 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,5 +1,6 @@ use crate::player::{AudioBackend, SpotifyPlayerSettings}; use gio::prelude::SettingsExt; +use libadwaita::ColorScheme; use librespot::playback::config::Bitrate; const SETTINGS: &str = "dev.alextren.Spot"; @@ -50,6 +51,8 @@ impl SpotifyPlayerSettings { )), _ => None, }?; + let gapless = settings.boolean("gapless-playback"); + let ap_port_val = settings.uint("ap-port"); if ap_port_val > 65535 { panic!("Invalid access point port"); @@ -66,6 +69,7 @@ impl SpotifyPlayerSettings { Some(Self { bitrate, backend, + gapless, ap_port, }) } @@ -73,7 +77,7 @@ impl SpotifyPlayerSettings { #[derive(Debug, Clone)] pub struct SpotSettings { - pub prefers_dark_theme: bool, + pub theme_preference: ColorScheme, pub player_settings: SpotifyPlayerSettings, pub window: WindowGeometry, } @@ -81,9 +85,14 @@ pub struct SpotSettings { impl SpotSettings { pub fn new_from_gsettings() -> Option { let settings = gio::Settings::new(SETTINGS); - let prefers_dark_theme = settings.boolean("prefers-dark-theme"); + let theme_preference = match settings.enum_("theme-preference") { + 0 => Some(ColorScheme::ForceLight), + 1 => Some(ColorScheme::ForceDark), + 2 => Some(ColorScheme::Default), + _ => None, + }?; Some(Self { - prefers_dark_theme, + theme_preference, player_settings: SpotifyPlayerSettings::new_from_gsettings()?, window: WindowGeometry::new_from_gsettings(), }) @@ -93,7 +102,7 @@ impl SpotSettings { impl Default for SpotSettings { fn default() -> Self { Self { - prefers_dark_theme: true, + theme_preference: ColorScheme::PreferDark, player_settings: Default::default(), window: Default::default(), } diff --git a/src/spot.gresource.xml b/src/spot.gresource.xml index 2e9be3c1..e80b831b 100644 --- a/src/spot.gresource.xml +++ b/src/spot.gresource.xml @@ -21,6 +21,8 @@ app/components/details/release_details.ui app/components/playlist_details/playlist_details.ui + app/components/playlist_details/playlist_header.ui + app/components/playlist_details/playlist_header.css app/components/artist_details/artist_details.css app/components/artist_details/artist_details.ui @@ -48,13 +50,16 @@ app/components/selection/selection_toolbar.css app/components/headerbar/headerbar.ui - - app/components/sidebar_listbox/sidebar.css - app/components/sidebar_listbox/sidebar_icon_widget.ui + app/components/playlist_details/playlist_headerbar.ui + + app/components/sidebar/sidebar_row.ui + app/components/sidebar/create_playlist.ui + + app/components/scrolling_header/scrolling_header.ui app/components/selection/icons/music-queue-symbolic.svg app/components/selection/icons/playlist2-symbolic.svg - app/components/sidebar_listbox/icons/library-music-symbolic.svg + app/components/sidebar/icons/library-music-symbolic.svg - + \ No newline at end of file diff --git a/src/window.ui.in b/src/window.ui.in index aea463e2..703f3ddc 100644 --- a/src/window.ui.in +++ b/src/window.ui.in @@ -87,6 +87,9 @@ 200 1 +