Commit Graph

304 Commits

Author SHA1 Message Date
8ffb6a0690 feat: accessibility follow-up — heading hierarchy, keyboard resize, contrast fix
- Fix heading hierarchy: modal titles h3→h2 (RecurrenceModal, two WeeklyView dialogs),
  SettingsSidebar h4→h3 for Localisation, Data Export, Backup & Restore sections
- Add keyboard resize handle: role=slider, tabIndex, aria-valuemin/max/now/text,
  ArrowUp/Down keys to adjust task duration in 15-min increments
- Add aria-label to CalendarEventModal notes textarea fallback
- Color contrast: raise --weekly-text-light from #a6a6a7 (~2.4:1) to #767676 (~4.5:1)
  on white background to meet WCAG AA

v1.86.0
2026-04-06 00:25:08 +02:00
5c01869444 feat: comprehensive accessibility pass — ARIA, focus traps, keyboard move, live regions
- Modals (SearchModal, ImportListModal, CalendarEventModal): role=dialog,
  aria-modal, aria-label, focus trap via keydown Tab handler, aria-hidden on backdrop
- OnboardingWizard: role=dialog on card, aria-hidden on overlay, aria-current=step
  on progress dots wrapped in <nav><ol>, aria-label on nav buttons
- GridTaskBlock: aria-label on all ~12 action buttons (complete, edit, add subtask,
  notes, rolling, recurrence, project, link, delete, move), aria-expanded/aria-pressed
  where applicable, aria-hidden on all decorative SVGs, aria-label on inline edit
  textarea and subtask inputs; note indicator div → button
- Keyboard task move: new "Move Task" dialog in GridTaskBlock with date+time
  inputs, routed via onMoveTask prop → moveTaskToSlot in WeeklyView
- WeeklyView: visually-hidden aria-live="polite" region with announce() helper;
  announces task add, complete/incomplete, delete, sync complete/failed
- Forms: aria-invalid + aria-describedby + role=alert on error paragraphs in
  TaskForm; auth error div gets id + role=alert; email input gets aria-describedby;
  show/hide password button gets aria-label + aria-pressed
- Spinners: role=status + aria-label on standalone spinners (TaskItem delete,
  WeeklyView sync); aria-hidden on inline button spinners (AuthForm, TaskForm,
  CalendarSettings, SettingsSidebar, EmailAuthForm)
- layout.tsx: Open Graph and Twitter Card meta tags added

v1.85.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 18:18:08 +02:00
2016b1cb18 fix: weather sidebar toggle — remove sub-checkboxes, fix toggle reliability
Remove the per-field weather checkboxes from the quick-settings sidebar;
those belong in the full settings modal only.

Also make the toggle more reliable: it now updates both the per-view
viewSettings override (saveViewSetting) AND the local profile state
(setProfile) so that effectiveWeatherEnabled is guaranteed to flip on
the next render regardless of which branch getEffective() takes.

v1.83.4
2026-04-05 12:42:41 +02:00
b6c47c81b3 fix: show weather sidebar section when weatherEnabled even without location
The previous condition only checked weatherLat || weatherLon, so users
who enabled weather in settings but hadn't picked a city yet would never
see the sidebar toggle. Now shows if weatherEnabled OR lat/lon is set.

v1.83.3
2026-04-05 12:35:57 +02:00
1a44f769a7 feat: add weather display checkboxes to left sidebar quick-settings
When weather is enabled and a location is configured, the sidebar now
shows per-item checkboxes (Symbol, Temperatur, Gefühlt, Wind, Böen,
Regenw., Niederschlag, Luftfeuchte, UV) below the weather toggle.
Checkboxes are hidden when weather is toggled off. All changes go
through saveViewSetting("weatherDisplay", ..., true) — same path as
the settings modal — so they stay view-specific and persist correctly.

v1.83.2
2026-04-05 12:28:48 +02:00
55c21ff6a6 fix: sidebar toggles now correctly update per-view settings
Someday, All-day, Checkboxes, Project-Icons, and Weather toggles in the
left quick-settings panel were calling saveSetting() (global profile PATCH)
instead of saveViewSetting(..., true) (per-view override).

getEffective() checks the per-view override first, so whenever a per-view
setting existed (set via the settings modal) the global update was silently
ignored and the toggle appeared broken.

