Preserve passive canvas geometry while contextual help is open
This commit is contained in:
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user