modified: .gitignore

modified:   Cargo.lock
	modified:   Cargo.toml
	modified:   src/dlp.rs
	modified:   src/main.rs
	modified:   src/main_screen.rs
	deleted:    src/playlist_icon.rs
	modified:   src/sync.rs
This commit is contained in:
Michael Wain 2025-02-11 19:58:42 +03:00
parent 58e87e615a
commit 8f8a79411b
8 changed files with 183 additions and 446 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
target/
target/
.env

438
Cargo.lock generated
View File

@ -53,65 +53,6 @@ dependencies = [
"libc",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
dependencies = [
"anstyle",
"once_cell",
"windows-sys 0.59.0",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
@ -165,18 +106,6 @@ dependencies = [
"serde",
]
[[package]]
name = "bit_field"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.8.0"
@ -251,46 +180,6 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "clap"
version = "4.5.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "color-eyre"
version = "0.6.3"
@ -327,18 +216,6 @@ dependencies = [
"rgb",
]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "compact_str"
version = "0.8.1"
@ -378,38 +255,13 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crossterm"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
"bitflags 2.8.0",
"bitflags",
"crossterm_winapi",
"futures-core",
"mio",
@ -429,12 +281,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "crunchy"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
[[package]]
name = "darling"
version = "0.20.10"
@ -479,6 +325,39 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "diesel"
version = "2.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04001f23ba8843dc315804fa324000376084dfb1c30794ff68dd279e6e5696d5"
dependencies = [
"diesel_derives",
"libsqlite3-sys",
"time",
]
[[package]]
name = "diesel_derives"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f2c3de51e2ba6bf2a648285696137aaf0f5f487bcbea93972fe8a364e131a4"
dependencies = [
"diesel_table_macro_syntax",
"dsl_auto_type",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "diesel_table_macro_syntax"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25"
dependencies = [
"syn",
]
[[package]]
name = "dirs"
version = "6.0.0"
@ -511,6 +390,26 @@ dependencies = [
"syn",
]
[[package]]
name = "dotenvy"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]]
name = "dsl_auto_type"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "139ae9aca7527f85f26dd76483eb38533fd84bd571065da1739656ef71c5ff5b"
dependencies = [
"darling",
"either",
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "either"
version = "1.13.0"
@ -555,21 +454,6 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "exr"
version = "1.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0"
dependencies = [
"bit_field",
"half",
"lebe",
"miniz_oxide 0.8.3",
"rayon-core",
"smallvec",
"zune-inflate",
]
[[package]]
name = "eyre"
version = "0.6.12"
@ -586,15 +470,6 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "fdeflate"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
dependencies = [
"simd-adler32",
]
[[package]]
name = "flate2"
version = "1.0.35"
@ -759,16 +634,6 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "gif"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"
dependencies = [
"color_quant",
"weezl",
]
[[package]]
name = "gimli"
version = "0.28.1"
@ -794,16 +659,6 @@ dependencies = [
"tracing",
]
[[package]]
name = "half"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
"cfg-if",
"crunchy",
]
[[package]]
name = "hashbrown"
version = "0.15.2"
@ -1116,24 +971,6 @@ dependencies = [
"icu_properties",
]
[[package]]
name = "image"
version = "0.24.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"exr",
"gif",
"jpeg-decoder",
"num-traits",
"png",
"qoi",
"tiff",
]
[[package]]
name = "indenter"
version = "0.3.3"
@ -1175,12 +1012,6 @@ version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.13.0"
@ -1209,15 +1040,6 @@ dependencies = [
"serde_json",
]
[[package]]
name = "jpeg-decoder"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
dependencies = [
"rayon",
]
[[package]]
name = "js-sys"
version = "0.3.77"
@ -1234,12 +1056,6 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lebe"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libc"
version = "0.2.169"
@ -1261,10 +1077,20 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.8.0",
"bitflags",
"libc",
]
[[package]]
name = "libsqlite3-sys"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad8935b44e7c13394a179a438e0cebba0fe08fe01b54f152e29a93b5cf993fd4"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
name = "libusb1-sys"
version = "0.7.0"
@ -1322,12 +1148,12 @@ dependencies = [
"color-eyre",
"color-thief",
"crossterm",
"diesel",
"dirs",
"dotenvy",
"futures",
"image",
"itunesdb",
"libmath",
"rascii_art",
"ratatui",
"regex",
"rusb",
@ -1335,7 +1161,6 @@ dependencies = [
"serde_json",
"soundcloud",
"strum 0.27.0",
"throbber-widgets-tui",
"tokio",
"tokio-util",
"toml",
@ -1370,7 +1195,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
dependencies = [
"adler2",
"simd-adler32",
]
[[package]]
@ -1447,7 +1271,7 @@ version = "0.10.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6"
dependencies = [
"bitflags 2.8.0",
"bitflags",
"cfg-if",
"foreign-types",
"libc",
@ -1550,19 +1374,6 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "png"
version = "0.17.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
dependencies = [
"bitflags 1.3.2",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide 0.8.3",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
@ -1587,15 +1398,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "qoi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
dependencies = [
"bytemuck",
]
[[package]]
name = "quote"
version = "1.0.38"
@ -1673,25 +1475,13 @@ dependencies = [
"getrandom 0.2.15",
]
[[package]]
name = "rascii_art"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e27f573a36aab4d4f2dd4aae8f44e8c5409a3d2cefce01d116cb11de546b1c65"
dependencies = [
"ansi_term",
"clap",
"image",
"unicode-segmentation",
]
[[package]]
name = "ratatui"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [
"bitflags 2.8.0",
"bitflags",
"cassowary",
"compact_str",
"crossterm",
@ -1707,26 +1497,6 @@ dependencies = [
"unicode-width 0.2.0",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "rdrand"
version = "0.4.0"
@ -1742,7 +1512,7 @@ version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [
"bitflags 2.8.0",
"bitflags",
]
[[package]]
@ -1875,7 +1645,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.8.0",
"bitflags",
"errno",
"libc",
"linux-raw-sys",
@ -1956,7 +1726,7 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.8.0",
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
@ -2071,12 +1841,6 @@ dependencies = [
"libc",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "slab"
version = "0.4.9"
@ -2226,7 +1990,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.8.0",
"bitflags",
"core-foundation",
"system-configuration-sys",
]
@ -2294,27 +2058,6 @@ dependencies = [
"once_cell",
]
[[package]]
name = "throbber-widgets-tui"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d36b5738d666a2b4c91b7c24998a8588db724b3107258343ebf8824bf55b06d"
dependencies = [
"rand 0.8.5",
"ratatui",
]
[[package]]
name = "tiff"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e"
dependencies = [
"flate2",
"jpeg-decoder",
"weezl",
]
[[package]]
name = "time"
version = "0.3.37"
@ -2322,12 +2065,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
dependencies = [
"deranged",
"itoa",
"libc",
"num-conv",
"num_threads",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
@ -2336,6 +2081,16 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "tinystr"
version = "0.7.6"
@ -2616,12 +2371,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "valuable"
version = "0.1.1"
@ -2748,12 +2497,6 @@ dependencies = [
"rustls-pki-types",
]
[[package]]
name = "weezl"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
[[package]]
name = "winapi"
version = "0.3.9"
@ -2921,7 +2664,7 @@ version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
dependencies = [
"bitflags 2.8.0",
"bitflags",
]
[[package]]
@ -3029,12 +2772,3 @@ dependencies = [
"quote",
"syn",
]
[[package]]
name = "zune-inflate"
version = "0.2.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
dependencies = [
"simd-adler32",
]

View File

@ -23,8 +23,7 @@ tokio-util = { version = "0.7.12", features = ["codec"] }
strum = { version = "0.27", features = ["derive"] }
soundcloud = { version = "0.1.4", git = "https://gitea.awain.net/alterwain/soundcloud_api.git" }
itunesdb = { version = "0.1.1", git = "https://gitea.awain.net/alterwain/ITunesDB.git" }
throbber-widgets-tui = "0.8.0"
image = { version = "0.24.9", default-features = false, features = ["jpeg", "png"] }
ureq = "3.0.5"
rascii_art = "0.4.5"
color-thief = "0.2"
color-thief = "0.2"
diesel = { version = "2.2.7", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] }
dotenvy = "0.15"

View File

@ -2,19 +2,27 @@ use std::{path::PathBuf, process::Stdio};
use regex::Regex;
use serde::Deserialize;
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::Sender};
use tokio::{
io::{AsyncBufReadExt, BufReader},
process::Command,
sync::mpsc::Sender,
};
use crate::sync::AppEvent;
#[derive(Debug, Deserialize)]
pub struct DownloadProgress {
progress_percentage: String,
progress_total: String,
speed: String,
eta: String
pub progress_percentage: String,
pub progress_total: String,
pub speed: String,
pub eta: String,
}
pub async fn download_from_soundcloud(playlist_url: &str, download_dir: &PathBuf, sender: Sender<AppEvent>) -> std::result::Result<(), Box<dyn std::error::Error>> {
pub async fn download_from_soundcloud(
playlist_url: &str,
download_dir: &PathBuf,
sender: Sender<AppEvent>,
) -> std::result::Result<(), Box<dyn std::error::Error>> {
let dl_rx: Regex = Regex::new(r"\[download\] Downloading item \d+ of \d+").unwrap();
if download_dir.exists() {
@ -23,6 +31,8 @@ pub async fn download_from_soundcloud(playlist_url: &str, download_dir: &PathBuf
let _ = std::fs::create_dir_all(download_dir);
let args = &[
"-f",
"mp3",
"--ignore-errors",
"--newline",
"--progress-template",
@ -41,7 +51,6 @@ pub async fn download_from_soundcloud(playlist_url: &str, download_dir: &PathBuf
let mut child = command.spawn()?;
let stdout = child.stdout.take().unwrap();
let mut reader = BufReader::new(stdout).lines();
@ -54,7 +63,7 @@ pub async fn download_from_soundcloud(playlist_url: &str, download_dir: &PathBuf
let cur = s.first().unwrap().trim().parse().unwrap();
let max = s.last().unwrap().trim().parse().unwrap();
let _ = sender.send(AppEvent::OverallProgress((cur, max))).await;
},
}
None => {
if line.starts_with("{") {
let progress: DownloadProgress = serde_json::from_str(&line).unwrap();
@ -65,4 +74,4 @@ pub async fn download_from_soundcloud(playlist_url: &str, download_dir: &PathBuf
}
Ok(())
}
}

View File

@ -25,7 +25,6 @@ use wait_screen::WaitScreen;
mod config;
mod dlp;
mod main_screen;
mod playlist_icon;
mod screen;
mod sync;
mod util;
@ -115,7 +114,13 @@ impl App {
let screen: &mut MainScreen = a.as_any().downcast_mut::<MainScreen>().unwrap();
screen.progress = Some((c, max));
screen.download_screen();
}
},
AppEvent::CurrentProgress(progress) => {
let a = self.screens.get_mut(&AppState::MainScreen).unwrap();
let screen: &mut MainScreen = a.as_any().downcast_mut::<MainScreen>().unwrap();
screen.s_progress = Some(progress);
screen.download_screen();
},
_ => {}
}
}

View File

@ -12,7 +12,7 @@ use soundcloud::sobjects::CloudPlaylists;
use strum::IntoEnumIterator;
use tokio::sync::mpsc::UnboundedSender;
use crate::{screen::AppScreen, sync::AppEvent};
use crate::{dlp::DownloadProgress, screen::AppScreen, sync::AppEvent};
struct Playlist {
id: u64,
@ -29,6 +29,7 @@ pub struct MainScreen {
tab_titles: Vec<String>,
soundcloud: Option<Vec<Playlist>>,
pub progress: Option<(u32, u32)>,
pub s_progress: Option<DownloadProgress>,
sender: UnboundedSender<AppEvent>,
}
@ -71,11 +72,9 @@ impl AppScreen for MainScreen {
frame.render_widget(tabs, chunks[0]);
if self.selected_tab != -1 {
//frame.render_widget(self.render_tab(), chunks[1]);
self.render_tab(frame, chunks[1]);
} else {
self.render_progress(frame, chunks[1]);
match self.selected_tab {
-1 => self.render_progress(frame, chunks[1]),
_ => self.render_tab(frame, chunks[1]),
}
// Render Status Bar
@ -106,6 +105,7 @@ impl MainScreen {
max_rows: 0,
soundcloud: None,
progress: None,
s_progress: None,
selected_tab: 0,
tab_titles: vec![
"YouTube".to_string(),
@ -131,6 +131,9 @@ impl MainScreen {
}
fn next_tab(&mut self) {
if self.selected_tab < 0 {
return;
}
self.selected_tab = std::cmp::min(
self.selected_tab + 1,
(self.tab_titles.len() - 1).try_into().unwrap(),
@ -139,6 +142,9 @@ impl MainScreen {
}
fn previous_tab(&mut self) {
if self.selected_tab < 0 {
return;
}
self.selected_tab = std::cmp::max(0, self.selected_tab - 1);
self.update_max_rows();
}
@ -186,12 +192,16 @@ impl MainScreen {
.direction(Direction::Vertical)
.constraints([
Constraint::Min(0), // Main content
Constraint::Length(3), // Progress bar
Constraint::Length(6), // Progress bar
Constraint::Length(6), // Progress bar
])
.split(area);
let main_content = Paragraph::new("Main content goes here!")
.block(Block::default().borders(Borders::ALL).title("Main"));
let main_content = Paragraph::new("Please wait").block(
Block::default()
.borders(Borders::ALL)
.title("Downloading has started!"),
);
frame.render_widget(main_content, chunks[0]);
@ -210,6 +220,31 @@ impl MainScreen {
));
frame.render_widget(gauge, chunks[1]);
if self.s_progress.is_none() {
return;
}
let s: String = self
.s_progress
.as_ref()
.unwrap()
.progress_percentage
.chars()
.filter(|c| c.is_ascii_digit() || *c == '.')
.collect();
let ratio: f64 = s.parse::<f64>().unwrap_or(0.0);
let gauge = Gauge::default()
.block(Block::default().borders(Borders::ALL).title(format!(
" Downloading Item (ETA: {}) ",
self.s_progress.as_ref().unwrap().eta
)))
.gauge_style(Style::default().fg(Color::Green))
.ratio(ratio / 100.0)
.label(self.s_progress.as_ref().unwrap().progress_total.to_string());
frame.render_widget(gauge, chunks[2]);
}
fn render_tab(&self, frame: &mut Frame, area: Rect) /*-> Table<'_>*/

View File

@ -1,61 +0,0 @@
use image::DynamicImage;
use ratatui::{buffer::Buffer, layout::Rect, style::Color, widgets::Widget};
#[derive(Default, Clone)]
pub struct PlaylistIcon {
colors: Vec<[u8; 3]>,
}
impl PlaylistIcon {
pub fn new(img: DynamicImage) -> Self {
let img_rgb = img.to_rgb8();
let pixels = img_rgb.as_raw();
let r = color_thief::get_palette(pixels, color_thief::ColorFormat::Rgb, 10, 4)
.unwrap()
.iter()
.map(|c| [c.r, c.g, c.b])
.collect::<Vec<[u8; 3]>>();
Self { colors: r }
}
fn lerp(a: &[u8; 3], b: &[u8; 3], n: f32) -> [u8; 3] {
let r = (b[0] as f32 - a[0] as f32) * n + b[0] as f32;
let g = (b[1] as f32 - a[1] as f32) * n + b[1] as f32;
let b = (b[2] as f32 - a[2] as f32) * n + b[2] as f32;
[r as u8, g as u8, b as u8]
}
}
impl Widget for PlaylistIcon {
fn render(self, area: Rect, buf: &mut Buffer) {
let mut i = 0;
let start = self.colors.first().unwrap_or(&[255u8, 255u8, 255u8]);
let end = &[0u8, 0u8, 0u8];
let mut c = *start;
for y in area.top()..area.bottom() {
for x in area.left()..area.right() {
let n = (((area.bottom() - y).pow(2) + (area.right() - x).pow(2)) as f32).sqrt();
c = PlaylistIcon::lerp(start, end, n);
buf[(x, y)]
.set_char(' ')
.set_bg(Color::Rgb(c[0], c[1], c[2]))
.set_fg(Color::Rgb(c[0], c[1], c[2]));
}
i = match self.colors.len() {
0 => 0,
_ => {
if i >= self.colors.len() - 1 {
0
} else {
i + 1
}
}
};
}
}
}

View File

@ -2,10 +2,19 @@ use std::path::{Path, PathBuf};
use itunesdb::xobjects::XDatabase;
use soundcloud::sobjects::CloudPlaylists;
use tokio::{fs::File, io::{AsyncReadExt, AsyncWriteExt}, sync::mpsc::{Sender, UnboundedReceiver}};
use tokio::{
fs::File,
io::{AsyncReadExt, AsyncWriteExt},
sync::mpsc::{Sender, UnboundedReceiver},
};
use tokio_util::sync::CancellationToken;
use crate::{config::{get_config_path, get_configs_dir, get_temp_dl_dir, get_temp_itunesdb, LyricaConfiguration}, dlp::{self, DownloadProgress}};
use crate::{
config::{
get_config_path, get_configs_dir, get_temp_dl_dir, get_temp_itunesdb, LyricaConfiguration,
},
dlp::{self, DownloadProgress},
};
pub enum AppEvent {
SearchIPod,
@ -16,10 +25,14 @@ pub enum AppEvent {
SoundcloudGot(CloudPlaylists),
DownloadPlaylist(String),
CurrentProgress(DownloadProgress),
OverallProgress((u32, u32))
OverallProgress((u32, u32)),
}
pub fn initialize_async_service(sender: Sender<AppEvent>, receiver: UnboundedReceiver<AppEvent>, token: CancellationToken) {
pub fn initialize_async_service(
sender: Sender<AppEvent>,
receiver: UnboundedReceiver<AppEvent>,
token: CancellationToken,
) {
tokio::spawn(async move {
let mut receiver = receiver;
loop {
@ -52,7 +65,7 @@ pub fn initialize_async_service(sender: Sender<AppEvent>, receiver: UnboundedRec
let _ = sender.send(AppEvent::ITunesParsed(xdb)).await;
let p = get_config_path();
if !p.exists() {
if !p.exists() {
let config = LyricaConfiguration::default();
let cfg_str = toml::to_string_pretty(&config).unwrap();
let mut file = File::create(&p).await.unwrap();
@ -62,7 +75,7 @@ pub fn initialize_async_service(sender: Sender<AppEvent>, receiver: UnboundedRec
let mut content = String::new();
file.read_to_string(&mut content).await.unwrap();
let config: LyricaConfiguration = toml::from_str(&content).unwrap();
let app_version = soundcloud::get_app().await.unwrap().unwrap();
let client_id = soundcloud::get_client_id().await.unwrap().unwrap();
let playlists = soundcloud::get_playlists(config.get_soundcloud().user_id, client_id, app_version).await.unwrap();
@ -70,7 +83,9 @@ pub fn initialize_async_service(sender: Sender<AppEvent>, receiver: UnboundedRec
let _ = sender.send(AppEvent::SoundcloudGot(playlists)).await;
},
AppEvent::DownloadPlaylist(playlist_url) => {
let _ = dlp::download_from_soundcloud(&playlist_url, &get_temp_dl_dir(), sender.clone()).await;
if let Ok(()) = dlp::download_from_soundcloud(&playlist_url, &get_temp_dl_dir(), sender.clone()).await {
// TODO: sync with db
}
}
_ => {}
}
@ -79,4 +94,4 @@ pub fn initialize_async_service(sender: Sender<AppEvent>, receiver: UnboundedRec
}
}
});
}
}