Commit Graph

322 Commits

Author SHA1 Message Date
2586e3ce34 fix: list view time grid on mobile + legacy FA icon prefix
- Mobile quick settings view switcher now correctly toggles showTimeGrid
  when switching views (list → off, simple/calendar → on), matching
  the desktop switcher behaviour. This removes the unwanted time column
  in list view on mobile.
- ProjectIcon: normalise legacy icon names stored as "faHeart" / "faHouse"
  (camelCase with "fa" prefix) to "heart" / "house" so the FA icon lookup
  succeeds instead of falling through to the text fallback.

v1.81.3
2026-03-31 10:12:58 +02:00
bb34e083d5 fix: make CalendarEventModal more compact for small smartphone screens
- Modal uses flexbox column layout: scrollable body + pinned action bar
- maxHeight raised to 96vh, width uses calc(100vw - 12px)
- iconRow: gap 10→8px, padding 6→3px, minHeight 28→24px
- iconCol: width 20→18px
- inlineSelect: fontSize 0.8→0.78rem, padding 2→1px
- Title: fontSize 1.1→1rem, padding 4→3px
- Date inputs: padding 4→3px, fontSize 0.8→0.78rem, smaller labels
- Notes: minHeight 50→36px, padding tightened
- Action buttons: padding and font slightly reduced
- All section paddings reduced from 16px to 14px

v1.81.2
2026-03-31 09:59:56 +02:00
5bcf281502 fix: mobile sync icon no longer shifts date; selected day tracks last clicked column
- Mobile header: removed spinner/error from inside the date button,
  placed as a fixed-width (24px) sibling slot after the button — date
  text position is now stable regardless of sync state
- Selected day: added selectedDay state tracking the last day column
  the user clicked; passed to getSelectedDay() so "Selektierter Tag"
  in the header reflects the actual cursor position, not just visibleDays[0]
- getSelectedDay() priority: explicit selection → today if visible → first visible day
- Navigating to a new week resets selectedDay so the header stays accurate

