chiark / gitweb /
Use feed updates to lengthen the home timeline.
authorSimon Tatham <anakin@pobox.com>
Sun, 31 Dec 2023 07:31:19 +0000 (07:31 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 31 Dec 2023 07:31:19 +0000 (07:31 +0000)
Untested as yet, but this _should_ replicate the behaviour from the
Python version where you're reading your home timeline and a new post
quietly appears below what you can currently see.

src/client.rs
src/file.rs
src/tui.rs

index d0649a4020221cd0c2ac457940990fd2770a2ad0..f9c3c50229757819a053a7e05928869f9c18f8ad 100644 (file)
@@ -1,5 +1,5 @@
 use reqwest::Url;
-use std::collections::{HashMap, VecDeque};
+use std::collections::{HashMap, HashSet, VecDeque};
 use std::io::Read;
 
 use super::auth::{AuthConfig,AuthError};
@@ -414,6 +414,32 @@ impl Client {
         Ok(())
     }
 
-    pub fn process_stream_update(&mut self, _up: StreamUpdate) {
+    pub fn process_stream_update(&mut self, up: StreamUpdate) ->
+        Result<HashSet<FeedId>, ClientError>
+    {
+        let mut updates = HashSet::new();
+
+        match (up.id, up.response) {
+            (StreamId::User, StreamResponse::Line(_)) => {
+                self.fetch_feed(&FeedId::Home, FeedExtend::Future)?;
+                updates.insert(FeedId::Home);
+            },
+
+            // FIXME: we probably _should_ handle EOF from the
+            // subthread, though I'm not quite sure how yet. Stream
+            // connections seem to occasionally - as in, "on a
+            // minority of days" - spontaneously close from the server
+            // end, so just quietly restarting it is probably a good
+            // first step. But we wouldn't want to keep doing that in
+            // a way that became obnoxious, so at some point we have
+            // to switch to strategy #2, which is to notify the user
+            // of a problem and let them decide. So probably this
+            // function ends up returning a Result, and our owner
+            // responds to an error by putting it in the Error Log.
+
+            _ => (),
+        }
+
+        Ok(updates)
     }
 }
index 42bf948914b0bb6012a8b3183ce7e07414f526ca..667550545150a76d17fbcc4538189ca6398bdf9d 100644 (file)
@@ -1,5 +1,5 @@
 use std::cmp::{min, max};
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
 
 use super::client::{Client, ClientError, FeedId, FeedExtend};
 use super::coloured_string::ColouredString;
@@ -25,7 +25,8 @@ struct FeedFileContents {
 
 impl FeedFileContents {
     fn update_items(&mut self, client: &mut Client) {
-        // FIXME: deal with the feed having been extended
+        // FIXME: if the feed has been extended rather than created,
+        // we should be able to make less effort than this
 
         let feed = client.borrow_feed(&self.id);
         let ids: Vec<_> = feed.ids.iter().map(|x| x.clone()).collect();
@@ -414,6 +415,14 @@ impl ActivityState for FeedFile {
             _ => LogicalAction::Nothing,
         }
     }
+
+    fn handle_feed_updates(&mut self, feeds_updated: &HashSet<FeedId>,
+                           client: &mut Client) {
+        if feeds_updated.contains(&self.contents.id) {
+            self.contents.update_items(client);
+            self.ensure_enough_rendered();
+        }
+    }
 }
 
 pub fn home_timeline(client: &mut Client) ->
index cb550a1e4c7f9f356d1d3225f7e69d7710a8d327..331daecd4e76f6e3d93c3f672a26d692b82e737a 100644 (file)
@@ -10,11 +10,12 @@ use ratatui::{
     prelude::{Buffer, CrosstermBackend, Rect, Terminal},
     style::{Style, Color, Modifier},
 };
+use std::collections::HashSet;
 use std::io::{Stdout, Write, stdout};
 use unicode_width::UnicodeWidthStr;
 
 use super::activity_stack::*;
-use super::client::{Client, ClientError, StreamId, StreamUpdate};
+use super::client::{Client, ClientError, FeedId, StreamId, StreamUpdate};
 use super::coloured_string::{ColouredString, ColouredStringSlice};
 use super::menu::*;
 use super::file::*;
@@ -337,8 +338,14 @@ impl Tui {
                     }
                 },
                 Ok(SubthreadEvent::StreamEv(update)) => {
-                    self.client.process_stream_update(update);
-                    // FIXME: perhaps also notify state of a change
+                    match self.client.process_stream_update(update) {
+                        Ok(feeds_updated) =>
+                            state.handle_feed_updates(feeds_updated,
+                                                      &mut self.client),
+
+                        // FIXME: errors here should go in the Error Log
+                        _ => (),
+                    }
                 }
             }
         }
@@ -374,6 +381,8 @@ pub trait ActivityState {
         (Vec<ColouredString>, CursorPosition);
     fn handle_keypress(&mut self, key: OurKey, client: &mut Client) ->
         LogicalAction;
+    fn handle_feed_updates(&mut self, _feeds_updated: &HashSet<FeedId>,
+                           _client: &mut Client) {}
 }
 
 struct TuiLogicalState {
@@ -482,6 +491,15 @@ impl TuiLogicalState {
         }
     }
 
+    fn handle_feed_updates(&mut self, feeds_updated: HashSet<FeedId>,
+                           client: &mut Client) {
+        // FIXME: if the mentions feed is updated, we may need to
+        // actually change the activity stack to throw the user into
+        // Read Messages.
+
+        self.activity_state.handle_feed_updates(&feeds_updated, client);
+    }
+
     fn changed_activity(&mut self, client: &mut Client) {
         self.activity_state = new_activity_state(
             self.activity_stack.top(), client);