fixed touchscreen scrolling in the settings menu and made the items larger

This commit is contained in:
jess 2026-05-09 13:12:12 -07:00
parent 2a28d6f53d
commit 6b11beff44
3 changed files with 114 additions and 37 deletions

View File

@ -183,6 +183,11 @@ impl App {
&& y < viewport_height - player::TRANSPORT_H && y < viewport_height - player::TRANSPORT_H
} }
/// checks whether a logical-coords point falls inside the right-aligned settings overlay panel.
pub fn point_in_settings(&self, x: f32, _y: f32, viewport_width: f32) -> bool {
self.show_settings && x >= viewport_width - player::SETTINGS_W && x <= viewport_width
}
/// scans a folder, replaces the library, queues art, and starts decoding the first track. /// scans a folder, replaces the library, queues art, and starts decoding the first track.
fn apply_picked_folder(&mut self, folder: PathBuf) { fn apply_picked_folder(&mut self, folder: PathBuf) {
#[cfg(all(target_os = "ios", debug_assertions))] #[cfg(all(target_os = "ios", debug_assertions))]

View File

@ -386,7 +386,7 @@ fn params_from(s: &super::app::Settings) -> VizParams {
} }
} }
const SETTINGS_W: f32 = 340.0; pub const SETTINGS_W: f32 = 340.0;
/// right-aligned settings panel built from grouped slider and toggle rows. /// right-aligned settings panel built from grouped slider and toggle rows.
fn settings_overlay(app: &App) -> Element<'_, Message, Theme, iced_wgpu::Renderer> { fn settings_overlay(app: &App) -> Element<'_, Message, Theme, iced_wgpu::Renderer> {
@ -530,23 +530,26 @@ fn slider_row<'a, F>(
where where
F: 'a + Fn(f32) -> Message, F: 'a + Fn(f32) -> Message,
{ {
let label_w = 96.0; let label_w = 110.0;
let value_w = 56.0; let value_w = 60.0;
container(
row![ row![
container(text(label).size(12).color(palette::text_dim())) container(text(label).size(13).color(palette::text_dim()))
.width(Length::Fixed(label_w)), .width(Length::Fixed(label_w)),
slider(range, value, on_change).step(step).width(Length::Fill), slider(range, value, on_change).step(step).width(Length::Fill).height(28.0),
container( container(
text(value_text) text(value_text)
.size(12) .size(13)
.color(palette::text()) .color(palette::text())
.align_x(iced_wgpu::core::alignment::Horizontal::Right) .align_x(iced_wgpu::core::alignment::Horizontal::Right)
) )
.width(Length::Fixed(value_w)) .width(Length::Fixed(value_w))
.align_right(Length::Fixed(value_w)), .align_right(Length::Fixed(value_w)),
] ]
.spacing(10) .spacing(12)
.align_y(iced_wgpu::core::Alignment::Center) .align_y(iced_wgpu::core::Alignment::Center)
)
.height(Length::Fixed(44.0))
.into() .into()
} }
@ -584,13 +587,16 @@ fn toggle_row<'a, F>(
where where
F: 'a + Fn(bool) -> Message, F: 'a + Fn(bool) -> Message,
{ {
container(
row![ row![
container(text(label).size(12).color(palette::text_dim())) container(text(label).size(13).color(palette::text_dim()))
.width(Length::Fixed(96.0)), .width(Length::Fixed(110.0)),
checkbox(value).on_toggle(on_change).size(16), checkbox(value).on_toggle(on_change).size(26),
] ]
.spacing(10) .spacing(12)
.align_y(iced_wgpu::core::Alignment::Center) .align_y(iced_wgpu::core::Alignment::Center)
)
.height(Length::Fixed(40.0))
.into() .into()
} }

View File

@ -42,9 +42,21 @@ pub struct ViewportHandle {
/// marks an active touch originating over the sidebar, routing vertical drags to wheel scrolls. /// marks an active touch originating over the sidebar, routing vertical drags to wheel scrolls.
touch_in_sidebar: bool, touch_in_sidebar: bool,
/// classification of an active touch over the settings panel: pending until SLOP, then tap/drag/scroll.
settings_touch: SettingsTouch,
pub state: App, pub state: App,
} }
/// classifies an in-flight settings-panel touch once its dominant axis is known.
#[derive(Copy, Clone, PartialEq, Eq)]
enum SettingsTouch {
None,
Pending,
Drag,
Scroll,
}
/// stub clipboard handed to iced, returning empty on reads and dropping writes. /// stub clipboard handed to iced, returning empty on reads and dropping writes.
struct NullClipboard; struct NullClipboard;
impl clipboard::Clipboard for NullClipboard { impl clipboard::Clipboard for NullClipboard {
@ -153,11 +165,10 @@ impl ViewportHandle {
self.needs_redraw = true; self.needs_redraw = true;
} }
/// folds an iOS touch into mouse-style events, treating sidebar drags as wheel scrolls. /// folds an iOS touch into mouse-style events, treating sidebar/settings vertical drags as wheel scrolls.
pub fn push_touch(&mut self, x: f32, y: f32, pressed: bool, moved: bool) { pub fn push_touch(&mut self, x: f32, y: f32, pressed: bool, moved: bool) {
const TOUCH_TAP_SLOP: f32 = 10.0; const TOUCH_TAP_SLOP: f32 = 10.0;
if !pressed && !moved { if !pressed && !moved {
if self.touch_in_sidebar { if self.touch_in_sidebar {
if let Some((sx, sy)) = self.touch_start.take() { if let Some((sx, sy)) = self.touch_start.take() {
if self.touch_drift <= TOUCH_TAP_SLOP { if self.touch_drift <= TOUCH_TAP_SLOP {
@ -166,33 +177,85 @@ impl ViewportHandle {
} }
} }
} else { } else {
match self.settings_touch {
SettingsTouch::None => {
self.push_mouse_button(x, y, 0, false); self.push_mouse_button(x, y, 0, false);
} }
SettingsTouch::Pending => {
if let Some((sx, sy)) = self.touch_start {
self.push_mouse_button(sx, sy, 0, true);
self.push_mouse_button(sx, sy, 0, false);
}
}
SettingsTouch::Drag => {
self.push_mouse_button(x, y, 0, false);
}
SettingsTouch::Scroll => {}
}
}
self.last_touch = None; self.last_touch = None;
self.touch_start = None;
self.touch_drift = 0.0; self.touch_drift = 0.0;
self.touch_in_sidebar = false; self.touch_in_sidebar = false;
self.settings_touch = SettingsTouch::None;
return; return;
} }
if pressed && !moved { if pressed && !moved {
let logical = self.viewport.logical_size();
let h = self.viewport.logical_size().height; let h = logical.height;
let w = logical.width;
self.touch_in_sidebar = self.state.point_in_sidebar(x, y, h); self.touch_in_sidebar = self.state.point_in_sidebar(x, y, h);
let in_settings = self.state.point_in_settings(x, y, w);
self.touch_start = Some((x, y)); self.touch_start = Some((x, y));
self.touch_drift = 0.0; self.touch_drift = 0.0;
self.last_touch = Some((x, y)); self.last_touch = Some((x, y));
if self.touch_in_sidebar { if self.touch_in_sidebar {
self.push_mouse_move(x, y); self.push_mouse_move(x, y);
self.settings_touch = SettingsTouch::None;
} else if in_settings {
self.settings_touch = SettingsTouch::Pending;
self.push_mouse_move(x, y);
} else { } else {
self.settings_touch = SettingsTouch::None;
self.push_mouse_button(x, y, 0, true); self.push_mouse_button(x, y, 0, true);
} }
return; return;
} }
self.push_mouse_move(x, y);
if let Some((px, py)) = self.last_touch { if let Some((px, py)) = self.last_touch {
let dx = x - px; let dx = x - px;
let dy = y - py; let dy = y - py;
self.touch_drift += (dx * dx + dy * dy).sqrt(); self.touch_drift += (dx * dx + dy * dy).sqrt();
if self.settings_touch == SettingsTouch::Pending && self.touch_drift > TOUCH_TAP_SLOP {
if let Some((sx, sy)) = self.touch_start {
let total_dx = (x - sx).abs();
let total_dy = (y - sy).abs();
if total_dy > total_dx {
self.settings_touch = SettingsTouch::Scroll;
} else {
self.settings_touch = SettingsTouch::Drag;
self.push_mouse_button(sx, sy, 0, true);
}
}
}
match self.settings_touch {
SettingsTouch::Scroll => {
if dy.abs() > 0.0 {
let p = Point::new(x, y);
self.events.push(Event::Mouse(mouse::Event::WheelScrolled {
delta: mouse::ScrollDelta::Pixels { x: 0.0, y: dy },
}));
self.cursor = mouse::Cursor::Available(p);
}
}
SettingsTouch::Drag => {
self.push_mouse_move(x, y);
}
SettingsTouch::Pending => {}
SettingsTouch::None => {
self.push_mouse_move(x, y);
if self.touch_in_sidebar && dy.abs() > 0.0 { if self.touch_in_sidebar && dy.abs() > 0.0 {
let p = Point::new(x, y); let p = Point::new(x, y);
self.events.push(Event::Mouse(mouse::Event::WheelScrolled { self.events.push(Event::Mouse(mouse::Event::WheelScrolled {
@ -201,6 +264,8 @@ impl ViewportHandle {
self.cursor = mouse::Cursor::Available(p); self.cursor = mouse::Cursor::Available(p);
} }
} }
}
}
self.last_touch = Some((x, y)); self.last_touch = Some((x, y));
} }
@ -425,6 +490,7 @@ fn finalise(
touch_start: None, touch_start: None,
touch_drift: 0.0, touch_drift: 0.0,
touch_in_sidebar: false, touch_in_sidebar: false,
settings_touch: SettingsTouch::None,
state, state,
}) })
} }