Commit Graph
166 Commits
Author SHA1 Message Date
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 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 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
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 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
Oğuz YılmazandClaude Opus 5 13e2855484 feat: set the tab title on Settings, Calendar, Contacts and Files
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>
2026-10-07 08:26:23 +03:00
Linus Rath 85b3bb86ed fix: keep the meeting link when duplicating an event #1170 2026-10-05 23:09:48 +02:00
Linus Rath 0b4d0b0f3c feat: limit the day and week views to working hours and days #1164 2026-10-02 22:56:16 +02:00
Linus Rath 692be6aa9d Merge pull request #1095 from lucletoffe/fix/calendar-location-links
fix(calendar): surface the meeting link and open the location in maps
2026-09-30 20:32:44 +02:00
Linus Rath e127f5d24b fix: reuse the translated saving label on the event Save button #921 2026-09-30 14:23:33 +02:00
Linus Rath 7282adbb06 Merge pull request #921 from texchi2/fix/calendar-save-in-flight
fix(calendar): show in-flight state on Save, and surface the silent length-guard rejection
2026-09-30 14:23:09 +02:00
Linus Rath fa789a6d9f Merge pull request #748 from lucletoffe/fix/calendar-blank-cn-and-description
fix(calendar): stop writing blank participant names and empty descriptions
2026-09-30 14:21:20 +02:00
Linus Rath 62e07608fd fix: stop the mail list hiding dividers between some rows 2026-09-30 00:21:21 +02:00
Sebastian SanitzandClaude Opus 5.5 695cc7303f fix(calendar): add translations for the all-day expand toggle
The expand/collapse toggle referenced calendar.events.show_more and
show_less, which were missing from every locale (translations test failed),
and passed a defaultMessage option next-intl does not support. Add both keys
to all 27 locales, reusing each locale's existing email_composer.show_less
wording, and drop the unsupported option.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:08:15 +02:00
Sebastian SanitzandClaude Opus 5.5 ea6d0ee678 fix(calendar): size the week view all-day area from the visible week
The all-day/tasks area in the week view took its height from
(allDayRowCount + taskRowCount) across every loaded day. Since free
scrolling loads 37 to 180 days, one crowded day anywhere in that range
blew the header up to 250+ px for every week and pushed the time grid down;
tasks were also stacked below the global all-day row count, leaving a gap
on days without all-day events.

- Stack each day's tasks directly below that day's all-day events.
- Size the area from the days in view only: track the first visible day by
  date (so columns prepended while loading do not shift it) plus the number
  of visible columns (7 on desktop, by width on mobile).
- Cap the area at 3 rows with an expand/collapse toggle when a visible day
  has more entries.

Tests cover per-day task stacking, the 3-row cap and toggle, an empty week
next to a crowded one, and the area growing when scrolling into it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 23:42:30 +02:00
Linus Rath be3c4b0d99 feat: draw calendar events as solid blocks and toasts as plain cards 2026-09-27 12:45:19 +02:00
Linus Rath 09e0e2cfb3 fix: show events you declined struck through in the calendar #1110 2026-09-26 21:32:08 +02:00
Linus Rath 078e9f9676 feat: show tasks with due dates in the calendar month view #1107 2026-09-26 20:47:13 +02:00
lucletoffeandClaude Opus 5.5 8eaaa4edd8 fix(calendar): keep app-scheme meeting links and match service labels exactly
A virtual location in an app scheme (msteams:, zoommtg:) is kept as a last
resort instead of hiding the meeting link; script schemes never reach the
href. A location only joins the meeting when the whole label is a service
name, so "Salle Teams" still opens the maps. Recognise Zoom's /wc/ join
path, and clear the copy-feedback timer on unmount.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 10:00:01 +02:00
lucletoffeandClaude Opus 5.5 12410124ad fix(calendar): surface the meeting link and open the location in maps
Invitations - Teams above all - leave virtualLocations empty: LOCATION reads
"Microsoft Teams Meeting" and the join URL sits in the description between
help and dial-in links, so the popover showed no meeting link and "Copy
meeting link" was not offered. Find the join URL of known conferencing
services (Teams, Zoom, Meet, Webex, Jitsi, Whereby, GoTo) in the location
or description, unwrapping Outlook Safe Links. Nothing is written to the
event.