All five toggles now call saveViewSetting(key, !value, true) which updates
viewSettings[currentView][key] directly — matching exactly what the settings
modal's view-tab checkboxes do.

v1.83.1
2026-04-05 12:14:52 +02:00
a6a1a68c73 feat: upgrade notes/url to full sidebar+kanban coverage, fix onNotes save bug, harden URL sanitization
- Fix onNotes prop in all three TaskItem render sites: was calling
  setSelectedTaskForNotes (ignoring HTML), now correctly calls
  updateTaskNotes so inline RichTextEditor saves on every change
- NotesSidebar: replace plain markdown textarea+toolbar with RichTextEditor;
  add URL field with open/clear actions
- Kanban detail modal: add URL field; replace plain textarea with RichTextEditor
- Tasks API: add sanitizeUrl() helper — strips javascript:/data: schemes,
  normalises missing protocol to https:// before storing
- Remove dead code in TaskItem: notesRef, handleNotesBlur, insertMarkdown
  (all replaced by RichTextEditor)

v1.83.0
2026-04-05 11:59:44 +02:00
388618e62c fix: URL and rich-text notes now work in someday area tasks
TaskItem (used for all someday list tasks) was missing URL support entirely.
Added:
- onUrl prop wired to updateTaskUrl at both someday TaskItem render sites
  (slot tasks and unindexed/remaining tasks)
- URL indicator (clickable link badge) shown inline on the task row
- Link action button in the task-actions bar that opens an inline URL editor
- URL popup with input, clear button, and open-in-new-tab shortcut

Also upgraded TaskItem's notes editor from plain markdown textarea to
RichTextEditor (same as GridTaskBlock), so inline hyperlinks in notes work
in the someday area too.

v1.82.1
2026-04-05 11:43:57 +02:00
7bc43d3c98 feat: add hyperlink support to tasks
Option A — URL field per task:
- New url String? column in Task schema (migration: 20260403_add_task_url)
- Link icon button in GridTaskBlock action bar; click to open inline URL popup
  with input, clear (×) button, and open-in-new-tab shortcut
- Blue link indicator shown inline on the task card when a URL is set
- updateTaskUrl() in WeeklyView persists to DB via PATCH /api/tasks

Option B — Rich text notes with inline hyperlinks:
- GridTaskBlock notes popup upgraded from plain markdown textarea to
  RichTextEditor (Tiptap), which already has bold/italic/underline/
  bullet/blockquote/link toolbar and full link support
- Notes now save on every change via onChange (no blur required)

v1.82.0
2026-04-03 15:04:44 +02:00
f94f83af73 fix: restore project icons and persist someday tab assignments across reconnects
Project icons (faHeart, faBriefcase etc.) were rendering as literal text in
GridTaskBlock because the lookup skipped the legacy "faX" → "x" normalization
that ProjectIcon does. Added the same normalization before allIcons.find().

Someday list tabs now survive provider disconnects and reconnects:
- customTabs (empty tabs) saved to viewSettings in DB instead of localStorage only
- assignListToTab saves a title→tab mapping in viewSettings.somedayTabPrefs
- Profile load merges DB customTabs with localStorage for migration
- Import route reads somedayTabPrefs and auto-applies tab when creating/
  relinking a SomedayList by title match

v1.81.20
2026-04-03 11:11:11 +02:00
4cab83e545 fix: slot buttons now update the time grid via saveViewSetting
The SettingsSidebar stores cellDuration in viewSettings (per-view) via
saveViewSetting, so getEffective() returns that value and ignores local
state. The QuickSettings/header/mobile buttons were only calling
setCellDuration (local state) + saveSetting (cookie), which getEffective
overrides. Now all three button groups also call saveViewSetting so the
grid immediately reflects the selected slot size.

v1.81.18
2026-04-02 22:58:15 +02:00
ca67817b7b fix: revert slot options to 15/20/30/60, fix sidebar indicator
- Removed 45m, restored 60m in CellDuration type and all button groups
- Slot indicator now correctly highlights the active slot in the sidebar
  (was broken because 60m users had no matching button when 45 was listed)

