diff --git a/internal/client/smtpimap/imap/err.go b/internal/client/smtpimap/imap/err.go index 767bb509..53c0aaa3 100644 --- a/internal/client/smtpimap/imap/err.go +++ b/internal/client/smtpimap/imap/err.go @@ -21,7 +21,14 @@ func (c *Client) handleError(err error) *errx.MailError { case imap.ResponseCodeAuthorizationFailed: return errx.ErrMailAuthorizationFailed default: - return errx.ErrMailUnknownImapError(string(imapErr.Code)) + // A NO/BAD without a response code (Gmail's "NO System Error") + // has only its text; an empty code rendered as "Something went + // wrong: " in the mailbox's error list. + detail := string(imapErr.Code) + if detail == "" { + detail = imapErr.Text + } + return errx.ErrMailUnknownImapError(detail) } } diff --git a/web/src/components/app/unibox/ThreadView.tsx b/web/src/components/app/unibox/ThreadView.tsx index d7f1d4cd..8e55b361 100644 --- a/web/src/components/app/unibox/ThreadView.tsx +++ b/web/src/components/app/unibox/ThreadView.tsx @@ -160,14 +160,11 @@ export function ThreadView({ threadId, emailId }: ThreadViewProps) { const threadLabels = useThreadLabels(threadId); const [labelMenuOpen, setLabelMenuOpen] = React.useState(false); - // CRM context rail (right side). Open by default on wide screens (lg+), - // where it renders as a static rail. Below lg it renders as an overlay - // drawer, so it starts closed and is opened from the header toggle. - const [crmOpen, setCrmOpen] = React.useState( - () => - typeof window !== "undefined" && - window.matchMedia("(min-width: 1024px)").matches, - ); + // CRM context rail (right side). Starts closed at every width and is + // opened from the header toggle: on wide screens it renders as a static + // rail, below lg as an overlay drawer. It used to open by itself on lg+, + // which put the contact form in front of every thread the reader opened. + const [crmOpen, setCrmOpen] = React.useState(false); // `c` opens the label menu while a thread is open — ignored while // typing into the composer / any input so it never eats keystrokes.