ElyShow: an open dialog is never pushed aside; a stuck show start is gone (S-04)
This commit is contained in:
13 files changed
+59
-26
No files matched your search
@@ -186,8 +186,8 @@ impl Deck {
|
||||
return log::info!("show: a chart dialog for tab {tab} came late");
|
||||
}
|
||||
let editing = Editing::new(tab, chart, window, cx);
|
||||
deck.dialog = Some(Dialog::Chart(Box::new(editing)));
|
||||
cx.notify();
|
||||
// Refused while another dialog is open; it says so.
|
||||
let _ = deck.open_dialog(Dialog::Chart(Box::new(editing)), cx);
|
||||
})
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
||||
@@ -128,8 +128,8 @@ impl Deck {
|
||||
Ok((check, slides)) if deck.dialog_due(asked, id) => {
|
||||
let found = findings(&check, &slides, &missing);
|
||||
log::info!("show: the check found {} things", found.len());
|
||||
deck.dialog = Some(Dialog::Check(found));
|
||||
cx.notify();
|
||||
// Refused while another dialog is open; it says so.
|
||||
let _ = deck.open_dialog(Dialog::Check(found), cx);
|
||||
}
|
||||
Ok(_) => log::info!("show: the check is no longer due"),
|
||||
Err(error) => deck.engine_failed(&format!("the check: {error}"), cx),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! ElyShow's one open dialog.
|
||||
|
||||
use ely_gpui_component::forms::TextInput;
|
||||
use ely_gpui_component::{forms::TextInput, primitives::Severity};
|
||||
use ely_office::prelude::*;
|
||||
use gpui::{App, Context, Entity, IntoElement as _};
|
||||
|
||||
use crate::deck::Deck;
|
||||
@@ -41,6 +42,18 @@ pub(crate) fn edit(
|
||||
}
|
||||
|
||||
impl Deck {
|
||||
/// Opens `dialog`, or hands it back while another is open.
|
||||
pub(crate) fn open_dialog(&mut self, dialog: Dialog, cx: &mut Context<Self>) -> Result<(), Dialog> {
|
||||
if self.dialog.is_some() {
|
||||
let text = Deck::text(cx, "show.dialog.busy", &[]);
|
||||
self.toast(text, Severity::Warning, cx);
|
||||
return Err(dialog);
|
||||
}
|
||||
self.dialog = Some(dialog);
|
||||
cx.notify();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A read that will open a dialog; earlier ones lapse.
|
||||
pub fn ask_dialog(&mut self) -> u64 {
|
||||
self.dialog_asked += 1;
|
||||
@@ -56,9 +69,9 @@ impl Deck {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether read `asked` may open its dialog now.
|
||||
/// Whether read `asked` still stands; `open_dialog` checks the rest.
|
||||
pub fn dialog_due(&self, asked: u64, id: u64) -> bool {
|
||||
self.dialog_asked == asked && self.dialog.is_none() && self.core.active == Some(id)
|
||||
self.dialog_asked == asked && self.core.active == Some(id)
|
||||
}
|
||||
|
||||
/// The open dialog, drawn.
|
||||
|
||||
@@ -34,8 +34,8 @@ impl Deck {
|
||||
match ely_lok::templates("presnt") {
|
||||
Ok(templates) => {
|
||||
log::info!("show: {} bundled templates", templates.len());
|
||||
self.dialog = Some(Dialog::New(Choosing { templates }));
|
||||
cx.notify();
|
||||
// Refused while another dialog is open; it says so.
|
||||
let _ = self.open_dialog(Dialog::New(Choosing { templates }), cx);
|
||||
}
|
||||
Err(error) => self.engine_failed(&error.to_string(), cx),
|
||||
}
|
||||
|
||||
@@ -148,7 +148,8 @@ impl Deck {
|
||||
|worker, doc| ely_lok::show::slide_show(&worker.values(doc, ely_lok::show::SLIDE_SHOW)?),
|
||||
move |deck, read, _, cx| match read {
|
||||
Ok(slides) if deck.dialog_due(asked, id) => {
|
||||
deck.dialog = Some(Dialog::Output(Output {
|
||||
// Refused while another dialog is open; it says so.
|
||||
let output = Output {
|
||||
tab: id,
|
||||
print,
|
||||
kind: Kind::Slides,
|
||||
@@ -156,8 +157,8 @@ impl Deck {
|
||||
per: 3,
|
||||
current,
|
||||
hidden: slides.iter().map(|slide| slide.hidden).collect(),
|
||||
}));
|
||||
cx.notify();
|
||||
};
|
||||
let _ = deck.open_dialog(Dialog::Output(output), cx);
|
||||
}
|
||||
Ok(_) => log::info!("show: the output dialog is no longer due"),
|
||||
Err(error) => deck.engine_failed(&format!("the slides: {error}"), cx),
|
||||
|
||||
@@ -77,8 +77,8 @@ impl Deck {
|
||||
input.set_text(text, cx);
|
||||
input
|
||||
});
|
||||
self.dialog = Some(Dialog::Remark { tab, edit, field });
|
||||
cx.notify();
|
||||
// Refused while another dialog is open; it says so.
|
||||
let _ = self.open_dialog(Dialog::Remark { tab, edit, field }, cx);
|
||||
}
|
||||
|
||||
/// Sends the dialog's text: a new comment or an edit.
|
||||
|
||||
@@ -196,11 +196,11 @@ impl Deck {
|
||||
};
|
||||
match cx.displays().len() {
|
||||
1 => deck.open_show(starting, cx),
|
||||
_ => {
|
||||
deck.show_starting = true;
|
||||
deck.dialog = Some(Dialog::Show(starting));
|
||||
cx.notify();
|
||||
}
|
||||
_ => match deck.open_dialog(Dialog::Show(starting), cx) {
|
||||
Ok(()) => deck.show_starting = true,
|
||||
Err(Dialog::Show(refused)) => discard(worker, refused.doc, refused.copy, cx),
|
||||
Err(_) => unreachable!("the show dialog comes back"),
|
||||
},
|
||||
}
|
||||
},
|
||||
cx,
|
||||
|
||||
@@ -21,12 +21,8 @@ use crate::dialog::{Dialog, edit};
|
||||
impl Deck {
|
||||
pub fn ask_table(&mut self, cx: &mut Context<Self>) {
|
||||
if let Some(tab) = self.core.active {
|
||||
self.dialog = Some(Dialog::Table {
|
||||
tab,
|
||||
columns: 3,
|
||||
rows: 3,
|
||||
});
|
||||
cx.notify();
|
||||
// Refused while another dialog is open; it says so.
|
||||
let _ = self.open_dialog(Dialog::Table { tab, columns: 3, rows: 3 }, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,23 @@ fn the_table_dialog_inserts_a_table() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_open_dialog_is_not_pushed_aside() {
|
||||
let dir = tempfile::tempdir().expect("a temp dir");
|
||||
let mut cx = TestAppContext::single();
|
||||
let Some(deck) = blank(&mut cx, dir.path()) else {
|
||||
eprintln!("SKIP: no LOK build");
|
||||
return;
|
||||
};
|
||||
update(&mut cx, &deck, |deck, cx| deck.ask_table(cx));
|
||||
update(&mut cx, &deck, |deck, cx| deck.ask_new(cx));
|
||||
// The chart dialog opens after a background read.
|
||||
update(&mut cx, &deck, |deck, cx| deck.ask_chart(cx));
|
||||
cx.run_until_parked();
|
||||
let kept = cx.update(|app| matches!(deck.read(app).dialog, Some(crate::dialog::Dialog::Table { .. })));
|
||||
assert!(kept, "the table dialog stays");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_notes_reach_the_slide() {
|
||||
let dir = tempfile::tempdir().expect("a temp dir");
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
pub(super) const EN: &[(&str, &str)] = &[
|
||||
("menu.slide", "Slide"),
|
||||
("show.dialog.busy", "Finish or close the open dialog first"),
|
||||
("show.slide.new", "New Slide"),
|
||||
("show.slide.duplicate", "Duplicate Slide"),
|
||||
("show.slide.delete", "Delete Slide"),
|
||||
@@ -189,6 +190,7 @@ pub(super) const EN: &[(&str, &str)] = &[
|
||||
|
||||
pub(super) const ZH_CN: &[(&str, &str)] = &[
|
||||
("menu.slide", "幻灯片"),
|
||||
("show.dialog.busy", "请先完成或关闭已打开的对话框"),
|
||||
("show.slide.new", "新建幻灯片"),
|
||||
("show.slide.duplicate", "复制幻灯片"),
|
||||
("show.slide.delete", "删除幻灯片"),
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
- [x] S-01 切换幻灯片后主画布不重画 — 已由 be31260(R2.4)修好并有单测,此处补勾
|
||||
- [x] S-02 `deck.rs` 超过 500 行 — 随 S-03 把 Extra 移到 extra.rs,deck.rs 463 行
|
||||
- [x] S-03 ElyShow 的缩放一两帧后弹回“适合幻灯片”,缩放功能不可用 — 只在标签首次观察时适合一次;R1 PASS
|
||||
- [ ] S-04 选屏对话框被别的对话框顶掉后,`show_starting` 卡住、放映副本泄漏
|
||||
- [x] S-04 选屏对话框被别的对话框顶掉后,`show_starting` 卡住、放映副本泄漏 — 有对话框开着时不再顶掉它,提示先完成;选屏对话框被拒即丢副本;R2 PASS
|
||||
- [ ] S-05 一条批注的时间恰为午夜或只有日期,整个批注栏不显示
|
||||
- [ ] S-06 导出或打印的“从–到”填 0 时导出全部幻灯片
|
||||
- [ ] S-07 母版视图下演示检查的行按幻灯片序号跳转
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
FAIL
|
||||
|
||||
apps/ely-show/src/chart.rs:189 — `open_chart` 的异步回调仍直接覆盖 `deck.dialog`;其守卫只核对标签与选中图表,绕过了新增的 `open_dialog`。单屏隔离探针先调用 `ask_table`,再调用 `ask_chart` 并推进调度,原表格对话框被图表对话框替换,保留原对话框的断言失败(`/tmp/ely-s04-chart-probe.log`)。两屏下,选屏对话框打开后执行“插入图表”会走同一覆盖路径,丢弃 `Starting`,保留 `show_starting = true`,且跳过 `discard`,因此 S-04 的放映卡住与副本泄漏路径仍存在。修复方向:让图表回调中的首次打开经过 `open_dialog`,保留当前对话框并显示忙碌提示;补充图表入口的覆盖回归测试。临时副本仅把这处首次打开改为 `open_dialog` 后,同一探针通过(`/tmp/ely-s04-chart-control.log`)。独立验证:LOK worker 与 ElyShow 构建成功,ElyShow 80 项测试、ely-ui 34 项测试及注释检查通过;移除拒绝逻辑后,现有 `an_open_dialog_is_not_pushed_aside` 测试失败。原生双屏选屏流程受单屏环境限制;隔离源码副本、独立构建目录与增量缓存均已清理。
|
||||
@@ -0,0 +1 @@
|
||||
PASS
|
||||
Reference in new issue
Block a user