feat(viewer): Markdown and plain-text documents are drawn as text
check / check (push) Canceled after 0s

A text/markdown file (or text/x-markdown) is drawn as formatted text by
egui_commonmark, with no image loading, so a document never makes the
viewer read a file or the network; any other text/* type as its
selectable text. UTF-8 only (a leading byte-order mark dropped), at most
2 MiB; past that or not UTF-8, the viewer says why. The documents page's
tile shows the text's first lines. The SHA-256 row is cut to its column
(it ran off the panel and widened the page under it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-23 09:05:32 -06:00
1 parent d64e0e9cdf
commit 7cc08a0039
6 files changed
+263 -7

No files matched your search

+13 -1
View File
@@ -157,6 +157,18 @@ fn tile(
.image(tex.id(), img_rect, uv, egui::Color32::WHITE);
}
}
Render::Text { text, .. } => {
// The first lines of the text, as written, clipped to the thumb.
let head: String = text.lines().take(14).collect::<Vec<_>>().join("\n");
let galley =
ui.painter()
.layout(head, theme::regular(10.5), p.muted, thumb.width() - 16.0);
ui.painter().with_clip_rect(thumb.shrink(4.0)).galley(
thumb.min + vec2(8.0, 8.0),
galley,
p.muted,
);
}
Render::Loading => {
ui.painter().text(
thumb.center(),
@@ -273,7 +285,7 @@ fn detail(ui: &mut Ui, b: &Books, a: &Attachment, shell: &mut Shell<'_>) {
ui.label(fmt::timestamp(&a.created_at));
ui.end_row();
k(ui, "SHA-256");
widgets::copyable(
widgets::copyable_truncated(
ui,
RichText::new(&a.blob_sha).monospace().size(11.5),
&a.blob_sha,
+24
View File
@@ -631,6 +631,30 @@ pub fn render(ui: &mut Ui, b: &Books, a: &Attachment, shell: &mut Shell<'_>, wid
.color(p.negative),
);
}
Render::Text { text, markdown } => {
let (text, markdown) = (text.clone(), *markdown);
egui::Frame::new()
.fill(p.surface)
.stroke(Stroke::new(1.0, p.border))
.corner_radius(CornerRadius::same(6))
.inner_margin(egui::Margin::same(14))
.show(ui, |ui| {
ui.set_width(width - 30.0);
if markdown {
egui_commonmark::CommonMarkViewer::new()
.max_image_width(Some((width - 30.0) as usize))
.show(ui, &mut shell.receipts.markdown, &text);
} else {
ui.add(
egui::Label::new(
RichText::new(text).font(egui::FontId::monospace(12.0)),
)
.selectable(true)
.wrap(),
);
}
});
}
Render::Ready(pages) => {
for (i, tex) in pages.iter().enumerate() {
let size = tex.size_vec2();