chiark / gitweb /
Ability to display sensitive toots folded up.
authorSimon Tatham <anakin@pobox.com>
Wed, 10 Jan 2024 08:37:34 +0000 (08:37 +0000)
committerSimon Tatham <anakin@pobox.com>
Thu, 11 Jan 2024 08:14:03 +0000 (08:14 +0000)
Not currently used: all our current DisplayStyleGetters
unconditionally return true from their unfolded method.

This has to apply to the quoted line of a toot in Re: lines, as well
as the full display of the post contents.

src/file.rs
src/text.rs

index 1ddf913dede410302ce8ecc20de57aa261604ed3..5b0e5e1f5840a858e91b0ad8d7093336d7b0dece 100644 (file)
@@ -327,6 +327,8 @@ impl DisplayStyleGetter for FileDisplayStyles {
             }
         )
     }
+
+    fn unfolded(&self, _id: &str) -> bool { true }
 }
 
 struct File<Type: FileType, Source: FileDataSource> {
index 4fd9dad02fa6579ab3bffa3c376523d98f2bb5f9..845914d774ff515c4784485f436d6d013306d8f7 100644 (file)
@@ -44,10 +44,12 @@ impl ConsumableHighlight for Option<Highlight> {
 // providing information to modify how things are displayed
 pub trait DisplayStyleGetter {
     fn poll_options(&self, id: &str) -> Option<HashSet<usize>>;
+    fn unfolded(&self, id: &str) -> bool;
 }
 struct DefaultDisplayStyle;
 impl DisplayStyleGetter for DefaultDisplayStyle {
     fn poll_options(&self, _id: &str) -> Option<HashSet<usize>> { None }
+    fn unfolded(&self, _id: &str) -> bool { true }
 }
 
 pub trait TextFragment {
@@ -935,34 +937,69 @@ fn test_extendable() {
 
 pub struct InReplyToLine {
     para: Paragraph,
+    warning: Option<Paragraph>,
+    id: String,
 }
 
 impl InReplyToLine {
-    pub fn new(post: Paragraph) -> Self {
+    pub fn new(post: Paragraph, warning: Option<String>, id: &str) -> Self {
         let mut para = Paragraph::new().add(ColouredString::plain("Re: "));
         let currlen = para.words.len();
         para.push_para(&post);
         para.delete_mention_words_from(currlen);
-        InReplyToLine { para }
+
+        let warning = warning.map(|text| {
+            let mut para = Paragraph::new()
+                .add(ColouredString::plain("Re: "))
+                .add(ColouredString::uniform("[-]", 'r'));
+            para.end_word();
+            para.add(ColouredString::plain(&text))
+        });
+
+        InReplyToLine {
+            para,
+            warning,
+            id: id.to_owned(),
+        }
     }
 
     pub fn from_id(id: &str, client: &mut Client) -> Self {
-        let parent_text = match client.status_by_id(id) {
+        let st = client.status_by_id(id);
+        let parent_text = match &st {
             Ok(st) => Html::new(&st.content).to_para(),
             Err(e) => Paragraph::new().add(ColouredString::plain(
                 &format!("[unavailable: {}]", e)
             )),
         };
-        Self::new(parent_text)
+
+        let warning = match &st {
+            Ok(st) => if st.sensitive {
+                Some(st.spoiler_text.clone())
+            } else {
+                None
+            }
+            Err(..) => None
+        };
+
+        Self::new(parent_text, warning, id)
     }
 }
 
 impl TextFragment for InReplyToLine {
     fn render_highlighted(&self, width: usize, _highlight: Option<Highlight>,
-                          _style: &dyn DisplayStyleGetter)
+                          style: &dyn DisplayStyleGetter)
                           -> Vec<ColouredString>
     {
-        let rendered_para = self.para.render(width - min(width, 3));
+        let which_para = match self.warning.as_ref() {
+            Some(folded) => if !style.unfolded(&self.id) {
+                folded
+            } else {
+                &self.para
+            }
+            None => &self.para,
+        };
+
+        let rendered_para = which_para.render(width - min(width, 3));
         let mut it = rendered_para.iter();
         // "Re:" guarantees the first line must exist at least
         let first_line = it.next().unwrap();
@@ -1755,7 +1792,7 @@ pub struct StatusDisplay {
     via: Option<UsernameHeader>,
     irt: Option<InReplyToLine>,
     vis: Option<VisibilityLine>,
-    warning: Option<Paragraph>,
+    warning: Option<String>,
     content: Html,
     media: Vec<Media>,
     poll: Option<Poll>,
@@ -1795,11 +1832,7 @@ impl StatusDisplay {
         };
 
         let warning = if st.sensitive {
-            let mut para = Paragraph::new();
-            para = para.add(ColouredString::uniform("Content note:", 'r'));
-            para.end_word();
-            para = para.add(ColouredString::plain(&st.spoiler_text));
-            Some(para)
+            Some(st.spoiler_text.clone())
         } else {
             None
         };
@@ -1915,17 +1948,36 @@ impl TextFragment for StatusDisplay {
         push_fragment(&mut lines, self.vis.render(width));
         push_fragment(&mut lines, self.irt.render(width));
         push_fragment(&mut lines, self.blank.render(width));
-        push_fragment_opt_highlight(&mut lines, self.warning.render(width));
-        let rendered_content = self.content.render(width);
-        let content_empty = rendered_content.is_empty();
-        push_fragment_opt_highlight(&mut lines, rendered_content);
-        if !content_empty {
-            push_fragment(&mut lines, self.blank.render(width));
+
+        let folded = self.warning.is_some() && !style.unfolded(&self.id);
+        if let Some(warning_text) = &self.warning {
+            let mut para = Paragraph::new();
+            para = para.add(&ColouredString::uniform(
+                if folded {"[-]"} else {"[+]"}, 'r'));
+            para.end_word();
+            para = para.add(&ColouredString::plain(&warning_text));
+            push_fragment_opt_highlight(&mut lines, para.render(width));
         }
-        for m in &self.media {
-            push_fragment_opt_highlight(&mut lines, m.render(width));
-            push_fragment_opt_highlight(&mut lines, self.blank.render(width));
+
+        if folded {
+            push_fragment(&mut lines, self.blank.render(width));
+        } else {
+            let rendered_content = self.content.render(width);
+            let content_empty = rendered_content.is_empty();
+            push_fragment_opt_highlight(&mut lines, rendered_content);
+            if !content_empty {
+                push_fragment(&mut lines, self.blank.render(width));
+            }
+            for m in &self.media {
+                push_fragment_opt_highlight(&mut lines, m.render(width));
+                push_fragment_opt_highlight(
+                    &mut lines, self.blank.render(width));
+            }
         }
+
+        // Even if we're folded, display the fact of there being a
+        // poll, because otherwise it's just too painful to try to
+        // conditionalise selecting the poll options.
         if let Some(poll) = &self.poll {
             push_fragment_opt_highlight(&mut lines, poll.title.render(width));
             let poll_options_selected = style.poll_options(&poll.id);
@@ -1936,8 +1988,8 @@ impl TextFragment for StatusDisplay {
                     *voted, |opts| opts.contains(&i));
                 let option = Paragraph::new().set_indent(0, 2).add(
                     &ColouredString::uniform(
-                        if voted {"[X]"} else {"[ ]"}, 'H'))
-                    .add(desc);
+                        if voted {"[X]"} else {"[ ]"}, 'H'));
+                let option = if folded { option } else { option.add(desc) };
                 let push_fragment_opt_highlight = if highlighting_this_option {
                     push_fragment_highlighted
                 } else {