Commit Graph
2273 Commits
Author SHA1 Message Date
Linus Rath efefbd1358 fix: show the resolved date format on the automatic region option 2026-10-11 17:04:19 +02:00
Linus Rath bf00ea27cf fix(files): show the loading skeleton instead of "No files yet" before the first listing 2026-10-11 17:00:56 +02:00
Linus Rath a4909ae106 fix(files): drop the cursor outline from a file once it is deselected 2026-10-11 16:57:00 +02:00
Linus Rath 814c81d24a fix: round file sizes to what people read, like 67 KB or 2.1 MB 2026-10-11 16:53:49 +02:00
Linus Rath 958aa500b8 feat(files): add right-click menus to My files, folders, starred and recent in the sidebar 2026-10-11 16:50:08 +02:00
Linus Rath 8f146509ca fix(files): give the image zoom bar the same card and buttons as the rest of the app 2026-10-11 16:44:37 +02:00
Linus Rath dfa68a1d2f fix(files): keep the items a drag selection covers after letting go 2026-10-11 16:42:43 +02:00
Linus Rath e60840c0e6 fix(files): say the upload was canceled instead of counting it as done
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.
2026-10-11 16:40:32 +02:00
Linus Rath cd5fe770e4 feat: show file uploads as a toast like every other notice
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.
2026-10-11 16:38:05 +02:00
Linus Rath 87915f8bf1 feat(files): zoom and pan images in the preview, close by clicking beside them
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
2026-10-11 16:32:51 +02:00
Linus Rath d07939fc04 feat(files): drop the large file upload warning 2026-10-11 16:25:11 +02:00
Linus Rath 4ba39cef0e feat(files): rework the Files app layout and interactions
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.
2026-10-11 16:23:19 +02:00
Linus Rath f94f4fc605 feat(calendar): match the calendar layout to the rest of the app
The calendar bar spanned both the sidebar and the grid, and the sidebar
opened with a full-width primary "Create event" button. Neither exists
in mail or contacts, so the calendar looked like a different app.

- the sidebar runs full height with a title row and a "+" button, like
  the contacts sidebar
- the view bar sits over the grid only and uses the density header
  padding, so its border lines up with the sidebar header
- calendar rows and section headers follow the contacts sidebar: full
  width 32px rows, chevron on the left
2026-10-10 23:46:37 +02:00
Linus Rath 6d9bd1e4d0 Merge remote-tracking branch 'origin/main' 2026-10-10 23:20:25 +02:00
Linus Rath d3c5ed257d fix(calendar): drop the inline start time from short events in narrow columns 2026-10-10 23:16:45 +02:00
Linus Rath 8251cfa050 feat(calendar): lay out the agenda as a schedule with the date beside each day
Each day is now one row: the date on the left (a large day number,
today in a filled circle, with the short weekday and month and a
Today or Tomorrow label) and its events beside it. Every event shows
its time range in a column of its own, then the calendar dot and the
title, with location and calendar on one muted line below. The grey
day header bars are gone.
2026-10-10 23:09:57 +02:00
Linus Rath 7eebc45f4f feat(calendar): show "N more" in busy month cells and open days from the date
On wide screens a month row keeps its height instead of growing for
the busiest day. A day with more entries than fit shows the first ones
and a "+N more" link that opens the day view, and clicking a date
number opens that day too. Today keeps the filled circle and the
selected day is tinted instead of looking the same. Phones still grow
the row to fit and open a day by tapping the cell.
2026-10-10 23:07:30 +02:00
Linus Rath 2dd90a7b5c feat(calendar): open a clicked event as a card with its actions on top
On wide screens a click on an event now opens its card next to it
instead of the side panel. The card stays until it is closed and has
edit, delete, more and close buttons at the top, a square in the
event's colour beside the title, and a line naming the calendar.
More opens the same menu as a right-click (duplicate, export, copy).
Delete asks for confirmation inside the card, and edit goes straight
to the form. Hover previews still work as before while no card is
open. Phones keep opening the full editor.
2026-10-10 23:03:08 +02:00
Linus Rath d5ce67e167 feat(calendar): create events from a quick editor next to the clicked slot
Clicking or dragging over empty time in the week or day view used to
open the full event panel. On wide screens it now draws the new event
at that spot as a "(No title)" block and opens a small editor beside
it with a title field, the picked time, a calendar picker, Save and
"More options". More options carries the title, time and calendar
over into the full editor. Enter saves, Escape or a click elsewhere
discards. Phones keep opening the full editor.

