From: Simon Tatham Date: Sat, 6 Jan 2024 13:57:23 +0000 (+0000) Subject: When thrown into Read Mentions, show the new mention. X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=3e0a8610981e6680058672a3e7bc37a85db7962c;p=mastodonochrome.git When thrown into Read Mentions, show the new mention. This adds an 'is_interrupt' flag to every change of activity; the only activity constructor that uses it is mentions(), which uses it to vary the policy about file positioning. When you enter Read Mentions on your own initiative, you get the same position you were at before, but when _thrown_ into it, you go to the new message. In order to still show the new message when you're _already_ in your mentions, we remove ReadMentions from the list of activities that don't cause a reload of ReadMentions. --- diff --git a/TODO.md b/TODO.md index df7f094..6e9c965 100644 --- a/TODO.md +++ b/TODO.md @@ -32,16 +32,11 @@ Each of those should instead catch the error, make an Error Log record, and transfer you to the error-log viewer with a beep, just the way Mono did it. -## Tracking what you've read +## LDB checkpointing -When you restart Mastodonochrome and open a feed, it ought to put in -view the first thing you haven't yet read in that feed. This means -tracking what _is_ read during run time, and saving it to a file in -the config directory. - -Similarly, when the client automatically moves you into the Read -Mentions field because a new mention has arrived, it should -automatically jump the position to the first unread one. +It would be nice to checkpoint the LDB to disk every few minutes, if +it's changed, as a precaution against data loss if the client crashes +after sitting in the same `File` for a long time. ## Reading @@ -111,6 +106,18 @@ and also showing a red error marker for 'no alt text here yet'. You should be able to post polls, again via some kind of internal editor markup that inserts magic delimiter characters. +### Mentions arriving while you're editing + +If you got a beep for an incoming mention while you were writing a +post of your own, then in real Mono, finishing up your post causes you +to be belatedly thrown into your mentions. Perhaps we should replicate +that. + +### Saving a draft + +If you ESC out of the editor, your draft should be saved to come back +to. + ## Editor improvements ### Block cut and paste diff --git a/src/activity_stack.rs b/src/activity_stack.rs index 42a0135..ad9b3c9 100644 --- a/src/activity_stack.rs +++ b/src/activity_stack.rs @@ -67,10 +67,13 @@ pub struct ActivityStack { impl Activity { pub fn throw_into_mentions(&self) -> bool { - // ReadMentions itself doesn't count. This will have to return - // false for post-editing activities. + // When you're editing a post, you don't get thrown into your + // mentions. From anywhere else, you do. + // + // This even counts the ReadMentions activity _itself_ - it + // gets reinitialised, because that's the simplest way to jump + // you down to the new message. match self { - Activity::Util(UtilityActivity::ReadMentions) | Activity::NonUtil(NonUtilityActivity::ComposeToplevel) | Activity::NonUtil(NonUtilityActivity::PostComposeMenu) | Activity::Util(UtilityActivity::ComposeReply(..)) | diff --git a/src/file.rs b/src/file.rs index 8110e0f..f0458c3 100644 --- a/src/file.rs +++ b/src/file.rs @@ -365,14 +365,17 @@ impl File { FilePosition::item_top(latest_read_index + 1) } else { FilePosition::item_bottom(latest_read_index) - } + }; } } // But if we have an actual FilePosition in our SavedFilePos, - // it's even better to use that. - if let Some(file_pos) = saved_pos.and_then(|sp| sp.file_pos) { - initial_pos = file_pos; + // it's even better to use that ... unless we're supposed to + // be showing a new thing eagerly. + if !show_new { + if let Some(file_pos) = saved_pos.and_then(|sp| sp.file_pos) { + initial_pos = file_pos; + } } // Now clip initial_pos at the top and bottom of the data we have @@ -1377,7 +1380,7 @@ pub fn public_timeline(file_positions: &HashMap, } pub fn mentions(file_positions: &HashMap, - client: &mut Client) -> + client: &mut Client, is_interrupt: bool) -> Result, ClientError> { let feed = FeedId::Mentions; @@ -1386,7 +1389,7 @@ pub fn mentions(file_positions: &HashMap, let file = File::new( client, FeedSource::new(feed), ColouredString::general( "Mentions [ESC][R]", - "HHHHHHHHHHHHKKKHHKH"), desc, pos, false)?; + "HHHHHHHHHHHHKKKHHKH"), desc, pos, is_interrupt)?; Ok(Box::new(file)) } diff --git a/src/tui.rs b/src/tui.rs index 8662785..296bd9a 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -580,12 +580,12 @@ impl TuiLogicalState { LogicalAction::Nothing => break PhysicalAction::Nothing, LogicalAction::Goto(activity) => { self.activity_stack.goto(activity); - self.changed_activity(client, None); + self.changed_activity(client, None, false); break PhysicalAction::Nothing } LogicalAction::Pop => { self.activity_stack.pop(); - self.changed_activity(client, None); + self.changed_activity(client, None, false); break PhysicalAction::Nothing } LogicalAction::PopOverlaySilent => { @@ -612,7 +612,7 @@ impl TuiLogicalState { act => panic!("can't postcompose {act:?}"), }; self.activity_stack.chain_to(newact); - self.changed_activity(client, Some(post)); + self.changed_activity(client, Some(post), false); break PhysicalAction::Nothing } LogicalAction::PostReEdit(post) => { @@ -624,7 +624,7 @@ impl TuiLogicalState { act => panic!("can't reedit {act:?}"), }; self.activity_stack.chain_to(newact); - self.changed_activity(client, Some(post)); + self.changed_activity(client, Some(post), false); break PhysicalAction::Nothing } }; @@ -638,7 +638,7 @@ impl TuiLogicalState { if feeds_updated.contains(&FeedId::Mentions) { if self.activity_stack.top().throw_into_mentions() { self.activity_stack.goto(UtilityActivity::ReadMentions.into()); - self.changed_activity(client, None); + self.changed_activity(client, None, true); } // FIXME: we'd quite like a double-beep if you're in the composer @@ -648,7 +648,8 @@ impl TuiLogicalState { } } - fn changed_activity(&mut self, client: &mut Client, post: Option) { + fn changed_activity(&mut self, client: &mut Client, post: Option, + is_interrupt: bool) { if let Some((feed_id, saved_pos)) = self.activity_state.save_file_position() { @@ -661,10 +662,10 @@ impl TuiLogicalState { } } self.activity_state = self.new_activity_state( - self.activity_stack.top(), client, post); + self.activity_stack.top(), client, post, is_interrupt); self.overlay_activity_state = match self.activity_stack.overlay() { Some(activity) => - Some(self.new_activity_state(activity, client, None)), + Some(self.new_activity_state(activity, client, None, false)), None => None, }; if let Some(area) = self.last_area { @@ -682,7 +683,8 @@ impl TuiLogicalState { } fn new_activity_state(&self, activity: Activity, client: &mut Client, - post: Option) -> Box + post: Option, is_interrupt: bool) + -> Box { let result = match activity { Activity::NonUtil(NonUtilityActivity::MainMenu) => @@ -704,7 +706,7 @@ impl TuiLogicalState { Activity::NonUtil(NonUtilityActivity::HashtagTimeline(ref id)) => hashtag_timeline(client, id), Activity::Util(UtilityActivity::ReadMentions) => - mentions(&self.file_positions, client), + mentions(&self.file_positions, client, is_interrupt), Activity::Util(UtilityActivity::EgoLog) => ego_log(&self.file_positions, client), Activity::Overlay(OverlayActivity::GetUserToExamine) =>