The location was plain text unless it was a URL. It is now always a link:
a URL opens as is, a location that only names the service joins the
meeting, anything else opens a Google Maps search (the Maps app on a
phone). A copy button sits next to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 09:52:56 +02:00
Linus Rath 691cde6468 fix: explain why calendar subscriptions fail with not authenticated #1073 2026-09-23 18:31:27 +02:00
Linus Rath 6f82493dda fix: show the calendar import dropdown above the day and week views #1049 2026-09-23 18:24:36 +02:00
Linus Rath 28fd880582 fix: keep single-occurrence edits on that occurrence and keep its details 2026-09-23 13:40:01 +02:00
Linus Rath f95b826434 feat: let attendees answer a single occurrence of a recurring event #1086 2026-09-23 13:06:41 +02:00
Linus Rath d7fdd7ce61 fix: offer to save an event when the server refuses its invitations
From 0.16.21 Stalwart fails the whole CalendarEvent/set with
`forbidden` when the account may not send scheduling messages, so an
event with attendees was not saved at all and the calendar showed only
"Failed to save event".

Such a refusal now surfaces as SchedulingDeniedError, and the calendar
names the server's reason and offers to save the event without sending
the invitations.
2026-09-22 21:25:20 +02:00
Linus Rath d7548a4bab refactor: migrate icon set from Lucide to Tabler Icons 2026-09-19 13:32:41 +02:00
Tex LH Chi e9a72ec17e fix(calendar): show in-flight state on Save and surface the silent length-guard rejection 2026-09-18 17:43:21 +08:00
Linus Rath 5de98bc04b feat: add Bulwark Lite static export build 2026-09-17 23:54:33 +02:00
Linus Rath ee4763d5c0 Merge pull request #1036 from dealerweb/fix/calendar-principal-fetch
fix(calendar): stop the account principal fetch from failing on every load
2026-09-17 22:03:26 +02:00
Linus Rath 0cc1602933 Merge pull request #1037 from dealerweb/fix/mini-calendar-jump
fix(calendar): jump to the day picked in the mini calendar
2026-09-17 22:03:21 +02:00
Linus Rath 2e88a0c830 Merge main into fix/calendar-participants
Resolves the two conflicts in components/calendar/event-modal.tsx created
by #967 (RSVP controls), both keep-both:

- #967's canRsvp memo and #986's resolveContactName hook are both kept;
  they are independent and were simply inserted at the same point.
- #967's RsvpBar component is kept, and StatusBadge takes #986's
  signature ({ status, t }) since #986 drops the isOrganizer prop and
  updates both call sites to match.
2026-09-17 21:54:08 +02:00
Linus Rath e2f50cbb88 Merge pull request #967 from wrycu/fix/ui-rsvp
fix: rsvp controls
2026-09-17 21:49:38 +02:00
dealerweb 464586d0c1 fix(calendar): jump to the day picked in the mini calendar
Since the freely scrolling views (#759) the day, week and month views are
positioned by their own focus rather than by the selected date, and a grid
click deliberately only marks a day that is already on screen. The mini
calendar shared that handler, so picking a day there highlighted it but
left the view where it was. Give it its own handler that jumps to the day
(keeping the mobile month-to-day switch), the same path the prev/next/today
controls and deep links use.
2026-09-15 12:44:36 +02:00
dealerweb bc5302568d fix(calendar): wait for the JMAP client before loading the account principal
The calendar loads the principal's alias addresses so an alias-organised
event is recognised as the user's own. The fetch fired on mount, but after
a page load the JMAP client is restored asynchronously: the call failed
with "Not authenticated" in the console, and the once-only guard then
blocked the retry for the rest of the session, leaving the aliases empty.

Move the logic into useAccountPrincipalEmails, which waits for the client
and fetches once, and cover the sequence with a hook test.
2026-09-15 12:44:36 +02:00
Linus Rath ae403b06af feat: setting to turn off free scrolling in the calendar 2026-09-09 18:27:01 +02:00
Linus Rath 15a5497a12 feat: freely scrolling month, week and day views #759 2026-09-09 16:38:55 +02:00
Linus Rath 60e05c0041 feat: infinite scroll for the calendar agenda view 2026-09-09 15:19:53 +02:00
Linus Rath f349500546 fix: preserve task alarms that the edit dialog does not show #504 2026-09-07 22:34:47 +02:00
Linus Rath d28d8dcd86 fix: report calendar clear failures instead of counting zero #434 2026-09-07 22:34:47 +02:00
Linus Rath 07bbde4786 fix: make the iCal subscription size limit configurable and show the real error #692 2026-09-07 22:34:47 +02:00