From 8f8a79411b8f0f58cc204f6221cf8068950e34e5 Mon Sep 17 00:00:00 2001 From: "alterwain@protonmail.com" Date: Tue, 11 Feb 2025 19:58:42 +0300 Subject: [PATCH] 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 --- .gitignore | 3 +- Cargo.lock | 438 +++++++++---------------------------------- Cargo.toml | 7 +- src/dlp.rs | 27 ++- src/main.rs | 9 +- src/main_screen.rs | 53 +++++- src/playlist_icon.rs | 61 ------ src/sync.rs | 31 ++- 8 files changed, 183 insertions(+), 446 deletions(-) delete mode 100644 src/playlist_icon.rs diff --git a/.gitignore b/.gitignore index 9f97022..5f32e70 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -target/ \ No newline at end of file +target/ +.env \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 5966747..4cc5eb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", -] diff --git a/Cargo.toml b/Cargo.toml index c27913d..847c62d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" \ No newline at end of file +color-thief = "0.2" +diesel = { version = "2.2.7", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] } +dotenvy = "0.15" \ No newline at end of file diff --git a/src/dlp.rs b/src/dlp.rs index 20070b0..7f15ee4 100644 --- a/src/dlp.rs +++ b/src/dlp.rs @@ -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) -> std::result::Result<(), Box> { +pub async fn download_from_soundcloud( + playlist_url: &str, + download_dir: &PathBuf, + sender: Sender, +) -> std::result::Result<(), Box> { 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(()) -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index aea9569..d219353 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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::().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::().unwrap(); + screen.s_progress = Some(progress); + screen.download_screen(); + }, _ => {} } } diff --git a/src/main_screen.rs b/src/main_screen.rs index 47e84ee..bc3b001 100644 --- a/src/main_screen.rs +++ b/src/main_screen.rs @@ -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, soundcloud: Option>, pub progress: Option<(u32, u32)>, + pub s_progress: Option, sender: UnboundedSender, } @@ -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::().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<'_>*/ diff --git a/src/playlist_icon.rs b/src/playlist_icon.rs deleted file mode 100644 index fbbed9c..0000000 --- a/src/playlist_icon.rs +++ /dev/null @@ -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::>(); - - 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 - } - } - }; - } - } -} diff --git a/src/sync.rs b/src/sync.rs index 8ff8a43..51ddf6b 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -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, receiver: UnboundedReceiver, token: CancellationToken) { +pub fn initialize_async_service( + sender: Sender, + receiver: UnboundedReceiver, + token: CancellationToken, +) { tokio::spawn(async move { let mut receiver = receiver; loop { @@ -52,7 +65,7 @@ pub fn initialize_async_service(sender: Sender, 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, 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, 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, receiver: UnboundedRec } } }); -} \ No newline at end of file +}