Cancelling an upload ended the loop like a normal finish, and the Files
app then reported every picked file as uploaded. Uploads now return how
many files went up and whether they were cancelled, so a cancel shows
"Upload canceled" (with the count of files that made it, if any).
Folder uploads also passed no cancel signal or progress callback to the
blob upload, so Cancel did not stop the file in flight and the progress
line stood still; they now behave like file uploads.
Uploads in Files had their own card with a thick progress bar, larger
corners and a heavier shadow, so they looked unlike the toasts around
them.
Toasts can now show work in progress: the thin line at the bottom fills
with progress instead of counting down, and the toast stays until it is
updated or removed. Uploads use it, with the file and percentage below
the title and Cancel as the toast action.
The image viewer only zoomed with its buttons, scaled the image inside
a fixed box so a zoomed image could not be moved, and the area around
the image swallowed clicks, so clicking beside it did nothing.
Both the Files image viewer and the attachment preview now use one
viewer that:
- zooms with the wheel, trackpad or two-finger pinch, centred on the
pointer, and with a zoom bar at the bottom (-, percentage, +, fit,
rotate)
- toggles between fit and full size on double-click or double-tap
- pans by dragging, or with the arrow keys, while zoomed
- closes on a click or tap beside the image, but not after a drag
- keeps + / - / 0 / r as shortcuts and Escape to close
The Files app had two layouts (folders inline or in a tree), a back bar
and a permanent warning above the list, a toolbar of ten unlabelled
icons, and a Recent list whose entries did nothing. In the tree layout
folders could not be renamed or deleted at all, and the default view,
default sort and hidden-files settings were ignored.
It now follows the contacts and calendar layout:
- a full-height sidebar with a "+" New menu, My files with the folder
tree, Starred, Recent and Shared with me; folders accept dropped items
- a header with collapsing breadcrumbs (also drop targets), search, sort,
list/grid switch and a details toggle; selecting items swaps it for an
action bar
- list rows open from the name and select from the row, with hover
actions; the grid shows folders as chips and files as cards with
lazy, cached thumbnails
- a details panel for the selection or the current folder, empty-folder
and no-results states, a floating upload card, a dismissible
stability warning, and keyboard navigation with the arrow keys
- touch: tap opens, long-press selects, a "+" button in narrow panes
The tree is built from the listing the store already fetches instead of
one full fetch per folder, so it is current after every change. Recent
files open in their folder, and the settings for view, sort, hidden
files and icons now apply. The inline/sidebar setting is gone.
Calendar, contacts, files and settings still drew the left navigation
rail under Mountain View, so moving away from mail switched to the
default frame. They now show the Mountain View top bar too, without the
mail search and the menu button, which only make sense in mail.
Only the mail shell updated document.title, so every other surface sat at the
static value the root layout renders: the tab could not tell you where you
were, and on a multi-account setup it could not tell you whose mailbox you
were in either.
Each surface now sets "<screen> - <account> - <app>" through the shared
useDocumentTitle hook. Labels reuse the sidebar navigation translations, so
the tab and the rail never disagree about what a screen is called - no new
translation keys.
Refs #1159
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The preview hands the attachment's blob to the browser's own viewer,
which picks the viewer from the blob's type and downloads anything it
cannot show - under the blob's UUID. It only corrected the exact
application/octet-stream declaration from the file name. Other
declarations kept the preview from working: IBM i (AS/400) systems send
every attachment as application/x-as400attachment, some senders use
application/x-pdf or force-download, and the octet-stream check was
case-sensitive.
Move the decision into previewBlobType(): a PDF, image, audio or video
preview takes the first type its viewer can show - declared, then
served, then the one the file name implies. Other previews keep the
declared type unless it is generic, and the name never yields a
script-capable type.
An attached `.eml` was sanitized and shown in a locked sandbox iframe,
but its remote images still loaded, with no CSP, whatever the user's
remote-content policy said. The preview now uses the viewer's
`sanitizeEmailBodyForIframe` and the strict iframe CSP unless the policy
is `allow`, and sends no referrer.