v1.81.17
2026-04-02 22:51:01 +02:00
6f45140d26 feat: add 45m slot option, replace 60m in sub-hour controls
- CellDuration now includes 45 (15 | 20 | 30 | 45 | 60)
- getTimeSlots rewritten to use minutes-based generation so 45-min slots
  work correctly (08:00, 08:45, 09:30, 10:15...) — also cleaner for all
  other durations
- getSlotHeight(45) = 45px (1px per minute, proportional)
- All three slot button groups (sidebar, desktop header, mobile) now show
  [15, 20, 30, 45] instead of [15, 20, 30, 60]

v1.81.16
2026-04-02 22:43:01 +02:00
09caf5ffa0 fix: email-based user lookup, slot controls, sub-hour toggle
API routes (goal, weather, calendar/sync, calendar/events):
- All user lookups now use session email instead of session ID so stale
  JWTs after DB restore/migration no longer break requests (P2003 FK error)

WeeklyView QuickSettings sidebar:
- effectiveCellDuration now uses local cellDuration state as fallback
  instead of stale profile.cellDuration — slot buttons now actually update
  the time grid
- Added 20m slot option to all three button groups (sidebar, header, mobile)
- Added :15/:30/:45 sub-hour slots toggle to QuickSettings sidebar
- Slot controls now highlight using effectiveCellDuration (per-view aware)
- Someday and All-day toggles now use effective value, not global profile

v1.81.15
2026-04-02 22:34:26 +02:00
86c462c920 fix: all-day label top-aligned, weather 502 silent, toggle consistency
- All-day label column uses flex-start so label is visible in small area
- Weather API returns empty data (200) instead of 502 when forecast range
  is out of bounds, suppressing console noise on future/past navigation
- QuickSettings toggles for project icons and checkboxes now use effective
  (per-view-aware) value, consistent with other toggles

v1.81.13
2026-04-02 13:10:25 +02:00
091004e87e fix: all-day badge shows count for visible days only
Previously showed total allDayEvents.length (all events in the loaded
week). Now counts unique events that appear on at least one currently
visible day column, so in 1-day view it shows that day's count, in
3-day view the count across those 3 days, etc.

v1.81.12
2026-04-02 10:39:51 +02:00
024ceaf255 chore: remove redundant Zeitplan/Schedule toggle from QuickSettings
The showTimeGrid toggle is now implicit in the view style selector
(list → grid off, simple/calendar → grid on), making the explicit
Schedule eye toggle obsolete.

v1.81.11
2026-04-02 10:36:58 +02:00
1201e3f169 fix: remove stray .profile. dereference causing TypeError on SSE sync
Line 2243 read data.user.profile.viewStyle — data.user.profile is
undefined (the shape is data.user.viewStyle), causing:
  TypeError: Cannot read properties of undefined (reading 'viewStyle')
This crash fired every time the SSE sync callback received new data.

v1.81.10
2026-04-02 10:35:42 +02:00
076211720f fix: hide redundant weekday header when selected-day header + single column
When the active header display is 'current_day' (selected day) AND
viewDays === 1, the in-column weekday header duplicates the information
already shown in the top header bar. Added 'header-current-day-single'
class to the container under that condition, then CSS display:none on
.weekly-day-header. With multiple columns visible the header is shown
normally so each day column is still identifiable.

v1.81.9
2026-04-02 10:31:47 +02:00
676c5612ed fix: 4 mobile issues — slot indicator, view days, list header, scroll sync
1. cellDuration indicator: compare against local `cellDuration` state
   (not effectiveCellDuration which reads stale profile.cellDuration
   since saveSetting bails early for DEVICE_SETTINGS_KEYS)

2. viewDays on mobile now uses orientation instead of fixed width:
   portrait (h > w) → 1 day, landscape → 3 days, for ≤768px.
   Applied consistently in useEffect, early profile load, and cookie
   override blocks so the responsive value is never overridden by
   the saved DB preference on mobile.

3. list-view day header on mobile: changed from sticky to
   position:relative so it flows with content and never covers tasks

4. time/day column scroll sync: weekly-days-grid was overflow-y:auto
   on mobile, creating an independent scroll container that drifted
   from the time column. Changed to overflow-y:visible so only
   time-grid-wrapper scrolls. Added touch-action:pan-y to day columns
   so iOS handles pan immediately without waiting for JS.

