From: Simon Tatham Date: Mon, 1 Jan 2024 09:47:08 +0000 (+0000) Subject: Abstract out FeedDataSource. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=cb227922ac581cde643caa4259c0a8b1f5a06193;p=mastodonochrome.git Abstract out FeedDataSource. Now a FileContents doesn't _have_ to contain a FeedId; I can replace it with an alternative trait implementation containing a fixed set of things. --- diff --git a/src/file.rs b/src/file.rs index f1541a3..a93aa9f 100644 --- a/src/file.rs +++ b/src/file.rs @@ -24,6 +24,45 @@ impl FilePosition { } } +trait FileDataSource { + fn get(&self, client: &mut Client) -> (Vec, isize); + fn init(&self, client: &mut Client) -> Result<(), ClientError>; + fn try_extend(&self, client: &mut Client) -> Result; + fn updated(&self, feeds_updated: &HashSet) -> bool; + fn extendable(&self) -> bool; +} + +struct FeedSource { + id: FeedId, +} + +impl FeedSource { + fn new(id: FeedId) -> Self { FeedSource { id } } +} + +impl FileDataSource for FeedSource { + fn get(&self, client: &mut Client) -> (Vec, isize) { + let feed = client.borrow_feed(&self.id); + let ids = feed.ids.iter().map(|x| x.clone()).collect(); + (ids, feed.origin) + } + + fn init(&self, client: &mut Client) -> Result<(), ClientError> { + client.fetch_feed(&self.id, FeedExtend::Initial)?; + Ok(()) + } + + fn try_extend(&self, client: &mut Client) -> Result { + client.fetch_feed(&self.id, FeedExtend::Past) + } + + fn updated(&self, feeds_updated: &HashSet) -> bool { + feeds_updated.contains(&self.id) + } + + fn extendable(&self) -> bool { true } +} + trait FileType { type Item: TextFragment + Sized; @@ -69,22 +108,21 @@ impl FileType for EgoNotificationFeedType { } } -struct FileContents { - id: FeedId, +struct FileContents { + source: Source, header: FileHeader, extender: Option, origin: isize, items: Vec, } -impl FileContents { +impl FileContents { 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 - let feed = client.borrow_feed(&self.id); - let ids: Vec<_> = feed.ids.iter().map(|x| x.clone()).collect(); - self.origin = feed.origin; + let (ids, origin) = self.source.get(client); + self.origin = origin; self.items.clear(); for id in ids { @@ -127,23 +165,29 @@ impl FileContents { } } -struct File { - contents: FileContents, +struct File { + contents: FileContents, rendered: HashMap>, pos: FilePosition, last_size: Option<(usize, usize)>, } -impl File { - fn new(client: &mut Client, id: FeedId, desc: ColouredString) -> +impl File { + fn new(client: &mut Client, source: Source, desc: ColouredString) -> Result { - client.fetch_feed(&id, FeedExtend::Initial)?; + source.init(client)?; + + let extender = if source.extendable() { + Some(ExtendableIndicator::new()) + } else { + None + }; let mut contents = FileContents { - id: id, + source: source, header: FileHeader::new(desc), - extender: Some(ExtendableIndicator::new()), + extender, origin: 0, items: Vec::new(), }; @@ -350,7 +394,9 @@ impl File { } } -impl ActivityState for File { +impl + ActivityState for File +{ fn resize(&mut self, w: usize, h: usize) { if self.last_size != Some((w, h)) { self.last_size = Some((w, h)); @@ -456,8 +502,7 @@ impl ActivityState for File { }, Pr('0') | Home => { if self.at_top() && self.contents.extender.is_some() { - let action = match client.fetch_feed(&self.contents.id, - FeedExtend::Past) { + let action = match self.contents.source.try_extend(client) { Ok(any_new) => { self.rendered.remove(&self.contents.first_index()); if let Some(i) = self.contents.extender_index() { @@ -501,7 +546,7 @@ impl ActivityState for File { fn handle_feed_updates(&mut self, feeds_updated: &HashSet, client: &mut Client) { - if feeds_updated.contains(&self.contents.id) { + if self.contents.source.updated(feeds_updated) { self.contents.update_items(client); self.ensure_enough_rendered(); } @@ -511,8 +556,8 @@ impl ActivityState for File { pub fn home_timeline(client: &mut Client) -> Result, ClientError> { - let file = File::::new( - client, FeedId::Home, ColouredString::general( + let file = File::::new( + client, FeedSource::new(FeedId::Home), ColouredString::general( "Home timeline ", "HHHHHHHHHHHHHHHHHKH"))?; Ok(Box::new(file)) @@ -521,8 +566,8 @@ pub fn home_timeline(client: &mut Client) -> pub fn local_timeline(client: &mut Client) -> Result, ClientError> { - let file = File::::new( - client, FeedId::Local, ColouredString::general( + let file = File::::new( + client, FeedSource::new(FeedId::Local), ColouredString::general( "Local public timeline ", "HHHHHHHHHHHHHHHHHHHHHHHHHKH"))?; Ok(Box::new(file)) @@ -531,8 +576,8 @@ pub fn local_timeline(client: &mut Client) -> pub fn public_timeline(client: &mut Client) -> Result, ClientError> { - let file = File::::new( - client, FeedId::Public, ColouredString::general( + let file = File::::new( + client, FeedSource::new(FeedId::Public), ColouredString::general( "Public timeline

", "HHHHHHHHHHHHHHHHHHHKH"))?; Ok(Box::new(file)) @@ -541,8 +586,8 @@ pub fn public_timeline(client: &mut Client) -> pub fn mentions(client: &mut Client) -> Result, ClientError> { - let file = File::::new( - client, FeedId::Mentions, ColouredString::general( + let file = File::::new( + client, FeedSource::new(FeedId::Mentions), ColouredString::general( "Mentions [ESC][R]", "HHHHHHHHHHHHKKKHHKH"))?; Ok(Box::new(file)) @@ -551,8 +596,8 @@ pub fn mentions(client: &mut Client) -> pub fn ego_log(client: &mut Client) -> Result, ClientError> { - let file = File::::new( - client, FeedId::Ego, ColouredString::general( + let file = File::::new( + client, FeedSource::new(FeedId::Ego), ColouredString::general( "Ego Log [ESC][L][L][E]", "HHHHHHHHHHHKKKHHKHHKHHKH"))?; Ok(Box::new(file))