The colour dot for a shared (non-owned) local calendar was disabled and the
colour write hit the owner-only PUT /calendars/{id} (404 for recipients). The
dot is now always editable and colour changes go through the dedicated
PUT /calendars/{id}/color endpoint, storing a recipient's own per-user colour
server-side (synced across devices) without granting write or rename. Renaming
stays owner-only. Parity with Android + server.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- UserProfile decodes directory_hidden; updateProfile() sends it; Settings has
a "hide my profile" toggle (excludes you from share/group pickers).
- GroupMember decodes shares_calendar; the group filter list now only shows
members who actually share a calendar (no phantom empty rows).
- Robust custom decoders (decodeIfPresent) for the new fields.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The server now reports per-calendar sync failures (e.g. expired
credentials) alongside an otherwise-successful events response, via an
"errors" array. Previously such failures were silently swallowed, so a
calendar could appear enabled while showing zero events with no
explanation.
- Decode the new "errors" field into SyncError (source/name/message),
following the existing JSONSerialization + from(json:) convention.
- CalendarStore.syncErrors captures these on successful personal
fetches (loadEvents, prefetchBackground); left untouched on a hard
fetch failure so it isn't conflated with lastError. Group overlay
fetches never populate it (the endpoint doesn't apply there).
- CalendarHostView shows a second red warning banner alongside the
existing lastError banner, reusing the same visual style.
Notifications now show "in 30 Min. · 10:00" instead of just the time,
giving users immediate context about how soon the event is.
Default event duration picker moved from the View section to right below
the privacy setting, grouped under the calendar/profile settings area.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Reminder editor: presets + custom number+unit (minutes/hours/days/weeks)
- Grey out + footer hint when the selected calendar's reminders are muted;
reminders are kept, scheduler already skips them
- New synced setting defaultEventDurationMinutes for new events
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
C1 — Localization: route the remaining hardcoded German strings through
L10n (LoginView, ServerSetupView, SettingsView email, EventDetailSheet) so
"System Default" + English device language shows fully English text.
C2 — Per-calendar reminders: parse the new reminders_enabled flag on every
calendar type; CalendarStore persists a reminderDisabledKeys set and passes
it to NotificationScheduler, which skips events of muted calendars (default
and per-event reminders). Filter sheet gains a per-calendar reminder toggle
(leading swipe + bell.slash indicator), reconciled from the server and
synced back via PUT.
C3 — Widgets:
- Shared WidgetTime.range helper; Today / Today & Tomorrow / Three Days /
Up Next now show start–end instead of only the start time.
- This Week: show up to 6 events per day (was 3) to use the height.
- Two Weeks: mini event-title pills instead of bare dots.
- Two Months: weeks expand to fill the column (no more empty lower third).
- Day & Events: smaller header/strip/rows so content stops clipping.
- Next 5 days → Next 7 days (range + labels), higher row cap.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per-event reminders (multiple, local calendars only) in the editor, prefilled
from a new "default reminder" setting that applies to all events otherwise.
CalEvent gains `reminders`; AppSettings/SettingsSync sync default_reminder_minutes
(always group). New NotificationScheduler requests permission and schedules the
soonest ≤60 upcoming reminders via UNUserNotificationCenter, rescheduling on
load/sync/edit and when the default changes (skipped in group overlay).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Kalenderverwaltung: tappbarer ColorPicker pro Kalender (lokal/iCal direkt;
CalDAV/Google/HA klappen ihre Unterkalender mit je eigenem Farbwähler auf).
Neue API: updateLocalCalendarColor, updateICalColor, setCalendarColor
(caldav/google/homeassistant) -> PUT …/{id} {color}. Geteilte Kalender
read-only (nur Besitzer).
- Top-Bar: Gruppen-Umschalter nur bei vorhandenen Gruppen, "Heute" nicht mehr
quetschbar (fixedSize), kompaktere Icons -> "Heute" wird nicht mehr zu "H…".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neue Settings-Sektionen: Anzeigename + E-Mail ändern (Login-Name read-only),
Private-Termine-Sichtbarkeit (busy/hidden) und Auswahl des für Gruppen
sichtbaren Kalenders. Gezielte API-PUTs, damit nicht die ganze AppSettings
überschrieben wird.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add two-way settings sync (SettingsSync) with toggle, app-start/foreground/
10-min pull and debounced push; server wins; view/week-start/dim-past always
sync. Wire previously-ignored settings (hour height, contrasts, week start,
default view, dim past) into the actual UI.
- Make AppSettings decoding resilient (decodeIfPresent) so getSettings no longer
fails on iOS-only fields the server omits; keep text/bg/line colors local-only;
month divider/label colors now sync.
- Auto-refresh after create/edit (cache-busting) and optimistic removal on
delete; switch delete confirm to a centered alert. Add HA event deletion.
- Calendar visibility: fix inverted hide/show toggle; normalize calendar keys so
local filtering works for all sources; sync banish with server sidebar_hidden
(CalDAV/Google/HA), refetch on un-banish.
- Manual "sync with server" button in the menu.
- Upcoming widget shows next 5 days (renamed).
- Week/Day view: route multi-day timed events to the all-day strip so they no
longer render as a full-height block.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>