v1.81.1
2026-03-31 09:31:36 +02:00
e800d87235 feat: overhaul header display options with mobile portrait/landscape settings
- Rename options to be clearer:
  - "Vollständiges Datum" → "Heutiges Datum" (always today's date)
  - "Aktueller Tag" → "Selektierter Tag" with custom format input
  - "Benutzerdefiniert" → "Woche Benutzerdefiniert" (week-based tokens)
- Add custom format input for "Selektierter Tag" (headerCurrentDayFormat)
  with tokens: DDDD, DDD, DD, MMMM, MMM, MM, YYYY, WW
- Add separate header display settings for Mobile Portrait and
  Mobile Landscape (mobilePortraitHeaderDisplay, mobileLandscapeHeaderDisplay)
- Move refresh/sync icon to fixed-width slot right of date — date no
  longer shifts when the icon appears or the spinner replaces it
- Add 3 new Prisma fields (db push required on deploy)
- All 5 languages updated (EN, DE, FR, ES, IT)

v1.81.0
2026-03-31 09:14:16 +02:00
033603e899 feat: add "Current Day" header display option
New "Current Day" option in the header display settings shows the
currently visible day formatted as "Mo., 30. März 2026" (weekday +
full date), using the user's locale.

- Available in all views (simple, calendar, list, kanban)
- In kanban view: defaults to "Current Day" when no setting is chosen
- On mobile portrait: existing behavior preserved (always shows current day)
- On mobile landscape: respects the new setting like other options
- No year separator shown (year is already part of the format)
- Added to all 5 languages (EN, DE, FR, ES, IT)

v1.80.4
2026-03-31 08:23:46 +02:00
7306549311 fix: show currently visible day in mobile portrait header
In portrait mode the header now always shows the day currently on
screen (getVisibleDays()[0]), so swiping left/right updates the
header to reflect the active day. Formatted as weekday + full date
using the user's locale (e.g. "Mo., 30. März 2026").

v1.80.3
2026-03-31 07:51:40 +02:00
687e1e1d08 fix: show day + date in mobile portrait header instead of KW
In portrait mode on mobile, the header center now displays the full
date with weekday (e.g. "Mo. 30. März 2026") using the user's language
locale. Falls back to today if today is in the visible week, otherwise
uses the week's reference date. Landscape mobile keeps existing behavior.

v1.80.2
2026-03-31 01:01:46 +02:00
8a0af281a5 fix: pair setWeekStartDay with saveSetting in SettingsSidebar
Phase 2 migrated weekStartDay reads to profile.weekStartDay, exposing a
pre-existing gap: the Mon/Sun buttons called setWeekStartDay() without
saveSetting(), so profile.weekStartDay never updated on click.

v1.80.1
2026-03-30 23:06:12 +02:00
bfb749a8a6 refactor: Phase 2 — consolidate profile state reads
Replace all individual useState reads (viewStyle, timeFormat, language,
cellDuration, showTimeGrid, showNextTask, showSomeday, showAllDay, etc.)
with profile.fieldName reads. Individual useState declarations remain; only
read sites are migrated. No UI logic changed.

- getEffective() calls use profile.fieldName as global fallback
- workingHoursStart/End derived from profile.startHour/endHour
- All JSX reads (className, conditionals, child props) use profile.*
- SettingsSidebar value props use profile.* (setters unchanged)
- Add weekStartDay: 1 to profile defaults
- ProjectsSidebar function body reverted (uses language prop, not profile)
- darkMode excluded: localStorage-only, not an API profile field

v1.80.1
2026-03-30 22:51:40 +02:00
a5f6edd82d perf: fix stale auto-save bug + extract SettingsSidebar to lazy chunk
- saveSetting: add setProfile(p => ({...p, [key]: value})) so profile
  stays in sync with individual setting changes — prevents auto-save
  from overwriting fresh settings with stale profile object values
- Extract SettingsSidebar (4725 lines) from WeeklyView.tsx into its own
  file; lazy-load with next/dynamic so the ~4500-line settings panel
  is deferred until the user opens settings
- Extract shared constants/helpers to src/lib/:
  fontConstants.ts (AVAILABLE_FONTS, FONT_WEIGHTS, isCustomFont)
  weeklyViewTranslations.ts (translations object, ~1100 lines)
  weeklyViewConstants.ts (WeatherDisplayKey, WEATHER_DISPLAY_DEFAULTS)
- WeeklyView.tsx: 16,209 → 10,364 lines (-36%)

v1.80.0
2026-03-30 22:03:09 +02:00
6fed38381c perf: limit recurring task projection + O(1) calendar event dedup
- tasks/route.ts: add per-unit instance cap for virtual task projection
  (daily: 60, weekly: 26, monthly: 12, yearly: 3) to prevent unbounded
  generation from high-frequency recurring tasks
- WeeklyView: extract calendarEditabilityMap as a separate useMemo keyed
  on connections; replace O(n²) nested find() loop with O(1) Map.get()
  lookup in the calendarEvents deduplication useMemo

v1.79.0
2026-03-30 16:02:56 +02:00
6e8ed34578 perf: batch sync DB lookups, fix calendar cache race, lazy-load IconPicker
- tasks/sync GET: batch Google/Outlook/Synology credential fetches with
  Promise.all instead of sequential awaits; move per-list Synology
  findMany outside the loop to eliminate N+1
- calendar/sync: replace fire-and-forget background refresh with 800ms
  Promise.race so fast refreshes return fresh data without blocking
- Extract icon data to iconRegistry.ts; lazy-load IconPicker via
  next/dynamic so picker UI code is deferred until needed

v1.78.0
2026-03-30 15:54:12 +02:00
6b292f8d07 fix: remove sticky weekday header inside scroll area on mobile
The .time-grid-wrapper .weekly-day-header was set to position:sticky, causing
the day name (MITTWOCH 1. APR.) to appear as a ghost header while scrolling.
The correct sticky element on mobile is the existing day-bar overlay (DO 2.4.)
at the top. Reverted .weekly-day-header to position:relative.

v1.77.6
2026-03-29 16:40:16 +02:00
b8c8e9257a fix: retry individual Apple calendar fetches on network timeout
Batch errors like 'fetch failed' were only retried at the login/client-init
level. Per-calendar fetchCalendarObjects calls had no retry, so a single
transient iCloud network timeout silently dropped all events from that
calendar. Now wraps each fetchCalendarObjects with withRetry(2 retries, 3s/6s).

v1.77.5
2026-03-29 16:29:26 +02:00
4c1ef5019e fix: iOS scroll blocked by enforcement interval + missing touch-action on slots
Three root causes fixed:

1. Scroll enforcement interval (every 50ms for 2s) was the main blocker:
   The setInterval forced gridRef.scrollTop on every frame, making iOS think
   the page was always scrolling programmatically. User touches during those
   2 seconds were overridden. The header appeared 'stuck' because the view
   was frozen. Replaced with a single setTimeout scroll (300ms on first load,
   50ms on subsequent). Added history.scrollRestoration='manual' so Safari
   doesn't fight us with scroll position restoration.

2. touch-action: pan-y was only on .time-grid-wrapper — NOT inherited by CSS.
   Slot child elements had touch-action: auto (default), so iOS still waited
   for JS before committing scroll on day column touches. Added touch-action:
   pan-y directly to .time-slots-container (the actual touched element area).
   Time column labels have no JS handlers so iOS scrolled them freely — this
   explains why time column worked but day columns didn't.

3. align-items: start on .weekly-days-grid was wrong (added in last commit).
   Removed — CSS grid default stretch is correct.

v1.77.4
2026-03-29 16:14:53 +02:00
aef7c291b4 fix: iOS scroll + sticky day headers — remove React onTouchStart from slots
Root cause: React registers onTouchStart props as non-passive listeners at the
app root. iOS Safari sees any non-passive touchstart on an ancestor and blocks
the scroll gesture on those elements, waiting for JS to finish. This is why
the time column (no handlers) scrolled freely but day columns (slots had
onTouchStart) were frozen.

Changes:
- Removed onTouchStart prop from all time-slot divs — no more React touch
  handlers in the time grid, so iOS never blocks scroll
- Added data-slot-blocked attribute to occupied/protected slots
- Moved slot long-press logic into the permanent native touchstart listener
  on document (passive: true), reading slot/date from data attributes
- Added touch-action: pan-y on .time-grid-wrapper — explicitly tells iOS
  that vertical pan = scroll even if child content has touch handlers
- CSS: align-items: start on .weekly-days-grid so sticky headers in each
  day column have a proper scroll context
- Reinforced position:sticky on .time-grid-wrapper .weekly-day-header

v1.77.3
2026-03-29 15:58:18 +02:00
b6e5303665 fix: day column scroll blocked on iOS by DOM addEventListener inside onTouchStart
The slot onTouchStart called attachTouchListeners() which did
document.addEventListener() synchronously — DOM manipulation inside a touch
handler makes iOS Safari uncertain about scroll intent and blocks vertical
scroll on day columns (but not the time column which has no handlers).

Fix: attach all touch listeners ONCE at mount (permanent, passive). The slot
onTouchStart only writes to a ref (zero DOM side effects). The non-passive
drag-tracking listener is still added dynamically but only after the 500ms
long-press actually activates, at which point the user has clearly committed
to a drag gesture rather than a scroll.

v1.77.2
2026-03-29 15:47:20 +02:00
a3a55c9575 fix: day columns were blocking scroll on iOS — remove overflow-y from time-slots-container
.time-slots-container and .time-column-slots had overflow-y: auto which created
independent scroll contexts inside each day column, eating touch events and
preventing the parent time-grid-wrapper from scrolling.

v1.77.1
2026-03-29 15:25:21 +02:00
517798ce6c feat: fade/blur header text on hover + fix iOS scroll freeze during calendar fetch
- Header center (KW/year/goal/quote) now fades to 20% opacity and blurs
  on hover so the controls behind it are readable on smaller screens
- Fix iOS scroll freeze: touchmove listener on grid slots was non-passive,
  causing Safari to wait ~20s (iCloud sync duration) before allowing scroll;
  now attaches a passive listener initially and only upgrades to non-passive
  when the long-press drag actually activates (after 500ms hold)

v1.77.0
2026-03-29 14:43:23 +02:00
bf61733317 fix: eliminate iOS scroll bounce by using single scroll container for time grid
The time grid previously had two separate overflow-y:auto scroll containers
(the time-column labels + the day columns grid), synced via JS scrollTop
assignment. On iOS Safari, this caused severe desync and bounce effects:
momentum scroll continued after touch-end, and the programmatic scrollTop
correction fought against native momentum, making the grid stutter/bounce.

Changes:
- time-grid-wrapper is now the SINGLE overflow-y:auto scroll container
  (ref=gridRef, onScroll handler moved here from weekly-days-grid)
- time-column and weekly-days-grid have overflow:visible — they scroll
  with their parent wrapper without fighting each other
- Removed handleTimeColumnScroll, timeColumnRef, timeGridWrapperRef
  (all sync logic now redundant)
- jumpToHour and initial scroll position now set only gridRef.scrollTop
- CSS: weekly-days-grid overflow changed to visible
- CSS: re-enabled position:sticky on .weekly-day-header for mobile —
  sticky now works correctly since scroll container is an overflow-y parent
- CSS: hid time-column-header on mobile (saves vertical space)

v1.76.2
2026-03-29 11:32:47 +02:00
ba17025bb9 fix: sync showProjectIcons and showTaskCheckboxes between settings panel and quick toggle
Both settings were stored as per-view overrides by the full settings panel
but the quick sidebar toggles read/wrote the global profile value. The
per-view override took precedence in getEffective(), so global changes
from the quick toggle were silently ignored.

- Settings panel now calls saveField() (global profile) for these two
  settings instead of saveViewSetting() (per-view override)
- On change, also clears any stale per-view overrides via
  saveViewSetting(key, value, false) so the global value always wins
- Quick sidebar eye icons now reflect effectiveShowTaskCheckboxes /
  effectiveShowProjectIcons instead of the raw profile values

v1.76.1
2026-03-29 11:19:32 +02:00
620118e6d5 feat: add cross-provider calendar sync tool
Users can now create sync rules to automatically sync events between
any two connected calendar providers (Google, Apple, Outlook, Synology).

- New Prisma models: CalendarSyncRule + CalendarSyncMapping
- Sync engine in src/lib/calendar-cross-sync.ts: fingerprint-based
  change detection, anti-loop protection, one-way and two-way support
- API routes: GET/POST rules, PATCH/DELETE rule by id, POST run
- CalendarSyncRulesPanel component with rule list, add/edit form,
  toggle enable/disable, Sync Now button with result summary
- New "Sync" tab in settings sidebar (between Connections and Account)
- Sync rules run automatically after each forced calendar cache refresh

v1.76.0
2026-03-29 10:58:07 +02:00
d8c30cdb1f fix: double event on recurring create + mobile sticky day bar
- Skip optimistic UI update for new recurring events (causes duplicate
  when force-sync fetches expanded instances with different IDs)
- Mobile sticky day bar: listen on gridRef scroll instead of window
  (time-grid scrolls inside weekly-days-grid, not window)
- Remove broken position:sticky from mobile day headers (CSS sticky
  doesn't work inside CSS grid scroll containers); use fixed overlay only
- Also propagate isRecurring flag in create response for Google/Outlook

v1.75.8

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 09:34:09 +02:00
51301bc497 fix: redesign recurring delete as overlay with loading indicator
Replace inline delete buttons (Dieses/Künftige/Alle) with a proper
overlay dialog matching the recurring edit overlay style. Shows animated
dots on the active delete option while processing. Other options dim
during deletion.

v1.75.7

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 12:09:20 +01:00
de3b4a103e fix: show midnight hour label without shifting task positions
Remove translateY on first time-slot-label only (via :first-child) instead
of adding padding-top which broke task alignment. Reverts padding approach.

v1.75.6

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 11:16:08 +01:00
b126328536 fix: show midnight "0" hour label - was clipped above scroll area
The first time-slot label's translateY(-50%) pushed it above the container
top edge. Added padding-top to time-column-slots and time-slots-container,
and disabled the translate on the first label. Reverted 00→0.

v1.75.5

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 11:06:03 +01:00
94747a9508 fix: display midnight hour as "00" instead of "0" in time grid
v1.75.4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 10:59:36 +01:00
77e8e87b90 fix: eliminate extra iCloud login during sync - use stored calendars
Apple sync was doing 2 logins per cycle: getAppleCalendars (to get calendar
list for filtering) + getUpcomingEventsBatch (to fetch events). Now uses
stored calendar metadata from DB for filtering, reducing to 1 login total.

Same optimization applied to Synology. Also adds 24:00 end-of-day line
to time grid, and throttles tab-focus sync to max once per 5 minutes.

v1.75.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 10:58:09 +01:00
f6e158af8f fix: reduce iCloud CalDAV connections to prevent rate limiting
- Apple/Synology: batch fetch events with single client login instead of N separate connections
- Apple: add client cache (5min TTL) to reuse authenticated DAVClient across operations
- Apple: add retry with backoff for transient ConnectTimeoutError/SSL failures
- Increase cache stale threshold from 2min to 15min
- Increase background sync interval from 2min to 15min
- Throttle tab-focus sync to at most once per 5min

v1.75.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 09:35:25 +01:00
62848255d7 fix: remove visible hours UI controls
The scrollable time grid already shows all 24 hours and auto-scrolls
to the preferred start hour on load, making the start/end hour
filter controls redundant. Removed from sidebar, header, and
full settings modal.

v1.75.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 21:05:02 +01:00
c05b31d1c6 feat: mobile sticky day bar overlay using IntersectionObserver
Instead of relying on CSS position:sticky (unreliable on iOS Safari),
adds a fixed overlay bar at the top of the viewport that shows the
current day name as the user scrolls through stacked day columns.
Uses IntersectionObserver to track which day header is near the
viewport top. Appears after scrolling past 80px, with blur backdrop.

v1.75.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 18:57:15 +01:00
11e7b14c17 fix: add debug logging for Outlook recurring event updates
Log the event ID decomposition, update payload, and Graph API
response status to diagnose why recurring event updates aren't
persisting for Outlook.

v1.74.8

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:39:50 +01:00
59778d34fa fix: faster calendar sync - 2min interval, sync on tab focus
- Reduced cache stale threshold from 15 minutes to 2 minutes
- Reduced background sync polling from 15 minutes to 2 minutes
- Added visibilitychange listener: syncs calendars and tasks when
  the user switches back to the tab (catches external edits in
  Apple Calendar, Google Calendar, etc.)

v1.74.7

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 13:28:00 +01:00
e4c1208b29 fix: targeted sync after event changes - only refresh affected provider
Instead of force-refreshing all calendar providers after create/update/delete,
now only the specific connection that owns the modified calendar is refreshed.
This significantly speeds up recurring event operations when multiple
providers are connected.

v1.74.6

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 13:05:39 +01:00
245fed5f81 fix: match event font to task font (family, size, weight)
Calendar events now use --weekly-task-font, --weekly-task-size,
and --weekly-task-weight instead of separate event font variables,
so events and tasks always look consistent.

v1.74.5

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:57:34 +01:00
b6d39910e5 fix: animated dots on save button while creating events
Dots pulse sequentially (. . .) to give clear visual feedback
that the operation is still in progress.

v1.74.4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:43:33 +01:00
2f973bf8af fix: show provider icon on all events, better save button feedback
- Always show provider icon (Google/Apple/Outlook/Synology) at
  bottom-right of event blocks using FontAwesome icons
- Save button shows "Erstelle..." / "Creating..." while saving
  instead of just "..." to reduce user confusion during sync

v1.74.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:31:36 +01:00
3b1deb80e1 fix: force sync after all calendar event operations
All create, update, and delete operations now trigger an immediate
forced refresh from providers instead of relying on stale cache.
Previously, deleting recurring events left ghost instances visible
until the next background sync cycle.

v1.74.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:10:27 +01:00
8d8ba73d17 fix: provider icon in event modal, hide synology URL, recurring event display
- Show provider icon (Google/Apple/Outlook/Synology) left of calendar color dot
- Hide URL field when Synology calendar is selected (not supported)
- Force refresh after creating recurring events so all instances show immediately
  (previously only the first occurrence appeared until next sync cycle)

v1.74.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:42:26 +01:00
cfa4fb023c feat: redesign calendar event modal for mobile
Compact, icon-driven layout inspired by Google Calendar:
- Icon-row layout with left-aligned icons for each field
- Color accent bar and save button match selected calendar color
- Toggle switch for all-day instead of checkbox
- Compact From/To time inputs
- Tighter spacing throughout, smaller font sizes
- German translations for all labels
- Footer bar with subtle background
- Shorter delete buttons for recurring events (This/Future/All)

v1.74.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:27:06 +01:00
fbeb4db990 fix: sticky day headers on mobile, reorder FAB menu
- Fixed weekly-days-grid applying fixed height in non-time-grid views
  (simple/list), which broke the scroll context for sticky headers
- Reordered mobile FAB menu: Aufgabe, Termin, Projekt, Fokus, Suchen
- Changed "Suche" to "Suchen" in FAB menu

v1.73.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 03:04:43 +01:00
8926fe27c2 fix: restore sticky day headers on mobile in simple view
overflow-x: hidden on .simple-view .weekly-day-column was creating a
scrolling context that broke position: sticky on the day header.
Changed to overflow-x: clip which clips content without affecting sticky.

v1.73.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 02:57:11 +01:00
dd16e5604a fix: restore sticky day headers on mobile
Non-passive touchmove listener was permanently attached to document,
breaking browser scroll optimizations. Now only attached during active
long-press and removed immediately after.

v1.73.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 02:38:02 +01:00
98a47a62de feat: long-press drag-to-create calendar events on mobile
Tap and hold (~500ms) on an empty time slot to activate, then drag to
select time range. Opens calendar event modal with pre-filled times.
Includes haptic vibration feedback on activation. Normal tap and scroll
gestures are not affected.

v1.73.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 02:29:19 +01:00
39934d23bf fix: rolling tasks now properly avoid overlapping existing tasks
Collision detection rewritten to check duration-based overlap instead
of exact startTime match. Rolling tasks find the next truly free slot.

v1.72.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 02:12:05 +01:00
e1190a8fe6 fix: attach calendar color to created/updated events for cache + frontend
Events created or updated via the API were missing the calendar's
backgroundColor, causing them to render without their provider color.

v1.72.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 02:10:11 +01:00
08959c6ddb feat: drag-to-create calendar events, fix rolling tasks, fix Outlook recurring
- Drag on empty time slots to create calendar events with pre-filled time range
- Rolling tasks now work per-task without requiring global autoRolling setting
- Add firstDayOfWeek to Outlook weekly recurrence patterns
- Add debug logging for Outlook recurrence creation

v1.72.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 01:56:16 +01:00
131f92bd72 fix: Outlook event timezone offset on create/update responses
Outlook Graph API returns datetimes in the user's timezone without Z suffix
by default. The sync path already requested UTC and appended Z, but
create/update responses did not. This caused the optimistic UI update to
show events 1 hour off until the next sync corrected it.

Fix: add Prefer: outlook.timezone="UTC" header to create/update calls
and normalize response datetimes with Z suffix.

v1.71.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 00:03:17 +01:00
92593cf616 fix: prevent Prisma connection pool exhaustion in production
Cache PrismaClient globally in ALL environments (was only cached in dev).
Without this, production could create multiple PrismaClient instances,
each with its own connection pool, exhausting the database connections.

v1.71.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 23:17:29 +01:00
e1e31cef20 fix: use updateCalendarObject instead of updateObject for CalDAV updates
iCloud returned 501 Not Implemented for updateObject calls.
Switch to updateCalendarObject which properly sends CalDAV PUT requests.
Fixed in both Apple Calendar and Synology Calendar update + recurring delete paths.

v1.71.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 22:27:35 +01:00