Commit Graph

26 Commits

Author SHA1 Message Date
Scarriffle
6881c68935 iOS drawer: flat reorderable calendars, long-press menu, left-swipe close, header actions
Testing feedback:
- calendars are now one flat, drag-reorderable list (no per-source grouping);
  order is device-local (CalendarStore.calendarOrder, mirrors the web cal_order).
  Reordering is done via a 'Sort' toggle (native edit mode with drag handles).
- banish + reminder-mute moved from row swipe actions to a long-press context
  menu, which frees the horizontal swipe: swiping the drawer left closes it.
- the hamburger moved to the LEFT (drawer opens left); new device-local setting
  'Hide menu button' (open via edge-swipe only), not synced.
- the settings entry moved from the footer into the header as an icon, next to a
  restored manual-sync icon and the close button; the footer button is gone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 16:19:29 +02:00
Scarriffle
e008d5d98a iOS drawer: compact show/hide-all, single menu button, corner-safe footer
Testing feedback:
- show-all / hide-all are now side by side (bordered), not two big stacked rows
- the busy quick-access strip becomes a single "Einstellungen" button that
  opens the full menu (which already holds accounts/profile/groups/server/sync/
  logout)
- extra horizontal + bottom padding so the footer button is not clipped by the
  iPhone's rounded corners / home indicator

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 06:09:38 +02:00
Scarriffle
d90a1a552c iOS: left side drawer (calendars + groups + nav) and opt-in top-bar colour
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>
2026-07-14 22:24:24 +02:00
Scarriffle
69ed8bf67d Birthdays: single calendar model + sync on server-sync (iOS)
- 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>
2026-07-13 19:07:46 +02:00
Scarriffle
cf990e4279 Add birthday feature (iOS)
- 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>
2026-07-12 21:58:31 +02:00
Scarriffle
325f357357 fix(visibility): auto-reconcile server sidebar_hidden on launch/resume/sync
Hiding or showing a calendar on the web sets enabled=false + sidebar_hidden
server-side, so the server stops returning that calendar's events entirely.
The app only reconciled these per-calendar flags when the filter sheet or the
accounts screen happened to be opened — never on launch, resume or the
periodic pull. So a calendar re-enabled on the web stayed invisible (still
banished locally, and its events weren't in the cache) until a manual sync or
relaunch — the "hide it on the web and the app won't bring it back" bug.

Add CalendarStore.reconcileCalendarVisibility(api:) which pulls the account
lists, updates the banished set from the server's sidebar_hidden flags, and
returns whether anything changed. CalendarHostView now runs it (via
syncFromServer) on launch, on scenePhase .active, in the periodic loop, and on
manual sync — forcing a refetch when the set changed so a re-enabled calendar's
events actually reappear without user intervention.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 22:04:58 +02:00
Scarriffle
8ed474663e feat: surface per-calendar sync errors from /api/caldav/events
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.
2026-07-02 18:25:47 +02:00
Scarriffle
59a879ea23 fix: move Today button to the right so the month title sits centered (iOS)
Left side now holds only the prev/next chevrons; "Heute" moved next to the
burger menu on the right (both flat and Liquid Glass bars), so the month title
is centered again instead of pushed right by a heavy left cluster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 10:14:08 +02:00
Scarriffle
f480b438cb feat: top bar declutter — view/filter/groups/sync into one burger popup (iOS)
The top bar now shows only nav + title + a single burger. Tapping it opens a
compact menu: View (with a fixed icon, no longer per-view), Filter, Groups
(if any), Sync, and an "Einstellungen" entry that opens the existing full menu.
Removed the separate group/view/filter icons from both the flat bar and the
Liquid Glass toolbar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 16:23:56 +02:00
Scarriffle
587a0e65fa feat: event reminders + default reminder setting + local notifications (iOS)
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>
2026-06-06 16:21:08 +02:00
Scarriffle
e7d8effb47 fix: Liquid Glass month title as inline content strip (not the system toolbar)
The NavigationStack toolbar title never refreshes on month change on iOS 26
(4 approaches tried: principal Text, navigationTitle, @Observable store). The
title now renders as a normal inline Text in a top safe-area inset just below
the system glass toolbar — the same mechanism as the flat variant, which does
update. The system toolbar keeps the buttons + the real Liquid Glass look.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 21:30:07 +02:00
Scarriffle
68349d36e5 feat: non-emoji group icons (SF Symbols) for consistent cross-platform look
Group icons are now semantic keys (people/home/heart/work/school/sports/party/
pet/travel/music/food/star) rendered as SF Symbols in the picker, group list,
switcher, banner and filter — instead of OS emoji that looked different on every
platform. Legacy emoji values still render as a fallback. GroupCombinedView uses
the server display_title.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:20:32 +02:00
Scarriffle
451d3d4d6b fix: Liquid Glass month title updates via @Observable store (visibleMonth)
The system NavigationStack toolbar title would not refresh on a plain @State
change (title kept disappearing on iPhone). Moved visibleMonth into the
@Observable CalendarStore so the toolbar's read is tracked with @Observable's
fine-grained observation and refreshes on month change. Reverted the @State/.id
workaround. Real system glass bar retained.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:06:53 +02:00
Scarriffle
51218b9aa3 fix: restore real Liquid Glass bar; drive title via @State so it refreshes
The custom safeAreaInset bar removed the actual iOS-26 Liquid Glass look
("no glass even though enabled"). Restored the system NavigationStack glass
toolbar and instead fixed the disappearing month title by driving it from a
@State (navTitle) updated via onChange(of: titleString) and keyed with .id,
which forces the system bar to refresh on month change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 18:22:16 +02:00
Scarriffle
b61a90d960 feat: hide individual member calendars in the group view (iOS)
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>
2026-06-01 18:00:30 +02:00
Scarriffle
8521a28520 fix: visible Liquid Glass again, group icon on group events, week today colour
- Liquid Glass: the calendar content now scrolls underneath a translucent
  safeAreaInset bar (real glass look restored) while the inline title stays
  reliable — toggling Liquid Glass is visibly different again.
- Group events are prefixed with the group's own emoji icon (from group
  settings) instead of a generic people glyph, so they're recognisable.
