ElyShow: an unreadable comment time no longer empties the comments column (S-05)
This commit is contained in:
5 files changed
+55
-15
No files matched your search
@@ -19,20 +19,21 @@ use gpui::{
|
||||
use crate::deck::Deck;
|
||||
use crate::dialog::Dialog;
|
||||
|
||||
/// Each comment as a thread quoted with its slide.
|
||||
fn threads(remarks: &[Remark], cx: &App) -> Result<Vec<Thread>, String> {
|
||||
/// Threads quoted with their slides; unreadable comments apart.
|
||||
fn threads(remarks: &[Remark], cx: &App) -> (Vec<Thread>, Vec<(String, String)>) {
|
||||
let authors: Vec<&str> = remarks
|
||||
.iter()
|
||||
.map(|remark| remark.author.as_str())
|
||||
.collect();
|
||||
remarks
|
||||
let (good, bad): (Vec<_>, Vec<_>) = remarks
|
||||
.iter()
|
||||
.map(|remark| {
|
||||
let at = remark
|
||||
.at
|
||||
.parse::<jiff::civil::DateTime>()
|
||||
.and_then(|at| at.to_zoned(jiff::tz::TimeZone::system()))
|
||||
.map_err(|error| format!("a bad comment time {}: {error}", remark.at))?;
|
||||
.map_err(|error| (remark.at.clone(), error.to_string()))?
|
||||
.timestamp();
|
||||
let hue = authors
|
||||
.iter()
|
||||
.position(|name| *name == remark.author)
|
||||
@@ -43,14 +44,16 @@ fn threads(remarks: &[Remark], cx: &App) -> Result<Vec<Thread>, String> {
|
||||
quote: Some(Deck::text(cx, "show.remark.slide", &[("n", &slide)])),
|
||||
comments: vec![Comment {
|
||||
author: Peer::new(remark.author.clone(), remark.author.clone(), hue),
|
||||
at: at.timestamp(),
|
||||
at,
|
||||
body: remark.text.clone().into(),
|
||||
reactions: Vec::new(),
|
||||
}],
|
||||
resolved: false,
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
.partition(Result::is_ok);
|
||||
let bad = bad.into_iter().filter_map(Result::err).collect();
|
||||
(good.into_iter().filter_map(Result::ok).collect(), bad)
|
||||
}
|
||||
|
||||
impl Deck {
|
||||
@@ -166,14 +169,15 @@ impl Deck {
|
||||
.active_tab()
|
||||
.map(|tab| tab.extra.remarks.clone())
|
||||
.unwrap_or_default();
|
||||
let threads = match threads(&remarks, cx) {
|
||||
Ok(threads) => threads,
|
||||
Err(error) => {
|
||||
log::error!("show: {error}");
|
||||
let message = InlineMessage::new(Severity::Danger, error);
|
||||
return div().p_2().child(message).into_any_element();
|
||||
}
|
||||
};
|
||||
let (threads, bad) = threads(&remarks, cx);
|
||||
for (at, error) in &bad {
|
||||
log::error!("show: a bad comment time {at}: {error}");
|
||||
}
|
||||
// One line however many: the comments below stay in view.
|
||||
let bad = bad.first().map(|(at, _)| {
|
||||
let n = bad.len().to_string();
|
||||
InlineMessage::new(Severity::Danger, Deck::text(cx, "show.remark.bad", &[("n", &n), ("at", at)]))
|
||||
});
|
||||
let active = self.shown_remark();
|
||||
let act = |id: &'static str,
|
||||
key: &str,
|
||||
@@ -227,6 +231,7 @@ impl Deck {
|
||||
.gap_2()
|
||||
.p_2()
|
||||
.child(head)
|
||||
.children(bad)
|
||||
.child(div().flex_1().min_h_0().child(sidebar))
|
||||
.into_any_element()
|
||||
}
|
||||
@@ -289,3 +294,32 @@ impl Deck {
|
||||
(!pins.is_empty()).then(|| div().absolute().inset_0().children(pins).into_any_element())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ely_lok::show::Remark;
|
||||
use gpui::TestAppContext;
|
||||
|
||||
use super::threads;
|
||||
|
||||
#[test]
|
||||
fn one_unreadable_time_spares_the_other_comments() {
|
||||
let cx = TestAppContext::single();
|
||||
cx.update(|cx| ely_ui::i18n::install_as("en-US", cx));
|
||||
let remark = |id: &str, at: &str| Remark {
|
||||
id: id.into(),
|
||||
author: "A".into(),
|
||||
text: "t".into(),
|
||||
at: at.into(),
|
||||
part: 0,
|
||||
anchor: (0, 0, 0, 0),
|
||||
};
|
||||
// The kernel writes an empty date as 0-00-00.
|
||||
let remarks = [remark("1", "2025-03-01"), remark("2", "0-00-00"), remark("3", "2025-03-01T10:15:00")];
|
||||
let (good, bad) = cx.update(|cx| threads(&remarks, cx));
|
||||
let keys: Vec<_> = good.iter().map(|thread| thread.key.to_string()).collect();
|
||||
assert_eq!(keys, ["1", "3"]);
|
||||
assert_eq!(bad.len(), 1);
|
||||
assert_eq!(bad[0].0, "0-00-00");
|
||||
}
|
||||
}
|
||||
@@ -174,6 +174,7 @@ pub(super) const EN: &[(&str, &str)] = &[
|
||||
"These notes are formatted; Ely shows them read-only to keep it.",
|
||||
),
|
||||
("show.remark.slide", "Slide {n}"),
|
||||
("show.remark.bad", "Comments with unreadable times: {n}, first {at}"),
|
||||
("show.remark.text", "Comment"),
|
||||
("show.remark.new_title", "New Comment"),
|
||||
("show.remark.edit_title", "Edit Comment"),
|
||||
@@ -353,6 +354,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
|
||||
("show.notes.none", "这张幻灯片没有备注框。"),
|
||||
("show.notes.rich", "备注带格式,为保留格式在此只读。"),
|
||||
("show.remark.slide", "第 {n} 张幻灯片"),
|
||||
("show.remark.bad", "时间读不出的批注:{n} 条,第一条为 {at}"),
|
||||
("show.remark.text", "批注"),
|
||||
("show.remark.new_title", "新建批注"),
|
||||
("show.remark.edit_title", "编辑批注"),
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
- [x] S-02 `deck.rs` 超过 500 行 — 随 S-03 把 Extra 移到 extra.rs,deck.rs 463 行
|
||||
- [x] S-03 ElyShow 的缩放一两帧后弹回“适合幻灯片”,缩放功能不可用 — 只在标签首次观察时适合一次;R1 PASS
|
||||
- [x] S-04 选屏对话框被别的对话框顶掉后,`show_starting` 卡住、放映副本泄漏 — 有对话框开着时不再顶掉它,提示先完成;选屏对话框被拒即丢副本;R2 PASS
|
||||
- [ ] S-05 一条批注的时间恰为午夜或只有日期,整个批注栏不显示
|
||||
- [x] S-05 一条批注的时间恰为午夜或只有日期,整个批注栏不显示 — 读不出时间的批注只占一行汇总,其余照常显示(jiff 本可读只有日期的时间);R2 PASS
|
||||
- [ ] S-06 导出或打印的“从–到”填 0 时导出全部幻灯片
|
||||
- [ ] S-07 母版视图下演示检查的行按幻灯片序号跳转
|
||||
- [ ] S-08 刚编辑过幻灯片就进备注栏键入,备注可能丢
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
FAIL
|
||||
|
||||
apps/ely-show/src/remarks.rs:229 — Unscrollable error rows can still hide every readable comment (SHOW-08). The danger messages occupy the outer column above the sidebar, while scrolling belongs exclusively to the sidebar below them. Reproduction: render the actual remarks pane at 280×600 with one comment dated `2025-03-01` and twelve comments dated `0-00-00`. Native macOS rendering shows only errors; the readable comment and later errors lie below the viewport. Three downward scroll gestures at different heights leave the screenshot pixel-identical, preventing selection, editing and navigation to the readable comment. A layout probe also fails with eight bad dates, placing the readable row at y=740 in a 600-high pane. The supplied unit test passes because it checks only `threads()`. Put the errors into a scrollable layout that preserves access to readable comments, and cover multiple invalid timestamps with a rendered-pane scrolling regression test. Evidence: `/tmp/ely-s05-r1-layout.log` and `/tmp/ely-s05-r1-native.log`.
|
||||
@@ -0,0 +1 @@
|
||||
PASS
|
||||
Reference in new issue
Block a user