v1.81.7
2026-04-02 09:29:48 +02:00
3657fb284f fix: reverse FAB menu order + persist iOS PWA session
- FAB menu items reordered so Task is closest to button (top),
  Search is furthest (bottom)
- auth.ts: session maxAge=30d + updateAge=1d so the JWT cookie is
  written as a persistent cookie (Max-Age header), preventing iOS
  PWA from losing the session when the app is closed/backgrounded

v1.81.5
2026-04-01 20:25:23 +02:00
ef7fbf4a9c feat: add weather toggle to QuickSettings sidebar
Shows a per-view weather Eye/EyeOff toggle in the left sidebar panel,
only visible when a weather location is configured.

v1.81.4
2026-03-31 10:16:09 +02:00
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
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
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
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
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
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
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
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
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
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
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
da2ebbedb5 feat: show location in events, fix HTML in notes, fix CalDAV TZID, reduce collapsed all-day space
- Strip HTML tags from descriptions before sending to CalDAV providers (Apple/Synology)
- Show event location underneath time in calendar event blocks (like Google Calendar)
- Fix German umlaut rendering by adding latin-ext font subset
- Fix CalDAV event updates losing TZID on DTSTART/DTEND (Apple Calendar recurring edit fix)
- Add error logging for CalDAV PUT responses
- Reduce wasted space when all-day events section is collapsed (24px max)
- Fix quotes with missing umlauts (ä, ö, ü, ß)

v1.71.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 22:14:21 +01:00
948d239867 feat: redesign recurring edit dialogs with Google Calendar style and i18n
- Redesigned drag/resize and modal recurring edit dialogs with radio buttons
  (This event / This and following / All events) with descriptions
- Added German/English i18n to both recurring edit dialogs
- Repeat-on day buttons now respect weekStartDay setting (Mon/Sun start)
- Added language prop to CalendarEventModal

v1.70.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 16:40:33 +01:00
74a8c9a9a9 feat: recurring event edit confirmation (this event / all events)
When editing a recurring calendar event (via modal or drag/resize),
the user is now asked whether changes apply to just this instance or
all events in the series.

- Modal: Save button shows "This event" / "All events" options for
  recurring events
- Drag/resize: centered overlay prompt with same options + cancel
- API PATCH: editMode=all routes update to the series master ID
  (recurringEventId) instead of the instance ID
- Cancel on drag prompt reverts to original position

v1.69.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:41:21 +01:00
ff3d458b6d fix: reduce external API calls ~10x by optimizing sync intervals
Root cause: background calendar sync every 2min with forceRefresh:true
+ task sync every 5min + cache stale threshold of 2min = 12,500+
Google Calendar + 8,800 Google Tasks API calls/day for a single user.

Changes:
- Calendar background sync: 2min → 15min
- Task sync polling: 5min → 15min
- Cache stale threshold: 2min → 15min
- Remove forceRefresh:true from background sync (let staleness check
  decide naturally)
- Remove redundant 8s re-fetch after background sync
- User actions (create/update/delete) still sync immediately

Expected reduction: ~10-15x fewer external API calls.

v1.68.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:35:22 +01:00
13bd90bd2a fix: cross-day drag-and-drop + persist showCalendarProviderIcon setting
- Cross-day drag now works: getEventsForSlot uses drag state's current
  start time to assign the dragged event to the correct day column
- Add showCalendarProviderIcon to Prisma schema, profile API GET/PATCH
  so the setting persists across sessions (was frontend-only before)
- DB migration applied via prisma db push

v1.68.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:30:42 +01:00
343cc87e4d fix: strip HTML tags from event description in note tooltip
Calendar providers return descriptions with HTML tags (e.g. <p>test</p>).
Strip them before displaying in the hover tooltip.

v1.67.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:26:58 +01:00
1e789d93ae feat: cross-day drag, note icon, Google recurring fix, no popup on drag
- Fix Google recurring events missing isRecurring flag (recurringEventId
  was not mapped from Google API response)
- Add note icon (FileText) on events with descriptions, tooltip on hover
- Cross-day drag-and-drop: detect day column under cursor and shift date
- Fix event detail popup opening after drag/resize by setting ref before
  async operations
