From a503a4c2eb72a6b5bdf9d85de19c6679d6b59962 Mon Sep 17 00:00:00 2001 From: Mollusk Date: Wed, 27 May 2026 15:49:08 -0400 Subject: [PATCH] feat: Add Settings page and refactor view navigation --- src/app/mod.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/src/app/mod.rs b/src/app/mod.rs index 36957bd..7cf8dc8 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -14,6 +14,13 @@ use tokio::sync::Mutex; static UI_RX: OnceLock>>> = OnceLock::new(); +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Screen { + Home, + Room, + Settings, +} + #[derive(Debug, Clone)] pub enum AppMessage { NicknameChanged(String), @@ -31,6 +38,8 @@ pub enum AppMessage { InputDeviceChanged(String), OutputDeviceChanged(String), EventOccurred(Event), + NavigateToSettings, + NavigateBack, } fn core_subscription() -> impl iced::futures::Stream { @@ -65,6 +74,7 @@ pub struct AppState { peer_volumes: HashMap, audio_levels: HashMap, controller: Arc, + current_screen: Screen, } impl Default for AppState { @@ -91,6 +101,7 @@ impl Default for AppState { peer_volumes: HashMap::new(), audio_levels: HashMap::new(), controller, + current_screen: Screen::Home, } } } @@ -161,15 +172,15 @@ fn update(state: &mut AppState, message: AppMessage) -> Task { UiEvent::RoomJoined { ticket, self_id } => { state.ticket = ticket; state.self_id = self_id; - state.status_message = "Connected to room".to_string(); - state.peers.clear(); - state.audio_levels.clear(); + state.status_message = "Connected".to_string(); + state.current_screen = Screen::Room; } UiEvent::RoomLeft => { state.ticket = "".to_string(); state.peers.clear(); state.audio_levels.clear(); state.status_message = "Ready to connect".to_string(); + state.current_screen = Screen::Home; } UiEvent::PeerJoined { id, state: peer_state } => { state.peers.insert(id, peer_state); @@ -229,6 +240,16 @@ fn update(state: &mut AppState, message: AppMessage) -> Task { } } AppMessage::EventOccurred(_) => {} + AppMessage::NavigateToSettings => { + state.current_screen = Screen::Settings; + } + AppMessage::NavigateBack => { + if state.ticket.is_empty() { + state.current_screen = Screen::Home; + } else { + state.current_screen = Screen::Room; + } + } } Task::none() } @@ -303,7 +324,43 @@ fn view(state: &AppState) -> Element<'_, AppMessage> { } }; - if state.ticket.is_empty() { + let top_bar = row![ + horizontal_space(), + button(text("⚙ Settings").size(14)) + .on_press(AppMessage::NavigateToSettings) + .style(b_style(color_surface, color_blue, color_text, 6.0)) + .padding(8) + ].width(iced::Length::Fill).padding(10); + + if state.current_screen == Screen::Settings { + let content = column![ + text("Settings").size(32).color(color_text), + vertical_space(20.0), + text("Future settings and controls will be added here.").size(16).color(color_subtext), + vertical_space(40.0), + button( + text("Back") + .size(16) + .align_x(iced::alignment::Horizontal::Center) + ) + .on_press(AppMessage::NavigateBack) + .style(b_style(color_surface, color_blue, color_text, 8.0)) + .padding(14) + .width(iced::Length::Fixed(150.0)) + ] + .align_x(iced::alignment::Horizontal::Center) + .spacing(10); + + return container(content) + .width(iced::Length::Fill) + .height(iced::Length::Fill) + .center_x(iced::Length::Fill) + .center_y(iced::Length::Fill) + .style(c_style(color_crust, Color::TRANSPARENT, 0.0)) + .into(); + } + + if state.current_screen == Screen::Home { // --- HOME SCREEN --- let logo = text("PEERSPEAK") .size(36) @@ -384,11 +441,15 @@ fn view(state: &AppState) -> Element<'_, AppMessage> { .padding(30) .width(420); - container(content) + container( + column![ + top_bar, + vertical_space(40.0), + content + ].align_x(iced::alignment::Horizontal::Center) + ) .width(iced::Length::Fill) .height(iced::Length::Fill) - .align_x(iced::alignment::Horizontal::Center) - .align_y(iced::alignment::Vertical::Center) .style(c_style(color_crust, Color::TRANSPARENT, 0.0)) .into() } else { @@ -569,6 +630,7 @@ fn view(state: &AppState) -> Element<'_, AppMessage> { container( column![ + top_bar, header_container, vertical_space(15.0), main_layout