- Week view: today's column header now uses the configured "today" colour
  instead of the accent colour (matches the current-time line).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 17:22:02 +02:00
Scarriffle
7f76df2600 fix: Liquid Glass month title now updates reliably (custom glass bar)
navigationTitle/principal items in the NavigationStack toolbar silently fail to
refresh on scroll-driven state changes (visibleMonth), so the month label
vanished on month change and only returned after an unrelated rebuild. The glass
variant now uses a custom top bar with the same inline Text title as the flat
variant (proven to update), styled with glassEffect (iOS 26) / ultraThinMaterial.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 09:00:48 +02:00
Scarriffle
852e46fcf8 fix: month title disappears in Liquid Glass mode on month change
The glass variant rendered the month title in a `.principal` ToolbarItem, which
SwiftUI drops when the state it reads (visibleMonth) changes while on screen —
it only reappeared on an unrelated rebuild (opening/closing the menu) and
vanished again on the next month change. Switched to `.navigationTitle`, which
the system updates reliably.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 08:50:32 +02:00
Scarriffle
c6f9981a54 fix: Gruppenansicht – Termine über Cache/Prefetch laden (kein Range-Gap)
Der Gruppen-Modus ersetzte events nur mit dem schmalen aktuellen Fetch, statt
denselben Cache/Prefetch-Pfad wie die Normalansicht zu nutzen -> Termine
erschienen erst nach Scrollen. Jetzt fetchForMode (personal/group) läuft durch
loadEvents + prefetchBackground + refreshFromCache; Moduswechsel lädt breit neu.
In der Gruppenansicht greift der "ausgeblendet"-Filter nicht.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 21:14:48 +02:00
Scarriffle
815f2cf01a feat: iOS Kalenderfarben änderbar + Top-Bar entzerrt
- 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>
2026-05-31 21:05:31 +02:00
Scarriffle
6dc8724a9a feat: iOS Gruppenansicht direkt im Kalender (Umschalter + Banner)
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>
2026-05-31 20:55:28 +02:00
Scarriffle
b1e0cf1fdc WIP: Widget-, Sync- & Event-Editor-Änderungen
Zwischenstand vor den Sharing/Gruppen/Import-Export-Features (gesichert,
damit die neuen Features sauber darauf aufbauen).
2026-05-31 19:22:12 +02:00
Scarriffle
4125bfc728 Settings sync, calendar visibility sync, event refresh & week-view fixes
- 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>
2026-05-27 20:44:14 +02:00
Scarriffle
d1004a9111 Fix month scroll event disappearance by improving visible month detection and cache refresh rules 2026-05-25 10:33:31 +02:00
Scarriffle
8b3cc11e25 Add localization (DE/EN), vertical-scroll month view, context menus, custom colors
- 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>
2026-05-19 22:00:49 +02:00
Scarriffle
e5529ca653 Initial Commit 2026-05-17 08:32:34 +02:00