- Add data-date attribute to day columns for drag target detection
- Use CSS class for icon row layout to prevent overlap

v1.67.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:03:33 +01:00
dbe60dd331 fix: deduplicate recurring event masters vs expanded instances
Recurring events appeared twice on their creation day because both the
series master (from POST cache) and the expanded instance (from sync)
had different IDs. Now filters out masters when instances exist, and
also deduplicates by title+startTime+calendarId as a fallback.

v1.66.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:55:39 +01:00
13de53fe0a feat: drag-to-move and resize handles for calendar events
Add resize handles (top/bottom) on hover to change event duration, and
drag-to-move support with live preview and 5-minute snapping. Includes
3px dead zone to distinguish clicks from drags, optimistic UI updates
with server rollback on failure, and recurring/provider icons on
time-grid events. Also fixes Google delete 410 Gone and Outlook delete
404/encodeURIComponent issues.

v1.66.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:35:01 +01:00
ba4f1ca280 feat: overlapping calendar events side by side + Outlook delete fix
- Overlapping calendar events on the same time slot are now rendered
  side by side instead of stacked on top of each other. Uses a greedy
  column assignment algorithm to compute layout per day.
- Outlook delete/update: use /me/events/{id} as primary endpoint
  (without encodeURIComponent) instead of calendar-scoped endpoint,
  with fallback. Fixes ErrorItemNotFound for recurring series masters.

v1.65.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:06:00 +01:00
e00834e0bb feat: optional provider icon on calendar event blocks
Adds a toggle in Calendar settings to show the provider icon
(Google/Apple/Outlook/Synology) in the bottom-right corner of
calendar event blocks. The recurring icon is grouped alongside
when both are visible.

v1.64.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:56:49 +01:00
c69a7d92a8 fix: show timezone in Localisation settings
Display the browser-detected timezone (e.g. Europe/Berlin) as a
read-only field in the Localisation settings tab.

v1.63.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:38:39 +01:00
fb7484c357 fix: CalDAV TZID parsing + recurring event icon on all providers
- Add icalTimeToUtcDate() helper to Apple/Synology parsers that
  correctly converts ICAL.Time with unresolved TZIDs to UTC dates
  (fixes +1h shift on Synology/Apple recurring events across DST)
- Add recurring icon (Repeat) to bottom-right of all calendar event
  blocks when event.isRecurring is true

v1.63.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:24:38 +01:00
6584b9c266 feat: add 'This & past' recurring event delete option
Adds a fourth delete option for recurring events: delete this instance
and all past occurrences. For CalDAV (Apple/Synology), this moves
DTSTART forward to the next occurrence. Includes optimistic UI removal.

v1.63.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 00:40:48 +01:00
8abbf4a286 fix: Outlook UTC date parsing and event deduplication
- Outlook returns dateTime without Z suffix despite timeZone being UTC,
  causing JS to parse as local time (1h shift). Now appends Z for UTC dates.
- Added frontend deduplication to prevent stacked rendering of duplicate events.
- Added Outlook event debug logging for recurring event investigation.

v1.62.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 00:22:56 +01:00
c302a036bb fix: pass isRecurring/recurringEventId for Google and Outlook events
Google and Outlook event mappings were missing isRecurring and
recurringEventId fields, so the modal never showed recurring delete
options and displayed recurring events as "Repeat: Never".

v1.62.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 23:49:40 +01:00
57eeb3d8e8 feat: recurring event delete options (this/future/all instances)
When deleting a recurring calendar event, users now choose between
deleting just this instance, this and future instances, or all instances.
Supports Google, Apple (iCloud), and Synology CalDAV providers.

v1.62.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 22:06:23 +01:00
1011aef639 fix: recurring event DST time shift and block height overflow
- Use TZID-based local time (instead of UTC 'Z') for DTSTART/DTEND
  when creating recurring CalDAV events, preventing DST-related time
  shifts (e.g. 13:40 CET showing as 14:40 CEST after clock change)
- Send browser timezone from CalendarEventModal to server
- Guard against NaN event duration (missing/invalid endTime) which
  caused event blocks to stretch to end of day

v1.61.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 21:23:24 +01:00
c5dc315f82 feat: sync calendar colors from all providers and add custom recurrence
- Store calendar colors (backgroundColor) from Apple and Synology
  during connection setup
