ElyDoc: an outline click goes to the heading drawn under it, even after a reread (D-06)

This commit is contained in:
ZacharyZhang-NY committed 2026-10-10 01:50:28 -04:00
1 parent 0b478701b5
commit db9b3975fe
4 files changed
+57 -7

No files matched your search

+1
View File
@@ -22,6 +22,7 @@ ely-ui.workspace = true
[dev-dependencies]
ely-ui = { workspace = true, features = ["test-support"] }
ely-gpui-component = { workspace = true, features = ["test-support"] }
env_logger.workspace = true
image.workspace = true
tempfile.workspace = true
+4 -6
View File
@@ -272,15 +272,13 @@ impl Render for Navigator {
if let Some(at) = self.outline.iter().position(|heading| heading.current) {
outline = outline.current(at.to_string());
}
let this = this.clone();
// The places shown: a reread may change the list.
let places: Vec<_> = self.outline.iter().map(|heading| heading.rect).collect();
let docs = self.docs.clone();
outline
.on_select(move |key, _, cx| {
let at: usize = key.parse().expect("an outline index");
let (to, docs) = {
let navigator = this.read(cx);
(navigator.outline[at].rect, navigator.docs.clone())
};
Navigator::jump(&docs, to, cx);
Navigator::jump(&docs, places[at], cx);
})
.into_any_element()
}
+51
View File
@@ -252,3 +252,54 @@ fn pdfs_export_a_range_and_locked_files_ask() {
"the locked text opens"
);
}
/// The navigator alone as a window's view.
struct Host(Entity<Navigator>);
impl gpui::Render for Host {
fn render(&mut self, _: &mut gpui::Window, _: &mut gpui::Context<Self>) -> impl gpui::IntoElement {
gpui::div().size_full().child(self.0.clone())
}
}
#[test]
fn an_outline_click_goes_where_its_row_was_drawn() {
let dir = tempfile::tempdir().expect("a temp dir");
let mut cx = TestAppContext::single();
let Some(docs) = docs(&mut cx, dir.path()) else {
eprintln!("SKIP: no LOK build");
return;
};
cx.update(ely_gpui_component::init_for_tests);
crate::tests::blank(&mut cx, &docs);
let navigator = cx.update(|app| docs.read(app).navigator.clone());
let heading = |n: i32| ely_lok::review::Heading { text: format!("Part {n}"), level: 0, rect: (0, n * 100, 10, 10), current: false };
cx.update(|app| navigator.update(app, |navigator, cx| {
navigator.outline = vec![heading(1), heading(2), heading(3)];
cx.notify();
}));
let (_, vcx) = cx.add_window_view(|_, _| Host(navigator.clone()));
let target = |vcx: &mut gpui::VisualTestContext| vcx.update(|_, app| docs.read(app).going.map(|going| going.3));
// Find where the drawn third row sits.
let third = (0..120)
.map(|step| gpui::point(gpui::px(40.), gpui::px(step as f32 * 4.)))
.find(|at| {
vcx.simulate_click(*at, gpui::Modifiers::none());
target(vcx) == Some((0, 300, 10, 10))
})
.expect("the third row is drawn");
vcx.update(|_, app| docs.update(app, |docs, _| docs.going = None));
// The list shrinks; the click lands on the old frame.
vcx.update(|window, app| {
navigator.update(app, |navigator, cx| {
navigator.outline.truncate(1);
cx.notify();
});
let (position, modifiers, button) = (third, gpui::Modifiers::none(), gpui::MouseButton::Left);
let down = gpui::MouseDownEvent { position, modifiers, button, click_count: 1, first_mouse: false };
window.dispatch_event(gpui::PlatformInput::MouseDown(down), app);
let up = gpui::MouseUpEvent { position, modifiers, button, click_count: 1 };
window.dispatch_event(gpui::PlatformInput::MouseUp(up), app);
});
assert_eq!(target(vcx), Some((0, 300, 10, 10)), "the click goes where its row was");
}
+1 -1
View File
@@ -52,7 +52,7 @@
- [x] D-03 界面线程同步持 worker 锁读内核(样式、字体、书签、公式、分节名) — 后台读取,回来核对标签、视图与对话框请求号
- [x] D-04 一条批注的时间读不出,全部批注与修订都不显示 — 逐条解析,读不出的批注写明作者与原因(AX 可读、可滚动),修订照留
- [x] D-05 邮件合并某条记录失败时内核文档泄漏 — 失败的记录照样关闭内核文档,再传出首个错误
- [ ] D-06 导航栏大纲点击按当前列表取下标,后台重读后可能越界
- [x] D-06 导航栏大纲点击按当前列表取下标,后台重读后可能越界 — 点击按绘制时的列表跳转;补点击路径的回归测试
- [ ] D-07 导航栏隐藏时仍随每次光标移动重读大纲与书签
- [ ] D-08 Linux、Windows 上“打印…”可用,导出 PDF 后才报“此平台未构建”
- [x] M-01 键入期间外部以相同内容重写文件,丢掉上次停顿之后键入的全部文字 — 先等页面送出未送的键;同文只接过文件与字节、标签为已保存;磁盘回到上次保存的文字时保留编辑并恢复自动保存;R1–R4 字节、自动保存、在途写入、已保存基线;R5 PASS