commit c4084a1fb5d03a97c220fd01097791492671a20f
parent e4658df8473dcf914ccfb65bffb27274ef3210d8
Author: William Casarin <jb55@jb55.com>
Date: Tue, 22 Apr 2025 10:48:11 -0700
ui: add note truncation
Truncate notes by default. We still need a show more button though
Diffstat:
4 files changed, 63 insertions(+), 19 deletions(-)
diff --git a/crates/notedeck_columns/src/timeline/route.rs b/crates/notedeck_columns/src/timeline/route.rs
@@ -75,18 +75,24 @@ pub fn render_timeline_route(
}
}
- TimelineKind::Thread(id) => ui::ThreadView::new(
- timeline_cache,
- unknown_ids,
- id.selected_or_root(),
- note_options,
- &accounts.mutefun(),
- note_context,
- &accounts.get_selected_account().map(|a| (&a.key).into()),
- )
- .id_source(egui::Id::new(("threadscroll", col)))
- .ui(ui)
- .map(Into::into),
+ TimelineKind::Thread(id) => {
+ // don't truncate thread notes for now, since they are
+ // default truncated everywher eelse
+ note_options.set_truncate(false);
+
+ ui::ThreadView::new(
+ timeline_cache,
+ unknown_ids,
+ id.selected_or_root(),
+ note_options,
+ &accounts.mutefun(),
+ note_context,
+ &accounts.get_selected_account().map(|a| (&a.key).into()),
+ )
+ .id_source(egui::Id::new(("threadscroll", col)))
+ .ui(ui)
+ .map(Into::into)
+ }
}
}
diff --git a/crates/notedeck_ui/src/note/contents.rs b/crates/notedeck_ui/src/note/contents.rs
@@ -119,6 +119,10 @@ pub fn render_note_contents(
let hide_media = options.has_hide_media();
let link_color = ui.visuals().hyperlink_color;
+ // The current length of the rendered blocks. Used in trucation logic
+ let mut current_len: usize = 0;
+ let truncate_len = 280;
+
if !options.has_is_preview() {
// need this for the rect to take the full width of the column
let _ = ui.allocate_at_least(egui::vec2(ui.available_width(), 0.0), egui::Sense::click());
@@ -210,18 +214,39 @@ pub fn render_note_contents(
}
BlockType::Text => {
- if options.has_scramble_text() {
- ui.add(
- egui::Label::new(rot13(block.as_str()))
- .wrap()
- .selectable(selectable),
+ // truncate logic
+ let mut truncate = false;
+ let block_str = if options.has_truncate()
+ && (current_len + block.as_str().len() > truncate_len)
+ {
+ truncate = true;
+ // The current block goes over the truncate length,
+ // we'll need to truncate this block
+ let block_str = block.as_str();
+ let closest = notedeck::abbrev::floor_char_boundary(
+ block_str,
+ truncate_len - current_len,
);
+ &(block_str[..closest].to_string() + "…")
} else {
+ let block_str = block.as_str();
+ current_len += block_str.len();
+ block_str
+ };
+
+ if options.has_scramble_text() {
ui.add(
- egui::Label::new(block.as_str())
+ egui::Label::new(rot13(block_str))
.wrap()
.selectable(selectable),
);
+ } else {
+ ui.add(egui::Label::new(block_str).wrap().selectable(selectable));
+ }
+
+ // don't render any more blocks
+ if truncate {
+ break;
}
}
diff --git a/crates/notedeck_ui/src/note/mod.rs b/crates/notedeck_ui/src/note/mod.rs
@@ -114,6 +114,11 @@ impl<'a, 'd> NoteView<'a, 'd> {
self
}
+ pub fn truncate(mut self, enable: bool) -> Self {
+ self.options_mut().set_truncate(enable);
+ self
+ }
+
pub fn small_pfp(mut self, enable: bool) -> Self {
self.options_mut().set_small_pfp(enable);
self
diff --git a/crates/notedeck_ui/src/note/options.rs b/crates/notedeck_ui/src/note/options.rs
@@ -21,12 +21,19 @@ bitflags! {
/// Whether the current note is a preview
const is_preview = 0b0000010000000000;
+
+ /// Is the content truncated? If the length is over a certain size it
+ /// will end with a ... and a "Show more" button.
+ const truncate = 0b0000100000000000;
}
}
impl Default for NoteOptions {
fn default() -> NoteOptions {
- NoteOptions::options_button | NoteOptions::note_previews | NoteOptions::actionbar
+ NoteOptions::options_button
+ | NoteOptions::note_previews
+ | NoteOptions::actionbar
+ | NoteOptions::truncate
}
}
@@ -60,6 +67,7 @@ impl NoteOptions {
create_bit_methods!(set_hide_media, has_hide_media, hide_media);
create_bit_methods!(set_scramble_text, has_scramble_text, scramble_text);
create_bit_methods!(set_is_preview, has_is_preview, is_preview);
+ create_bit_methods!(set_truncate, has_truncate, truncate);
pub fn new(is_universe_timeline: bool) -> Self {
let mut options = NoteOptions::default();