- Auto-refresh missing colors for existing Apple/Synology connections
- Show color dots next to calendar names in settings
- Add "Custom..." recurrence option with interval (every N days/weeks/
  months/years) and day-of-week selection for weekly recurrence
- Generate proper RRULE with INTERVAL and BYDAY for all providers
- Generate proper Outlook Graph recurrence with custom intervals

v1.61.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:35:22 +01:00
6fc0ccef74 fix: inline project icons so multi-line text wraps around them
Move project icons from flex siblings into the text span so that
multi-line task titles wrap around the icon instead of leaving
empty space below it.

v1.59.4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 13:58:43 +01:00
b6f5ba42ed fix: show project icons in time grid (GridTaskBlock) view
Add showProjectIcons prop to GridTaskBlock so project icons appear
next to task titles in simple and calendar views, not just list view.

v1.59.3
2026-03-23 13:17:06 +01:00
ccd069ae80 fix: add 'Show Icons for Projects' toggle to settings modal
Per-view setting with translations in all 5 languages (EN, DE, FR, ES, IT).

v1.59.2
2026-03-23 12:45:35 +01:00
b26d710fec fix: move sidebar toggle into header toolbar, left of view switcher
Removes the fixed-position button and places it inline in the desktop
header controls row with matching hover-to-reveal behavior.

v1.59.1
2026-03-23 12:38:38 +01:00
d7eeafb08f feat: add 'Project Icons' toggle to show icons on tasks
New per-view setting to display project icons next to task titles in
simple, calendar, and list views. Toggle via Quick Settings sidebar,
similar to the existing 'Checkboxes' toggle.

v1.59.0
2026-03-23 12:31:19 +01:00
9093149f5e feat: improved icon picker with search, FontAwesome and MDI icons
Replace the small grid of ~45 icons with a searchable IconPicker component
featuring ~250 icons from FontAwesome and Material Design Icons. Includes
keyword search, library tabs (All/FA/MDI), and categories covering tech,
home, sports, food, nature, finance, health, and more.

v1.58.0
2026-03-23 11:13:21 +01:00
7e11b261a3 fix: move sidebar toggle button from bottom-left to top-left
v1.57.16
2026-03-23 10:29:38 +01:00
3da2acadf1 fix: project picker dropdown stays visible and above other tasks
Add picker-open class when project picker is shown to keep task-actions
visible even when mouse leaves the task hover area. Elevate z-index on
picker-open tasks so the dropdown isn't obscured by adjacent tasks.

v1.57.15
2026-03-23 10:28:17 +01:00
87aeb8ad47 fix: someday list delete buttons obscured by task items below
Raise z-index on the list header when delete confirmation is active
so Cancel/Delete buttons render above the task list items.

v1.57.10

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 00:37:24 +01:00
21a0547f3d fix: hide add-task input when someday list delete confirmation is shown
The "Add task..." input was overlapping the Cancel/Delete buttons,
making it impossible to click Delete.

v1.57.9

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 00:30:39 +01:00
3ec5a21714 fix: Apple Calendar ignoring selection state, causing duplicate events
Apple calendar events were fetched from ALL calendars regardless of the
user's Display checkbox selection. Now respects the stored selected state,
matching the behavior of Synology/Google/Outlook providers.

Also reverts the title-based deduplication which was too aggressive.

v1.57.7

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 00:12:28 +01:00
98f1c751e5 fix: deduplicate calendar events appearing in multiple calendars
Events with the same title, start, and end time from different calendars
are now shown only once instead of duplicated in the all-day and time grid.

v1.57.6

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 00:03:47 +01:00
ee4b540558 feat: add Notion provider integration + Apple Reminders deprecation note
- Notion OAuth integration: start/callback routes, calendar-events dispatch,
  CRUD operations (create/update/delete via Notion API)
- New notion-calendar.ts provider library with database discovery
- Onboarding wizard: expanded to 6 steps (header/tasks/display design),
  improved preview fidelity, universal dummy content, Notion in connect step
- Apple Calendar: label changed to "events only", added warning that
  Reminders are unsupported since iOS 13 (no CalDAV/API from Apple)
