diff --git a/Cargo.lock b/Cargo.lock index 6047441..99094ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,12 +27,6 @@ dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -80,9 +74,9 @@ checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "alot" @@ -134,9 +128,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -149,9 +143,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -183,9 +177,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "appit" @@ -207,9 +201,9 @@ dependencies = [ [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "arboard" @@ -237,7 +231,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -269,9 +263,9 @@ dependencies = [ [[package]] name = "ashpd" -version = "0.9.2" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d43c03d9e36dd40cab48435be0b09646da362c278223ca535493877b2c1dee9" +checksum = "e9c39d707614dbcc6bed00015539f488d8e3fe3e66ed60961efc0c90f4b380b3" dependencies = [ "async-fs", "async-net", @@ -339,9 +333,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock", "cfg-if", @@ -405,7 +399,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -445,7 +439,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -462,7 +456,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -473,23 +467,23 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "attribute-derive" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f18fc482cf559bca9efe778ba2fd0d1c16a31d5d24a2c886ed16b2d217e454" +checksum = "f1800e974930e9079c965b9ffbcb6667a40401063a26396c7b4f15edc92da690" dependencies = [ "attribute-derive-macro", "derive-where", "manyhow", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] name = "attribute-derive-macro" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85958950e587256a16c72325ff3c4f3e4db25999173e9ca2864665be84ff63b" +checksum = "5d908eb786ef94296bff86f90130b3b748b49401dc81fd2bb8b3dccd44cfacbd" dependencies = [ "collection_literals", "interpolator", @@ -498,7 +492,7 @@ dependencies = [ "proc-macro2", "quote 1.0.37", "quote-use", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -532,9 +526,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" +checksum = "fe7c2840b66236045acd2607d5866e274380afd87ef99d6226e961e2cb47df45" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -544,9 +538,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" +checksum = "ad3a619a9de81e1d7de1f1186dcba4506ed661a0e483d84410fdef0ee87b2f96" dependencies = [ "bindgen", "cc", @@ -566,7 +560,7 @@ dependencies = [ "addr2line", "cfg-if", "libc", - "miniz_oxide 0.8.0", + "miniz_oxide", "object", "rustc-demangle", "windows-targets 0.52.6", @@ -624,7 +618,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.85", + "syn 2.0.87", "which", ] @@ -663,9 +657,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitstream-io" -version = "2.5.3" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b81e1519b0d82120d2fd469d5bfb2919a9361c48b02d82d04befc1cdd2002452" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" [[package]] name = "block" @@ -739,7 +733,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -815,9 +809,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.31" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -905,9 +899,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -915,9 +909,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -934,14 +928,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "clipboard-win" @@ -1110,9 +1104,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -1185,7 +1179,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] name = "cushy" version = "0.4.0" -source = "git+https://github.com/khonsulabs/cushy.git?branch=main#0fe7f789693a12bf61c5a3cba32b69d0e3a8bb9a" +source = "git+https://github.com/khonsulabs/cushy.git?branch=main#620ab2dc44cd3ea9c6c3c61ca0086fee42baef37" dependencies = [ "ahash", "alot", @@ -1215,14 +1209,14 @@ dependencies = [ [[package]] name = "cushy-macros" version = "0.4.0" -source = "git+https://github.com/khonsulabs/cushy.git?branch=main#0fe7f789693a12bf61c5a3cba32b69d0e3a8bb9a" +source = "git+https://github.com/khonsulabs/cushy.git?branch=main#620ab2dc44cd3ea9c6c3c61ca0086fee42baef37" dependencies = [ "attribute-derive", "manyhow", "proc-macro2", "quote 1.0.37", "quote-use", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1290,7 +1284,7 @@ dependencies = [ "proc-macro2", "quote 1.0.37", "strsim 0.11.1", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1312,7 +1306,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1360,7 +1354,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1381,7 +1375,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1391,7 +1385,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1426,7 +1420,7 @@ dependencies = [ "oauth2", "palette", "plotters", - "reqwest 0.12.8", + "reqwest 0.12.9", "reqwest-middleware", "rspotify", "tokio", @@ -1450,6 +1444,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote 1.0.37", + "syn 2.0.87", +] + [[package]] name = "dlib" version = "0.5.2" @@ -1533,7 +1538,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1554,7 +1559,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1621,15 +1626,14 @@ dependencies = [ [[package]] name = "exr" -version = "1.72.0" +version = "1.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" dependencies = [ "bit_field", - "flume", "half", "lebe", - "miniz_oxide 0.7.4", + "miniz_oxide", "rayon-core", "smallvec", "zune-inflate", @@ -1643,15 +1647,15 @@ checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fdeflate" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" +checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" dependencies = [ "simd-adler32", ] @@ -1677,12 +1681,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1691,15 +1695,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "spin", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1708,9 +1703,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "font-types" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda6e36206148f69fc6ecb1bb6c0dedd7ee469f3db1d0dc2045beea28430ca43" +checksum = "b3971f9a5ca983419cdc386941ba3b9e1feba01a0ab888adf78739feb2798492" dependencies = [ "bytemuck", ] @@ -1765,7 +1760,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1866,9 +1861,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ "fastrand", "futures-core", @@ -1885,7 +1880,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2141,9 +2136,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "hassle-rs" @@ -2330,7 +2325,7 @@ dependencies = [ "http 1.1.0", "http-cache", "http-cache-semantics", - "reqwest 0.12.8", + "reqwest 0.12.9", "reqwest-middleware", "serde", "url", @@ -2479,7 +2474,7 @@ dependencies = [ "hyper 1.5.0", "hyper-util", "log", - "rustls 0.23.15", + "rustls 0.23.17", "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", @@ -2505,9 +2500,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -2545,6 +2540,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote 1.0.37", + "syn 2.0.87", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2553,19 +2666,30 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "image" -version = "0.25.4" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc144d44a31d753b02ce64093d532f55ff8dc4ebf2ffb8a63c0dda691385acae" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" dependencies = [ "bytemuck", "byteorder-lite", @@ -2607,7 +2731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.1", ] [[package]] @@ -2639,7 +2763,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2762,7 +2886,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kludgine" version = "0.11.0" -source = "git+https://github.com/khonsulabs/kludgine#2f7755a1a9b7cae67711f7c41ee2cd2c6b12fd64" +source = "git+https://github.com/khonsulabs/kludgine#3d7b7164230449f914fa48cc4ccdf2d28b7188f2" dependencies = [ "ahash", "alot", @@ -2808,9 +2932,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libdbus-sys" @@ -2823,13 +2947,12 @@ dependencies = [ [[package]] name = "libfuzzer-sys" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa" dependencies = [ "arbitrary", "cc", - "once_cell", ] [[package]] @@ -2844,9 +2967,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -2861,14 +2984,12 @@ dependencies = [ [[package]] name = "librespot-audio" -version = "0.5.0-dev" -source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#1a07ff535da49d61542df84e3aaeb6e7160d1172" +version = "0.5.0" +source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#b52a176c3076285006c6d39c6a0455e2b1033790" dependencies = [ "aes", - "byteorder", "bytes", "ctr", - "futures-core", "futures-util", "http-body-util", "hyper 1.5.0", @@ -2883,8 +3004,8 @@ dependencies = [ [[package]] name = "librespot-core" -version = "0.5.0-dev" -source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#1a07ff535da49d61542df84e3aaeb6e7160d1172" +version = "0.5.0" +source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#b52a176c3076285006c6d39c6a0455e2b1033790" dependencies = [ "aes", "base64 0.22.1", @@ -2915,6 +3036,7 @@ dependencies = [ "once_cell", "parking_lot", "pbkdf2", + "pin-project-lite", "priority-queue", "protobuf", "protobuf-json-mapping", @@ -2939,11 +3061,10 @@ dependencies = [ [[package]] name = "librespot-metadata" -version = "0.5.0-dev" -source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#1a07ff535da49d61542df84e3aaeb6e7160d1172" +version = "0.5.0" +source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#b52a176c3076285006c6d39c6a0455e2b1033790" dependencies = [ "async-trait", - "byteorder", "bytes", "librespot-core", "librespot-protocol", @@ -2957,8 +3078,8 @@ dependencies = [ [[package]] name = "librespot-oauth" -version = "0.5.0-dev" -source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#1a07ff535da49d61542df84e3aaeb6e7160d1172" +version = "0.5.0" +source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#b52a176c3076285006c6d39c6a0455e2b1033790" dependencies = [ "log", "oauth2", @@ -2968,10 +3089,9 @@ dependencies = [ [[package]] name = "librespot-playback" -version = "0.5.0-dev" -source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#1a07ff535da49d61542df84e3aaeb6e7160d1172" +version = "0.5.0" +source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#b52a176c3076285006c6d39c6a0455e2b1033790" dependencies = [ - "byteorder", "futures-util", "librespot-audio", "librespot-core", @@ -2989,8 +3109,8 @@ dependencies = [ [[package]] name = "librespot-protocol" -version = "0.5.0-dev" -source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#1a07ff535da49d61542df84e3aaeb6e7160d1172" +version = "0.5.0" +source = "git+https://github.com/photovoltex/librespot.git?branch=integrate-dealer#b52a176c3076285006c6d39c6a0455e2b1033790" dependencies = [ "protobuf", "protobuf-codegen", @@ -3002,6 +3122,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "litrs" version = "0.4.1" @@ -3083,7 +3209,7 @@ dependencies = [ "manyhow-macros", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3114,7 +3240,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3124,6 +3250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ "cfg-if", + "rayon", ] [[package]] @@ -3194,7 +3321,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3209,15 +3336,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -3450,7 +3568,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3512,7 +3630,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3794,7 +3912,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3870,7 +3988,7 @@ dependencies = [ "by_address", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3976,7 +4094,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4005,7 +4123,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4086,14 +4204,14 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] name = "polling" -version = "3.7.3" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", @@ -4144,7 +4262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4203,7 +4321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" dependencies = [ "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4327,7 +4445,7 @@ dependencies = [ "proc-macro-utils", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4428,6 +4546,7 @@ dependencies = [ "loop9", "quick-error", "rav1e", + "rayon", "rgb", ] @@ -4487,9 +4606,9 @@ dependencies = [ [[package]] name = "reflink-copy" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31414597d1cd7fdd2422798b7652a6329dda0fe0219e6335a13d5bcaa9aeb6" +checksum = "17400ed684c3a0615932f00c271ae3eea13e47056a1455821995122348ab6438" dependencies = [ "cfg-if", "rustix", @@ -4504,7 +4623,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -4519,9 +4638,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -4589,9 +4708,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", @@ -4640,7 +4759,7 @@ dependencies = [ "anyhow", "async-trait", "http 1.1.0", - "reqwest 0.12.8", + "reqwest 0.12.9", "serde", "thiserror", "tower-service", @@ -4648,9 +4767,9 @@ dependencies = [ [[package]] name = "rfd" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af382a047821a08aa6bfc09ab0d80ff48d45d8726f7cd8e44891f7cb4a4278e" +checksum = "46f6f80a9b882647d9014673ca9925d30ffc9750f2eed2b4490e189eaebd01e8" dependencies = [ "ashpd", "block2", @@ -4748,7 +4867,7 @@ dependencies = [ "async-trait", "log", "maybe-async", - "reqwest 0.12.8", + "reqwest 0.12.9", "serde_json", "thiserror", ] @@ -4787,9 +4906,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags 2.6.0", "errno", @@ -4826,9 +4945,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.15" +version = "0.23.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e" dependencies = [ "aws-lc-rs", "log", @@ -5008,9 +5127,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -5024,29 +5143,29 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "serde" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -5072,7 +5191,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5282,9 +5401,6 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] [[package]] name = "spinning_top" @@ -5331,6 +5447,12 @@ dependencies = [ "xxhash-rust", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -5374,7 +5496,7 @@ dependencies = [ "proc-macro2", "quote 1.0.37", "rustversion", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5385,9 +5507,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svg_fmt" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" +checksum = "ce5d813d71d82c4cbc1742135004e4a79fd870214c155443451c139c9470a0aa" [[package]] name = "swash" @@ -5508,9 +5630,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote 1.0.37", @@ -5542,10 +5664,21 @@ dependencies = [ ] [[package]] -name = "sys-locale" -version = "0.3.1" +name = "synstructure" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote 1.0.37", + "syn 2.0.87", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" dependencies = [ "libc", ] @@ -5626,9 +5759,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -5648,22 +5781,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5755,6 +5888,16 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -5772,9 +5915,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -5795,7 +5938,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5835,7 +5978,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.15", + "rustls 0.23.17", "rustls-pki-types", "tokio", ] @@ -5871,7 +6014,7 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls 0.23.15", + "rustls 0.23.17", "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", @@ -5951,7 +6094,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -6030,7 +6173,7 @@ dependencies = [ "httparse", "log", "rand", - "rustls 0.23.15", + "rustls 0.23.17", "rustls-pki-types", "sha1", "thiserror", @@ -6084,15 +6227,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-properties" version = "0.1.3" @@ -6137,9 +6271,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", @@ -6159,6 +6293,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -6295,7 +6441,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -6329,7 +6475,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6718,7 +6864,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -6729,7 +6875,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -6740,7 +6886,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -6751,7 +6897,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -7078,6 +7224,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "x11-dl" version = "2.21.0" @@ -7147,9 +7305,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" +checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f" [[package]] name = "xxhash-rust" @@ -7164,10 +7322,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" [[package]] -name = "zbus" -version = "4.4.0" +name = "yoke" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote 1.0.37", + "syn 2.0.87", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1162094dc63b1629fcc44150bcceeaa80798cd28bcbe7fa987b65a034c258608" dependencies = [ "async-broadcast", "async-executor", @@ -7182,19 +7364,17 @@ dependencies = [ "enumflags2", "event-listener", "futures-core", - "futures-sink", "futures-util", "hex", "nix", "ordered-stream", - "rand", "serde", "serde_repr", - "sha1", "static_assertions", "tracing", "uds_windows", - "windows-sys 0.52.0", + "windows-sys 0.59.0", + "winnow", "xdg-home", "zbus_macros", "zbus_names", @@ -7203,25 +7383,28 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.4.0" +version = "5.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +checksum = "2cd2dcdce3e2727f7d74b7e33b5a89539b3cc31049562137faf7ae4eb86cd16d" dependencies = [ "proc-macro-crate", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", + "zbus_names", + "zvariant", "zvariant_utils", ] [[package]] name = "zbus_names" -version = "3.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +checksum = "856b7a38811f71846fd47856ceee8bccaec8399ff53fb370247e66081ace647b" dependencies = [ "serde", "static_assertions", + "winnow", "zvariant", ] @@ -7249,7 +7432,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote 1.0.37", + "syn 2.0.87", + "synstructure", ] [[package]] @@ -7258,6 +7462,28 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote 1.0.37", + "syn 2.0.87", +] + [[package]] name = "zune-core" version = "0.4.12" @@ -7284,38 +7510,43 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.2.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +checksum = "a1200ee6ac32f1e5a312e455a949a4794855515d34f9909f4a3e082d14e1a56f" dependencies = [ "endi", "enumflags2", "serde", "static_assertions", "url", + "winnow", "zvariant_derive", + "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "4.2.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +checksum = "687e3b97fae6c9104fbbd36c73d27d149abf04fb874e2efbd84838763daa8916" dependencies = [ "proc-macro-crate", "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "syn 2.0.87", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "2.1.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +checksum = "20d1d011a38f12360e5fcccceeff5e2c42a8eb7f27f0dcba97a0862ede05c9c6" dependencies = [ "proc-macro2", "quote 1.0.37", - "syn 2.0.85", + "serde", + "static_assertions", + "syn 2.0.87", + "winnow", ] diff --git a/src/api.rs b/src/api.rs index 8731039..a1f1b24 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,4 +1,5 @@ use std::future::Future; +use std::sync::Arc; use std::time::{Duration, Instant}; use chrono::TimeDelta; @@ -6,7 +7,7 @@ use futures_util::lock::Mutex; use librespot_core::Session; use librespot_oauth::OAuthToken; use reqwest::StatusCode; -use rspotify::model::{Page, PrivateUser, SimplifiedPlaylist, UserId}; +use rspotify::model::{Page, PrivateUser, SavedTrack, SimplifiedPlaylist, UserId}; use rspotify::prelude::*; use rspotify::{AuthCodeSpotify, ClientError, ClientResult, Config, Token}; use rspotify::http::HttpError; @@ -20,6 +21,8 @@ pub struct SpotifyContext { token: Mutex } +pub type SpotifyContextRef = Arc; + impl SpotifyContext { pub fn new(session: Session, token: OAuthToken) -> SpotifyContext { let config = Config { @@ -112,6 +115,10 @@ impl SpotifyContext { self.api_with_retry(|api| api.current_user_playlists_manual(limit, offset)).await.ok_or(()) } + pub async fn current_user_saved_tracks(&self, limit: Option, offset: Option) -> Result, ()> { + self.api_with_retry(|api| api.current_user_saved_tracks_manual(None, limit, offset)).await.ok_or(()) + } + } fn librespot_token_to_rspotify(token: &OAuthToken) -> Token { diff --git a/src/main.rs b/src/main.rs index 8e1f62d..6c8ac63 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,40 +1,30 @@ use std::thread; -use api::SpotifyContext; +use api::{SpotifyContext, SpotifyContextRef}; use auth::get_token; use clap::Parser; use cli::Args; -use cushy::{figures::units::Lp, styles::Dimension, value::Dynamic, widget::MakeWidget, window::MakeWindow, Application, Open, PendingApp, Run, TokioRuntime}; +use cushy::{ + value::Dynamic, widget::MakeWidget, window::MakeWindow, Application, Open, PendingApp, Run, + TokioRuntime, +}; use librespot_core::{authentication::Credentials, Session, SessionConfig}; -use librespot_playback::{audio_backend, config::{AudioFormat, PlayerConfig}, mixer::NoOpVolume, player::Player}; -use widgets::{library::playlist::playlists_widget, virtual_list::{VirtualListContent, VirtualList}, ActivePage}; +use librespot_playback::{ + audio_backend, + config::{AudioFormat, PlayerConfig}, + mixer::NoOpVolume, + player::Player, +}; +use widgets::{library::playlist::playlists_widget, pages::liked::LikedSongsPage, ActivePage}; -mod vibrancy; -mod theme; -mod cli; -mod auth; -mod widgets; -mod rt; mod api; - -#[derive(Debug)] -struct TestVirtualList; - -impl VirtualListContent for TestVirtualList { - fn item_count(&self) -> impl cushy::value::IntoValue { - 50 - } - fn item_height(&self) -> impl cushy::value::IntoValue { - cushy::styles::Dimension::Lp(Lp::inches_f(0.5)) - } - fn widget_at(&self, index: usize) -> impl MakeWidget { - // println!("Creating item {}", index); - format!("Item {}", index) - } - fn width(&self) -> impl cushy::value::IntoValue { - Dimension::Lp(Lp::inches_f(10.)) - } -} +mod auth; +mod cli; +mod nodebug; +mod rt; +mod theme; +mod vibrancy; +mod widgets; fn main() -> cushy::Result { let args = Args::parse(); @@ -47,36 +37,44 @@ fn main() -> cushy::Result { let audio_format = AudioFormat::default(); let credentials = Credentials::with_access_token(&token.access_token); let backend = audio_backend::find(None).unwrap(); - + let session; { let guard = app.cushy().enter_runtime(); session = Session::new(session_config, None); - - let player = Player::new(player_config, session.clone(), Box::new(NoOpVolume), move || { - backend(None, audio_format) - }); - - tokio::spawn({ let session = session.clone(); async move { - if let Err(e) = session.connect(credentials, false).await { - println!("Error connecting: {}", e); + + let player = Player::new( + player_config, + session.clone(), + Box::new(NoOpVolume), + move || backend(None, audio_format), + ); + + tokio::spawn({ + let session = session.clone(); + async move { + if let Err(e) = session.connect(credentials, false).await { + println!("Error connecting: {}", e); + } } - }}); - + }); + thread::spawn(move || { let mut channel = player.get_player_event_channel(); loop { let event = channel.blocking_recv(); if let Some(event) = event { dbg!(event); - } else { break; } + } else { + break; + } } }); dbg!(session.user_data()); - - let context = SpotifyContext::new(session, token); + + let context = SpotifyContextRef::new(SpotifyContext::new(session, token)); let mut app = app.as_app(); tokio::spawn(async move { @@ -88,11 +86,10 @@ fn main() -> cushy::Result { let selected_page = Dynamic::new(ActivePage::default()); - // playlists_widget(playlists.items, selected_page) - // .and( - VirtualList::new(TestVirtualList) - // ) - // .into_columns() + playlists_widget(playlists.items, selected_page) + .and(LikedSongsPage::new(context.clone()).into_widget()) + .into_columns() + .expand() .make_window() .open(&mut app) .unwrap(); @@ -102,4 +99,4 @@ fn main() -> cushy::Result { } app.run() -} \ No newline at end of file +} diff --git a/src/nodebug.rs b/src/nodebug.rs new file mode 100644 index 0000000..2a30104 --- /dev/null +++ b/src/nodebug.rs @@ -0,0 +1,42 @@ +use std::{fmt::Debug, ops::{Deref, DerefMut}}; + +pub struct NoDebug { + inner: T, +} + +impl Debug for NoDebug { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("skipped").finish() + } +} + +impl From for NoDebug { + fn from(value: T) -> Self { + Self { inner: value } + } +} + +impl Deref for NoDebug { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for NoDebug { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl Default for NoDebug +where + T: Default, +{ + fn default() -> Self { + Self { + inner: T::default(), + } + } +} \ No newline at end of file diff --git a/src/widgets/library/playlist.rs b/src/widgets/library/playlist.rs index a9e320f..22f8748 100644 --- a/src/widgets/library/playlist.rs +++ b/src/widgets/library/playlist.rs @@ -1,80 +1,99 @@ -use cushy::{value::{Destination, Dynamic, IntoDynamic, IntoValue, Source, Value}, widget::{MakeWidget, WidgetList}, widgets::{button::{ButtonBackground, ButtonClick, ButtonHoverBackground}, grid::Orientation, Image, Stack}}; -use rspotify::model::SimplifiedPlaylist; use cushy::kludgine::Color; +use cushy::{ + value::{Destination, Dynamic, IntoDynamic, IntoValue, Source, Value}, + widget::{MakeWidget, WidgetList}, + widgets::{ + button::{ButtonBackground, ButtonClick, ButtonHoverBackground}, + grid::Orientation, + Image, Stack, + }, +}; +use rspotify::model::SimplifiedPlaylist; -use crate::{theme::{LIBRARY_BG, LIBRARY_BG_HOVER, LIBRARY_BG_SELECTED, LIBRARY_BG_SELECTED_HOVER}, widgets::{image::ImageExt, ActivePage, SelectedPage}}; +use crate::{ + theme::{LIBRARY_BG, LIBRARY_BG_HOVER, LIBRARY_BG_SELECTED, LIBRARY_BG_SELECTED_HOVER}, + widgets::{image::ImageExt, ActivePage, SelectedPage}, +}; -fn playlist_entry(playlist: impl IntoValue, selected_page: SelectedPage) -> impl MakeWidget { +fn playlist_entry( + playlist: impl IntoValue, + selected_page: SelectedPage, +) -> impl MakeWidget { let playlist: Value = playlist.into_value(); let id = playlist.map(|p| p.id.clone()); - let is_active = selected_page.map_each(move |page| - matches!(page, ActivePage::Playlist(p) if p.id == id) - ); + let is_active = + selected_page.map_each(move |page| matches!(page, ActivePage::Playlist(p) if p.id == id)); entry( - playlist - .map_each(|p| p.name.clone()) - .into_dynamic(), + playlist.map_each(|p| p.name.clone()).into_dynamic(), playlist .map_each(|playlist| playlist.images.first().map(|image| image.url.clone())) .into_dynamic(), is_active, move |_| { selected_page.set(ActivePage::Playlist(playlist.get())); - } + }, ) } -pub fn playlists_widget(playlists: impl IntoValue>, selected_page: SelectedPage) -> impl MakeWidget { +pub fn playlists_widget( + playlists: impl IntoValue>, + selected_page: SelectedPage, +) -> impl MakeWidget { let playlists: Value> = playlists.into_value(); Stack::new( Orientation::Row, - playlists - .map_each(move |t| { - let mut list = t.clone().into_iter().map(|playlist| playlist_entry(playlist, selected_page.clone())).collect::(); - list.insert(0, liked_songs_entry(selected_page.clone())); - list - }) + playlists.map_each(move |t| { + let mut list = t + .clone() + .into_iter() + .map(|playlist| playlist_entry(playlist, selected_page.clone())) + .collect::(); + list.insert(0, liked_songs_entry(selected_page.clone())); + list + }), ) .vertical_scroll() - .expand() + .expand_horizontally() } fn liked_songs_entry(selected_page: SelectedPage) -> impl MakeWidget { let is_active = selected_page.map_each(|page| matches!(page, ActivePage::LikedSongs)); entry( "Liked Songs", - Dynamic::new(Some("https://misc.scdn.co/liked-songs/liked-songs-300.png".to_string())), + Dynamic::new(Some( + "https://misc.scdn.co/liked-songs/liked-songs-300.png".to_string(), + )), is_active, move |_| { selected_page.set(ActivePage::LikedSongs); - } + }, ) } -fn entry(text: impl IntoValue, url: Dynamic>, is_active: Dynamic, callback: F) -> impl MakeWidget -where F: FnMut(Option) + Send + 'static { +fn entry( + text: impl IntoValue, + url: Dynamic>, + is_active: Dynamic, + callback: F, +) -> impl MakeWidget +where + F: FnMut(Option) + Send + 'static, +{ let (background, background_hover) = get_colors(is_active); Image::new_empty() - .with_url( - url - ) - .and( - text - .into_value() - .align_left() - .expand() - ) - .into_columns() - .into_button() - .on_click(callback) - .with(&ButtonBackground, background) - .with(&ButtonHoverBackground, background_hover) - .pad() + .with_url(url) + .and(text.into_value().align_left().expand()) + .into_columns() + .into_button() + .on_click(callback) + .with(&ButtonBackground, background) + .with(&ButtonHoverBackground, background_hover) + .pad() } /// Returns `background` and `background_hover` colors for a library entry. fn get_colors(is_active: impl IntoValue) -> (Value, Value) { - let is_active= is_active.into_value(); + let is_active = is_active.into_value(); let background = is_active.map_each(|active| { if *active { LIBRARY_BG_SELECTED @@ -90,4 +109,4 @@ fn get_colors(is_active: impl IntoValue) -> (Value, Value) { } }); (background, background_hover) -} \ No newline at end of file +} diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 037db5e..4c6a073 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -3,9 +3,8 @@ use rspotify::model::{SimplifiedAlbum, SimplifiedPlaylist}; pub mod image; pub mod library; -pub mod virtual_list; -pub mod probe; pub mod owned; +pub mod pages; #[derive(PartialEq, Debug, Default)] pub enum ActivePage { diff --git a/src/widgets/pages/liked.rs b/src/widgets/pages/liked.rs new file mode 100644 index 0000000..ea8b5e3 --- /dev/null +++ b/src/widgets/pages/liked.rs @@ -0,0 +1,100 @@ +use std::{ + collections::{HashMap, HashSet}, + ops::Range, + sync::{Arc, RwLock}, +}; + +use cushy::{ + figures::{units::Lp, Size}, + styles::{Dimension, DimensionRange}, + value::{Destination, Dynamic, Source}, + widget::MakeWidget, + widgets::VirtualList, +}; +use futures_util::lock::Mutex; +use rspotify::model::SavedTrack; + +use crate::{api::SpotifyContextRef, nodebug::NoDebug, rt::tokio_runtime}; + +const PER_PAGE: usize = 50; + +#[derive(Debug)] +pub struct LikedSongsPage { + tracks: Dynamic>, + total_tracks: Dynamic, + + context: NoDebug, + pages_loading: Arc>>, +} + +impl LikedSongsPage { + pub fn new(context: SpotifyContextRef) -> Self { + Self { + context: context.into(), + + tracks: Default::default(), + total_tracks: Default::default(), + pages_loading: Default::default(), + } + } + + pub fn into_widget(self) -> impl MakeWidget { + let tracks = self.tracks; + let pages_loading = self.pages_loading; + let context = self.context; + let total_tracks = self.total_tracks.clone(); + VirtualList::new( + total_tracks.clone().map_each(|total| (*total).max(1)), + move |index| { + let context = context.clone(); + let pages_loading = pages_loading.clone(); + let total_tracks = total_tracks.clone(); + let page = index / PER_PAGE; + tracks.map_ref({ + let tracks = tracks.clone(); + |loaded_tracks| { + if !loaded_tracks.contains_key(&index) + && !pages_loading.read().unwrap().contains(&page) + { + pages_loading.write().unwrap().insert(page); + tokio_runtime().spawn(async move { + println!("Loading page {} idx {}", page, index); + let saved_tracks = context + .current_user_saved_tracks( + Some(PER_PAGE as _), + Some((page * PER_PAGE) as _), + ) + .await; + let Ok(saved_tracks) = saved_tracks else { + eprintln!("Failed to load page {}", page); + // pages_loading.write().unwrap().remove(&page); + return; + }; + println!("Loaded page {} got tracks {}", page, saved_tracks.total); + total_tracks.set(saved_tracks.total as usize); + tracks.map_mut(|mut tracks| { + for (i, track) in saved_tracks.items.into_iter().enumerate() { + tracks.insert(i + saved_tracks.offset as usize, track); + } + }); + }); + } + } + }); + tracks + .map_each(move |tracks| { + if let Some(track) = tracks.get(&index) { + format!("{} - {}", track.track.name, track.track.artists[0].name) + } else { + format!("Loading...") + } + }) + .size(Size { + width: DimensionRange::default(), + height: Dimension::Lp(Lp::points(60)).into(), + }) + }, + ) + .expand_horizontally() + } +} diff --git a/src/widgets/pages/mod.rs b/src/widgets/pages/mod.rs new file mode 100644 index 0000000..2a7179f --- /dev/null +++ b/src/widgets/pages/mod.rs @@ -0,0 +1,2 @@ + +pub mod liked; \ No newline at end of file diff --git a/src/widgets/probe.rs b/src/widgets/probe.rs deleted file mode 100644 index b5acbda..0000000 --- a/src/widgets/probe.rs +++ /dev/null @@ -1,35 +0,0 @@ -use cushy::{figures::Fraction, value::{Destination, Dynamic, DynamicReader, IntoReadOnly, ReadOnly}, widget::{MakeWidget, Widget, WidgetRef}}; - -#[derive(Debug)] -pub struct ScalingProbe { - child: WidgetRef, - scale: Dynamic -} - -impl ScalingProbe { - pub fn new(child: impl MakeWidget) -> Self { - Self { - child: WidgetRef::new(child), - scale: Dynamic::new(Fraction::new_whole(1)) - } - } - - pub fn scale(&self) -> DynamicReader { - self.scale.create_reader() - } -} - -impl Widget for ScalingProbe { - fn redraw(&mut self, context: &mut cushy::context::GraphicsContext<'_, '_, '_, '_>) { - self.scale.set(context.gfx.scale()); - context.for_other(&self.child).expect("A child").redraw(); - } - fn layout( - &mut self, - available_space: cushy::figures::Size, - context: &mut cushy::context::LayoutContext<'_, '_, '_, '_>, - ) -> cushy::figures::Size { - let child = self.child.mounted(context); - context.for_other(&child).layout(available_space) - } -} \ No newline at end of file diff --git a/src/widgets/virtual_list.rs b/src/widgets/virtual_list.rs deleted file mode 100644 index 8e4e4aa..0000000 --- a/src/widgets/virtual_list.rs +++ /dev/null @@ -1,308 +0,0 @@ -use std::{collections::VecDeque, fmt::Debug, ops::Range}; - -use cushy::{context::{AsEventContext, EventContext}, figures::{units::{Px, UPx}, IntoSigned, Point, Rect, Round, ScreenScale, Size, Zero}, kludgine::app::winit::{event::{ MouseScrollDelta, TouchPhase}, window::CursorIcon}, styles::Dimension, value::{Destination, Dynamic, DynamicReader, IntoDynamic, IntoValue, Source}, widget::{EventHandling, MakeWidget, MountedWidget, Widget, HANDLED, IGNORED}, widgets::scroll::ScrollBar, window::DeviceId, ConstraintLimit}; - -use super::owned::OwnedWidget; - -/// A virtual list contents. -/// This simple virtual list assumes that all items have the same height, width and that the item count is known. -/// All the values are dynamic, so the list will update when the values change. -pub trait VirtualListContent: Debug { - /// Single item height - fn item_height(&self) -> impl IntoValue; - /// Width of the items - fn width(&self) -> impl IntoValue; - /// Number of items - fn item_count(&self) -> impl IntoValue; - /// Create a widget for the item at the given index. - /// This is called when the widget comes into view. The widget may be removed at any moment (by scrolling it out of view) and recreated later. - fn widget_at(&self, index: usize) -> impl MakeWidget; -} - -#[derive(Debug)] -struct VirtualListItem { - index: usize, - mounted: MountedWidget, -} - -#[derive(Debug)] -/// A virtual list widget. -/// Requires a [VirtualListContent] trait implementation to render the items. -/// Items are lazily recreated as they go in and out of view. -pub struct VirtualList { - virtual_list: T, - vertical_scroll: OwnedWidget, - items: VecDeque, - content_size: Dynamic>, - /// Maximum scroll value - max_scroll.y + control_size.height should be the height of the content. - pub max_scroll: DynamicReader>, - /// Current scroll value. The x value is always 0. Change the value to scroll the widget programmatically. - pub scroll: Dynamic>, - control_size: Dynamic>, - - /// Height of an item. Based on [VirtualListContent::item_height]. - pub item_height: DynamicReader, - /// Width of the items. Based on [VirtualListContent::width]. - pub width: DynamicReader, - /// Number of items. Based on [VirtualListContent::item_count]. - pub item_count: DynamicReader, - - visible_range: Dynamic> -} - -impl VirtualList { - pub fn new(virtual_list: T) -> Self { - let scroll = Dynamic::>::default(); - let item_height = virtual_list.item_height().into_value().into_dynamic().create_reader(); - let width = virtual_list.width().into_value().into_dynamic().create_reader(); - let item_count = virtual_list.item_count().into_value().into_dynamic().create_reader(); - let content_size = Dynamic::new(Size::default()); - - let y = scroll.map_each_cloned(|scroll| scroll.y); - y.for_each_cloned({ - let scroll = scroll.clone(); - move |y| { - if let Ok(mut scroll) = scroll.try_lock() { - if scroll.y != y { - scroll.y = y; - } - } - } - }) - .persist(); - let vertical = - ScrollBar::new(content_size.map_each_cloned(|size| size.height), y, true); - let max_scroll = (&vertical.max_scroll()) - .map_each_cloned(|y| Point::new(UPx::ZERO, y)) - .into_reader(); - - Self { - virtual_list, - vertical_scroll: OwnedWidget::new(vertical), - items: VecDeque::new(), - control_size: Dynamic::new(Size::default()), - content_size, - max_scroll, - scroll, - - item_height, - width, - item_count, - visible_range: Default::default() - } - } - - /// Returns a reader for the maximum scroll value. - /// - /// This represents the maximum amount that the scroll can be moved by. - #[must_use] - pub const fn max_scroll(&self) -> &DynamicReader> { - &self.max_scroll - } - - /// Returns a reader for the size of the scrollable area. - #[must_use] - pub fn content_size(&self) -> DynamicReader> { - self.content_size.create_reader() - } - - /// Returns a reader for the size of this Scroll widget. - #[must_use] - pub fn control_size(&self) -> DynamicReader> { - self.control_size.create_reader() - } - - /// Returns a reader for number of visible items. 0 indexed. - #[must_use] - pub fn visible_range(&self) -> DynamicReader> { - self.visible_range.create_reader() - } - - fn show_scrollbars(&mut self, context: &mut EventContext<'_>) { - let mut vertical = self.vertical_scroll.expect_made_mut().widget().lock(); - vertical - .downcast_mut::() - .expect("a ScrollBar") - .show(context); - } - - fn hide_scrollbars(&mut self, context: &mut EventContext<'_>) { - let mut vertical = self.vertical_scroll.expect_made_mut().widget().lock(); - vertical - .downcast_mut::() - .expect("a ScrollBar") - .hide(context); - } -} - -impl Widget for VirtualList { - fn hit_test(&mut self, _location: Point, _context: &mut EventContext<'_>) -> bool { - true - } - - fn hover( - &mut self, - _location: Point, - context: &mut EventContext<'_>, - ) -> Option { - self.show_scrollbars(context); - - None - } - - fn unhover(&mut self, context: &mut EventContext<'_>) { - self.hide_scrollbars(context); - } - - fn mounted(&mut self, context: &mut EventContext<'_>) { - for child in &mut self.items { - child.mounted.remount_if_needed(context); - } - } - - fn redraw(&mut self, context: &mut cushy::context::GraphicsContext<'_, '_, '_, '_>) { - for child in &mut self.items { - context.for_other(&child.mounted).redraw(); - } - let vertical = self - .vertical_scroll - .expect_made_mut() - .mounted(&mut context.as_event_context()); - context.for_other(&vertical).redraw(); - } - - fn layout( - &mut self, - available_space: Size, - context: &mut cushy::context::LayoutContext<'_, '_, '_, '_>, - ) -> Size { - let item_height = self.item_height.get_tracking_invalidate(context); - let item_height_upx = item_height.into_upx(context.gfx.scale()); - let item_count = self.item_count.get_tracking_invalidate(context); - let content_height = item_height * item_count as i32; - let content_height = content_height.into_upx(context.gfx.scale()); - let width = self.width.get_tracking_invalidate(context); - let width = width.into_upx(context.gfx.scale()); - - let new_control_size = Size::new( - width, - constrain_child(available_space.height, content_height), - ); - - let vertical = self - .vertical_scroll - .make_if_needed() - .mounted(&mut context.as_event_context()); - let scrollbar_layout = context.for_other(&vertical).layout(available_space); - context.set_child_layout( - &vertical, - Rect::new( - Point::new( - available_space.width - .fit_measured(new_control_size.width) - .saturating_sub(scrollbar_layout.width) - .into_signed(), - Px::ZERO, - ), - scrollbar_layout.into_signed(), - ), - ); - let scroll = self.scroll.get_tracking_invalidate(context); - - let start_item = (scroll.y / item_height_upx).floor().get() as usize; - let end_item = ((scroll.y + new_control_size.height) / item_height_upx).ceil().get() as usize; - let end_item = end_item.min(item_count-1); - - self.visible_range.set(start_item..end_item); - - let first = self.items.front().map(|t| t.index); - let last = self.items.back().map(|t| t.index); - let mut closure = |index| { - let widget = self.virtual_list.widget_at(index); - let mut widget = widget.widget_ref(); - let mounted = widget.mounted(&mut context.as_event_context()); - VirtualListItem { index, mounted } - }; - if self.items.is_empty() || first.unwrap() > end_item || last.unwrap() < start_item { - self.items.clear(); - self.items.extend((start_item..=end_item).map(closure)); - } else { - let first = first.expect("List is not empty"); - let last = last.expect("List is not empty"); - if first < start_item { - while self.items.front().is_some() && self.items.front().expect("Checked is some").index < start_item { - self.items.pop_front(); - } - } - if last > end_item { - while self.items.back().is_some() && self.items.back().expect("Checked is some").index > end_item { - self.items.pop_back(); - } - } - // no extend front :( - for item in (start_item..first).rev() { - self.items.push_front(closure(item)); - } - self.items.extend(((last+1)..=end_item).map(closure)); - } - - let item_size = Size::new(width, item_height_upx); - let constraint = item_size.map(ConstraintLimit::Fill); - - for item in &self.items { - context.for_other(&item.mounted).layout(constraint); - } - - let item_size = item_size.into_signed(); - let scroll = self.scroll.get_tracking_invalidate(context).into_signed(); - - for item in &self.items { - context.set_child_layout( - &item.mounted, - Rect::new( - Point::new(Px::ZERO, (item_height_upx * item.index as f32).into_signed() - scroll.y), - item_size, - ) - ); - } - - self.control_size.set(new_control_size); - self.content_size.set(Size::new(width, content_height)); - - new_control_size - } - - fn mouse_wheel( - &mut self, - _device_id: DeviceId, - delta: MouseScrollDelta, - _phase: TouchPhase, - context: &mut EventContext<'_>, - ) -> EventHandling { - let mut handled = false; - { - let mut vertical = self.vertical_scroll.expect_made().widget().lock(); - handled |= vertical - .downcast_mut::() - .expect("a ScrollBar") - .mouse_wheel(delta, context) - .is_break(); - } - if handled { - self.show_scrollbars(context); - context.set_needs_redraw(); - - HANDLED - } else { - IGNORED - } - } -} - -fn constrain_child(constraint: ConstraintLimit, measured: UPx) -> UPx { - match constraint { - ConstraintLimit::Fill(size) => size.min(measured), - // change from Scroll widget: returning just measured here would break the functionality (render too many items) - ConstraintLimit::SizeToFit(size) => size.min(measured), - } -} \ No newline at end of file