wip: async loading of both album sources
This commit is contained in:
parent
5978ebb9b0
commit
68e4789461
7 changed files with 633 additions and 173 deletions
423
src-tauri/Cargo.lock
generated
423
src-tauri/Cargo.lock
generated
|
@ -86,26 +86,6 @@ dependencies = [
|
|||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "audiotags"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f47bdf1acc4fa4113f8aa72bb3bfe62a61443c61d0d997b723ba61ce102c79b"
|
||||
dependencies = [
|
||||
"audiotags-dev-macro",
|
||||
"id3",
|
||||
"metaflac",
|
||||
"mp4ameta",
|
||||
"readme-rustdocifier",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "audiotags-dev-macro"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b79298591161f312f06327df7963063ee07466be303dcc3084a44ec293cb36e"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
@ -439,30 +419,6 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
|
@ -634,12 +590,6 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "embed-resource"
|
||||
version = "2.3.0"
|
||||
|
@ -650,7 +600,7 @@ dependencies = [
|
|||
"rustc_version",
|
||||
"toml 0.7.8",
|
||||
"vswhom",
|
||||
"winreg",
|
||||
"winreg 0.51.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -825,6 +775,12 @@ dependencies = [
|
|||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.28"
|
||||
|
@ -1151,6 +1107,25 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap 1.9.3",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
|
@ -1229,12 +1204,72 @@ dependencies = [
|
|||
"itoa 1.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-range"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa 1.0.9",
|
||||
"pin-project-lite",
|
||||
"socket2 0.4.9",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"hyper",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.57"
|
||||
|
@ -1365,6 +1400,12 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
|
@ -1497,10 +1538,8 @@ checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
|
|||
name = "lissen"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"audiotags",
|
||||
"id3",
|
||||
"rayon",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
|
@ -1613,15 +1652,10 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "metaflac"
|
||||
version = "0.2.5"
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1470d3cc1bb0d692af5eb3afb594330b8ba09fd91c32c4e1c6322172a5ba750"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"hex",
|
||||
"log",
|
||||
]
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
|
@ -1634,20 +1668,33 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp4ameta"
|
||||
version = "0.11.0"
|
||||
name = "mio"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb23d62e8eb5299a3f79657c70ea9269eac8f6239a76952689bcd06a74057e81"
|
||||
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"mp4ameta_proc",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp4ameta_proc"
|
||||
version = "0.6.0"
|
||||
name = "native-tls"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07dcca13d1740c0a665f77104803360da0bdb3323ecce2e93fa2c959a6d52806"
|
||||
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk"
|
||||
|
@ -1824,6 +1871,50 @@ dependencies = [
|
|||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
|
@ -2209,32 +2300,6 @@ version = "0.5.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "readme-rustdocifier"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08ad765b21a08b1a8e5cdce052719188a23772bcbefb3c439f0baaf62c56ceac"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
|
@ -2308,6 +2373,43 @@ version = "0.7.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
|
||||
dependencies = [
|
||||
"base64 0.21.4",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"winreg 0.50.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfd"
|
||||
version = "0.10.0"
|
||||
|
@ -2387,6 +2489,15 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
|
@ -2399,6 +2510,29 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "selectors"
|
||||
version = "0.22.0"
|
||||
|
@ -2479,6 +2613,18 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa 1.0.9",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.3.0"
|
||||
|
@ -2587,6 +2733,26 @@ version = "1.11.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soup2"
|
||||
version = "0.2.1"
|
||||
|
@ -3084,8 +3250,36 @@ checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
|
|||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.4",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3131,6 +3325,12 @@ dependencies = [
|
|||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.37"
|
||||
|
@ -3202,6 +3402,12 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
|
@ -3268,6 +3474,12 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.0.11"
|
||||
|
@ -3316,6 +3528,15 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||
dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
|
@ -3780,6 +4001,16 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.51.0"
|
||||
|
|
|
@ -1,26 +1,24 @@
|
|||
[package]
|
||||
name = "lissen"
|
||||
version = "0.0.0"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
repository = ""
|
||||
description = "A Tauri App"
|
||||
edition = "2021"
|
||||
license = ""
|
||||
name = "lissen"
|
||||
repository = ""
|
||||
version = "0.0.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.4", features = [] }
|
||||
tauri-build = {version = "1.4", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "1.4", features = [ "dialog-open", "shell-open"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
id3 = "1.8.0"
|
||||
rayon = "1.8.0"
|
||||
reqwest = {version = "0.11.20", features = ["json"] }
|
||||
serde = {version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tauri = {version = "1.4", features = ["dialog-open", "shell-open"] }
|
||||
walkdir = "2.4.0"
|
||||
anyhow = "1.0.75"
|
||||
audiotags = "0.4.1"
|
||||
|
||||
[features]
|
||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
use id3::{Tag, TagLike};
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
use tauri::Manager;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
#[derive(Debug, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct Album {
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct LocalAlbum {
|
||||
pub name: String,
|
||||
pub artist: String,
|
||||
pub year: i32,
|
||||
|
@ -14,15 +15,16 @@ pub struct Album {
|
|||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_local_albums(dirpath: String) -> Result<Vec<Album>, String> {
|
||||
async fn get_local_albums(
|
||||
dirpath: String,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<Vec<LocalAlbum>, String> {
|
||||
let mut result = HashSet::new();
|
||||
for entry in WalkDir::new(dirpath) {
|
||||
let entry = entry.map_err(|e| e.to_string())?;
|
||||
println!("{}", entry.path().display());
|
||||
for entry in WalkDir::new(dirpath).into_iter().filter_map(|e| e.ok()) {
|
||||
if entry.file_type().is_file() {
|
||||
let path = entry.path();
|
||||
if let Ok(tag) = Tag::read_from_path(path) {
|
||||
let album = Album {
|
||||
let album = LocalAlbum {
|
||||
name: tag.album().unwrap_or("").to_string(),
|
||||
artist: tag.artist().unwrap_or("").to_string(),
|
||||
year: tag.year().unwrap_or(0),
|
||||
|
@ -32,19 +34,124 @@ async fn get_local_albums(dirpath: String) -> Result<Vec<Album>, String> {
|
|||
.map(|ext| ext == "flac" || ext == "wav")
|
||||
.unwrap_or(false),
|
||||
};
|
||||
result.insert(album);
|
||||
let json_local_album = serde_json::to_value(&album).unwrap();
|
||||
let new = result.insert(album);
|
||||
if new {
|
||||
app_handle
|
||||
.emit_all("new_local_album", json_local_album)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(result.into_iter().collect())
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct ScrobbledAlbum {
|
||||
pub name: String,
|
||||
pub artist: String,
|
||||
pub playcount: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub enum Period {
|
||||
Overall,
|
||||
Week,
|
||||
Month,
|
||||
ThreeMonths,
|
||||
SixMonths,
|
||||
Year,
|
||||
}
|
||||
|
||||
impl ToString for Period {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Period::Overall => "overall",
|
||||
Period::Week => "7day",
|
||||
Period::Month => "1month",
|
||||
Period::ThreeMonths => "3month",
|
||||
Period::SixMonths => "6month",
|
||||
Period::Year => "12month",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_top_scrobbled_albums(
|
||||
user: String,
|
||||
period: Period,
|
||||
limit: u64,
|
||||
api_key: Option<String>,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<Vec<ScrobbledAlbum>, String> {
|
||||
let api_key = api_key
|
||||
.or_else(|| option_env!("LASTFM_API_KEY").map(|s| s.to_string()))
|
||||
.ok_or("No API key supplied.")?;
|
||||
|
||||
let period = period.to_string();
|
||||
|
||||
let page_size = 50;
|
||||
let mut final_result = Vec::new();
|
||||
let mut page = 1;
|
||||
while final_result.len() < limit as usize {
|
||||
let url = format!(
|
||||
"https://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user={user}&api_key={api_key}&period={period}&limit={page_size}&page={page}&format=json");
|
||||
println!("Fetching {}", url);
|
||||
|
||||
let resp = reqwest::get(&url)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
.json::<serde_json::Value>()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let albums = resp["topalbums"]["album"]
|
||||
.as_array()
|
||||
.ok_or("no albums found")?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
for album in albums {
|
||||
let name = album["name"].as_str().ok_or("no album name")?.to_string();
|
||||
let artist = album["artist"]["name"]
|
||||
.as_str()
|
||||
.ok_or("no artist name")?
|
||||
.to_string();
|
||||
let playcount = album["playcount"]
|
||||
.as_str()
|
||||
.ok_or("no playcount")?
|
||||
.parse()
|
||||
.map_err(|_| "failed to parse playcount")?;
|
||||
result.push(ScrobbledAlbum {
|
||||
name,
|
||||
artist,
|
||||
playcount,
|
||||
});
|
||||
}
|
||||
app_handle
|
||||
.emit_all(
|
||||
"new_scrobbled_albums",
|
||||
serde_json::to_value(&result).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
final_result.extend(result);
|
||||
|
||||
page += 1;
|
||||
}
|
||||
|
||||
Ok(final_result)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// https://github.com/tauri-apps/tauri/issues/5143#issuecomment-1311815517
|
||||
std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1");
|
||||
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![get_local_albums])
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
get_top_scrobbled_albums,
|
||||
get_local_albums
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
|
183
src/App.svelte
183
src/App.svelte
|
@ -1,39 +1,172 @@
|
|||
<script lang="ts">
|
||||
import Greet from './lib/Greet.svelte'
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { open } from "@tauri-apps/api/dialog";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { onMount } from "svelte";
|
||||
import { period, username } from "./stores";
|
||||
|
||||
interface ScrobbledAlbum {
|
||||
name: string;
|
||||
artist: string;
|
||||
playcount: number;
|
||||
}
|
||||
let scrobbledAlbums: ScrobbledAlbum[] = [];
|
||||
let loadingScrobbledAlbums = false;
|
||||
|
||||
interface LocalAlbum {
|
||||
name: string;
|
||||
artist: string;
|
||||
year: number;
|
||||
lossless: boolean;
|
||||
}
|
||||
let localAlbums: LocalAlbum[] = [];
|
||||
let loadingLocalAlbums = false;
|
||||
|
||||
onMount(() => {
|
||||
listen("new_local_album", (event) => {
|
||||
const album = event.payload as LocalAlbum;
|
||||
localAlbums = [...localAlbums, album];
|
||||
});
|
||||
listen("new_scrobbled_albums", (event) => {
|
||||
const newAlbums = event.payload as ScrobbledAlbum[];
|
||||
scrobbledAlbums = [...scrobbledAlbums, ...newAlbums];
|
||||
});
|
||||
});
|
||||
|
||||
async function loadScrobbles() {
|
||||
if (loadingScrobbledAlbums) {
|
||||
return;
|
||||
}
|
||||
scrobbledAlbums = [];
|
||||
loadingScrobbledAlbums = true;
|
||||
try {
|
||||
await invoke("get_top_scrobbled_albums", {
|
||||
user: $username,
|
||||
period: $period,
|
||||
limit: 200,
|
||||
});
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
}
|
||||
loadingScrobbledAlbums = false;
|
||||
}
|
||||
|
||||
async function loadLocal() {
|
||||
const selected = await open({
|
||||
directory: true,
|
||||
});
|
||||
if (typeof selected === "string" && selected.length > 0) {
|
||||
localAlbums = [];
|
||||
loadingLocalAlbums = true;
|
||||
try {
|
||||
await invoke("get_local_albums", {
|
||||
dirpath: selected,
|
||||
});
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
}
|
||||
loadingLocalAlbums = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleError(e: unknown) {
|
||||
console.error(e);
|
||||
alert(e);
|
||||
}
|
||||
</script>
|
||||
|
||||
<main class="container">
|
||||
<h1>Welcome to Tauri!</h1>
|
||||
<main>
|
||||
<div class="main">
|
||||
<div class="scrobbles">
|
||||
<div class="input">
|
||||
<label>
|
||||
Username:
|
||||
<input type="text" bind:value={$username} />
|
||||
</label>
|
||||
<label>
|
||||
Period:
|
||||
<select bind:value={$period}>
|
||||
<option value="Week">7 days</option>
|
||||
<option value="Month">1 month</option>
|
||||
<option value="ThreeMonths">3 months</option>
|
||||
<option value="SixMonths">6 months</option>
|
||||
<option value="Year">Year</option>
|
||||
<option value="Overall">Overall</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<div class="row">
|
||||
<a href="https://vitejs.dev" target="_blank">
|
||||
<img src="/vite.svg" class="logo vite" alt="Vite Logo" />
|
||||
</a>
|
||||
<a href="https://tauri.app" target="_blank">
|
||||
<img src="/tauri.svg" class="logo tauri" alt="Tauri Logo" />
|
||||
</a>
|
||||
<a href="https://svelte.dev" target="_blank">
|
||||
<img src="/svelte.svg" class="logo svelte" alt="Svelte Logo" />
|
||||
</a>
|
||||
<button on:click={loadScrobbles}>Load scrobbles</button>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Click on the Tauri, Vite, and Svelte logos to learn more.
|
||||
</p>
|
||||
|
||||
<div class="row">
|
||||
<Greet />
|
||||
<div class="display">
|
||||
<div class="label">Scrobbled albums: {scrobbledAlbums.length}</div>
|
||||
<div class="albums">
|
||||
{#each scrobbledAlbums as album}
|
||||
<div class="album">
|
||||
<div class="name">{album.name}</div>
|
||||
<div class="artist">{album.artist}</div>
|
||||
<div class="playcount">Played: {album.playcount}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="local">
|
||||
<div class="input">
|
||||
<button on:click={loadLocal}>Load local albums</button>
|
||||
</div>
|
||||
<div class="albums">
|
||||
{#each localAlbums as album}
|
||||
<div class="album">
|
||||
<div class="name">{album.name}</div>
|
||||
<div class="artist">{album.artist}</div>
|
||||
<div class="year">{album.year}</div>
|
||||
<div class="lossless">{album.lossless}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.logo.vite:hover {
|
||||
filter: drop-shadow(0 0 2em #747bff);
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.main > * {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
|
||||
.albums {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.album {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid white;
|
||||
border-radius: 2px;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.album {
|
||||
& .name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.logo.svelte:hover {
|
||||
filter: drop-shadow(0 0 2em #ff3e00);
|
||||
& .artist {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,27 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { open } from "@tauri-apps/api/dialog";
|
||||
|
||||
let name = "";
|
||||
let greetMsg = "";
|
||||
|
||||
async function greet() {
|
||||
const selected = await open({
|
||||
directory: true,
|
||||
});
|
||||
if (typeof selected === "string" && selected.length > 0) {
|
||||
const res = await invoke("get_local_albums", {
|
||||
dirpath: selected,
|
||||
});
|
||||
console.log({ res });
|
||||
}
|
||||
greetMsg = selected.toString();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<form class="row" on:submit|preventDefault={greet}>
|
||||
<button type="submit">Load</button>
|
||||
</form>
|
||||
<p>{greetMsg}</p>
|
||||
</div>
|
17
src/stores.ts
Normal file
17
src/stores.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { writable } from "svelte/store";
|
||||
|
||||
export const username = writable(localStorage.getItem("username"));
|
||||
username.subscribe((value) => (localStorage.username = value));
|
||||
|
||||
export type Period =
|
||||
| "Overall"
|
||||
| "Week"
|
||||
| "Month"
|
||||
| "ThreeMonths"
|
||||
| "SixMonths"
|
||||
| "Year";
|
||||
|
||||
export const period = writable<Period>(
|
||||
(localStorage.getItem("period") as Period) || "Overall"
|
||||
);
|
||||
period.subscribe((value) => (localStorage.period = value));
|
|
@ -54,6 +54,7 @@ h1 {
|
|||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
|
|
Loading…
Reference in a new issue