Fit modal dialogs to the phone screen on mobile
Add mobile::dialog_width(ctx, desired) — a min()-clamp that's a no-op on wide desktop screens. Clamp the Export and Export Progress modals and the Sample Import window to it. Render Preferences as an egui::Modal (dim backdrop, centered, no title bar) with a screen-fit scroll height when mobile_active(); desktop keeps its window. Extracted the preferences body into render_body() shared by both paths.
This commit is contained in:
parent
a0ac4f2d35
commit
f13a127c9d
|
|
@ -208,7 +208,7 @@ impl ExportDialog {
|
||||||
|
|
||||||
let modal_response = egui::Modal::new(egui::Id::new("export_dialog_modal"))
|
let modal_response = egui::Modal::new(egui::Id::new("export_dialog_modal"))
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.set_width(500.0);
|
ui.set_width(crate::mobile::dialog_width(ctx, 500.0));
|
||||||
|
|
||||||
ui.heading(window_title);
|
ui.heading(window_title);
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
|
|
@ -801,7 +801,7 @@ impl ExportProgressDialog {
|
||||||
|
|
||||||
egui::Modal::new(egui::Id::new("export_progress_modal"))
|
egui::Modal::new(egui::Id::new("export_progress_modal"))
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.set_width(400.0);
|
ui.set_width(crate::mobile::dialog_width(ctx, 400.0));
|
||||||
|
|
||||||
ui.heading("Exporting...");
|
ui.heading("Exporting...");
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
|
|
|
||||||
|
|
@ -6329,7 +6329,8 @@ impl eframe::App for EditorApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render preferences dialog
|
// Render preferences dialog
|
||||||
if let Some(result) = self.preferences_dialog.render(ctx, &mut self.config, &mut self.theme) {
|
let mobile = self.mobile_active();
|
||||||
|
if let Some(result) = self.preferences_dialog.render(ctx, &mut self.config, &mut self.theme, mobile) {
|
||||||
if result.buffer_size_changed {
|
if result.buffer_size_changed {
|
||||||
println!("⚠️ Audio buffer size will be applied on next app restart");
|
println!("⚠️ Audio buffer size will be applied on next app restart");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,13 @@ pub const MOBILE_NS: usize = usize::MAX;
|
||||||
const TRANSPORT_H: f32 = 60.0;
|
const TRANSPORT_H: f32 = 60.0;
|
||||||
const TOPBAR_H: f32 = 40.0;
|
const TOPBAR_H: f32 = 40.0;
|
||||||
|
|
||||||
|
/// Clamp a desktop dialog width to fit the current screen (with side margins). A no-op on wide
|
||||||
|
/// desktop screens (`min` keeps the desired width); on a phone-aspect window it shrinks to fit.
|
||||||
|
pub fn dialog_width(ctx: &egui::Context, desired: f32) -> f32 {
|
||||||
|
let avail = ctx.screen_rect().width() - 24.0;
|
||||||
|
desired.min(avail.max(200.0))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the mobile UI is requested via the `LB_MOBILE_UI` env var.
|
/// Returns true if the mobile UI is requested via the `LB_MOBILE_UI` env var.
|
||||||
/// Any non-empty value other than "0" enables it.
|
/// Any non-empty value other than "0" enables it.
|
||||||
pub fn is_mobile_env() -> bool {
|
pub fn is_mobile_env() -> bool {
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@ impl PreferencesDialog {
|
||||||
ctx: &egui::Context,
|
ctx: &egui::Context,
|
||||||
config: &mut AppConfig,
|
config: &mut AppConfig,
|
||||||
theme: &mut Theme,
|
theme: &mut Theme,
|
||||||
|
mobile: bool,
|
||||||
) -> Option<PreferencesSaveResult> {
|
) -> Option<PreferencesSaveResult> {
|
||||||
if !self.open {
|
if !self.open {
|
||||||
return None;
|
return None;
|
||||||
|
|
@ -160,13 +161,58 @@ impl PreferencesDialog {
|
||||||
let mut should_cancel = false;
|
let mut should_cancel = false;
|
||||||
let mut open = self.open;
|
let mut open = self.open;
|
||||||
|
|
||||||
|
// On mobile, render as a screen-fitting modal sheet (dim backdrop, centered) like the other
|
||||||
|
// mobile modals; on desktop, the familiar draggable window.
|
||||||
|
let width = crate::mobile::dialog_width(ctx, 550.0);
|
||||||
|
let scroll_h = if mobile {
|
||||||
|
(ctx.screen_rect().height() - 220.0).clamp(160.0, 400.0)
|
||||||
|
} else {
|
||||||
|
400.0
|
||||||
|
};
|
||||||
|
|
||||||
|
if mobile {
|
||||||
|
let resp = egui::Modal::new(egui::Id::new("preferences_modal")).show(ctx, |ui| {
|
||||||
|
self.render_body(ui, width, scroll_h, &mut should_save, &mut should_cancel);
|
||||||
|
});
|
||||||
|
if resp.backdrop_response.clicked() {
|
||||||
|
should_cancel = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
egui::Window::new("Preferences")
|
egui::Window::new("Preferences")
|
||||||
.open(&mut open)
|
.open(&mut open)
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.collapsible(false)
|
.collapsible(false)
|
||||||
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
|
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.set_width(550.0);
|
self.render_body(ui, width, scroll_h, &mut should_save, &mut should_cancel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update open state
|
||||||
|
self.open = open;
|
||||||
|
|
||||||
|
if should_cancel {
|
||||||
|
self.close();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if should_save {
|
||||||
|
return self.handle_save(config, theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn render_body(
|
||||||
|
&mut self,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
width: f32,
|
||||||
|
scroll_h: f32,
|
||||||
|
should_save: &mut bool,
|
||||||
|
should_cancel: &mut bool,
|
||||||
|
) {
|
||||||
|
ui.set_width(width);
|
||||||
|
|
||||||
// Error message
|
// Error message
|
||||||
if let Some(error) = &self.error_message {
|
if let Some(error) = &self.error_message {
|
||||||
|
|
@ -184,9 +230,7 @@ impl PreferencesDialog {
|
||||||
// Tab content
|
// Tab content
|
||||||
match self.tab {
|
match self.tab {
|
||||||
PreferencesTab::General => {
|
PreferencesTab::General => {
|
||||||
egui::ScrollArea::vertical()
|
egui::ScrollArea::vertical().max_height(scroll_h).show(ui, |ui| {
|
||||||
.max_height(400.0)
|
|
||||||
.show(ui, |ui| {
|
|
||||||
self.render_general_section(ui);
|
self.render_general_section(ui);
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
self.render_audio_section(ui);
|
self.render_audio_section(ui);
|
||||||
|
|
@ -208,7 +252,7 @@ impl PreferencesDialog {
|
||||||
// Buttons
|
// Buttons
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.button("Cancel").clicked() {
|
if ui.button("Cancel").clicked() {
|
||||||
should_cancel = true;
|
*should_cancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.button("Reset to Defaults").clicked() {
|
if ui.button("Reset to Defaults").clicked() {
|
||||||
|
|
@ -217,25 +261,10 @@ impl PreferencesDialog {
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
if ui.button("Save").clicked() {
|
if ui.button("Save").clicked() {
|
||||||
should_save = true;
|
*should_save = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Update open state
|
|
||||||
self.open = open;
|
|
||||||
|
|
||||||
if should_cancel {
|
|
||||||
self.close();
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if should_save {
|
|
||||||
return self.handle_save(config, theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_shortcuts_tab(&mut self, ui: &mut egui::Ui) {
|
fn render_shortcuts_tab(&mut self, ui: &mut egui::Ui) {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ impl SampleImportDialog {
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.collapsible(false)
|
.collapsible(false)
|
||||||
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
|
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
|
||||||
.default_width(700.0)
|
.default_width(crate::mobile::dialog_width(ctx, 700.0))
|
||||||
|
.max_width(crate::mobile::dialog_width(ctx, 700.0))
|
||||||
.default_height(500.0)
|
.default_height(500.0)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
// Folder info
|
// Folder info
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue