From: Simon Tatham Date: Sat, 27 Jan 2024 11:13:17 +0000 (+0000) Subject: Report posting errors in a way that allows retries. X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=d62b49004ae6984663d31e60cb2403fb4be996c9;p=mastodonochrome.git Report posting errors in a way that allows retries. Having written that into TODO.md in the previous commit, let's immediately polish it off, because I already know how to do it - the login workflow has exactly that kind of error report already. --- diff --git a/TODO.md b/TODO.md index 6929698..1838cd4 100644 --- a/TODO.md +++ b/TODO.md @@ -32,15 +32,12 @@ 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'. -Some error situations could be handled in a less generic way: - -* in `PostMenu::post`, if the server refuses the post, we should - display the error in the posting menu and let the user modify and - retry, similar to the way the login/registration flow does it. But - any error weirder than that should still go to the Error Log. -* similarly, in the `get_user_to_examine` and `get_post_id_to_read` - overlay activities, we should respond to 'no such thing' by letting - the user re-edit and try again, in case it was just a typo +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 diff --git a/src/posting.rs b/src/posting.rs index e4d5155..82ba71b 100644 --- a/src/posting.rs +++ b/src/posting.rs @@ -2,7 +2,7 @@ use std::iter::once; use sys_locale::get_locale; use super::client::{Client, ClientError}; -use super::coloured_string::ColouredString; +use super::coloured_string::{ColouredString, ColouredStringCommon}; use super::editor::EditableMenuLine; use super::text::*; use super::tui::{ @@ -137,6 +137,7 @@ struct PostMenu { cl_sensitive: CyclingMenuLine, el_content_warning: EditableMenuLine>, el_language: EditableMenuLine, + para_post_outcome: Paragraph, } impl PostMenu { @@ -190,6 +191,9 @@ impl PostMenu { post.m.language.clone(), ); + let para_post_outcome = + Paragraph::new().set_centred(true).set_indent(10, 10); + let mut pm = PostMenu { post, title, @@ -202,6 +206,7 @@ impl PostMenu { cl_sensitive, el_content_warning, el_language, + para_post_outcome, }; pm.fix_widths(); pm @@ -252,10 +257,23 @@ impl PostMenu { match client.post_status(&self.post) { Ok(_) => LogicalAction::Pop, - - // FIXME: if we can identify errors of the form "refusal - // to post because of something the user can reasonably - // fix", we should stay in this menu and let them retry + Err( + err @ ClientError::UrlFetchHTTPRich( + _, + reqwest::StatusCode::UNPROCESSABLE_ENTITY, + _, + ), + ) => { + self.para_post_outcome.clear(); + self.para_post_outcome.push_text( + ColouredString::uniform( + &format!("Posting error: {err}"), + 'r', + ), + false, + ); + LogicalAction::Beep + } Err(err) => LogicalAction::Error(err), } } @@ -267,6 +285,15 @@ impl ActivityState for PostMenu { w: usize, h: usize, ) -> (Vec, CursorPosition) { + let push_split_lines = + |lines: &mut Vec, output: Vec| { + for line in output { + for frag in line.split(w.saturating_sub(1)) { + lines.push(frag.into()); + } + } + }; + let mut lines = Vec::new(); let mut cursorpos = CursorPosition::End; lines.extend_from_slice(&self.title.render(w)); @@ -284,6 +311,9 @@ impl ActivityState for PostMenu { )); lines.push(self.el_language.render(w, &mut cursorpos, lines.len())); + lines.extend_from_slice(&BlankLine::render_static()); + push_split_lines(&mut lines, self.para_post_outcome.render(w)); + while lines.len() + 1 < h { lines.extend_from_slice(&BlankLine::render_static()); }