New icons, new side panel, table no longer shows playlists, as they are selectable seperately
This commit is contained in:
parent
847aa2bb4f
commit
70b92f4ebf
228
Cargo.lock
generated
228
Cargo.lock
generated
|
@ -579,6 +579,12 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
|
@ -953,6 +959,12 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color-hex"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecdffb913a326b6c642290a0d0ec8e8d6597291acdc07cc4c9cb4b3635d44cf9"
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
|
@ -1101,6 +1113,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
|
||||
|
||||
[[package]]
|
||||
name = "data-url"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
|
@ -1190,6 +1208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "20930a432bbd57a6d55e07976089708d4893f3d556cf42a0d79e9e321fa73b10"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"color-hex",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
@ -1283,9 +1302,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1b78779f35ded1a853786c9ce0b43fe1053e10a21ea3b23ebea411805ce41593"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"ehttp",
|
||||
"enum-map",
|
||||
"image",
|
||||
"log",
|
||||
"mime_guess2",
|
||||
"resvg",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
@ -1305,6 +1327,20 @@ dependencies = [
|
|||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ehttp"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59a81c221a1e4dad06cb9c9deb19aea1193a5eea084e8cd42d869068132bf876"
|
||||
dependencies = [
|
||||
"document-features",
|
||||
"js-sys",
|
||||
"ureq",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "emath"
|
||||
version = "0.27.2"
|
||||
|
@ -1508,6 +1544,12 @@ dependencies = [
|
|||
"miniz_oxide 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -1936,6 +1978,15 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html-escape"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
|
||||
dependencies = [
|
||||
"utf8-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.1.0"
|
||||
|
@ -2074,6 +2125,12 @@ dependencies = [
|
|||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imagesize"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.5.0"
|
||||
|
@ -2207,6 +2264,15 @@ version = "3.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
||||
|
||||
[[package]]
|
||||
name = "kurbo"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
|
@ -2329,11 +2395,13 @@ dependencies = [
|
|||
"egui_extras",
|
||||
"env_logger",
|
||||
"futures",
|
||||
"html-escape",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"notify-rust",
|
||||
"open",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -2873,6 +2941,12 @@ version = "2.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pico-args"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.5"
|
||||
|
@ -3138,6 +3212,12 @@ version = "0.6.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||
|
||||
[[package]]
|
||||
name = "rctree"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.3.5"
|
||||
|
@ -3178,9 +3258,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.6"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -3190,9 +3270,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.7"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -3201,9 +3281,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.4"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "renderdoc-sys"
|
||||
|
@ -3217,8 +3297,9 @@ version = "0.12.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
|
@ -3254,6 +3335,29 @@ dependencies = [
|
|||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resvg"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cadccb3d99a9efb8e5e00c16fbb732cbe400db2ec7fc004697ee7d97d86cf1f4"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pico-args",
|
||||
"rgb",
|
||||
"svgtypes",
|
||||
"tiny-skia",
|
||||
"usvg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rgb"
|
||||
version = "0.8.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.8"
|
||||
|
@ -3269,6 +3373,12 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roxmltree"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
|
@ -3320,6 +3430,7 @@ version = "0.23.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
|
@ -3334,7 +3445,7 @@ version = "2.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.22.1",
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
|
@ -3493,6 +3604,21 @@ version = "0.3.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "simplecss"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
|
@ -3633,6 +3759,9 @@ name = "strict-num"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||
dependencies = [
|
||||
"float-cmp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
|
@ -3646,6 +3775,16 @@ version = "2.6.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "svgtypes"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e44e288cd960318917cbd540340968b90becc8bc81f171345d706e7a89d9d70"
|
||||
dependencies = [
|
||||
"kurbo",
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
|
@ -3760,6 +3899,7 @@ dependencies = [
|
|||
"bytemuck",
|
||||
"cfg-if",
|
||||
"log",
|
||||
"png",
|
||||
"tiny-skia-path",
|
||||
]
|
||||
|
||||
|
@ -4019,6 +4159,22 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "2.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"flate2",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"url",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.2"
|
||||
|
@ -4030,6 +4186,56 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usvg"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38b0a51b72ab80ca511d126b77feeeb4fb1e972764653e61feac30adc161a756"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"log",
|
||||
"pico-args",
|
||||
"usvg-parser",
|
||||
"usvg-tree",
|
||||
"xmlwriter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usvg-parser"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bd4e3c291f45d152929a31f0f6c819245e2921bfd01e7bd91201a9af39a2bdc"
|
||||
dependencies = [
|
||||
"data-url",
|
||||
"flate2",
|
||||
"imagesize",
|
||||
"kurbo",
|
||||
"log",
|
||||
"roxmltree",
|
||||
"simplecss",
|
||||
"siphasher",
|
||||
"svgtypes",
|
||||
"usvg-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usvg-tree"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ee3d202ebdb97a6215604b8f5b4d6ef9024efd623cf2e373a6416ba976ec7d3"
|
||||
dependencies = [
|
||||
"rctree",
|
||||
"strict-num",
|
||||
"svgtypes",
|
||||
"tiny-skia-path",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
|
@ -4957,6 +5163,12 @@ version = "0.8.22"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26"
|
||||
|
||||
[[package]]
|
||||
name = "xmlwriter"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
||||
|
||||
[[package]]
|
||||
name = "zbus"
|
||||
version = "3.15.2"
|
||||
|
|
|
@ -11,16 +11,18 @@ anyhow = "1.0.81"
|
|||
camino = "1.1.6"
|
||||
clap = { version = "4.5.4", features = ["derive"] }
|
||||
eframe = "0.27.2"
|
||||
egui = "0.27.2"
|
||||
egui_extras = "0.27.2"
|
||||
egui = { version = "0.27.2", features = ["color-hex"] }
|
||||
egui_extras = { version = "0.27.2", features = ["all_loaders"] }
|
||||
env_logger = "0.11.3"
|
||||
futures = "0.3.30"
|
||||
html-escape = "0.2.13"
|
||||
lazy_static = "1.4.0"
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
notify-rust = "4.11.3"
|
||||
open = "5.3.0"
|
||||
reqwest = { version = "0.12.3", features = ["h2", "http2", "rustls-tls"], default-features = false }
|
||||
regex = "1.11.0"
|
||||
reqwest = { version = "0.12.3", features = ["blocking", "h2", "http2", "rustls-tls"], default-features = false }
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
serde_json = "1.0.115"
|
||||
# serde_traitobject = "0.2.8"
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
19
assets/note.svg
Normal file
19
assets/note.svg
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>music [#1005]</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Dribbble-Light-Preview" transform="translate(-260.000000, -3759.000000)" fill="#ffffff">
|
||||
<g id="icons" transform="translate(56.000000, 160.000000)">
|
||||
<path d="M224,3601.05129 L224,3610.55901 C224,3612.90979 222.17612,3614.95492 219.888035,3614.89646 C217.266519,3614.82877 215.248971,3612.1662 216.234285,3609.31593 C216.777356,3607.74464 218.297755,3606.71797 219.920978,3606.69233 C220.695653,3606.68105 220.976173,3606.88208 222.003416,3607.24105 L222.003416,3604.12822 C222.003416,3603.56207 221.556181,3603.10258 221.005124,3603.10258 L213.018786,3603.10258 C212.467729,3603.10258 212.020494,3603.56207 212.020494,3604.12822 L212.020494,3614.65851 C212.020494,3617.02057 210.179644,3619.07289 207.881575,3618.99801 C205.681339,3618.92622 203.914362,3617.02775 204.00321,3614.73031 C204.090061,3612.51594 205.989811,3610.84209 208.147121,3610.79081 C209.166377,3610.76619 209.352059,3610.92619 210.02391,3611.34363 L210.02391,3601.05129 C210.02391,3599.91795 210.91838,3599 212.020494,3599 L222.003416,3599 C223.106529,3599 224,3599.91795 224,3601.05129" id="music-[#1005]">
|
||||
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
4
assets/search.svg
Normal file
4
assets/search.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11 6C13.7614 6 16 8.23858 16 11M16.6588 16.6549L21 21M19 11C19 15.4183 15.4183 19 11 19C6.58172 19 3 15.4183 3 11C3 6.58172 6.58172 3 11 3C15.4183 3 19 6.58172 19 11Z" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 493 B |
1216
manifest.json
1216
manifest.json
File diff suppressed because it is too large
Load Diff
5
src/data.rs
Normal file
5
src/data.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
// pub const APP_ICON: egui::ImageSource = egui::include_image!("../assets/app_icon.png");
|
||||
pub const APP_ICON_BYTES: &[u8] = include_bytes!("../assets/app_icon.png");
|
||||
pub const NOTE_ICON: egui::ImageSource = egui::include_image!("../assets/note.svg");
|
||||
pub const SEARCH_ICON: egui::ImageSource = egui::include_image!("../assets/search.svg");
|
|
@ -143,8 +143,8 @@ impl Downloader {
|
|||
log::debug!("File {dl_file} doesnt exist, downloading");
|
||||
let mut cmd = match song.get_type() {
|
||||
|
||||
&SongType::Youtube => {
|
||||
log::debug!("Song {} is from yotube", song.get_url_str());
|
||||
SongType::Youtube | SongType::Soundcloud=> {
|
||||
log::debug!("Song {} is from youtube or sondclound", song.get_url_str());
|
||||
let mut cmd = tokio::process::Command::new(&cfg.cfg.ytdlp.path);
|
||||
cmd.args([
|
||||
"-x",
|
||||
|
@ -168,7 +168,7 @@ impl Downloader {
|
|||
]);
|
||||
cmd
|
||||
}
|
||||
url @ SongType::Soundcloud => {
|
||||
url => {
|
||||
log::error!("Unknown or unsupported hostname '{:?}'", url);
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![feature(downcast_unchecked)]
|
||||
#![feature(async_closure)]
|
||||
|
||||
use config::ConfigWrapper;
|
||||
|
||||
|
@ -13,8 +14,10 @@ mod constants;
|
|||
mod process_manager;
|
||||
mod ui;
|
||||
mod prompt;
|
||||
mod data;
|
||||
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let Ok(cfg) = ConfigWrapper::parse() else {
|
||||
return;
|
||||
};
|
||||
|
|
|
@ -18,7 +18,6 @@ lazy_static::lazy_static!(
|
|||
static PROC_INC: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
|
||||
|
||||
pub fn add_proc(mut cmd: Command, msg: String) -> anyhow::Result<()> {
|
||||
let mut proc = cmd.spawn()?;
|
||||
let id = PROC_INC.fetch_add(1, Ordering::AcqRel);
|
||||
|
@ -65,7 +64,7 @@ pub fn purge_done_procs() -> usize {
|
|||
finish_count
|
||||
}
|
||||
|
||||
/// Waits for processes to finish untill the proc count is lower or equal to `max`
|
||||
/// Waits for processes to finish until the proc count is lower or equal to `max`
|
||||
pub fn wait_for_procs_untill(max: usize) -> anyhow::Result<usize> {
|
||||
// NOTE: This looks really fucked because i dont want to deadlock the processes so i lock PROCESSES for as little as possible
|
||||
// NOTE: So its also kinda really slow
|
||||
|
|
|
@ -9,7 +9,7 @@ impl /* ComponentUi for */ ContextMenu {
|
|||
pub fn ui(gui: &mut crate::ui::gui::Gui, ui: &mut egui::Ui, pname: &String, sname: &String, song: &Song) {
|
||||
if ui.button("Edit").clicked() {
|
||||
let w = gui.windows.get_window::<GuiSongEditor>(WindowIndex::SongEdit);
|
||||
w.set_active_song(pname, sname, song.get_url_str());
|
||||
w.set_active_song(pname, sname, song.get_url_str(), song.get_type());
|
||||
gui.windows.open(WindowIndex::SongEdit, true);
|
||||
ui.close_menu();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ use super::Gui;
|
|||
pub mod nav;
|
||||
pub mod song_list;
|
||||
pub mod context_menu;
|
||||
pub mod side_nav;
|
||||
pub mod search_bar;
|
||||
|
||||
pub trait Component {
|
||||
fn ui(gui: &mut Gui, ctx: &egui::Context);
|
||||
|
@ -12,3 +14,7 @@ pub trait Component {
|
|||
pub trait ComponentUi {
|
||||
fn ui(gui: &mut Gui, ui: &mut egui::Ui);
|
||||
}
|
||||
|
||||
pub trait ComponentUiMut {
|
||||
fn ui(&mut self, gui: &mut Gui, ui: &mut egui::Ui);
|
||||
}
|
||||
|
|
53
src/ui/gui/components/search_bar.rs
Normal file
53
src/ui/gui/components/search_bar.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use egui::Color32;
|
||||
|
||||
use super::ComponentUiMut;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct SearchBar {
|
||||
text: String
|
||||
}
|
||||
|
||||
pub enum SearchType {
|
||||
Generic,
|
||||
Song,
|
||||
Url,
|
||||
Source,
|
||||
}
|
||||
|
||||
impl SearchBar {
|
||||
pub fn get_search(&self) -> (SearchType, String) {
|
||||
if self.text.starts_with("source:") {
|
||||
(
|
||||
SearchType::Source,
|
||||
self.text.strip_prefix("source:").unwrap_or("").to_string().to_lowercase()
|
||||
)
|
||||
} else if self.text.starts_with("song:") {
|
||||
(
|
||||
SearchType::Song,
|
||||
self.text.strip_prefix("song:").unwrap_or("").to_string().to_lowercase()
|
||||
)
|
||||
} else if self.text.starts_with("url:") {
|
||||
(
|
||||
SearchType::Url,
|
||||
self.text.strip_prefix("url:").unwrap_or("").to_string().to_lowercase()
|
||||
)
|
||||
} else {
|
||||
(
|
||||
SearchType::Generic,
|
||||
self.text.clone()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentUiMut for SearchBar {
|
||||
fn ui(&mut self, _: &mut crate::ui::gui::Gui, ui: &mut egui::Ui) {
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
let tint = Color32::from_hex("#333377").unwrap();
|
||||
ui.add(egui::Image::new(crate::data::SEARCH_ICON).tint(tint));
|
||||
ui.text_edit_singleline(&mut self.text);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
45
src/ui/gui/components/side_nav.rs
Normal file
45
src/ui/gui/components/side_nav.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use std::borrow::BorrowMut;
|
||||
|
||||
use egui::{Button, Color32, Label, RichText, Sense};
|
||||
|
||||
use super::ComponentUi;
|
||||
|
||||
|
||||
|
||||
pub struct SideNav;
|
||||
|
||||
impl ComponentUi for SideNav {
|
||||
fn ui(gui: &mut crate::ui::gui::Gui, ui: &mut egui::Ui) {
|
||||
let mut playlist_names = gui.manifest
|
||||
.get_playlists()
|
||||
.keys().cloned().collect::<Vec<String>>();
|
||||
|
||||
playlist_names.sort_by_key(|name| name.to_lowercase());
|
||||
ui.with_layout(egui::Layout::top_down(egui::Align::TOP), |ui| {
|
||||
|
||||
for pname in playlist_names {
|
||||
if gui.current_playlist.is_empty() {
|
||||
gui.current_playlist = pname.to_string();
|
||||
}
|
||||
ui.horizontal(|ui| {
|
||||
|
||||
let tint = Color32::from_hex("#333377").unwrap();
|
||||
ui.add(egui::Image::new(crate::data::NOTE_ICON).tint(tint));
|
||||
ui.horizontal(|ui| {
|
||||
let text;
|
||||
if gui.current_playlist == *pname {
|
||||
text = RichText::new(&pname).color(tint);
|
||||
} else {
|
||||
text = RichText::new(&pname);
|
||||
}
|
||||
let button = Label::new(text).sense(Sense::click());
|
||||
if ui.add(button).clicked() {
|
||||
gui.current_playlist = pname.to_string();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// #333377
|
||||
}
|
|
@ -3,126 +3,128 @@ use egui_extras::{Column, TableBuilder};
|
|||
|
||||
use crate::manifest::song::SongType;
|
||||
|
||||
use super::{context_menu::ContextMenu, ComponentUi};
|
||||
use super::{context_menu::ContextMenu, search_bar::SearchType, ComponentUi};
|
||||
|
||||
|
||||
pub struct SongList;
|
||||
#[derive(Debug, Default)]
|
||||
pub struct SongList {
|
||||
}
|
||||
|
||||
impl ComponentUi for SongList {
|
||||
fn ui(gui: &mut crate::ui::gui::Gui, ui: &mut egui::Ui) {
|
||||
let fltr_by;
|
||||
let filter_clean;
|
||||
if gui.filter.starts_with("playlist:") {
|
||||
fltr_by = "playlist";
|
||||
filter_clean = gui.filter.strip_prefix("playlist:").unwrap_or("").to_string().to_lowercase();
|
||||
} else if gui.filter.starts_with("source:") {
|
||||
fltr_by = "source";
|
||||
filter_clean = gui.filter.strip_prefix("source:").unwrap_or("").to_string().to_lowercase();
|
||||
} else if gui.filter.starts_with("url:") {
|
||||
fltr_by = "url";
|
||||
filter_clean = gui.filter.strip_prefix("url:").unwrap_or("").to_string();
|
||||
} else {
|
||||
fltr_by = "";
|
||||
filter_clean = gui.filter.clone();
|
||||
}
|
||||
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.colored_label(Color32::from_hex("#4444aa").unwrap(), "Filter: ");
|
||||
ui.text_edit_singleline(&mut gui.filter);
|
||||
});
|
||||
});
|
||||
{
|
||||
use crate::ui::gui::components::ComponentUiMut;
|
||||
let mut search = gui.search.clone();
|
||||
search.ui(gui, ui);
|
||||
gui.search = search;
|
||||
}
|
||||
|
||||
ui.vertical(|ui| {
|
||||
let available_height = ui.available_height();
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||
.resizable(true)
|
||||
//.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
//.column(
|
||||
// Column::remainder()
|
||||
// .at_least(40.0)
|
||||
// .clip(true)
|
||||
// .resizable(true),
|
||||
//)
|
||||
.column(Column::auto())
|
||||
.column(Column::remainder())
|
||||
//.column(Column::remainder())
|
||||
.min_scrolled_height(0.0)
|
||||
.max_scroll_height(available_height)
|
||||
.sense(egui::Sense::click());
|
||||
ui.vertical(|ui| {
|
||||
let available_height = ui.available_height();
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||
.resizable(true)
|
||||
//.column(Column::auto())
|
||||
//.column(Column::auto())
|
||||
//.column(
|
||||
// Column::remainder()
|
||||
// .at_least(40.0)
|
||||
// .clip(true)
|
||||
// .resizable(true),
|
||||
//)
|
||||
.column(Column::auto())
|
||||
.column(Column::remainder())
|
||||
//.column(Column::remainder())
|
||||
.min_scrolled_height(0.0)
|
||||
.max_scroll_height(available_height)
|
||||
.sense(egui::Sense::click());
|
||||
|
||||
let playlists = gui.manifest.get_playlists().clone();
|
||||
let playlists = gui.manifest.get_playlists().clone();
|
||||
|
||||
let songs = {
|
||||
let mut songs = Vec::new();
|
||||
for (pname, p) in playlists {
|
||||
for (sname, s) in p {
|
||||
songs.push((pname.clone(), sname, s));
|
||||
let songs = {
|
||||
let mut songs = Vec::new();
|
||||
for (pname, p) in playlists {
|
||||
for (sname, s) in p {
|
||||
songs.push((pname.clone(), sname, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
songs
|
||||
};
|
||||
|
||||
table.header(20.0, |mut header| {
|
||||
// header.col(|_|{});
|
||||
header.col(|ui| {
|
||||
ui.strong("Playlist");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("Source");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("Name");
|
||||
});
|
||||
}).body(|mut body| {
|
||||
for (pname, sname, s) in songs {
|
||||
if fltr_by == "playlist" && !filter_clean.is_empty() {
|
||||
if !pname.to_lowercase().contains(&filter_clean) {
|
||||
continue;
|
||||
}
|
||||
} else if fltr_by == "type" && !filter_clean.is_empty(){
|
||||
if !s.get_type().to_string().to_lowercase().contains(&filter_clean) {
|
||||
continue;
|
||||
}
|
||||
} else if fltr_by == "url" && !filter_clean.is_empty(){
|
||||
if !s.get_url_str().contains(&filter_clean) {
|
||||
continue;
|
||||
}
|
||||
} else if !filter_clean.is_empty() && !sname.to_lowercase().contains(&filter_clean) {
|
||||
continue;
|
||||
}
|
||||
body.row(18.0, |mut row| {
|
||||
|
||||
row.col(|ui| {
|
||||
ui.label(pname.clone())
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
});
|
||||
row.col(|ui| {
|
||||
let color =
|
||||
match s.get_type() {
|
||||
SongType::Youtube => Color32::from_hex("#FF0000").unwrap(),
|
||||
SongType::Spotify => Color32::from_hex("#1db954").unwrap(),
|
||||
SongType::Soundcloud => Color32::from_hex("#F26F23").unwrap()
|
||||
};
|
||||
|
||||
ui.colored_label(color, s.get_type().to_string())
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.hyperlink_to(sname.clone(), s.get_url_str())
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
});
|
||||
|
||||
row.response()
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
songs.sort_by_key(|song| song.1.to_lowercase());
|
||||
songs
|
||||
};
|
||||
|
||||
table.header(20.0, |mut header| {
|
||||
// header.col(|_|{});
|
||||
//header.col(|ui| {
|
||||
// ui.strong("Playlist");vec.sort_by_key(|name| name.to_lowercase());
|
||||
//});
|
||||
header.col(|ui| {
|
||||
ui.strong("Source");
|
||||
});
|
||||
}
|
||||
header.col(|ui| {
|
||||
ui.strong("Name");
|
||||
});
|
||||
}).body(|mut body| {
|
||||
for (pname, sname, s) in songs {
|
||||
if pname != gui.current_playlist {
|
||||
continue;
|
||||
}
|
||||
match gui.search.get_search() {
|
||||
(SearchType::Generic, filter) if !filter.is_empty() => {
|
||||
if !pname.to_lowercase().contains(&filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
(SearchType::Song, filter) if !filter.is_empty() => {
|
||||
if !sname.to_lowercase().contains(&filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
(SearchType::Source, filter) if !filter.is_empty() => {
|
||||
if !s.get_type().to_string().to_lowercase().contains(&filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
(SearchType::Url, filter) if !filter.is_empty() => {
|
||||
if !s.get_url_str().contains(&filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
(SearchType::Source, _) => (),
|
||||
(SearchType::Song, _) => (),
|
||||
(SearchType::Generic, _) => (),
|
||||
(SearchType::Url, _) => (),
|
||||
}
|
||||
body.row(18.0, |mut row| {
|
||||
|
||||
//row.col(|ui| {
|
||||
// ui.label(pname.clone())
|
||||
// .context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
//});
|
||||
row.col(|ui| {
|
||||
let color =
|
||||
match s.get_type() {
|
||||
SongType::Youtube => Color32::from_hex("#FF0000").unwrap(),
|
||||
SongType::Spotify => Color32::from_hex("#1db954").unwrap(),
|
||||
SongType::Soundcloud => Color32::from_hex("#F26F23").unwrap()
|
||||
};
|
||||
|
||||
ui.colored_label(color, s.get_type().to_string())
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.hyperlink_to(sname.clone(), s.get_url_str())
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
});
|
||||
|
||||
row.response()
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ mod windows;
|
|||
mod components;
|
||||
|
||||
use components::{Component, ComponentUi};
|
||||
use egui_extras::install_image_loaders;
|
||||
use windows::{State, WindowIndex, WindowManager};
|
||||
use crate::{config::ConfigWrapper, downloader::Downloader, manifest::Manifest};
|
||||
|
||||
|
@ -10,10 +11,11 @@ use crate::{config::ConfigWrapper, downloader::Downloader, manifest::Manifest};
|
|||
pub struct Gui {
|
||||
windows: WindowManager,
|
||||
manifest: Manifest,
|
||||
filter: String,
|
||||
downloader: Downloader,
|
||||
cfg: ConfigWrapper,
|
||||
downloading: bool,
|
||||
search: components::search_bar::SearchBar,
|
||||
current_playlist: String,
|
||||
}
|
||||
|
||||
impl Gui {
|
||||
|
@ -33,13 +35,13 @@ impl Gui {
|
|||
.with_inner_size([400.0, 300.0])
|
||||
.with_min_inner_size([300.0, 220.0])
|
||||
.with_icon(
|
||||
eframe::icon_data::from_png_bytes(&include_bytes!("../../../assets/icon.png")[..])?,
|
||||
eframe::icon_data::from_png_bytes(crate::data::APP_ICON_BYTES)?,
|
||||
),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if let Err(e) = eframe::run_native(
|
||||
"eframe template",
|
||||
"McMG",
|
||||
native_options,
|
||||
Box::new(|cc| Box::new(Gui::new(cc, manifest, downloader, cfg))),
|
||||
) {
|
||||
|
@ -59,7 +61,7 @@ impl Gui {
|
|||
|
||||
impl eframe::App for Gui {
|
||||
fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
|
||||
components::nav::NavBar::ui(self, ctx);
|
||||
install_image_loaders(ctx);
|
||||
{
|
||||
let mut state = State {
|
||||
cfg: self.cfg.clone(),
|
||||
|
@ -72,14 +74,24 @@ impl eframe::App for Gui {
|
|||
self.manifest = state.manifest;
|
||||
}
|
||||
|
||||
components::nav::NavBar::ui(self, ctx);
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
let avail_height = ui.available_height();
|
||||
// The central panel the region left after adding TopPanel's and SidePanel's
|
||||
//ui.heading(format!("Songs ({})", self.manifest.get_song_count()));
|
||||
components::song_list::SongList::ui(self, ui);
|
||||
ui.separator();
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
ui.with_layout(egui::Layout::top_down_justified(egui::Align::TOP), |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.set_height(avail_height);
|
||||
components::side_nav::SideNav::ui(self, ui);
|
||||
components::song_list::SongList::ui(self, ui);
|
||||
});
|
||||
ui.separator();
|
||||
|
||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
||||
egui::warn_if_debug_build(ui);
|
||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
||||
egui::warn_if_debug_build(ui);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
use crate::manifest::song::{Song, SongType};
|
||||
|
||||
use super::{State, Window};
|
||||
|
||||
|
||||
#[allow(clippy::pedantic)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct GuiImportPlaylist {
|
||||
ed_type: SongType,
|
||||
ed_name: String,
|
||||
ed_url: String,
|
||||
urls_to_add: Vec<String>,
|
||||
playlist_name: String,
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,7 +21,15 @@ impl Window for GuiImportPlaylist {
|
|||
.open(open)
|
||||
.show(ctx, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Type: Youtube");
|
||||
ui.label("Type: ");
|
||||
egui::ComboBox::from_id_source("new_playlist_window_type")
|
||||
.selected_text(format!("{:?}", self.ed_type))
|
||||
.show_ui(ui, |ui| {
|
||||
ui.selectable_value(&mut self.ed_type, SongType::Youtube, "Youtube");
|
||||
ui.selectable_value(&mut self.ed_type, SongType::Spotify, "Spotify");
|
||||
// ui.selectable_value(&mut self.ed_type, SongType::Soundcloud, "Soundcloud");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
|
@ -33,6 +46,20 @@ impl Window for GuiImportPlaylist {
|
|||
}
|
||||
});
|
||||
|
||||
if let Some(url) = self.urls_to_add.pop() {
|
||||
todo!();
|
||||
//let client = reqwest::blocking::Client::new();
|
||||
// let song_name = crate::crawler::spotify::get_song_name(&client, url.clone())?;
|
||||
|
||||
//if let Some(playlist) = state.manifest.get_playlist_mut(&self.playlist_name) {
|
||||
// let mut song = Song::from_url_str(url)?;
|
||||
// song.set_type(SongType::Spotify);
|
||||
// playlist.add_song(song_name, song);
|
||||
//}
|
||||
//let _ = state.manifest.save(None);
|
||||
}
|
||||
|
||||
|
||||
if save {
|
||||
let name = self.ed_name.clone();
|
||||
let url = self.ed_url.clone();
|
||||
|
@ -40,15 +67,22 @@ impl Window for GuiImportPlaylist {
|
|||
if state.manifest.get_playlist(&name).is_some() {
|
||||
log::error!("Playlist {name} already exists");
|
||||
}
|
||||
if self.ed_type == SongType::Spotify {
|
||||
todo!()
|
||||
//let client = reqwest::blocking::Client::new();
|
||||
//self.urls_to_add = crate::crawler::spotify::get_playlist_song_urls(&client, self.ed_url.clone())?;
|
||||
//self.playlist_name = self.ed_name.clone();
|
||||
//state.manifest.add_playlist(name.clone());
|
||||
} else if self.ed_type == SongType::Youtube {
|
||||
let songs = state.downloader.download_playlist_nb(&state.cfg, &url, &name, state.manifest.get_format()).unwrap();
|
||||
state.manifest.add_playlist(name.clone());
|
||||
|
||||
let songs = state.downloader.download_playlist_nb(&state.cfg, &url, &name, state.manifest.get_format()).unwrap();
|
||||
state.manifest.add_playlist(name.clone());
|
||||
let playlist = state.manifest.get_playlist_mut(&name).expect("Unreachable");
|
||||
|
||||
let playlist = state.manifest.get_playlist_mut(&name).expect("Unreachable");
|
||||
|
||||
for (sname, song) in songs {
|
||||
log::info!("Added: {sname}");
|
||||
playlist.add_song(sname, song);
|
||||
for (sname, song) in songs {
|
||||
log::info!("Added: {sname}");
|
||||
playlist.add_song(sname, song);
|
||||
}
|
||||
}
|
||||
let _ = state.manifest.save(None);
|
||||
*open = false;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use anyhow::bail;
|
||||
use egui::Color32;
|
||||
|
||||
use crate::manifest::song::SongType;
|
||||
|
||||
use super::{State, Window};
|
||||
|
||||
|
||||
|
@ -9,19 +11,20 @@ pub struct GuiSongEditor {
|
|||
song: (String, String),
|
||||
ed_url: String,
|
||||
ed_name: String,
|
||||
ed_type: SongType
|
||||
}
|
||||
|
||||
|
||||
impl Window for GuiSongEditor {
|
||||
fn ui(&mut self, state: &mut State, ctx: &egui::Context, open: &mut bool) -> anyhow::Result<()> {
|
||||
let mut save = false;
|
||||
let (playlist, song_name) = self.song.clone();
|
||||
let (playlist_name, song_name) = self.song.clone();
|
||||
|
||||
if playlist.is_empty() {
|
||||
if playlist_name.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Some(song) = state.manifest.get_song(&playlist, &song_name) else {
|
||||
let Some(song) = state.manifest.get_song(&playlist_name, &song_name) else {
|
||||
bail!("Failed to get song (1)");
|
||||
};
|
||||
let song = song.clone();
|
||||
|
@ -36,7 +39,7 @@ impl Window for GuiSongEditor {
|
|||
ui.label("[");
|
||||
ui.hyperlink_to("link", song.get_url().unwrap());
|
||||
ui.label("] ");
|
||||
ui.colored_label(Color32::LIGHT_BLUE, &playlist);
|
||||
ui.colored_label(Color32::LIGHT_BLUE, &playlist_name);
|
||||
ui.label(": ");
|
||||
ui.label(&song_name)
|
||||
});
|
||||
|
@ -44,6 +47,14 @@ impl Window for GuiSongEditor {
|
|||
ui.horizontal(|ui| {
|
||||
ui.label("Type: ");
|
||||
ui.label(song.get_type().to_string());
|
||||
egui::ComboBox::from_id_source("song_edit_window_type")
|
||||
.selected_text(format!("{:?}", self.ed_type))
|
||||
.show_ui(ui, |ui| {
|
||||
ui.selectable_value(&mut self.ed_type, SongType::Youtube, "Youtube");
|
||||
ui.selectable_value(&mut self.ed_type, SongType::Spotify, "Spotify");
|
||||
ui.selectable_value(&mut self.ed_type, SongType::Soundcloud, "Soundcloud");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
|
@ -61,21 +72,23 @@ impl Window for GuiSongEditor {
|
|||
});
|
||||
|
||||
if save {
|
||||
{
|
||||
let Some(song) = state.manifest.get_song_mut(&playlist, &song_name) else {
|
||||
let song = {
|
||||
let Some(song) = state.manifest.get_song_mut(&playlist_name, &song_name) else {
|
||||
bail!("Failed to get song (2)");
|
||||
};
|
||||
|
||||
song.get_url_str_mut().clone_from(&self.ed_url);
|
||||
}
|
||||
|
||||
let Some(playlist) = state.manifest.get_playlist_mut(&playlist) else {
|
||||
bail!("Failed to get playlist");
|
||||
song.get_type_mut().clone_from(&self.ed_type);
|
||||
song.clone()
|
||||
};
|
||||
|
||||
|
||||
let Some(playlist) = state.manifest.get_playlist_mut(&playlist_name) else {
|
||||
bail!("Failed to get playlist");
|
||||
};
|
||||
|
||||
playlist.remove_song(&song_name);
|
||||
playlist.add_song(self.ed_name.clone(), song);
|
||||
playlist.add_song(self.ed_name.clone(), song.clone());
|
||||
*open = false;
|
||||
let _ = state.manifest.save(None);
|
||||
}
|
||||
|
@ -85,10 +98,11 @@ impl Window for GuiSongEditor {
|
|||
}
|
||||
|
||||
impl GuiSongEditor {
|
||||
pub fn set_active_song(&mut self, pname: &str, sname: &str, url: &str) {
|
||||
pub fn set_active_song(&mut self, pname: &str, sname: &str, url: &str, typ: &SongType) {
|
||||
self.song.0 = pname.to_string();
|
||||
self.song.1 = sname.to_string();
|
||||
self.ed_name = sname.to_string();
|
||||
self.ed_url = url.to_string();
|
||||
self.ed_type = typ.clone();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user