feat(ui): unified modal dispatch; migrate 4 dialogs (Plan B)

Replace the per-dialog open flag with a single `active_modal:
Option<ModalKind>` and one `CloseModal` message. view_main matches it to
render the open dialog as an in-canvas modal.

Migrated off OS windows: About (content-sized), Shortcuts, Plugin
Manager and the Update notice (the latter three keep a bounded size via
a wrapping container, since their lists/scroll need defined bounds).

Native + web build; 75 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-16 19:07:25 +03:00
commit 6a3663b3f1
3 changed files with 70 additions and 70 deletions

View file

@ -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(),
}
}