chiark / gitweb /
Nicer handling of 'not found' in bottom-line prompts.
authorSimon Tatham <anakin@pobox.com>
Sat, 27 Jan 2024 11:39:39 +0000 (11:39 +0000)
committerSimon Tatham <anakin@pobox.com>
Sat, 27 Jan 2024 11:40:11 +0000 (11:40 +0000)
This was another remaining error-handling todo, now tada.

TODO.md
src/activity_stack.rs
src/editor.rs
src/tui.rs

diff --git a/TODO.md b/TODO.md
index 1838cd41dbcde183d36cd743c2a2bfecddc32f57..2230e4547115aa6bf31f8fb2693fbd903c7b4fa8 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -32,13 +32,6 @@ Error Log entries could usefully include various extra detail:
   context, like 'I was trying to fetch this status because this other
   one was replying to it'.
 
-In the `get_user_to_examine` and `get_post_id_to_read` overlay
-activities, a simple 'not found' error shouldn't throw the user into
-the Error Log. That's overkill. We should instead toggle to an overlay
-activity showing a friendlier bottom-line error message, and abort the
-attempt. (Then the user can try again via line recall if it was just a
-typo – at least, once we implement line recall.)
-
 We don't have good handling for I/O errors while saving the user's
 LDB. That's not a _client_ error, but we could make an extra enum
 branch in `ClientError` anyway, so that the TuiLogicalState could put
index ea9dadc7fd2deec550e0866d8ba2b7cb39a882ff..01e5d4c1e7fd4846379032f10da0719db1ea9dd9 100644 (file)
@@ -46,6 +46,7 @@ pub enum OverlayActivity {
     GetPostIdToRead,
     GetHashtagToRead,
     GetSearchExpression(SearchDirection),
+    BottomLineError(String),
 }
 
 #[derive(PartialEq, Eq, Debug, Clone, Hash)]
index 7c2834cd2fcc055eb12c7b9bb0e2f78ab2949908..748f789874588fcb2b4b7857c42204571959edfc 100644 (file)
@@ -1,7 +1,9 @@
 use std::cmp::{max, min};
 use unicode_width::UnicodeWidthChar;
 
-use super::activity_stack::{NonUtilityActivity, UtilityActivity};
+use super::activity_stack::{
+    NonUtilityActivity, OverlayActivity, UtilityActivity,
+};
 use super::client::{Client, ClientError};
 use super::coloured_string::*;
 use super::file::SearchDirection;
@@ -739,6 +741,42 @@ impl ActivityState for BottomLineEditorOverlay {
     }
 }
 
+struct BottomLineErrorOverlay {
+    line: CentredInfoLine,
+}
+
+impl BottomLineErrorOverlay {
+    fn new(msg: &str) -> Self {
+        let msg = ColouredString::uniform("Error: ", 'r')
+            + ColouredString::plain(msg)
+            + ColouredString::general("  [RET]", "   kkk ");
+        BottomLineErrorOverlay {
+            line: CentredInfoLine::new(msg),
+        }
+    }
+}
+
+impl ActivityState for BottomLineErrorOverlay {
+    fn draw(
+        &self,
+        w: usize,
+        _h: usize,
+    ) -> (Vec<ColouredString>, CursorPosition) {
+        (self.line.render(w), CursorPosition::End)
+    }
+
+    fn handle_keypress(
+        &mut self,
+        key: OurKey,
+        _client: &mut Client,
+    ) -> LogicalAction {
+        match key {
+            Return => LogicalAction::PopOverlaySilent,
+            _ => LogicalAction::Nothing,
+        }
+    }
+}
+
 pub trait EditableMenuLineData {
     // If SECRET, then the implementor of this trait promises that
     // display() will show the text as ***** when it's not being
@@ -949,10 +987,17 @@ pub fn get_user_to_examine() -> Box<dyn ActivityState> {
                         UtilityActivity::ExamineUser(account.id).into(),
                     ),
 
-                    // FIXME: it would be nice to discriminate errors
-                    // better here, and do something a bit less
-                    // terrifying for plain "account not found", like
-                    // allowing the user to re-edit
+                    Err(ClientError::UrlFetchHTTPRich(
+                        _,
+                        reqwest::StatusCode::NOT_FOUND,
+                        _,
+                    )) => LogicalAction::Goto(
+                        OverlayActivity::BottomLineError(
+                            format!("User '{}' not found", s)
+                        )
+                        .into(),
+                    ),
+
                     Err(err) => LogicalAction::Error(err),
                 }
             }
@@ -973,10 +1018,17 @@ pub fn get_post_id_to_read() -> Box<dyn ActivityState> {
                         UtilityActivity::InfoStatus(st.id).into(),
                     ),
 
-                    // FIXME: it would be nice to discriminate errors
-                    // better here, and do something a bit less
-                    // terrifying for plain "status not found", like
-                    // allowing the user to re-edit
+                    Err(ClientError::UrlFetchHTTPRich(
+                        _,
+                        reqwest::StatusCode::NOT_FOUND,
+                        _,
+                    )) => LogicalAction::Goto(
+                        OverlayActivity::BottomLineError(
+                            format!("Post id {} not found", s)
+                        )
+                        .into(),
+                    ),
+
                     Err(err) => LogicalAction::Error(err),
                 }
             }
@@ -1014,6 +1066,10 @@ pub fn get_search_expression(dir: SearchDirection) -> Box<dyn ActivityState> {
     ))
 }
 
+pub fn bottom_line_error(msg: &str) -> Box<dyn ActivityState> {
+    Box::new(BottomLineErrorOverlay::new(msg))
+}
+
 #[derive(Debug, PartialEq, Eq, Clone)]
 struct ComposeBufferRegion {
     start: usize,
index e3003943a0eb8b1af8f48671bcd90562961d6df4..dfeab48f1f59951b496a2cc2159f758a0f8b8528 100644 (file)
@@ -1043,6 +1043,9 @@ impl TuiLogicalState {
             Activity::Overlay(OverlayActivity::GetSearchExpression(dir)) => {
                 Ok(get_search_expression(dir))
             }
+            Activity::Overlay(OverlayActivity::BottomLineError(msg)) => {
+                Ok(bottom_line_error(&msg))
+            }
             Activity::Util(UtilityActivity::ExamineUser(ref name)) => {
                 examine_user(client, name)
             }