- Fixed 12h time format on now-line, wizard settings apply on completion

v1.57.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:02:25 +01:00
4ac73d3e03 feat: onboarding wizard for first-time users + UI fixes
- 6-step onboarding wizard (welcome, language, connect providers,
  view style, work hours, styling) for new signups
- Added hasCompletedOnboarding field to User schema
- Fixed subtask progress bar in GridTaskBlock (simple/calendar views)
- Fixed kanban drag-and-drop to someday area
- Fixed weather/provider icon overlap in time grid tasks
- Provider icon positioning: inline when weather on, top-right when off

v1.56.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:52:29 +01:00
452e1a0eab fix: make subtask progress bar more visible (wider + taller)
Increased progress bar from 24x4px to 36x5px for better visibility
in the task subtask indicator badge.

v1.55.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 08:43:13 +01:00
1f90526b5b fix: improved subtask expand/collapse in calendar and kanban views
Kanban cards now have inline subtask expand/collapse with progress bar,
chevron toggle, and checkbox list. Calendar view subtask badge updated
to match with ChevronDown icon, highlight when expanded, and wider
progress bar. Consistent UX across both views.

v1.55.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 08:34:43 +01:00
22a193180b fix: kanban detail modal footer layout - delete left, OK/Cancel right
Move trash icon to lower-left corner, add OK and Cancel buttons
in the lower-right corner.

v1.55.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 08:29:25 +01:00
ca7911c7ef feat: kanban card detail modal with full task editing
Click any kanban card to open a Trello-style detail modal with:
- Title editing
- Project assignment with dropdown
- Kanban stage selector
- Due date picker
- Someday list assignment
- Markdown notes editor
- Subtask management (add, toggle, edit, delete)
- Task deletion
Responsive design: slides up as bottom sheet on mobile.

v1.55.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 22:31:10 +01:00
aece7049c0 fix: make kanban cards clickable to open notes/details sidebar
Clicking a kanban card now opens the notes sidebar for editing notes,
subtasks, and other task details. Cards also show subtask count and
notes indicator. Added FileText icon import.

v1.54.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 19:42:20 +01:00
bce86aeb9b feat: kanban task creation and Google Tasks API quota optimization
Add inline task creation in kanban view columns - creates tasks in a
"Kanban" someday list (or project-named list if filtered by project).
Optimize Google Tasks sync: use updatedMin to fetch only changed tasks,
increase sync interval to 5min, handle 429 quota errors gracefully.

v1.54.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 19:28:15 +01:00
876bd1047b feat: real-time sync across devices via Server-Sent Events
Adds SSE-based push notifications so changes made on one device
appear instantly on all other connected devices for the same user.

- SSE notification hub (src/lib/sse.ts) with per-user client tracking
- Stream endpoint (/api/events/stream) with 30s heartbeat
- Task and list API routes notify connected clients on mutations
- Client auto-connects with 5s reconnect on connection loss
- Existing 2-minute polling sync remains as fallback

v1.53.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 07:44:00 +01:00
234bb25c1e feat: configurable weather display data per view
Users can now pick which weather data to show per time slot: icon,
temperature, feels like, wind speed, gusts, rain probability,
precipitation, humidity, and UV index. API now fetches all data
from Open-Meteo. Also fixed slot height for 20min duration.

v1.52.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 22:44:04 +01:00
a1f6166eb5 fix: replace 2h timeslot with 20min option
Timeslot options are now 15min (4/hr), 20min (3/hr), 30min (2/hr),
and 1h (1/hr). Removed the 2h option which didn't make sense.

v1.51.5

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 10:14:08 +01:00
918d87cbbb fix: credentials login error and all-day resize bar position
- Fix NextAuth CredentialsProvider + PrismaAdapter conflict by stubbing
  adapter session methods (JWT strategy doesn't use DB sessions)
- Improve login error handling with redirect:false for real error messages
- Move all-day section resize bar to top when allDayPosition is "below"
- Fix resize drag direction for top-positioned all-day handle

v1.51.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 09:02:26 +01:00
eeabe2c1c5 style: add icons to view style tabs in settings
Match the header view switcher icons (Calendar, CalendarDays, ListTodo,
Kanban) in the settings sidebar tab bar.

v1.51.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 08:35:50 +01:00