chiark / gitweb /
Make FeedFile generic across type of item.
authorSimon Tatham <anakin@pobox.com>
Sun, 31 Dec 2023 08:59:03 +0000 (08:59 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 31 Dec 2023 09:54:20 +0000 (09:54 +0000)
Now it can hold some other kind of TextFragment, instead of always
being StatusDisplay.

src/file.rs

index 667550545150a76d17fbcc4538189ca6398bdf9d..cae8abf60745ffac0106e3da6375c74416ddc1d0 100644 (file)
@@ -15,15 +15,34 @@ enum FilePosition {
     Fine(isize, usize),  // line #n of this item is just off bottom of screen
 }
 
-struct FeedFileContents {
+trait FeedType {
+    type Item: TextFragment + Sized;
+
+    fn get_from_client(id: &str, client: &mut Client) ->
+        Result<Self::Item, ClientError>;
+}
+
+struct StatusFeedType {}
+impl FeedType for StatusFeedType {
+    type Item = StatusDisplay;
+
+    fn get_from_client(id: &str, client: &mut Client) ->
+        Result<Self::Item, ClientError>
+    {
+        let st = client.status_by_id(&id)?;
+        Ok(StatusDisplay::new(st.clone(), client))
+    }
+}
+
+struct FeedFileContents<Type: FeedType> {
     id: FeedId,
     header: FileHeader,
     extender: Option<ExtendableIndicator>,
     origin: isize,
-    items: Vec<Box<dyn TextFragment>>,
+    items: Vec<Type::Item>,
 }
 
-impl FeedFileContents {
+impl<Type: FeedType> FeedFileContents<Type> {
     fn update_items(&mut self, client: &mut Client) {
         // FIXME: if the feed has been extended rather than created,
         // we should be able to make less effort than this
@@ -34,10 +53,9 @@ impl FeedFileContents {
 
         self.items.clear();
         for id in ids {
-            let st = client.status_by_id(&id)
-                .expect("Any id stored in a Feed should also be cached")
-                .clone();
-            self.items.push(Box::new(StatusDisplay::new(st, client)));
+            let item = Type::get_from_client(&id, client)
+                .expect("Any id stored in a Feed should also be cached");
+            self.items.push(item);
         }
     }
 
@@ -69,19 +87,19 @@ impl FeedFileContents {
             }
         } else {
             let index = self.phys_index(index);
-            &*self.items[index]
+            &self.items[index]
         }
     }
 }
 
-struct FeedFile {
-    contents: FeedFileContents,
+struct FeedFile<Type: FeedType> {
+    contents: FeedFileContents<Type>,
     rendered: HashMap<isize, Vec<ColouredString>>,
     pos: FilePosition,
     last_size: Option<(usize, usize)>,
 }
 
-impl FeedFile {
+impl<Type: FeedType> FeedFile<Type> {
     fn new(client: &mut Client, id: FeedId, desc: ColouredString) ->
         Result<Self, ClientError>
     {
@@ -278,7 +296,7 @@ impl FeedFile {
     }
 }
 
-impl ActivityState for FeedFile {
+impl<Type: FeedType> ActivityState for FeedFile<Type> {
     fn resize(&mut self, w: usize, h: usize) {
         if self.last_size != Some((w, h)) {
             self.last_size = Some((w, h));
@@ -428,26 +446,29 @@ impl ActivityState for FeedFile {
 pub fn home_timeline(client: &mut Client) ->
     Result<Box<dyn ActivityState>, ClientError>
 {
-    let file = FeedFile::new(client, FeedId::Home, ColouredString::general(
-        "Home timeline   <H>",
-        "HHHHHHHHHHHHHHHHHKH"))?;
+    let file = FeedFile::<StatusFeedType>::new(
+        client, FeedId::Home, ColouredString::general(
+            "Home timeline   <H>",
+            "HHHHHHHHHHHHHHHHHKH"))?;
     Ok(Box::new(file))
 }
 
 pub fn local_timeline(client: &mut Client) ->
     Result<Box<dyn ActivityState>, ClientError>
 {
-    let file = FeedFile::new(client, FeedId::Local, ColouredString::general(
-        "Local public timeline   <L>",
-        "HHHHHHHHHHHHHHHHHHHHHHHHHKH"))?;
+    let file = FeedFile::<StatusFeedType>::new(
+        client, FeedId::Local, ColouredString::general(
+            "Local public timeline   <L>",
+            "HHHHHHHHHHHHHHHHHHHHHHHHHKH"))?;
     Ok(Box::new(file))
 }
 
 pub fn public_timeline(client: &mut Client) ->
     Result<Box<dyn ActivityState>, ClientError>
 {
-    let file = FeedFile::new(client, FeedId::Public, ColouredString::general(
-        "Public timeline   <P>",
-        "HHHHHHHHHHHHHHHHHHHKH"))?;
+    let file = FeedFile::<StatusFeedType>::new(
+        client, FeedId::Public, ColouredString::general(
+            "Public timeline   <P>",
+            "HHHHHHHHHHHHHHHHHHHKH"))?;
     Ok(Box::new(file))
 }