fix(imap, unibox): show the server's text for a codeless IMAP error; contact rail starts closed

- An IMAP NO/BAD without a response code (Gmail's "NO System Error")
  rendered as "Something went wrong: " in the mailbox's error list. Fall
  back to the server's text when the code is empty.
- The unibox contact rail opened by itself on lg+ screens, putting the
  contact form in front of every thread the reader opened. It now starts
  closed at every width and opens from the header toggle.
This commit is contained in:
SUMAN JANA
2026-09-09 15:47:50 +00:00
parent 05847328af
commit 73d9c18bfe
2 changed files with 13 additions and 9 deletions
+8 -1
View File
@@ -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)
}
}
+5 -8
View File
@@ -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.