The pinned checklist duplicated what the transcript already renders inline (action steps, subtask cards, verb chips, agent narration - the Pencil-style reading flow), while eating a third of the panel's height. The transcript is now the single progress surface; the checklist widget, its hit/scroll wiring on both hosts and its ChatState fields are removed.
124 lines
4.3 KiB
Rust
124 lines
4.3 KiB
Rust
use super::WidgetHostNative;
|
|
|
|
fn nested_frame_doc(depth: usize) -> String {
|
|
let mut src = String::from(r#"{"version":"0.8.0","children":["#);
|
|
for i in 0..depth {
|
|
src.push_str(&format!(
|
|
r##"{{"type":"frame","id":"nest-{i:05}","name":"Nested Layer {i:05}","x":8,"y":6,"width":400,"height":220,"fill":[{{"type":"solid","color":"#ffffff20"}}],"stroke":{{"thickness":1,"fill":[{{"type":"solid","color":"#0088ff"}}]}},"children":["##
|
|
));
|
|
}
|
|
for _ in 0..depth {
|
|
src.push_str("]}");
|
|
}
|
|
src.push_str("]}");
|
|
src
|
|
}
|
|
|
|
fn seed(host: &mut WidgetHostNative, json: &str) {
|
|
let doc = jian_ops_schema::load_str(json)
|
|
.expect("fixture JSON parses")
|
|
.value;
|
|
*host.editor_state_mut() = op_editor_core::EditorState::from_document(doc);
|
|
host.mark_paint_dirty_for_test();
|
|
}
|
|
|
|
fn run_deep_layer_fixture(test: impl FnOnce() + Send + 'static) {
|
|
let handle = std::thread::Builder::new()
|
|
.name("op-host-native-deep-layer-fixture".into())
|
|
.stack_size(64 * 1024 * 1024)
|
|
.spawn(test)
|
|
.expect("spawn deep layer fixture test");
|
|
if let Err(payload) = handle.join() {
|
|
std::panic::resume_unwind(payload);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn layer_panel_trackpad_pan_scrolls_horizontally() {
|
|
run_deep_layer_fixture(|| {
|
|
let mut host = WidgetHostNative::new();
|
|
seed(&mut host, &nested_frame_doc(50));
|
|
let viewport_w = 1200.0;
|
|
let viewport_h = 800.0;
|
|
let panel = op_editor_ui::widgets::LayerPanel::from_editor(host.editor_state());
|
|
let rect = op_editor_ui::Rect {
|
|
origin: op_editor_ui::Point2D::new(0.0, op_editor_ui::widgets::TOP_BAR_HEIGHT),
|
|
size: op_editor_ui::Point2D::new(
|
|
host.editor_state().editor_ui.layer_panel_width,
|
|
viewport_h - op_editor_ui::widgets::TOP_BAR_HEIGHT,
|
|
),
|
|
};
|
|
let regions = panel.regions(rect);
|
|
assert!(regions.layers.max_horizontal_offset > 0.0);
|
|
|
|
assert!(host.apply_pan_gesture(
|
|
80.0,
|
|
regions.layers_rows_top + 12.0,
|
|
-180.0,
|
|
0.0,
|
|
viewport_w,
|
|
viewport_h
|
|
));
|
|
|
|
assert!(host.editor_state().editor_ui.layer_layers_h_scroll.offset > 0.0);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn design_md_panel_wheel_scrolls_content_without_zooming_canvas() {
|
|
let mut host = WidgetHostNative::new();
|
|
let viewport_w = 1200.0;
|
|
let viewport_h = 800.0;
|
|
let mut markdown = String::from("# Design System: Long\n\n## Color Palette\n");
|
|
for index in 0..40 {
|
|
markdown.push_str(&format!(
|
|
"- **color-{index:02}** (#{index:02X}{index:02X}{index:02X}) - role {index}\n"
|
|
));
|
|
}
|
|
host.editor_state_mut().editor_ui.design_md_panel_open = true;
|
|
host.editor_state_mut().doc.design_md = Some(op_editor_core::parse_design_md(&markdown));
|
|
let panel_rect = host
|
|
.design_md_panel_rect(viewport_w, viewport_h)
|
|
.expect("design.md panel rect");
|
|
let panel = op_editor_ui::widgets::DesignMdPanel::for_editor(host.editor_state())
|
|
.expect("design.md panel");
|
|
assert!(panel.max_scroll(panel_rect) > 0.0);
|
|
let zoom = host.editor_state().viewport.zoom;
|
|
|
|
assert!(host.apply_wheel(
|
|
panel_rect.origin.x + panel_rect.size.x / 2.0,
|
|
panel_rect.origin.y + panel_rect.size.y / 2.0,
|
|
-120.0,
|
|
viewport_w,
|
|
viewport_h
|
|
));
|
|
|
|
assert!(host.editor_state().editor_ui.design_md_scroll.offset > 0.0);
|
|
assert_eq!(host.editor_state().viewport.zoom, zoom);
|
|
}
|
|
|
|
#[test]
|
|
fn locale_picker_wheel_scrolls_select_state_without_zooming_canvas() {
|
|
let mut host = WidgetHostNative::new();
|
|
let viewport_w = 1200.0;
|
|
let viewport_h = 800.0;
|
|
host.editor_state_mut().editor_ui.locale_picker.open = true;
|
|
host.editor_state_mut().editor_ui.locale_picker.hover = Some(0);
|
|
let zoom = host.editor_state().viewport.zoom;
|
|
let picker = host.locale_picker_rect(viewport_w);
|
|
|
|
assert!(host.apply_wheel(
|
|
picker.origin.x + picker.size.x / 2.0,
|
|
picker.origin.y + op_editor_ui::widgets::LocalePicker::row_height(),
|
|
-80.0,
|
|
viewport_w,
|
|
viewport_h
|
|
));
|
|
|
|
let state = &host.editor_state().editor_ui.locale_picker;
|
|
assert!(state.open);
|
|
assert!(state.scroll.offset > 0.0);
|
|
assert_eq!(state.hover, None);
|
|
assert_eq!(host.editor_state().viewport.zoom, zoom);
|
|
}
|