feat: responsive full-window settings layout

The Settings screen now follows the full window width/height instead of a
fixed 460x500 card. Device/privacy pickers and the noise-gate slider fill
the available width, and controls are laid out in 2 columns so a single
dropdown never stretches across the whole window:

- Input Device | Output Device
- Mic Sensitivity | Network Privacy (top-aligned)
- The 8 custom chime path fields remain a 2-column grid

Section spacing tightened so everything (incl. Back) fits on 1080p without
scrolling. The styled card now fills the page (max_width cap dropped).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 15:37:56 -04:00
co-authored by Claude Opus 4.8
parent fe4c7f9ee5
commit 821102beb6
+34 -25
View File
@@ -482,68 +482,78 @@ fn view(state: &AppState) -> Element<'_, AppMessage> {
.on_input(move |val| AppMessage::CustomSoundPathChanged(sound, val))
.style(t_style)
.padding(8)
].spacing(4).width(iced::Length::Fixed(320.0))
].spacing(4).width(iced::Length::Fill)
};
let settings_content = scrollable(
column![
text("Settings").size(24).color(color_blue),
vertical_space(20.0),
text("Device Settings").size(14).color(color_subtext),
vertical_space(10.0),
text("Device Settings").size(14).color(color_subtext),
vertical_space(6.0),
row![
column![
text("Input Device").size(12).color(Color::from_rgb8(180, 180, 180)),
pick_list(
&state.input_devices[..],
state.selected_input.as_ref(),
AppMessage::InputDeviceSelected,
).width(iced::Length::Fixed(320.0)),
].spacing(4).width(iced::Length::Fixed(320.0)),
vertical_space(10.0),
).width(iced::Length::Fill),
].spacing(4).width(iced::Length::Fill),
column![
text("Output Device").size(12).color(Color::from_rgb8(180, 180, 180)),
pick_list(
&state.output_devices[..],
state.selected_output.as_ref(),
AppMessage::OutputDeviceSelected,
).width(iced::Length::Fixed(320.0)),
].spacing(4).width(iced::Length::Fixed(320.0)),
vertical_space(20.0),
).width(iced::Length::Fill),
].spacing(4).width(iced::Length::Fill),
].spacing(20).width(iced::Length::Fill),
vertical_space(12.0),
row![
column![
text(format!("Mic Sensitivity (Noise Gate): {:.1}%", state.config.noise_gate_threshold * 100.0)).size(14).color(color_subtext),
slider(0.0..=0.1, state.config.noise_gate_threshold, AppMessage::NoiseGateChanged).step(0.001)
].spacing(10).width(iced::Length::Fixed(320.0)),
vertical_space(20.0),
].spacing(8).width(iced::Length::Fill),
column![
text("Network Privacy").size(14).color(color_subtext),
pick_list(
&NetworkMode::ALL[..],
Some(state.config.network_mode),
AppMessage::NetworkModeSelected,
).width(iced::Length::Fixed(320.0)),
).width(iced::Length::Fill),
text(network_mode_hint(state.config.network_mode)).size(11).color(color_subtext),
text("Takes effect on your next room join.").size(11).color(color_surface),
].spacing(6).width(iced::Length::Fixed(320.0)),
vertical_space(20.0),
].spacing(4).width(iced::Length::Fill),
].spacing(20).align_y(iced::alignment::Vertical::Top).width(iced::Length::Fill),
vertical_space(12.0),
column![
text("Notification Chimes").size(14).color(color_subtext),
checkbox(state.config.notifications_enabled)
.label("Enable sound notifications")
.on_toggle(AppMessage::ToggleNotifications),
].spacing(10).width(iced::Length::Fixed(320.0)),
vertical_space(20.0),
].spacing(8).width(iced::Length::Fill),
vertical_space(12.0),
text("Custom Chime Files (WAV Paths)").size(14).color(color_subtext),
row![
path_field("Self Join", Sound::SelfJoin),
path_field("Self Leave", Sound::SelfLeave),
path_field("Peer Join", Sound::PeerJoin),
].spacing(20).width(iced::Length::Fill),
row![
path_field("Self Leave", Sound::SelfLeave),
path_field("Peer Leave", Sound::PeerLeave),
].spacing(20).width(iced::Length::Fill),
row![
path_field("Reconnect Attempt", Sound::ReconnectAttempt),
path_field("Reconnected", Sound::Reconnected),
].spacing(20).width(iced::Length::Fill),
row![
path_field("Mic Toggle", Sound::MicToggle),
path_field("Reconnect Failed", Sound::ReconnectFailed),
].spacing(20).width(iced::Length::Fill),
vertical_space(30.0),
vertical_space(14.0),
button(
text("Back")
.size(16)
@@ -556,21 +566,20 @@ fn view(state: &AppState) -> Element<'_, AppMessage> {
]
.align_x(iced::alignment::Horizontal::Center)
.spacing(10)
.width(iced::Length::Fill)
);
let settings_box = container(settings_content)
.style(c_style(color_mantle, color_surface, 12.0))
.padding(30)
.width(460)
.height(500);
.padding(24)
.width(iced::Length::Fill)
.height(iced::Length::Fill);
let content = column![settings_box].align_x(iced::alignment::Horizontal::Center);
return container(content)
return container(settings_box)
.width(iced::Length::Fill)
.height(iced::Length::Fill)
.padding(24)
.center_x(iced::Length::Fill)
.center_y(iced::Length::Fill)
.style(c_style(color_crust, Color::TRANSPARENT, 0.0))
.into();
}