The placeholder for an event being created is now drawn like a saved
event, in the calendar's colour, instead of a dashed outline.
2026-10-10 22:57:37 +02:00
Linus Rath 95d21c49a9 feat(calendar): open a day from the week header and show a clearer now line
The week and day headers now show a small weekday above a large date,
with today's date in a filled circle and its weekday in the primary
colour. Clicking a date in the week header opens that day in the day
view. The all-day row moved below the dates, where it lines up with
the columns it belongs to.

The current time line is thicker with a larger dot at the start of
today's column, and events shorter than 45 minutes show their start
time next to the title instead of hiding it.
2026-10-10 22:38:59 +02:00
Linus Rath 90b1db0432 feat(calendar): fold calendar lists and show options on hover in the sidebar
The calendar list in the sidebar now works like Google Calendar's:
- "My calendars" and a new "Other calendars" section (shared
  calendars, still grouped by owner) fold away, and stay folded
- each calendar has a checkbox filled in its colour with a check mark
- hovering a calendar shows an options button that opens the same
  menu as a right-click

In the mini month, today is the filled circle and the selected day is
tinted, so the two no longer look alike.
2026-10-10 22:34:35 +02:00
Linus Rath beda42a500 refactor(calendar): keep the webmail's own buttons in the new calendar bar
The previous commit copied Google Calendar's look along with its
layout. The bar and the sidebar now use the webmail's regular buttons,
sizes and title style again; only the arrangement stays: menu button,
Today and arrows with the title, the view menu on the right and the
create button at the top of the sidebar.
2026-10-10 22:30:56 +02:00
Linus Rath b5373bd528 feat(calendar): move the calendar bar above the sidebar like google calendar
The bar now spans the sidebar and the grid. It starts with a menu
button that hides or shows the sidebar (remembered across visits),
then a pill Today button, the arrows and a large period title. On
the right a view menu lists Day, Week, Month and Agenda (and Tasks)
with their shortcut keys, and import and subscribe moved into a
"more actions" menu instead of a button of their own.

The Create button moved to the top of the sidebar. While the sidebar
is hidden or an overlay, a compact create button sits in the bar.
2026-10-10 22:28:38 +02:00
Linus Rath 1421e29a6d fix: toggle the focused conversation by key under Mountain View #1061
The x shortcut passed the bare email id, which the key-based selection
no longer accepts. It now passes the email, so the toggle hits the
right account's row in unified views.
2026-10-10 22:05:41 +02:00
Linus Rath 7cbd33dbc8 fix: act on the ticked account's mail in batch actions #1061
Batch delete grouped the selection by bare email id, so with the same
id in two accounts, permanent-deleting B's row destroyed A's message
and left B's alone. Copy had the same lookup and went out through the
wrong account.

- resolve the selection to email objects by key, including ticked
  members of an expanded thread that are not list rows
- delete, move, mark read, tag and copy group by those objects
- rows, thread checkboxes, drag and drop compare by key, so ticked
  rows show as checked in unified and tag views
- the Mountain View toolbar uses the same resolver
2026-10-10 21:51:19 +02:00
Linus Rath e567df3ab3 Merge pull request #1061 from lucamzanon/fix/cross-account-selection-key
fix: scope batch selection to the owning account
2026-10-10 19:29:02 +02:00
Linus Rath 7533fc516b fix: renew push for every connected account, not only the active one #1054
The background resync only touched the active client, so accounts
turned on from the all-accounts panel lapsed when the server's push
subscription expired after seven days. The resync now walks every
connected login in turn, active one first, and runs again once the
background logins finish connecting. Single-account behaviour is
unchanged.

The panel also lists which accounts failed to enable and why, instead
of only a count.
2026-10-10 19:24:43 +02:00
Linus Rath 02923fc1f1 Merge pull request #1054 from lucamzanon/feat/multi-account-push
feat: enable push notifications for several accounts at once
2026-10-10 19:24:10 +02:00
Linus Rath 53c1bd29a1 fix: show a toast when a Mountain View toolbar action fails #1168
The toolbar's run() had only try/finally, so a failed archive or tag
write rejected silently. Delete, move and archive now go through
runBatchEmailAction with the same messages as the default list, and
tag, read and spam actions show their success and error toasts.

