From 85e61af9a96c6f7055d7a92b24bce984a4678c7b Mon Sep 17 00:00:00 2001 From: Samuel Oldham Date: Wed, 25 Sep 2024 20:33:37 +0100 Subject: [PATCH 01/10] Initial commit --- psst-gui/src/data/config.rs | 2 ++ psst-gui/src/delegate.rs | 6 ++-- psst-gui/src/main.rs | 17 ++++++++++-- psst-gui/src/ui/menu.rs | 4 +-- psst-gui/src/ui/mod.rs | 51 ++++++++++++++++++++++++++++++---- psst-gui/src/ui/preferences.rs | 49 +++++++++++++++++++++++++++++++- psst-gui/src/ui/user.rs | 10 +++++-- 7 files changed, 123 insertions(+), 16 deletions(-) diff --git a/psst-gui/src/data/config.rs b/psst-gui/src/data/config.rs index cbb897f4..5852fdc2 100644 --- a/psst-gui/src/data/config.rs +++ b/psst-gui/src/data/config.rs @@ -100,6 +100,7 @@ pub struct Config { pub sort_criteria: SortCriteria, pub paginated_limit: usize, pub seek_duration: usize, + pub kiosk_mode: bool, } impl Default for Config { @@ -118,6 +119,7 @@ impl Default for Config { sort_criteria: Default::default(), paginated_limit: 500, seek_duration: 10, + kiosk_mode: false, } } } diff --git a/psst-gui/src/delegate.rs b/psst-gui/src/delegate.rs index 617071b2..1437ab05 100644 --- a/psst-gui/src/delegate.rs +++ b/psst-gui/src/delegate.rs @@ -71,13 +71,13 @@ impl Delegate { } } - fn show_preferences(&mut self, ctx: &mut DelegateCtx) { + fn show_preferences(&mut self, config: &Config, ctx: &mut DelegateCtx) { match self.preferences_window { Some(id) => { ctx.submit_command(commands::SHOW_WINDOW.to(id)); } None => { - let window = ui::preferences_window(); + let window = ui::preferences_window(config); self.preferences_window.replace(window.id); ctx.new_window(window); } @@ -113,7 +113,7 @@ impl AppDelegate for Delegate { self.show_account_setup(ctx); Handled::Yes } else if cmd.is(commands::SHOW_PREFERENCES) { - self.show_preferences(ctx); + self.show_preferences(&data.config, ctx); Handled::Yes } else if cmd.is(cmd::CLOSE_ALL_WINDOWS) { self.close_all_windows(ctx); diff --git a/psst-gui/src/main.rs b/psst-gui/src/main.rs index 8832a3ac..453d26b9 100644 --- a/psst-gui/src/main.rs +++ b/psst-gui/src/main.rs @@ -13,6 +13,7 @@ mod widget; use druid::AppLauncher; use env_logger::{Builder, Env}; use webapi::WebApi; +use std::env; use crate::{ data::{AppState, Config}, @@ -33,7 +34,14 @@ fn main() { let config = Config::load().unwrap_or_default(); let paginated_limit = config.paginated_limit; - let state = AppState::default_with_config(config); + let mut state = AppState::default_with_config(config); + + let args: Vec = env::args().collect(); + state.config.kiosk_mode = false; + if !args.is_empty() && (args.contains(&"-k".to_string()) || args.contains(&"-kiosk".to_string())) { + state.config.kiosk_mode = true; + } + WebApi::new( state.session.clone(), Config::proxy().as_deref(), @@ -54,7 +62,12 @@ fn main() { WebApi::global().load_local_tracks(state.config.username().unwrap()); } else { // No configured credentials, open the account setup. - let window = ui::account_setup_window(); + let mut window = ui::account_setup_window(); + + if state.config.kiosk_mode { + window = ui::kiosk_setup_window(); + } + delegate = Delegate::with_preferences(window.id); launcher = AppLauncher::with_window(window).configure_env(ui::theme::setup); }; diff --git a/psst-gui/src/ui/menu.rs b/psst-gui/src/ui/menu.rs index 76bd16fe..ecaa4a13 100644 --- a/psst-gui/src/ui/menu.rs +++ b/psst-gui/src/ui/menu.rs @@ -5,8 +5,8 @@ use crate::{ data::{AppState, Nav}, }; -pub fn main_menu(_window: Option, _data: &AppState, _env: &Env) -> Menu { - if cfg!(target_os = "macos") { +pub fn main_menu(_window: Option, data: &AppState, _env: &Env) -> Menu { + if cfg!(target_os = "macos") && !data.config.kiosk_mode { Menu::empty().entry(mac_app_menu()) } else { Menu::empty() diff --git a/psst-gui/src/ui/mod.rs b/psst-gui/src/ui/mod.rs index 0f7b9b6b..7d74cc05 100644 --- a/psst-gui/src/ui/mod.rs +++ b/psst-gui/src/ui/mod.rs @@ -3,7 +3,7 @@ use std::time::Duration; use druid::{ im::Vector, widget::{CrossAxisAlignment, Either, Flex, Label, List, Scroll, Slider, Split, ViewSwitcher}, - Color, Env, Insets, Key, LensExt, Menu, MenuItem, Selector, Widget, WidgetExt, WindowDesc, + Color, Env, Insets, Key, LensExt, Menu, MenuItem, Selector, Widget, WidgetExt, WindowDesc, WindowState, }; use druid_shell::Cursor; @@ -42,12 +42,19 @@ pub mod user; pub mod utils; pub fn main_window(config: &Config) -> WindowDesc { - let win = WindowDesc::new(root_widget()) + let mut win = WindowDesc::new(root_widget()) .title(compute_main_window_title) - .with_min_size((theme::grid(65.0), theme::grid(50.0))) .window_size(config.window_size) .show_title(false) .transparent_titlebar(true); + if config.kiosk_mode { + win = win.set_window_state(WindowState::Maximized) + .resizable(false) + .show_titlebar(false); + } else { + win = win.with_min_size((theme::grid(65.0), theme::grid(50.0))) + + } if cfg!(target_os = "macos") { win.menu(menu::main_menu) } else { @@ -55,7 +62,8 @@ pub fn main_window(config: &Config) -> WindowDesc { } } -pub fn preferences_window() -> WindowDesc { +pub fn preferences_window(config: &Config) -> WindowDesc { + // Change this let win_size = (theme::grid(50.0), theme::grid(55.0)); // On Windows, the window size includes the titlebar. @@ -66,12 +74,20 @@ pub fn preferences_window() -> WindowDesc { win_size }; - let win = WindowDesc::new(preferences_widget()) + let mut win = WindowDesc::new(preferences_widget()) .title("Preferences") - .window_size(win_size) .resizable(false) .show_title(false) .transparent_titlebar(true); + + if config.kiosk_mode { + win = win.set_window_state(WindowState::Maximized) + .resizable(false) + .set_always_on_top(true) + .show_titlebar(false); + } else { + win = win.window_size(win_size) + } if cfg!(target_os = "macos") { win.menu(menu::main_menu) } else { @@ -82,9 +98,24 @@ pub fn preferences_window() -> WindowDesc { pub fn account_setup_window() -> WindowDesc { let win = WindowDesc::new(account_setup_widget()) .title("Login") + .resizable(false) + .show_title(false) .window_size((theme::grid(50.0), theme::grid(45.0))) + .transparent_titlebar(true); + if cfg!(target_os = "macos") { + win.menu(menu::main_menu) + } else { + win + } +} + +pub fn kiosk_setup_window() -> WindowDesc { + let win = WindowDesc::new(kiosk_setup_widget()) + .title("Setup") .resizable(false) .show_title(false) + .set_window_state(WindowState::Maximized) + .show_titlebar(false) .transparent_titlebar(true); if cfg!(target_os = "macos") { win.menu(menu::main_menu) @@ -109,6 +140,14 @@ fn account_setup_widget() -> impl Widget { ) } +fn kiosk_setup_widget() -> impl Widget { + ThemeScope::new( + preferences::kiosk_setup_widget() + .background(theme::BACKGROUND_DARK) + .expand(), + ) +} + fn root_widget() -> impl Widget { let playlists = Scroll::new(playlist::list_widget()) .vertical() diff --git a/psst-gui/src/ui/preferences.rs b/psst-gui/src/ui/preferences.rs index d9c5d403..c6f4436d 100644 --- a/psst-gui/src/ui/preferences.rs +++ b/psst-gui/src/ui/preferences.rs @@ -47,6 +47,29 @@ pub fn account_setup_widget() -> impl Widget { .padding(theme::grid(4.0)) } +pub fn kiosk_setup_widget() -> impl Widget { + Flex::column() + .must_fill_main_axis(true) + .cross_axis_alignment(CrossAxisAlignment::Start) + .with_spacer(theme::grid(2.0)) + .with_child( + Label::new("Please insert your Spotify Premium credentials.") + .with_font(theme::UI_FONT_MEDIUM) + .with_line_break_mode(LineBreaking::WordWrap), + ) + .with_spacer(theme::grid(2.0)) + .with_child( + Label::new( + "Psst connects only to the official servers, and does not store your password.", + ) + .with_text_color(theme::PLACEHOLDER_COLOR) + .with_line_break_mode(LineBreaking::WordWrap), + ) + .with_spacer(theme::grid(6.0)) + .with_child(account_tab_widget(AccountTab::KioskSetup).expand_width()) + .padding(theme::grid(4.0)) +} + pub fn preferences_widget() -> impl Widget { const PROPAGATE_FLAGS: Selector = Selector::new("app.preferences.propagate-flags"); @@ -247,6 +270,11 @@ fn general_tab_widget() -> impl Widget { .lens(AppState::config.then(Config::paginated_limit)), ); + col = col.with_default_spacer() + .with_child(Button::new("Done") + .align_right() + .on_click(|ctx, _, _| {ctx.submit_command(commands::CLOSE_WINDOW)})); + col } @@ -254,12 +282,14 @@ fn general_tab_widget() -> impl Widget { enum AccountTab { FirstSetup, InPreferences, + KioskSetup, } fn account_tab_widget(tab: AccountTab) -> impl Widget { let mut col = Flex::column().cross_axis_alignment(match tab { AccountTab::FirstSetup => CrossAxisAlignment::Center, AccountTab::InPreferences => CrossAxisAlignment::Start, + AccountTab::KioskSetup => CrossAxisAlignment::Start, }); if matches!(tab, AccountTab::InPreferences) { @@ -295,7 +325,11 @@ fn account_tab_widget(tab: AccountTab) -> impl Widget { if matches!(tab, AccountTab::InPreferences) { col = col.with_child(Button::new("Log Out").on_left_click(|ctx, _, _, _| { ctx.submit_command(cmd::LOG_OUT); - })) + })) + .with_default_spacer() + .with_child(Button::new("Done") + .align_right() + .on_click(|ctx, _, _| {ctx.submit_command(commands::CLOSE_WINDOW)})) } col.controller(Authenticate::new(tab)) @@ -391,6 +425,11 @@ impl> Controller for Authenticate { AccountTab::InPreferences => { ctx.submit_command(cmd::SESSION_CONNECT); } + AccountTab::KioskSetup => { + ctx.submit_command(cmd::SHOW_MAIN); + ctx.submit_command(commands::CLOSE_WINDOW); + ctx.submit_command(commands::SHOW_PREFERENCES); + } } } data.preferences.auth.access_token.clear(); @@ -442,6 +481,10 @@ fn cache_tab_widget() -> impl Widget { } }, )); + col = col.with_default_spacer() + .with_child(Button::new("Done") + .align_right() + .on_click(|ctx, _, _| {ctx.submit_command(commands::CLOSE_WINDOW)})); col.controller(MeasureCacheSize::new()) .lens(AppState::preferences) @@ -534,4 +577,8 @@ fn about_tab_widget() -> impl Widget { .with_child(commit_hash) .with_child(build_time) .with_child(remote_url) + .with_default_spacer() + .with_child(Button::new("Done") + .align_right() + .on_click(|ctx, _, _| {ctx.submit_command(commands::CLOSE_WINDOW)})) } diff --git a/psst-gui/src/ui/user.rs b/psst-gui/src/ui/user.rs index 5ba2c88f..68fe6350 100644 --- a/psst-gui/src/ui/user.rs +++ b/psst-gui/src/ui/user.rs @@ -7,7 +7,7 @@ use druid::{ use crate::{ data::{AppState, Library, UserProfile}, webapi::WebApi, - widget::{icons, icons::SvgIcon, Async, Empty, MyWidgetExt}, + widget::{icons::{self, SvgIcon}, Async, Empty, MyWidgetExt}, }; use super::theme; @@ -51,7 +51,13 @@ pub fn user_widget() -> impl Widget { .with_child(user_profile) .padding(theme::grid(1.0)), ) - .with_child(preferences_widget(&icons::PREFERENCES)) + .with_child( + Either::new( + |data: &AppState, _| !data.config.kiosk_mode, + preferences_widget(&icons::PREFERENCES), + Empty, + ) + ) } fn preferences_widget(svg: &SvgIcon) -> impl Widget { From 14ededf931940156564028f41e091c4eed7a731f Mon Sep 17 00:00:00 2001 From: Samuel Oldham Date: Wed, 25 Sep 2024 20:36:27 +0100 Subject: [PATCH 02/10] add extra - --- psst-gui/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psst-gui/src/main.rs b/psst-gui/src/main.rs index 453d26b9..31ba05a3 100644 --- a/psst-gui/src/main.rs +++ b/psst-gui/src/main.rs @@ -38,7 +38,7 @@ fn main() { let args: Vec = env::args().collect(); state.config.kiosk_mode = false; - if !args.is_empty() && (args.contains(&"-k".to_string()) || args.contains(&"-kiosk".to_string())) { + if !args.is_empty() && (args.contains(&"-k".to_string()) || args.contains(&"--kiosk".to_string())) { state.config.kiosk_mode = true; } From c91c77c6f49bd62e22b434434f3e00b344885e82 Mon Sep 17 00:00:00 2001 From: Jackson Goode Date: Thu, 26 Sep 2024 13:26:06 -0700 Subject: [PATCH 03/10] Fix so macOS can run kiosk --- psst-gui/src/main.rs | 11 +++---- psst-gui/src/ui/home.rs | 52 ++++++++++++++++------------------ psst-gui/src/ui/mod.rs | 46 +++++++++++++++++++----------- psst-gui/src/ui/preferences.rs | 43 ++++++++++++++++------------ psst-gui/src/ui/user.rs | 17 +++++------ 5 files changed, 92 insertions(+), 77 deletions(-) diff --git a/psst-gui/src/main.rs b/psst-gui/src/main.rs index 31ba05a3..009d3f9d 100644 --- a/psst-gui/src/main.rs +++ b/psst-gui/src/main.rs @@ -12,8 +12,8 @@ mod widget; use druid::AppLauncher; use env_logger::{Builder, Env}; -use webapi::WebApi; use std::env; +use webapi::WebApi; use crate::{ data::{AppState, Config}, @@ -37,10 +37,7 @@ fn main() { let mut state = AppState::default_with_config(config); let args: Vec = env::args().collect(); - state.config.kiosk_mode = false; - if !args.is_empty() && (args.contains(&"-k".to_string()) || args.contains(&"--kiosk".to_string())) { - state.config.kiosk_mode = true; - } + state.config.kiosk_mode = args.iter().any(|arg| arg == "-k" || arg == "--kiosk"); WebApi::new( state.session.clone(), @@ -63,10 +60,10 @@ fn main() { } else { // No configured credentials, open the account setup. let mut window = ui::account_setup_window(); - + if state.config.kiosk_mode { window = ui::kiosk_setup_window(); - } + } delegate = Delegate::with_preferences(window.id); launcher = AppLauncher::with_window(window).configure_env(ui::theme::setup); diff --git a/psst-gui/src/ui/home.rs b/psst-gui/src/ui/home.rs index 8ea7d916..8e56a043 100644 --- a/psst-gui/src/ui/home.rs +++ b/psst-gui/src/ui/home.rs @@ -37,17 +37,16 @@ pub fn home_widget() -> impl Widget { } fn simple_title_label(title: &str) -> impl Widget { - Flex::column() - .with_default_spacer() - .with_child(Label::new(title) - .with_text_size(theme::grid(2.5)) - .align_left() - .padding((theme::grid(1.5), 0.0)) + Flex::column().with_default_spacer().with_child( + Label::new(title) + .with_text_size(theme::grid(2.5)) + .align_left() + .padding((theme::grid(1.5), 0.0)), ) } pub fn made_for_you() -> impl Widget { - Async::new(spinner_widget, loaded_results_widget, || {Empty}) + Async::new(spinner_widget, loaded_results_widget, || Empty) .lens( Ctx::make( AppState::common_ctx, @@ -64,7 +63,7 @@ pub fn made_for_you() -> impl Widget { } pub fn recommended_stations() -> impl Widget { - Async::new(spinner_widget, loaded_results_widget, || {Empty}) + Async::new(spinner_widget, loaded_results_widget, || Empty) .lens( Ctx::make( AppState::common_ctx, @@ -82,27 +81,24 @@ pub fn recommended_stations() -> impl Widget { fn uniquely_yours_results_widget() -> impl Widget> { Either::new( - |results: &WithCtx, _| { - results.data.playlists.is_empty() - }, + |results: &WithCtx, _| results.data.playlists.is_empty(), Empty, - Flex::column().with_default_spacer() - .with_child(Label::new("Uniquely yours") - .with_text_size(theme::grid(2.5)) - .align_left() - .padding((theme::grid(1.5), 0.0)) - ).with_child( - Scroll::new( - Flex::row() - .with_child(playlist_results_widget()) + Flex::column() + .with_default_spacer() + .with_child( + Label::new("Uniquely yours") + .with_text_size(theme::grid(2.5)) + .align_left() + .padding((theme::grid(1.5), 0.0)), ) - .align_left(), - ), + .with_child( + Scroll::new(Flex::row().with_child(playlist_results_widget())).align_left(), + ), ) } pub fn uniquely_yours() -> impl Widget { - Async::new(spinner_widget, uniquely_yours_results_widget, || {Empty}) + Async::new(spinner_widget, uniquely_yours_results_widget, || Empty) .lens( Ctx::make( AppState::common_ctx, @@ -119,7 +115,7 @@ pub fn uniquely_yours() -> impl Widget { } pub fn user_top_mixes() -> impl Widget { - Async::new(spinner_widget, loaded_results_widget, || {Empty}) + Async::new(spinner_widget, loaded_results_widget, || Empty) .lens( Ctx::make( AppState::common_ctx, @@ -136,7 +132,7 @@ pub fn user_top_mixes() -> impl Widget { } pub fn best_of_artists() -> impl Widget { - Async::new(spinner_widget, loaded_results_widget, || {Empty}) + Async::new(spinner_widget, loaded_results_widget, || Empty) .lens( Ctx::make( AppState::common_ctx, @@ -153,7 +149,7 @@ pub fn best_of_artists() -> impl Widget { } pub fn your_shows() -> impl Widget { - Async::new(spinner_widget, loaded_results_widget, || {Empty}) + Async::new(spinner_widget, loaded_results_widget, || Empty) .lens( Ctx::make( AppState::common_ctx, @@ -170,7 +166,7 @@ pub fn your_shows() -> impl Widget { } pub fn jump_back_in() -> impl Widget { - Async::new(spinner_widget, loaded_results_widget, || {Empty}) + Async::new(spinner_widget, loaded_results_widget, || Empty) .lens( Ctx::make( AppState::common_ctx, @@ -187,7 +183,7 @@ pub fn jump_back_in() -> impl Widget { } pub fn shows_that_you_might_like() -> impl Widget { - Async::new(spinner_widget, loaded_results_widget, || {Empty}) + Async::new(spinner_widget, loaded_results_widget, || Empty) .lens( Ctx::make( AppState::common_ctx, diff --git a/psst-gui/src/ui/mod.rs b/psst-gui/src/ui/mod.rs index 7d74cc05..b1ed1422 100644 --- a/psst-gui/src/ui/mod.rs +++ b/psst-gui/src/ui/mod.rs @@ -3,7 +3,8 @@ use std::time::Duration; use druid::{ im::Vector, widget::{CrossAxisAlignment, Either, Flex, Label, List, Scroll, Slider, Split, ViewSwitcher}, - Color, Env, Insets, Key, LensExt, Menu, MenuItem, Selector, Widget, WidgetExt, WindowDesc, WindowState, + Color, Env, Insets, Key, LensExt, Menu, MenuItem, Selector, Widget, WidgetExt, WindowDesc, + WindowState, }; use druid_shell::Cursor; @@ -42,19 +43,31 @@ pub mod user; pub mod utils; pub fn main_window(config: &Config) -> WindowDesc { - let mut win = WindowDesc::new(root_widget()) + let mut win = WindowDesc::new(root_widget(config)) .title(compute_main_window_title) - .window_size(config.window_size) .show_title(false) .transparent_titlebar(true); + if config.kiosk_mode { - win = win.set_window_state(WindowState::Maximized) - .resizable(false) - .show_titlebar(false); + win = win + .set_window_state(WindowState::Maximized) + .resizable(false) + .show_titlebar(false) + .set_always_on_top(true); + + // Set the window size to the primary monitor's work area and position it at (0, 0) + if let Some(monitor) = druid::Screen::get_monitors().first() { + let work_area = monitor.virtual_work_rect(); + win = win + .window_size(work_area.size()) + .set_position(druid::Point::new(0.0, 0.0)); + } } else { - win = win.with_min_size((theme::grid(65.0), theme::grid(50.0))) - + win = win + .window_size(config.window_size) + .with_min_size((theme::grid(65.0), theme::grid(50.0))); } + if cfg!(target_os = "macos") { win.menu(menu::main_menu) } else { @@ -63,7 +76,7 @@ pub fn main_window(config: &Config) -> WindowDesc { } pub fn preferences_window(config: &Config) -> WindowDesc { - // Change this + // Change this let win_size = (theme::grid(50.0), theme::grid(55.0)); // On Windows, the window size includes the titlebar. @@ -81,10 +94,11 @@ pub fn preferences_window(config: &Config) -> WindowDesc { .transparent_titlebar(true); if config.kiosk_mode { - win = win.set_window_state(WindowState::Maximized) - .resizable(false) - .set_always_on_top(true) - .show_titlebar(false); + win = win + .set_window_state(WindowState::Maximized) + .resizable(false) + .set_always_on_top(true) + .show_titlebar(false); } else { win = win.window_size(win_size) } @@ -148,7 +162,7 @@ fn kiosk_setup_widget() -> impl Widget { ) } -fn root_widget() -> impl Widget { +fn root_widget(config: &Config) -> impl Widget { let playlists = Scroll::new(playlist::list_widget()) .vertical() .expand_height(); @@ -158,8 +172,8 @@ fn root_widget() -> impl Widget { .with_child(sidebar_menu_widget()) .with_default_spacer() .with_flex_child(playlists, 1.0) - .padding(if cfg!(target_os = "macos") { - // Accommodate the window controls on Mac. + .padding(if cfg!(target_os = "macos") && !config.kiosk_mode { + // Accommodate the window controls on macOS Insets::new(0.0, 24.0, 0.0, 0.0) } else { Insets::ZERO diff --git a/psst-gui/src/ui/preferences.rs b/psst-gui/src/ui/preferences.rs index c6f4436d..07782f67 100644 --- a/psst-gui/src/ui/preferences.rs +++ b/psst-gui/src/ui/preferences.rs @@ -270,10 +270,11 @@ fn general_tab_widget() -> impl Widget { .lens(AppState::config.then(Config::paginated_limit)), ); - col = col.with_default_spacer() - .with_child(Button::new("Done") - .align_right() - .on_click(|ctx, _, _| {ctx.submit_command(commands::CLOSE_WINDOW)})); + col = col.with_default_spacer().with_child( + Button::new("Done") + .align_right() + .on_click(|ctx, _, _| ctx.submit_command(commands::CLOSE_WINDOW)), + ); col } @@ -323,13 +324,16 @@ fn account_tab_widget(tab: AccountTab) -> impl Widget { ); if matches!(tab, AccountTab::InPreferences) { - col = col.with_child(Button::new("Log Out").on_left_click(|ctx, _, _, _| { - ctx.submit_command(cmd::LOG_OUT); - })) - .with_default_spacer() - .with_child(Button::new("Done") - .align_right() - .on_click(|ctx, _, _| {ctx.submit_command(commands::CLOSE_WINDOW)})) + col = col + .with_child(Button::new("Log Out").on_left_click(|ctx, _, _, _| { + ctx.submit_command(cmd::LOG_OUT); + })) + .with_default_spacer() + .with_child( + Button::new("Done") + .align_right() + .on_click(|ctx, _, _| ctx.submit_command(commands::CLOSE_WINDOW)), + ) } col.controller(Authenticate::new(tab)) @@ -481,10 +485,11 @@ fn cache_tab_widget() -> impl Widget { } }, )); - col = col.with_default_spacer() - .with_child(Button::new("Done") - .align_right() - .on_click(|ctx, _, _| {ctx.submit_command(commands::CLOSE_WINDOW)})); + col = col.with_default_spacer().with_child( + Button::new("Done") + .align_right() + .on_click(|ctx, _, _| ctx.submit_command(commands::CLOSE_WINDOW)), + ); col.controller(MeasureCacheSize::new()) .lens(AppState::preferences) @@ -578,7 +583,9 @@ fn about_tab_widget() -> impl Widget { .with_child(build_time) .with_child(remote_url) .with_default_spacer() - .with_child(Button::new("Done") - .align_right() - .on_click(|ctx, _, _| {ctx.submit_command(commands::CLOSE_WINDOW)})) + .with_child( + Button::new("Done") + .align_right() + .on_click(|ctx, _, _| ctx.submit_command(commands::CLOSE_WINDOW)), + ) } diff --git a/psst-gui/src/ui/user.rs b/psst-gui/src/ui/user.rs index 68fe6350..f0a4efa3 100644 --- a/psst-gui/src/ui/user.rs +++ b/psst-gui/src/ui/user.rs @@ -7,7 +7,10 @@ use druid::{ use crate::{ data::{AppState, Library, UserProfile}, webapi::WebApi, - widget::{icons::{self, SvgIcon}, Async, Empty, MyWidgetExt}, + widget::{ + icons::{self, SvgIcon}, + Async, Empty, MyWidgetExt, + }, }; use super::theme; @@ -51,13 +54,11 @@ pub fn user_widget() -> impl Widget { .with_child(user_profile) .padding(theme::grid(1.0)), ) - .with_child( - Either::new( - |data: &AppState, _| !data.config.kiosk_mode, - preferences_widget(&icons::PREFERENCES), - Empty, - ) - ) + .with_child(Either::new( + |data: &AppState, _| !data.config.kiosk_mode, + preferences_widget(&icons::PREFERENCES), + Empty, + )) } fn preferences_widget(svg: &SvgIcon) -> impl Widget { From b3fc3e518a8d99ad8fd81a1df32622256e46b370 Mon Sep 17 00:00:00 2001 From: Samuel Oldham Date: Fri, 27 Sep 2024 14:36:42 +0100 Subject: [PATCH 04/10] This should make preferences large --- psst-gui/src/ui/mod.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/psst-gui/src/ui/mod.rs b/psst-gui/src/ui/mod.rs index b1ed1422..27e3edd9 100644 --- a/psst-gui/src/ui/mod.rs +++ b/psst-gui/src/ui/mod.rs @@ -52,8 +52,7 @@ pub fn main_window(config: &Config) -> WindowDesc { win = win .set_window_state(WindowState::Maximized) .resizable(false) - .show_titlebar(false) - .set_always_on_top(true); + .show_titlebar(false); // Set the window size to the primary monitor's work area and position it at (0, 0) if let Some(monitor) = druid::Screen::get_monitors().first() { @@ -94,6 +93,13 @@ pub fn preferences_window(config: &Config) -> WindowDesc { .transparent_titlebar(true); if config.kiosk_mode { + if let Some(monitor) = druid::Screen::get_monitors().first() { + let work_area = monitor.virtual_work_rect(); + win = win + .window_size(work_area.size()) + .set_position(druid::Point::new(0.0, 0.0)); + } + win = win .set_window_state(WindowState::Maximized) .resizable(false) @@ -124,13 +130,22 @@ pub fn account_setup_window() -> WindowDesc { } pub fn kiosk_setup_window() -> WindowDesc { - let win = WindowDesc::new(kiosk_setup_widget()) + + let mut win = WindowDesc::new(kiosk_setup_widget()) .title("Setup") .resizable(false) .show_title(false) .set_window_state(WindowState::Maximized) .show_titlebar(false) .transparent_titlebar(true); + + if let Some(monitor) = druid::Screen::get_monitors().first() { + let work_area = monitor.virtual_work_rect(); + win = win + .window_size(work_area.size()) + .set_position(druid::Point::new(0.0, 0.0)); + } + if cfg!(target_os = "macos") { win.menu(menu::main_menu) } else { From 620fb2753e18b6234f3ecb86e9b8f6caafb47681 Mon Sep 17 00:00:00 2001 From: Samuel Oldham Date: Fri, 27 Sep 2024 14:38:42 +0100 Subject: [PATCH 05/10] Change line of where resizeable is --- psst-gui/src/ui/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/psst-gui/src/ui/mod.rs b/psst-gui/src/ui/mod.rs index 27e3edd9..c8c1f7aa 100644 --- a/psst-gui/src/ui/mod.rs +++ b/psst-gui/src/ui/mod.rs @@ -88,7 +88,6 @@ pub fn preferences_window(config: &Config) -> WindowDesc { let mut win = WindowDesc::new(preferences_widget()) .title("Preferences") - .resizable(false) .show_title(false) .transparent_titlebar(true); @@ -107,6 +106,7 @@ pub fn preferences_window(config: &Config) -> WindowDesc { .show_titlebar(false); } else { win = win.window_size(win_size) + .resizable(false) } if cfg!(target_os = "macos") { win.menu(menu::main_menu) @@ -130,10 +130,8 @@ pub fn account_setup_window() -> WindowDesc { } pub fn kiosk_setup_window() -> WindowDesc { - let mut win = WindowDesc::new(kiosk_setup_widget()) .title("Setup") - .resizable(false) .show_title(false) .set_window_state(WindowState::Maximized) .show_titlebar(false) @@ -143,7 +141,8 @@ pub fn kiosk_setup_window() -> WindowDesc { let work_area = monitor.virtual_work_rect(); win = win .window_size(work_area.size()) - .set_position(druid::Point::new(0.0, 0.0)); + .set_position(druid::Point::new(0.0, 0.0)) + .resizable(false); } if cfg!(target_os = "macos") { From b718257de2e1b0f30983a23435ab9f8a9acd6ab9 Mon Sep 17 00:00:00 2001 From: Samuel Oldham Date: Fri, 27 Sep 2024 17:55:49 +0100 Subject: [PATCH 06/10] Make preferences and log in small, force preference to stay always on top --- psst-gui/src/delegate.rs | 6 ++--- psst-gui/src/ui/mod.rs | 48 ++++++---------------------------- psst-gui/src/ui/preferences.rs | 2 +- 3 files changed, 12 insertions(+), 44 deletions(-) diff --git a/psst-gui/src/delegate.rs b/psst-gui/src/delegate.rs index 1437ab05..617071b2 100644 --- a/psst-gui/src/delegate.rs +++ b/psst-gui/src/delegate.rs @@ -71,13 +71,13 @@ impl Delegate { } } - fn show_preferences(&mut self, config: &Config, ctx: &mut DelegateCtx) { + fn show_preferences(&mut self, ctx: &mut DelegateCtx) { match self.preferences_window { Some(id) => { ctx.submit_command(commands::SHOW_WINDOW.to(id)); } None => { - let window = ui::preferences_window(config); + let window = ui::preferences_window(); self.preferences_window.replace(window.id); ctx.new_window(window); } @@ -113,7 +113,7 @@ impl AppDelegate for Delegate { self.show_account_setup(ctx); Handled::Yes } else if cmd.is(commands::SHOW_PREFERENCES) { - self.show_preferences(&data.config, ctx); + self.show_preferences(ctx); Handled::Yes } else if cmd.is(cmd::CLOSE_ALL_WINDOWS) { self.close_all_windows(ctx); diff --git a/psst-gui/src/ui/mod.rs b/psst-gui/src/ui/mod.rs index c8c1f7aa..f1b7d455 100644 --- a/psst-gui/src/ui/mod.rs +++ b/psst-gui/src/ui/mod.rs @@ -74,40 +74,17 @@ pub fn main_window(config: &Config) -> WindowDesc { } } -pub fn preferences_window(config: &Config) -> WindowDesc { +pub fn preferences_window() -> WindowDesc { // Change this let win_size = (theme::grid(50.0), theme::grid(55.0)); - // On Windows, the window size includes the titlebar. - let win_size = if cfg!(target_os = "windows") { - const WINDOWS_TITLEBAR_OFFSET: f64 = 56.0; - (win_size.0, win_size.1 + WINDOWS_TITLEBAR_OFFSET) - } else { - win_size - }; - - let mut win = WindowDesc::new(preferences_widget()) + let win = WindowDesc::new(preferences_widget()) .title("Preferences") + .window_size(win_size) + .resizable(false) .show_title(false) + .set_always_on_top(true) .transparent_titlebar(true); - - if config.kiosk_mode { - if let Some(monitor) = druid::Screen::get_monitors().first() { - let work_area = monitor.virtual_work_rect(); - win = win - .window_size(work_area.size()) - .set_position(druid::Point::new(0.0, 0.0)); - } - - win = win - .set_window_state(WindowState::Maximized) - .resizable(false) - .set_always_on_top(true) - .show_titlebar(false); - } else { - win = win.window_size(win_size) - .resizable(false) - } if cfg!(target_os = "macos") { win.menu(menu::main_menu) } else { @@ -130,21 +107,12 @@ pub fn account_setup_window() -> WindowDesc { } pub fn kiosk_setup_window() -> WindowDesc { - let mut win = WindowDesc::new(kiosk_setup_widget()) + let win = WindowDesc::new(kiosk_setup_widget()) .title("Setup") + .resizable(false) .show_title(false) - .set_window_state(WindowState::Maximized) - .show_titlebar(false) + .window_size((theme::grid(50.0), theme::grid(45.0))) .transparent_titlebar(true); - - if let Some(monitor) = druid::Screen::get_monitors().first() { - let work_area = monitor.virtual_work_rect(); - win = win - .window_size(work_area.size()) - .set_position(druid::Point::new(0.0, 0.0)) - .resizable(false); - } - if cfg!(target_os = "macos") { win.menu(menu::main_menu) } else { diff --git a/psst-gui/src/ui/preferences.rs b/psst-gui/src/ui/preferences.rs index 07782f67..f276f934 100644 --- a/psst-gui/src/ui/preferences.rs +++ b/psst-gui/src/ui/preferences.rs @@ -430,9 +430,9 @@ impl> Controller for Authenticate { ctx.submit_command(cmd::SESSION_CONNECT); } AccountTab::KioskSetup => { - ctx.submit_command(cmd::SHOW_MAIN); ctx.submit_command(commands::CLOSE_WINDOW); ctx.submit_command(commands::SHOW_PREFERENCES); + ctx.submit_command(cmd::SHOW_MAIN); } } } From ac0f303269757284ca7e423ad73ea81ad7ac1031 Mon Sep 17 00:00:00 2001 From: Samuel Oldham Date: Fri, 27 Sep 2024 18:52:14 +0100 Subject: [PATCH 07/10] test --- psst-gui/src/ui/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/psst-gui/src/ui/mod.rs b/psst-gui/src/ui/mod.rs index f1b7d455..07253559 100644 --- a/psst-gui/src/ui/mod.rs +++ b/psst-gui/src/ui/mod.rs @@ -45,8 +45,7 @@ pub mod utils; pub fn main_window(config: &Config) -> WindowDesc { let mut win = WindowDesc::new(root_widget(config)) .title(compute_main_window_title) - .show_title(false) - .transparent_titlebar(true); + .show_title(false); if config.kiosk_mode { win = win @@ -64,7 +63,8 @@ pub fn main_window(config: &Config) -> WindowDesc { } else { win = win .window_size(config.window_size) - .with_min_size((theme::grid(65.0), theme::grid(50.0))); + .with_min_size((theme::grid(65.0), theme::grid(50.0))) + .transparent_titlebar(true); } if cfg!(target_os = "macos") { From eb024c3931a257989c9e739069f82c873a36bb50 Mon Sep 17 00:00:00 2001 From: Samuel Oldham Date: Fri, 27 Sep 2024 19:43:16 +0100 Subject: [PATCH 08/10] Small fixes --- psst-gui/src/main.rs | 6 ++++-- psst-gui/src/ui/mod.rs | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/psst-gui/src/main.rs b/psst-gui/src/main.rs index 009d3f9d..7ccc63e4 100644 --- a/psst-gui/src/main.rs +++ b/psst-gui/src/main.rs @@ -59,10 +59,12 @@ fn main() { WebApi::global().load_local_tracks(state.config.username().unwrap()); } else { // No configured credentials, open the account setup. - let mut window = ui::account_setup_window(); + let window = ui::account_setup_window(); if state.config.kiosk_mode { - window = ui::kiosk_setup_window(); + let window = ui::kiosk_setup_window(); + } else { + } delegate = Delegate::with_preferences(window.id); diff --git a/psst-gui/src/ui/mod.rs b/psst-gui/src/ui/mod.rs index 07253559..ed686629 100644 --- a/psst-gui/src/ui/mod.rs +++ b/psst-gui/src/ui/mod.rs @@ -75,9 +75,16 @@ pub fn main_window(config: &Config) -> WindowDesc { } pub fn preferences_window() -> WindowDesc { - // Change this let win_size = (theme::grid(50.0), theme::grid(55.0)); + // On Windows, the window size includes the titlebar. + let win_size = if cfg!(target_os = "windows") { + const WINDOWS_TITLEBAR_OFFSET: f64 = 56.0; + (win_size.0, win_size.1 + WINDOWS_TITLEBAR_OFFSET) + } else { + win_size + }; + let win = WindowDesc::new(preferences_widget()) .title("Preferences") .window_size(win_size) From 70a739c2182213035da465c7c6aa4bd5f574674f Mon Sep 17 00:00:00 2001 From: Jackson Goode Date: Fri, 27 Sep 2024 13:39:28 -0700 Subject: [PATCH 09/10] Linting --- psst-gui/src/main.rs | 3 +-- psst-gui/src/ui/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/psst-gui/src/main.rs b/psst-gui/src/main.rs index 7ccc63e4..650693e0 100644 --- a/psst-gui/src/main.rs +++ b/psst-gui/src/main.rs @@ -62,9 +62,8 @@ fn main() { let window = ui::account_setup_window(); if state.config.kiosk_mode { - let window = ui::kiosk_setup_window(); + let window = ui::kiosk_setup_window(); } else { - } delegate = Delegate::with_preferences(window.id); diff --git a/psst-gui/src/ui/mod.rs b/psst-gui/src/ui/mod.rs index ed686629..e0be42c2 100644 --- a/psst-gui/src/ui/mod.rs +++ b/psst-gui/src/ui/mod.rs @@ -84,7 +84,7 @@ pub fn preferences_window() -> WindowDesc { } else { win_size }; - + let win = WindowDesc::new(preferences_widget()) .title("Preferences") .window_size(win_size) From 5113a3c9d7992b0f3699eeb8431ae4f2555da35f Mon Sep 17 00:00:00 2001 From: Jackson Goode Date: Fri, 27 Sep 2024 13:44:53 -0700 Subject: [PATCH 10/10] Fixup linting issue --- psst-gui/src/main.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/psst-gui/src/main.rs b/psst-gui/src/main.rs index 650693e0..0e0bed1d 100644 --- a/psst-gui/src/main.rs +++ b/psst-gui/src/main.rs @@ -46,30 +46,29 @@ fn main() { paginated_limit, ) .install_as_global(); - - let delegate; - let launcher; - if state.config.has_credentials() { + let (delegate, launcher) = if state.config.has_credentials() { // Credentials are configured, open the main window. let window = ui::main_window(&state.config); - delegate = Delegate::with_main(window.id); - launcher = AppLauncher::with_window(window).configure_env(ui::theme::setup); + let delegate = Delegate::with_main(window.id); // Load user's local tracks for the WebApi. WebApi::global().load_local_tracks(state.config.username().unwrap()); - } else { - // No configured credentials, open the account setup. - let window = ui::account_setup_window(); - if state.config.kiosk_mode { - let window = ui::kiosk_setup_window(); + (delegate, AppLauncher::with_window(window)) + } else { + // No configured credentials, open the setup window. + let window = if state.config.kiosk_mode { + ui::kiosk_setup_window() } else { - } + ui::account_setup_window() + }; + let delegate = Delegate::with_preferences(window.id); - delegate = Delegate::with_preferences(window.id); - launcher = AppLauncher::with_window(window).configure_env(ui::theme::setup); + (delegate, AppLauncher::with_window(window)) }; + let launcher = launcher.configure_env(ui::theme::setup); + launcher .delegate(delegate) .launch(state)