Preserve passive canvas geometry while contextual help is open

This commit is contained in:
2026-09-24 23:10:46 -07:00
parent e0812b3932
commit f83068757a
4 changed files with 112 additions and 1 deletions
+10
View File
@@ -1383,6 +1383,16 @@ impl App {
| Message::SourceSymbolsReady(_)
| Message::SourceRenameReady(_)
| Message::DiagramUsagesReady(_)
| Message::ScenarioCanvas(
behavior::scenario::CanvasEvent::Scrolled(..)
| behavior::scenario::CanvasEvent::Restored(..)
| behavior::scenario::CanvasEvent::Viewport(..)
)
| Message::TopologyCanvas(
behavior::topology::CanvasEvent::Scrolled(..)
| behavior::topology::CanvasEvent::Viewport(..)
)
| Message::StateDiagram(behavior::state_edit::Event::Viewport(..))
)
{
return Task::none();
@@ -272,3 +272,77 @@ fn context_help_rejects_a_reference_picker_open_queued_from_the_inspector() {
before
);
}
#[test]
fn context_help_accepts_live_process_viewport_and_rejects_stale_measurements() {
use crate::behavior::topology::CanvasEvent;
let mut project = Project::empty();
let owner = project
.add_element(Kind::Process, Layer::Oa, "Response process", None)
.unwrap();
let mut app = App::with_project(project);
send(&mut app, Message::Select(owner));
send(&mut app, Message::Page(Page::Behavior));
let context = app.topology_context().unwrap();
send(
&mut app,
Message::TopologyCanvas(CanvasEvent::Viewport(context, iced::Size::new(640., 480.))),
);
let initial = app.behavior.topology.camera_boundary();
let before = app.document.snapshot();
send(&mut app, Message::Help);
assert!(app.context_help);
assert_eq!(app.guide.topic, Topic::Chains);
let resized = iced::Size::new(420., 330.);
let context = app.topology_context().unwrap();
send(
&mut app,
Message::TopologyCanvas(CanvasEvent::Viewport(context, resized)),
);
let measured = app.behavior.topology.camera_boundary();
assert!(
measured != initial,
"Help must admit passive viewport measurements"
);
assert!(app.context_help);
let epoch = app.canvas_epoch;
for field in 0..3 {
let mut stale = app.topology_context().unwrap();
match field {
0 => stale.document = Id::new_v4(),
1 => stale.owner = Id::new_v4(),
_ => stale.revision += 1,
}
send(
&mut app,
Message::TopologyCanvas(CanvasEvent::Viewport(stale, iced::Size::new(999., 777.))),
);
assert!(app.behavior.topology.camera_boundary() == measured);
assert_eq!(app.canvas_epoch, epoch);
}
send(&mut app, Message::CloseContextHelp);
assert!(!app.context_help);
assert!(app.behavior.topology.camera_boundary() == measured);
let context = app.topology_context().unwrap();
let epoch = app.canvas_epoch;
send(
&mut app,
Message::TopologyCanvas(CanvasEvent::Viewport(context, resized)),
);
assert_eq!(
app.canvas_epoch, epoch,
"The size observed behind Help is already current"
);
let context = app.topology_context().unwrap();
send(
&mut app,
Message::TopologyCanvas(CanvasEvent::Viewport(context, iced::Size::new(700., 500.))),
);
assert!(app.behavior.topology.camera_boundary() != measured);
assert_eq!(app.page, Page::Behavior);
assert_eq!(app.selected, owner);
assert!(Arc::ptr_eq(&before, &app.document.snapshot()));
assert!(!app.document.can_undo());
}
+1 -1
View File
@@ -17,6 +17,6 @@ Rejected alternatives: ordinary navigation to the Guide page cleared selection a
## Verification status
Implementation and six focused state/admission regression tests are prepared. First intermediate `cargo check -p oa-desktop --locked` passed before later overlay and input changes; it is not a check of the final candidate. Current build, focused tests, strict lint, formatting, native comparison and fresh final review remain pending. Baseline captures and raw build logs are local-only until the evidence publication step. No new executable, integrated change, issue closure or release is claimed.
Implementation and seven focused state/admission regression tests are prepared. The [independent source review](compact-context-help-source-review-20260925.md) records the corrected findings, including passive viewport updates while Help is open. First intermediate `cargo check -p oa-desktop --locked` passed before later overlay and input changes; it is not a check of the final candidate. Current build, focused tests, strict lint, formatting, native comparison and fresh final review remain pending. Baseline captures and raw build logs are local-only until the evidence publication step. No new executable, integrated change, issue closure or release is claimed.
Required native checks: minimum and normal windows; Traceability and Allocation space comparison; multi-selection with long names; Help/F1/Close/Escape with property and behavior drafts; editor focus and canvas scroll/camera restoration; active feedback plus operation failure; State and Process controls; subsequent edit/Undo/Redo and source preservation. Linux remains deferred under the recorded user instruction.
@@ -0,0 +1,27 @@
# Compact contextual help: independent source review
Review date: 2026-09-25. Scope: Gitea issue #39 compact editing chrome and contextual Help, reviewed against base `715036e1` and the issue screenshot. Reviewed source includes `e0812b3932fbb36100516f0981dc9c646eeda56d` plus the subsequent local passive-geometry admission patch and regression test in this change. This is source-review evidence, not native acceptance or executed test evidence.
Criteria: [editing workspace UX review](../docs/ui-review.md), especially preserving pending edits and selection, stable canvas geometry, accessible disclosure, and retaining actionable feedback.
## Findings addressed in source
- The initial Help action used ordinary page navigation, clearing multiselection and selected bends, including before a pending behavior form rejected navigation. Contextual Help now overlays the existing workspace. Close/Escape changes reading state without navigating or applying drafts.
- App-level modal admission originally ran after allocation and reference-picker fast paths. Help now gates user messages at the beginning of `App::update`; allocation and behavior keyboard ownership are also disabled while Help is open.
- Combining live gesture feedback with multiselection controls could leave no width for feedback at the configured minimum window size. Selection controls now keep a compact, fixed-height row; current drawing/allocation feedback uses the existing application footer.
- Footer feedback initially replaced operation status, concealing errors while a promoted edge or drawing tool remained selected. The footer now retains operation status alongside feedback and exposes complete text in its tooltip.
- Conditional modal wrapping could recreate the editor widget tree. Both closed and open states now use the same outer Stack with the workspace as its first child.
- State/Process selection guidance removed from persistent chrome was missing from its target Help articles. The States and Chains articles now include group selection, primary-properties semantics and relevant tool/read-only guidance.
- The new early modal gate initially rejected passive behavior viewport/scroll notifications. It now admits Process/Scenario geometry and State viewport notifications to their existing context-validated handlers, preventing resize observations from being lost while Help is open.
## Regression coverage added
[`context_help_tests.rs`](../crates/oa-desktop/src/app/context_help_tests.rs) covers property drafts and multiselection, source drafts, pending state-transition forms, blocked background actions, contextual Help topic dispatch, Close/Escape, allocation input ownership, queued inspector reference-picker admission, and valid/stale Process viewport measurements during Help and after closing. Assertions include accepted-model snapshot identity and absence of history changes where applicable. Passive geometry intentionally validates document/owner/revision; stale pointer epochs alone do not invalidate measurements.
The reviewer did not compile or execute these tests. Suggested focused command: `cargo test -p oa-desktop context_help_tests`. The integration owner records actual execution and native results separately.
## Scope and remaining verification
Production changes reviewed: desktop App messages/admission, allocation input ownership, Escape bridging, behavior keyboard ownership, architecture/State/Process toolbar layout, guide article disclosure and footer feedback; supporting architecture/UI-review documentation. Regression tests and this record are review artifacts. No model schema, persistence format or authored-model transformation is introduced.
No further concrete source blocker was identified after the fixes above. Native checks remain necessary at 1100×700 and a representative normal size: Help discovery and keyboard reading/dismissal, focus and caret return, preservation of canvas camera/selection and form drafts, resize while Help is open, multiselection control visibility, allocation refusal/destination feedback, current operation failures, and stable canvas bounds through selection/gesture changes. Source inspection and App tests do not establish layout quality, keyboard scrolling, pointer behavior or usability.