A window snapped to half the screen (640-800 px) or a 1366x768 laptop
at 150 % (911 px) got the phone and tablet layout: bottom tab bar,
folders in a drawer, Settings as a phone list with a Back arrow. The
layout switched at the 64rem (1024 px) breakpoint.
Now the phone layout starts below 600 px. From 600 to 1024 px the app
is a compact desktop: app rail at the side, folder sidebar folded to
its icons (the existing collapsed state, opened per session with its
toggle), Settings with its two panes and a narrower page list. Below
840 px the split layout opens a message in the list's place, as the
focused layout does. This holds in the browser and the desktop app,
in the Pro shell (which now runs from 600 px) and under Mountain View.
- `hooks/use-media-query.ts`: classifyWidth, PHONE_BELOW 600,
FULL_DESKTOP 1024; the tablet class (`isTablet`) is gone, the store
has `isCompact` instead. Plugins still see "tablet" for it.
- `app/globals.css`: a `desk:` breakpoint at 37.5rem for the layout
classes, and a `tap:` variant for 44px rows on phones and touch
screens below 1024 px (was every window below 1024 px).
- Touch screens below 1024 px keep swiping list rows (was phones only).
- The boot skeletons, boot script, mail app, sidebar, reader, admin
shell and calendar, contacts and files follow the new widths.
Tests changed with the behaviour: the tablet cases in pro-gate,
mail-app-mv-composer-move, mail-app-compose-handoff,
mail-app-thread-expand-mark-read, mobile-tour-end and
thread-list-item-columns now run on a phone or a compact desktop, as
those widths no longer exist as a tablet. mail-app-short-window-tab-bar
is replaced by mail-app-compact-layout: a phone on its side is a
compact desktop with the rail at the side, so the short-window tab bar
rule is gone. Class and media-query assertions follow desk:/tap: and
37.5rem; the 32px-text test uses 1100 px, since 1440 px at 32px is now
a compact desktop.
The default layout showed only the newest message of a thread in the
reader and unfolded the rest as rows inside the list. The reader now
shows the conversation on every layout but a phone's, as Mountain View
does: older messages folded to one line each, unread ones unfolded, the
newest open. A conversation is one row in the list, with no chevron,
and `x` no longer unfolds it. "Show emails as individual messages"
keeps the single message.
Two existing tests changed their setup, not their assertions: the
attachment download tests in `blob-routing.test.tsx` turn threading off
so the conversation fetch doesn't take the requests they count, and the
`x` expansion tests now run on Mountain View on a tablet, the one place
where the list still unfolds a conversation.
The selection bar showed Archive, Delete and Tag, with Move only in its
more menu and both read buttons only on wide bars. The reading pane said
"No conversation selected" next to a selection, and the first-run tips
took a third of the list.
- The bar has Archive, Delete, Move, one read/unread button ("Mark as
read" while anything selected is unread) and Tag, then the rest.
- With a selection the empty reading pane shows "5 conversations
selected" and the same buttons.
- The first-run tips sit in the empty reading pane where it shows beside
the list; phones and layouts without that pane keep them above the list.
- A bulk move's toast names the folder.
The formatter cache test expected the numeric date for every older mail; earlier this year it now reads "Oct 24" unless a date order is picked in the region settings, so the test expects that for those dates.
The badge test said a differing sender name gets "via <identity>"; that badge is gone, so it now checks that nothing is shown and that the sub-address tag still is.
The toolbar measure test counted only item width reads; a pass that fits now reads no item widths, so it counts the toolbar's own scrollWidth reads too.
Two sidebar tests asserted the old unread-count button (it filtered the
folder to unread without opening it, in a 24px target); they now check
that the count is plain text and opens the folder.
The default layout's switcher listed accounts without their unread, so an
existing test asserted that (account-switcher-mountain-view, 'unread-free');
it now expects each account's count. The idle-outside-Pro hook test now
uses one account, since a second connected account loads in every layout.
The shell now takes a message's signed attributes where it took a digest,
so a page can't get a login or TLS digest signed. A quiet option lets a
plugin answer from what's allowed, for anything the user didn't ask for.
An admin's install no longer covers the certificates on someone's own
computer: a managed plugin gets `keystore` when that person says yes, also
when an update adds it, and it's forgotten once everyone has signed out.
Changed test assertions: the fixture plugin needs a grant now, as managed
alone is no longer enough, and the bridge gets an options argument.
A wipe by name took any username and server with no session behind it. It
now needs a sealed cookie the account got while it was signed in, since a
dropped account has no session cookie left. The old wipe test asserted that
a name alone was enough, which is the behaviour being removed.