The top bar also starts update polling. It replaces the rail, which
used to start it, so the update dot on the admin icon never showed.
2026-10-10 19:24:10 +02:00
Linus Rath 4af42858f0 Merge pull request #1168 from lucamzanon/feat/mountain-view-layout
feat: add Mountain View, an optional alternative layout
2026-10-10 19:23:59 +02:00
Linus Rath 5f749fea63 fix: sign out of one account without dropping the others #1201
Logout switched to the first account in the list. After a restore that
is often an account still waiting for sign-in, which has no client, so
logout took the full sign-out path and dropped every account. It now
switches to the first account that is connected.

Boot also counted waiting accounts when deciding whether any account
could be restored, so a reload with only waiting accounts left showed a
connection error instead of the login page.
2026-10-10 19:23:59 +02:00
Linus Rath d4b3b86329 Merge pull request #1201 from lucamzanon/feat/account-archive-list
feat: optional encrypted backup of the account list
2026-10-10 19:23:28 +02:00
Linus Rath c46da33604 fix: block a second save while a plugin's form-save hook runs #1202
The hook ran before the modal entered its saving state, so Save and
Ctrl+Enter stayed live while a plugin handler was busy. Each extra press
created another event with a fresh uid and sent another invitation.

- mark the modal as saving before the hook runs
- pass uid and attendees to the conflict-check view too
- don't send a null meeting link when creating an event
2026-10-10 19:23:27 +02:00
Linus Rath 21c527018c Merge pull request #1202 from siennathesane/feat/calendar-event-form-save-hook
feat(plugins): expose event uid + attendees and fire the form-save hook
2026-10-10 19:23:07 +02:00
Linus Rath 911fb883e3 Merge pull request #1144 from lucamzanon/fix/keep-merged-mailbox-on-switch
fix(settings): keep the merged mailbox when switching to another account
2026-10-10 19:23:06 +02:00
Linus Rath 2ca1e071ad Merge pull request #1195 from lucamzanon/perf/folder-list-cache
perf(mail): open a visited folder at once and load it behind its rows
2026-10-10 19:23:06 +02:00
Linus Rath 5de0c1bb41 Merge pull request #1200 from lucamzanon/fix/opaque-editor-toolbar
fix(compose): keep body text from showing through the pinned toolbar
2026-10-10 19:23:06 +02:00
Linus Rath 9a743a5117 Merge pull request #1193 from dealerweb/fix/document-title-whitespace-loop
fix: keep a subject with runs of whitespace from freezing the tab title
2026-10-10 19:23:05 +02:00
Sienna Meridian Satterwhite 388c12e01b feat(plugins): expose event uid + attendees and fire the form-save hook
Plugins rendering in calendar-event-actions could never see the event's
uid or participants, so a meeting plugin minted a fresh room on every
click and could never propagate attendee or time changes; and of the
declared calendar hooks, none ever fired — the form-save bus existed but
had no emit site anywhere.

- calendar-event-actions eventData gains uid (undefined for new drafts)
  and attendees (email list), so plugins can key meetings off the event
  and fan out to participants.
- onCalendarEventFormSave now fires in handleSave as a transform:
  handlers receive the accumulated patch plus the form view and may
  return a patch (currently { virtualLocation }) merged into the saved
  event — a meeting plugin refreshes its link in the same save that
  sends scheduling messages, so attendees always get the current URL.
- Both buses are typed; contract tests cover the patch flow.

Testing: vitest plugin-hooks suite (41 passing), tsc clean, eslint clean
on touched files.
2026-10-09 15:56:25 +01:00
lucamzanon 9560a8b74f feat: optional encrypted backup of the account list
Users with several accounts can save the list of accounts in their browser
(address, server, label, colour) on the webmail server and bring it back on
another device. The list is encrypted in the browser with a password the user
chooses (PBKDF2-SHA-256, 600,000 iterations, AES-256-GCM, owner bound as
additional data); the server stores only the envelope, one file per owner
under SETTINGS_DATA_DIR/account-archives. No mailbox passwords are included.

