fractal/
user_facing_error.rs1use std::time::{Duration, SystemTime};
2
3use gettextrs::gettext;
4use matrix_sdk::{ClientBuildError, Error, HttpError};
5use ruma::api::client::error::{ErrorBody, ErrorKind, RetryAfter};
6
7use crate::ngettext_f;
8
9pub trait UserFacingError {
10 fn to_user_facing(&self) -> String;
11}
12
13impl UserFacingError for HttpError {
14 fn to_user_facing(&self) -> String {
15 if let HttpError::Reqwest(error) = self {
16 if error.is_timeout() {
18 gettext("Connection timed out.")
19 } else {
20 gettext("Could not connect to the homeserver.")
21 }
22 } else if let Some(ErrorBody::Standard { kind, message }) =
23 self.as_client_api_error().map(|error| &error.body)
24 {
25 match kind {
26 ErrorKind::Forbidden { .. } => gettext("Invalid credentials."),
27 ErrorKind::UserDeactivated => gettext("Account deactivated."),
28 ErrorKind::LimitExceeded { retry_after } => {
29 if let Some(retry_after) = retry_after {
30 let duration = match retry_after {
31 RetryAfter::Delay(duration) => *duration,
32 RetryAfter::DateTime(until) => until
33 .duration_since(SystemTime::now())
34 .unwrap_or_else(|_| Duration::from_secs(1)),
38 };
39 let secs = duration.as_secs() as u32;
40 ngettext_f(
41 "Rate limit exceeded, retry in 1 second.",
44 "Rate limit exceeded, retry in {n} seconds.",
45 secs,
46 &[("n", &secs.to_string())],
47 )
48 } else {
49 gettext("Rate limit exceeded, try again later.")
50 }
51 }
52 _ => {
53 message.clone()
56 }
57 }
58 } else {
59 gettext("Unexpected connection error.")
60 }
61 }
62}
63
64impl UserFacingError for Error {
65 fn to_user_facing(&self) -> String {
66 match self {
67 Error::DecryptorError(_) => gettext("Could not decrypt the event."),
68 Error::Http(http_error) => http_error.to_user_facing(),
69 _ => gettext("Unexpected error."),
70 }
71 }
72}
73
74impl UserFacingError for ClientBuildError {
75 fn to_user_facing(&self) -> String {
76 match self {
77 ClientBuildError::Url(_) => gettext("Invalid URL."),
78 ClientBuildError::AutoDiscovery(_) => gettext("Could not discover homeserver."),
79 ClientBuildError::Http(err) => err.to_user_facing(),
80 ClientBuildError::SqliteStore(_) => gettext("Could not open the store."),
81 _ => gettext("Unexpected error."),
82 }
83 }
84}