Replace the boolean "month view as pages" toggle with a Monatswechsel dropdown:
Continuous scroll vs. Page by page — same names/format as the web client.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the top-bar menu popup with an off-canvas left drawer, opened by the
hamburger or a narrow left-edge swipe (kept off the content area so month/week
swipe stay free). The drawer hosts the calendar visibility list, a view
switcher, group switching, and quick access to Settings/Accounts/Profile/
Groups/Server plus sync and logout.
- extract the filter list into reusable CalendarFilterContent (shared by the
drawer and the still-present CalendarFilterSheet); the sheet is now a thin
wrapper
- new CalendarDrawer view; CalendarHostView hosts it as a ZStack overlay with a
scrim and edge-swipe gesture, and presents drawer destinations as sheets
- opt-in surface colour: surfaceColor (device-local) tints the flat top bar;
empty keeps the translucent .bar material. Settings row with an Auto reset.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Generalise the two-tier SettingsSync into a server-driven flag map: each
syncable key has an account-wide flag (fetched from the server); pull applies
only on-flagged keys, push (read-modify-write) sends only on-flagged keys plus
the flag map. Per-row link icon toggles a setting's sync; a global switch flips
all. Enabling a flag adopts this device's current value as the shared one.
- AppSettings: fix bg_color mapping (was background_color), add cache_months,
month_view_paged, sync_flags
- SettingsView: uniform rows (sync icon | name | value), ContrastSelector and
the button pickers replaced by menu dropdowns, every colour gets a reset to a
canonical default, global "sync all" toggle; account settings (privacy,
group calendar, hide profile) kept in their own block; language and text/line
contrast kept device-local (iOS-specific)
- unify default line colour to #3A3A52 across views
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Contacts sync fills only an EXISTING birthday calendar (birthdayCalendar),
never auto-creates it — deleting it no longer resurrects it on sync
- Accounts + menu gains "Geburtstagskalender" (only when none exists) to create
the single birthday calendar explicitly
- the Birthdays-from-Contacts section shows a "create one first" hint when there
is no birthday calendar; enabling sync only requests Contacts access
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- one birthday calendar per user; BirthdaysImporter auto-creates/targets it
(no picker) and reconciles per-device (external_uid contact:<deviceId>:<id>)
so multiple devices don't clash
- Contacts birthday sync now runs on every "Sync with server" (syncFromServer),
not just app launch and the manual button
- report the device after each sync (POST /api/birthdays/sync-report) for the
web device list
- Accounts: Birthdays-from-Contacts section drops the target picker, keeps the
reminder picker; removed the birthday toggle from the generic new-calendar sheet
- New-birthday sheet targets the single calendar, offers activation if none
- exclude the birthday calendar from the group-visible ("shared calendar") picker
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- LocalCalendar/CalEvent gain is_birthday + birthday fields; API sends
rrule/external_uid/birth_year and can create/update birthday calendars
- BirthdaysImporter: mirrors Contacts birthdays into a chosen birthday
calendar, reconciling by external_uid (leaves manual entries untouched)
- AccountsView: "birthday calendar" toggle + notify-days when creating a
calendar, and a "Birthdays from Contacts" section (enable + target + sync now)
- FAB long-press menu -> "New birthday" opens a minimal name+date mask
(BirthdayEditorSheet) targeting birthday calendars, with year-unknown option
- Event bars render display_title (age) and a cake icon via EventLabel
- NSContactsUsageDescription added to both app build configs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New device-local setting "Monatsansicht seitenweise wischen" (@AppStorage, no
server sync). Off keeps the continuous vertical scroll feed; on switches the
month view to a paged TabView — one month per screen, six height-filling week
rows, swipe left/right to change month (bounded ±monthsBack/Ahead range to keep
the TabView light). WeekRow gains a fillHeight flag so the same row renders at a
fixed height (scroll) or fills the page evenly (paged); its inner cells/divider
now size to the actual geometry. Paged selection is two-way bound to the store's
current date so prev/next/today and the title stay in sync.
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>
- 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>
The calendar filter, when a group overlay is active, now lists the group's
members (+ the shared group calendar) and lets you hide each one individually
(Outlook-style). Filtering is client-side via CalendarStore.hiddenGroupKeys
(per-member gm:<id> / group-calendar gc keys), reset when switching groups.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Gruppen sind nicht mehr nur im Menü versteckt: im Top-Bar gibt es einen
Gruppen-Umschalter (Persönlich / <Gruppe>). Beim Wählen einer Gruppe zeigt
der echte Monats-/Wochen-/Tagesansicht die kombinierte Überlagerung
(GET /groups/{id}/combined) mit server-definierten Farben und
Besitzer-Präfix; ein Banner "Gruppenansicht: <Name>" mit "Verlassen".
CalendarStore.activeGroup steuert den Modus.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ein doppelter Dictionary-Key liess die App beim Start abstürzen
("Dictionary literal contains duplicate keys"). Meine Dublette entfernt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kalenderverwaltung: pro lokalem Kalender ein Menü mit Teilen (SharingView:
Benutzer aus Verzeichnis, read/read_write, entfernbar), Importieren
(.ics File Picker) und Exportieren (Share Sheet). Geteilte Kalender mit
"geteilt von"-Badge; Gruppenkalender markiert.
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>
- Vertical-scroll month view with multi-day event spans, zig-zag month
divider, CW number per week, on-demand event loading while scrolling
- Top bar redesign: icon-only view picker on right, month title centered
- Long-press context menus on day cells (month) and hour slots (week/day)
for "New event", "Open in week view", "Open in day view", "Open in month view"
- Localization system with system/de/en switch covering top bar, view picker,
settings, menu, profile, server, accounts, event editor, agenda
- Three new color pickers (text/background/line) + today-marker color
applied in calendar views; current-time line now uses today color
- App icon: removed alpha channel, accent color set to icon green (#20A050)
- TestFlight: ITSAppUsesNonExemptEncryption=NO baked into Info.plist keys
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>