Off by default behind the admin feature gate accountArchiveEnabled, pinned
off in Lite. Every method of /api/account-archive needs a session cookie of
the owner, matched without regard to case, whose credential is checked
against the mail server on each call; listing included.

Restored accounts this browser lacks are listed as awaiting sign-in: they
survive a reload, and opening one leads to the sign-in form with the address
filled in. Accounts already present get their archived label and colour.
2026-10-09 10:54:38 +02:00
lucamzanon de6ae922d9 fix(push): use logical spacing in the all-accounts panel
pl-6 and mr-2 stayed on the left in right-to-left languages; ps-6 and
me-2 follow the reading direction.
2026-10-09 10:48:15 +02:00
lucamzanon e8da96a625 fix(compose): keep body text from showing through the pinned toolbar
The formatting toolbar sticks to the top of the composer while the body
scrolls. Its background was bg-muted/30 with a backdrop blur, and in a
browser that skips backdrop-filter the body text showed sharp under the
buttons. The toolbar now uses the colour bg-muted/30 gives over the
page, made opaque: it looks the same at rest and hides the text when
pinned.
2026-10-09 09:05:07 +02:00
lucamzanon 04cc00f895 fix(mountain-view): plain sheet under the conversation, round avatar button
Under the message the reply buttons sat on the tinted strip the default
layout uses for its quick reply, a different colour from the message
above them in the light theme. Mountain View now reads the whole
conversation on the page colour.

The account avatar in the top bar got a square highlight while every
other button there is round.
2026-10-09 08:35:17 +02:00
lucamzanon 4347d25890 fix(mountain-view): show the admin console link in the top bar
The top bar replaces the navigation rail on desktop, and with it went
the shield that takes a Stalwart admin to the console, so an admin under
Mountain View had no way in. The bar now shows it, with the same update
dot. The check that decides it moves out of the rail into
useStalwartAdmin so both use the same one.
2026-10-09 08:28:40 +02:00
lucamzanon 7c35ed360f fix(mountain-view): labels, selection and controls that did not match
- The refresh button was labelled "Loading" and the overflow menu
  "Mark folder as read"; they now say Refresh and More actions.
- The Starred row stayed highlighted while a tag was open, and its icon
  ignored the colourful-icons setting.
- Reply, Reply all and Forward use the standard small button size.
- With a single login the account popover offers one Sign out pill
  instead of a pill-less footer row.
- The compose backdrop matches the other dialogs.
- Layout settings hide the mail layout and toolbar label options, which
  do nothing under Mountain View; their values still apply to the
  default layout.
2026-10-09 08:27:01 +02:00
lucamzanon 19e06d02ad fix(mountain-view): keep the same top bar on every app
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.
2026-10-09 08:27:01 +02:00
dealerweb 8abb817111 fix: keep a subject with runs of whitespace from freezing the tab title
The browser reads document.title back with its whitespace stripped and
collapsed, so a title with two spaces in a row, a tab or a space at the
edge never reads back as written. useDocumentTitle put its title back on
every <head> mutation whenever the two differed, and its own write was
such a mutation: an endless loop that froze the tab at full CPU, for
example on opening a message whose subject has two spaces in a row. It
now also accepts what the browser read back after its own write.
2026-10-08 18:10:47 +02:00
Linus Rath a2e36e6e86 fix: open read-only documents in ONLYOFFICE without the -103 warning #1187 2026-10-08 14:32:39 +02:00
lucamzanon 250df2bb61 perf(mail): open a visited folder at once and load it behind its rows
Switching folders kept the previous folder's mail under a spinner until
the new page arrived, and a failed load emptied the folder.

The store now remembers the first page of each plain folder it showed
(in memory, 30 folders, keyed by login, shared owner, folder, category
filter and sort). Opening a remembered folder paints those rows straight
away and fetches in the background; the fresh page replaces them, and a
failure leaves them up with the error. What happens to the list on screen
- a message read, archived, deleted - is remembered with it.
2026-10-08 10:15:20 +02:00
lucamzanon 86caf46ac6 Merge remote-tracking branch 'origin/main' into up/fix/keep-merged-mailbox-on-switch
# Conflicts:
#	stores/settings-store.ts
2026-10-08 10:13:37 +02:00