From dcbb5a127bf80a6dc6c5f91e475271c141d4a1b0 Mon Sep 17 00:00:00 2001 From: servius Date: Wed, 28 Jan 2026 23:40:59 +0530 Subject: [PATCH] feat: Move settings to a tab based ui --- Cargo.lock | 223 +++++++++++++++++++++++++++++++++++++++- flake.lock | 11 +- flake.nix | 39 +++++-- ui-iced/Cargo.toml | 3 +- ui-iced/src/lib.rs | 66 ++++-------- ui-iced/src/settings.rs | 114 +++++++++++--------- 6 files changed, 344 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d831d9..7505fca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,7 +212,7 @@ dependencies = [ "bytes", "iref", "jiff", - "reqwest", + "reqwest 0.12.28", "serde", "serde_json", "tap", @@ -635,6 +635,28 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "aws-lc-rs" +version = "1.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "backtrace" version = "0.3.76" @@ -1141,6 +1163,19 @@ dependencies = [ "libc", ] +[[package]] +name = "chrono" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", +] + [[package]] name = "ciborium" version = "0.2.2" @@ -1289,6 +1324,15 @@ dependencies = [ "x11rb", ] +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + [[package]] name = "cocoa" version = "0.25.0" @@ -2347,6 +2391,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futf" version = "0.1.5" @@ -3422,6 +3472,30 @@ dependencies = [ "windows-registry 0.6.1", ] +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "iced" version = "0.14.0" @@ -3433,7 +3507,7 @@ dependencies = [ "iced_futures", "iced_renderer", "iced_runtime 0.14.0 (git+https://github.com/uttarayan21/iced?branch=0.14)", - "iced_widget", + "iced_widget 0.14.2 (git+https://github.com/uttarayan21/iced?branch=0.14)", "iced_winit 0.14.0 (git+https://github.com/uttarayan21/iced?branch=0.14)", "image", "thiserror 2.0.18", @@ -3458,6 +3532,22 @@ dependencies = [ "wgpu", ] +[[package]] +name = "iced_aw" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cc84cc77dcb1c384c60792de025fb4a72e23c3d8c65c4a34691684875fc5403" +dependencies = [ + "cfg-if", + "chrono", + "iced_core", + "iced_fonts", + "iced_widget 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-format", + "num-traits", + "web-time", +] + [[package]] name = "iced_beacon" version = "0.14.0" @@ -3521,10 +3611,33 @@ source = "git+https://github.com/uttarayan21/iced?branch=0.14#6fbe1ec83722c67cf7 dependencies = [ "iced_debug 0.14.0 (git+https://github.com/uttarayan21/iced?branch=0.14)", "iced_program 0.14.0 (git+https://github.com/uttarayan21/iced?branch=0.14)", - "iced_widget", + "iced_widget 0.14.2 (git+https://github.com/uttarayan21/iced?branch=0.14)", "log", ] +[[package]] +name = "iced_fonts" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214cff7c8499e328774216690e58e315a1a5f8f6fdd1035aed6298e62ffc4c1d" +dependencies = [ + "iced_core", + "iced_fonts_macros", + "iced_widget 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "iced_fonts_macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef5125e110cb19cd1910a28298661c98c5d9ab02eef43594968352940e8752e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", + "ttf-parser 0.25.1", +] + [[package]] name = "iced_futures" version = "0.14.0" @@ -3672,6 +3785,20 @@ dependencies = [ "wgpu", ] +[[package]] +name = "iced_widget" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1596afa0d3109c2618e8bc12bae6c11d3064df8f95c42dfce570397dbe957ab" +dependencies = [ + "iced_renderer", + "log", + "num-traits", + "rustc-hash 2.1.1", + "thiserror 2.0.18", + "unicode-segmentation", +] + [[package]] name = "iced_widget" version = "0.14.2" @@ -4850,6 +4977,16 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -5916,6 +6053,7 @@ version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -6294,6 +6432,44 @@ dependencies = [ "web-sys", ] +[[package]] +name = "reqwest" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "resvg" version = "0.45.1" @@ -6431,6 +6607,7 @@ version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ + "aws-lc-rs", "once_cell", "ring", "rustls-pki-types", @@ -6470,12 +6647,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.0", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework 3.5.1", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -8017,9 +8222,10 @@ dependencies = [ "gpui_util", "iced", "iced-video", + "iced_aw", "iced_wgpu", "iced_winit 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest", + "reqwest 0.13.1", "tap", "toml 0.9.11+spec-1.1.0", "tracing", @@ -8597,6 +8803,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weezl" version = "0.1.12" diff --git a/flake.lock b/flake.lock index 64df29b..02f5bcf 100644 --- a/flake.lock +++ b/flake.lock @@ -34,10 +34,10 @@ "crates-io-index": { "flake": false, "locked": { - "lastModified": 1763363725, - "narHash": "sha256-cxr5xIKZFP45yV1ZHFTB1sHo5YGiR3FA8D9vAfDizMo=", + "lastModified": 1769614137, + "narHash": "sha256-3Td8fiv6iFVxeS0hYq3xdd10ZvUkC9INMAiQx/mECas=", "ref": "refs/heads/master", - "rev": "0382002e816a4cbd17d8d5b172f08b848aa22ff6", + "rev": "c7e7d6394bc95555d6acd5c6783855f47d64c90d", "shallow": true, "type": "git", "url": "https://github.com/rust-lang/crates.io-index" @@ -50,7 +50,9 @@ }, "crates-nix": { "inputs": { - "crates-io-index": "crates-io-index" + "crates-io-index": [ + "crates-io-index" + ] }, "locked": { "lastModified": 1763364255, @@ -124,6 +126,7 @@ "inputs": { "advisory-db": "advisory-db", "crane": "crane", + "crates-io-index": "crates-io-index", "crates-nix": "crates-nix", "flake-utils": "flake-utils", "nix-github-actions": "nix-github-actions", diff --git a/flake.nix b/flake.nix index 98e55d5..908ae58 100644 --- a/flake.nix +++ b/flake.nix @@ -9,7 +9,14 @@ url = "github:nix-community/nix-github-actions"; inputs.nixpkgs.follows = "nixpkgs"; }; - crates-nix.url = "github:uttarayan21/crates.nix"; + crates-io-index = { + url = "git+https://github.com/rust-lang/crates.io-index?shallow=1"; + flake = false; + }; + crates-nix = { + url = "github:uttarayan21/crates.nix"; + inputs.crates-io-index.follows = "crates-io-index"; + }; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; @@ -179,28 +186,38 @@ devShells = rec { rust-shell = pkgs.mkShell.override { - stdenv = - if pkgs.stdenv.isLinux - then (pkgs.stdenvAdapters.useMoldLinker pkgs.clangStdenv) - else pkgs.clangStdenv; - } (commonArgs + stdenv = pkgs.clangStdenv; + # if pkgs.stdenv.isLinux + # then (pkgs.stdenvAdapters.useMoldLinker pkgs.clangStdenv) + # else pkgs.clangStdenv; + } + (commonArgs // { # GST_PLUGIN_PATH = "/run/current-system/sw/lib/gstreamer-1.0/"; GIO_EXTRA_MODULES = "${pkgs.glib-networking}/lib/gio/modules"; packages = with pkgs; [ toolchainWithRustAnalyzer - cargo-nextest + bacon + cargo-audit cargo-deny cargo-expand - bacon - cargo-make cargo-hack + cargo-make + cargo-nextest cargo-outdated lld lldb - cargo-audit (crates.buildCrate "cargo-with" {doCheck = false;}) + (crates.buildCrate "dioxus-cli" { + nativeBuildInputs = with pkgs; [pkg-config]; + buildInputs = [openssl]; + doCheck = false; + }) + (crates.buildCrate "cargo-hot" { + nativeBuildInputs = with pkgs; [pkg-config]; + buildInputs = [openssl]; + }) ] ++ (lib.optionals pkgs.stdenv.isDarwin [ apple-sdk_26 @@ -211,7 +228,7 @@ samply cargo-flamegraph perf - mold + # mold ]); }); default = rust-shell; diff --git a/ui-iced/Cargo.toml b/ui-iced/Cargo.toml index 263f9ac..f4db350 100644 --- a/ui-iced/Cargo.toml +++ b/ui-iced/Cargo.toml @@ -21,9 +21,10 @@ iced = { workspace = true, features = [ iced-video = { workspace = true } +iced_aw = "0.13.0" iced_wgpu = "0.14.0" iced_winit = "0.14.0" -reqwest = "0.12.24" +reqwest = "0.13" tap = "1.0.1" toml = "0.9.8" tracing = "0.1.41" diff --git a/ui-iced/src/lib.rs b/ui-iced/src/lib.rs index 474936c..88b0619 100644 --- a/ui-iced/src/lib.rs +++ b/ui-iced/src/lib.rs @@ -158,8 +158,6 @@ impl State { query: None, screen: Screen::Home, settings: settings::SettingsState::default(), - // username_input: String::new(), - // password_input: String::new(), is_authenticated: false, video: None, } @@ -175,17 +173,8 @@ pub enum Message { OpenItem(Option), LoadedItem(Option, Vec), Error(String), - SetToken(String), Back, Home, - // Login { - // username: String, - // password: String, - // config: api::JellyfinConfig, - // }, - // LoginSuccess(String), - // LoadedClient(api::JellyfinClient, bool), - // Logout, Video(video::VideoMessage), } @@ -252,15 +241,6 @@ fn update(state: &mut State, message: Message) -> Task { state.messages.push(err); Task::none() } - Message::SetToken(token) => { - tracing::info!("Authenticated with token: {}", token); - state - .jellyfin_client - .as_mut() - .map(|mut client| client.set_token(token)); - state.is_authenticated = true; - Task::none() - } Message::Back => { state.current = state.history.pop().unwrap_or(None); Task::none() @@ -271,7 +251,6 @@ fn update(state: &mut State, message: Message) -> Task { } Message::SearchQueryChanged(query) => { state.query = Some(query); - // Handle search query change Task::none() } Message::Search => { @@ -350,19 +329,17 @@ fn body(state: &State) -> Element<'_, Message> { fn header(state: &State) -> Element<'_, Message> { row([ - container( - Button::new( - Text::new( - state - .jellyfin_client - .as_ref() - .map(|c| c.config.server_url.as_str()) - .unwrap_or("No Server"), - ) - .align_x(Alignment::Start), - ) - .on_press(Message::Home), + text( + state + .jellyfin_client + .as_ref() + .map(|c| c.config.server_url.as_str()) + .unwrap_or("No Server"), ) + .align_x(Alignment::Start) + .pipe(button) + .on_press(Message::Home) + .pipe(container) .padding(10) .width(Length::Fill) .height(Length::Fill) @@ -371,18 +348,17 @@ fn header(state: &State) -> Element<'_, Message> { .style(container::rounded_box) .into(), search(state), - container( - row([ - button("Refresh").on_press(Message::Refresh).into(), - button("Settings") - .on_press(Message::Settings(settings::SettingsMessage::Open)) - .into(), - button("TestVideo") - .on_press(Message::Video(video::VideoMessage::Test)) - .into(), - ]) - .spacing(10), - ) + row([ + button("Refresh").on_press(Message::Refresh).into(), + button("Settings") + .on_press(Message::Settings(settings::SettingsMessage::Open)) + .into(), + button("TestVideo") + .on_press(Message::Video(video::VideoMessage::Test)) + .into(), + ]) + .spacing(10) + .pipe(container) .padding(10) .width(Length::Fill) .height(Length::Fill) diff --git a/ui-iced/src/settings.rs b/ui-iced/src/settings.rs index c7b9b9f..aef4108 100644 --- a/ui-iced/src/settings.rs +++ b/ui-iced/src/settings.rs @@ -66,7 +66,7 @@ pub enum ServerMessage { Clear, } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub enum SettingsScreen { #[default] Main, @@ -195,9 +195,28 @@ impl ServerForm { } mod screens { + use iced_aw::Tabs; + use super::*; pub fn settings(state: &State) -> Element<'_, Message> { - row([settings_list(state), settings_screen(state)]).into() + Tabs::new(|f| Message::Settings(SettingsMessage::Select(f))) + .push( + SettingsScreen::Main, + iced_aw::TabLabel::Text("General".into()), + main(state), + ) + .push( + SettingsScreen::Servers, + iced_aw::TabLabel::Text("Servers".into()), + server(state), + ) + .push( + SettingsScreen::Users, + iced_aw::TabLabel::Text("Users".into()), + user(state), + ) + .set_active_tab(&state.settings.screen) + .into() } pub fn settings_screen(state: &State) -> Element<'_, Message> { @@ -207,64 +226,65 @@ mod screens { SettingsScreen::Users => user(state), }) .width(Length::FillPortion(10)) + .height(Length::Fill) + .style(|theme| container::background(theme.extended_palette().background.base.color)) + .pipe(container) + .padding(10) + .style(|theme| container::background(theme.extended_palette().secondary.base.color)) + .width(Length::FillPortion(10)) .into() } pub fn settings_list(state: &State) -> Element<'_, Message> { - scrollable( - column( - [ - button(center_text("Main")).on_press(Message::Settings( - SettingsMessage::Select(SettingsScreen::Main), - )), - button(center_text("Servers")).on_press(Message::Settings( - SettingsMessage::Select(SettingsScreen::Servers), - )), - button(center_text("Users")).on_press(Message::Settings( - SettingsMessage::Select(SettingsScreen::Users), - )), - ] - .map(|p| p.clip(true).width(Length::Fill).into()), - ) - .width(Length::FillPortion(2)) - .spacing(10) - .padding(10), + column( + [ + button(center_text("General")).on_press(Message::Settings( + SettingsMessage::Select(SettingsScreen::Main), + )), + button(center_text("Servers")).on_press(Message::Settings( + SettingsMessage::Select(SettingsScreen::Servers), + )), + button(center_text("Users")).on_press(Message::Settings(SettingsMessage::Select( + SettingsScreen::Users, + ))), + ] + .map(|p| p.clip(true).width(Length::Fill).into()), ) + .width(Length::FillPortion(2)) + .spacing(10) + .padding(10) + .pipe(scrollable) .into() } pub fn main(state: &State) -> Element<'_, Message> { - // placeholder for now - container( - Column::new() - .push(text("Main Settings")) - .push(toggler(true).label("Foobar")) - .spacing(20) - .padding(20), - ) - .into() + Column::new() + .push(text("Main Settings")) + .push(toggler(true).label("HDR")) + .spacing(20) + .padding(20) + .pipe(container) + .into() } + pub fn server(state: &State) -> Element<'_, Message> { - container( - Column::new() - .push(text("Server Settings")) - .push(state.settings.server_form.view()) - // .push(toggler(false).label("Enable Server")) - .spacing(20) - .padding(20), - ) - .into() + Column::new() + .push(text("Server Settings")) + .push(state.settings.server_form.view()) + .spacing(20) + .padding(20) + .pipe(container) + .into() } + pub fn user(state: &State) -> Element<'_, Message> { - container( - Column::new() - .push(text("User Settings")) - .push(state.settings.login_form.view()) - // .push(userlist(&state)) - .spacing(20) - .padding(20), - ) - .into() + Column::new() + .push(text("User Settings")) + .push(state.settings.login_form.view()) + .spacing(20) + .padding(20) + .pipe(container) + .into() } }