diff --git a/src/app/mod.rs b/src/app/mod.rs index eae45f09a..f64f97c79 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -294,8 +294,9 @@ pub(super) struct OpenCADStudio { color_pick_target: Option, shortcuts_window: Option, about_window: Option, - /// In-canvas About modal (Plan B: shared overlay instead of an OS window). - about_open: bool, + /// The open in-canvas modal dialog, if any (Plan B: shared overlay instead + /// of OS windows). + active_modal: Option, plugin_manager_window: Option, /// New-release notification window — opened on startup when the /// GitHub releases API reports a newer version than this build. @@ -587,6 +588,17 @@ pub enum ColorPickTarget { Layer(usize), } +/// Which in-canvas modal dialog is currently open (Plan B). At most one shows +/// at a time; dialog-specific data lives in its own fields. Closed via the +/// modal's ✕ (`Message::CloseModal`). +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum ModalKind { + About, + Shortcuts, + PluginManager, + UpdateNotice, +} + /// Identifies a DimStyle field that can be edited in the dialog. #[derive(Debug, Clone, PartialEq, Eq)] pub enum DsField { @@ -994,7 +1006,8 @@ pub enum Message { ShortcutsPanelClose, // ── About window ──────────────────────────────────────────────────── AboutOpen, - AboutClose, + /// Close whatever in-canvas modal dialog is open (Plan B). + CloseModal, AboutCopyInfo, // ── Plugin Manager window ─────────────────────────────────────────── PluginManagerOpen, @@ -1416,7 +1429,7 @@ impl OpenCADStudio { color_pick_target: None, shortcuts_window: None, about_window: None, - about_open: false, + active_modal: None, plugin_manager_window: None, update_notice_window: None, assoc_prompt_window: None, diff --git a/src/app/update.rs b/src/app/update.rs index 5c5fa91e9..3daafa56f 100644 --- a/src/app/update.rs +++ b/src/app/update.rs @@ -5449,34 +5449,22 @@ impl OpenCADStudio { // ── Keyboard Shortcuts Panel ────────────────────────────────────── Message::ShortcutsPanelOpen => { - if let Some(id) = self.shortcuts_window { - return window::gain_focus(id); - } - let (id, task) = window::open(window::Settings { - size: iced::Size::new(720.0, 520.0), - resizable: true, - level: window::Level::AlwaysOnTop, - ..Default::default() - }); - self.shortcuts_window = Some(id); - task.map(|_| Message::Noop) + self.active_modal = Some(super::ModalKind::Shortcuts); + Task::none() } Message::ShortcutsPanelClose => { - if let Some(id) = self.shortcuts_window.take() { - window::close(id) - } else { - Task::none() - } + self.active_modal = None; + Task::none() } // ── About window ────────────────────────────────────────────── Message::AboutOpen => { - self.about_open = true; + self.active_modal = Some(super::ModalKind::About); Task::none() } - Message::AboutClose => { - self.about_open = false; + Message::CloseModal => { + self.active_modal = None; Task::none() } @@ -5492,24 +5480,12 @@ impl OpenCADStudio { // ── Plugin Manager window ───────────────────────────────────── Message::PluginManagerOpen => { - if let Some(id) = self.plugin_manager_window { - return window::gain_focus(id); - } - let (id, task) = window::open(window::Settings { - size: iced::Size::new(520.0, 460.0), - resizable: true, - level: window::Level::AlwaysOnTop, - ..Default::default() - }); - self.plugin_manager_window = Some(id); - task.map(|_| Message::Noop) + self.active_modal = Some(super::ModalKind::PluginManager); + Task::none() } Message::PluginManagerClose => { - if let Some(id) = self.plugin_manager_window.take() { - window::close(id) - } else { - Task::none() - } + self.active_modal = None; + Task::none() } Message::EnterViewport(handle) => { @@ -5788,35 +5764,17 @@ impl OpenCADStudio { }; self.update_notice_version = Some(info.version); self.update_notice_body = Some(info.body); - if let Some(id) = self.update_notice_window { - return window::gain_focus(id); - } - let (id, task) = window::open(window::Settings { - // Sized for the new release-notes panel — wide enough - // for typical GitHub release headlines, tall enough for - // a meaningful scroll preview without dwarfing the app. - size: iced::Size::new(560.0, 460.0), - resizable: true, - level: window::Level::AlwaysOnTop, - ..Default::default() - }); - self.update_notice_window = Some(id); - task.map(|_| Message::Noop) + self.active_modal = Some(super::ModalKind::UpdateNotice); + Task::none() } Message::UpdateNoticeClose => { - if let Some(id) = self.update_notice_window.take() { - window::close(id) - } else { - Task::none() - } + self.active_modal = None; + Task::none() } Message::UpdateNoticeOpenRelease => { crate::sys::open_url(crate::update_check::RELEASES_PAGE); - if let Some(id) = self.update_notice_window.take() { - window::close(id) - } else { - Task::none() - } + self.active_modal = None; + Task::none() } Message::AssocPromptYes => { self.mark_assoc_prompted(); diff --git a/src/app/view.rs b/src/app/view.rs index 555a4d7a3..107608e2d 100644 --- a/src/app/view.rs +++ b/src/app/view.rs @@ -1517,14 +1517,43 @@ impl OpenCADStudio { // ── In-canvas modal dialogs (Plan B) ─────────────────────────────── // Former pop-up windows render as overlays here, so they work on both // the native (single main window) and web builds. - if self.about_open { - crate::ui::modal::modal( + use crate::ui::modal::modal; + match self.active_modal { + Some(super::ModalKind::About) => { + modal(composed, crate::ui::about::view_window(), Message::CloseModal) + } + Some(super::ModalKind::Shortcuts) => modal( composed, - crate::ui::about::view_window(), - Message::AboutClose, - ) - } else { - composed.into() + // Content-heavy dialogs (lists / scroll) keep a bounded size — + // their inner `Fill` widgets fill it — instead of shrinking. + iced::widget::container(crate::ui::shortcuts::view_window( + &self.shortcut_overrides, + )) + .width(720) + .height(520), + Message::CloseModal, + ), + Some(super::ModalKind::PluginManager) => modal( + composed, + iced::widget::container(crate::ui::plugin_manager::view_window( + &crate::plugin::installed_manifests(), + )) + .width(520) + .height(460), + Message::CloseModal, + ), + Some(super::ModalKind::UpdateNotice) => { + let latest = self.update_notice_version.as_deref().unwrap_or("?"); + let body = self.update_notice_body.as_deref().unwrap_or(""); + modal( + composed, + iced::widget::container(crate::ui::update_notice::view_window(latest, body)) + .width(560) + .height(460), + Message::CloseModal, + ) + } + None => composed.into(), } }