Commit Graph

1008 Commits

Author SHA1 Message Date
jubnl 0104ecfee8 fix(mobile): prevent bottom nav from clipping scrollable content and dialogs
- Add --bottom-nav-h CSS token (84px + safe-area on mobile, 0px on desktop)
  to give all fixes a single source of truth for the nav height
- Apply token to JourneySettingsDialog (fixes #650) and PlacesSidebar
  day-picker sheet so bottom-anchored sheets clear the nav bar
- Add paddingBottom to TripPlannerPage Bookings, Lists, and Budget tab
  scroll containers so content can be scrolled past the nav
- Bump Modal z-index from z-50 to z-[200] so modals render above the
  bottom nav (both share z-50 with nav winning by DOM order)
2026-04-15 02:16:57 +02:00
Julien G. a3f368d547 Merge pull request #656 from mauriceboe/fix/trip-date-preserves-day-content
fix(trips): preserve day content when trip date range changes
2026-04-15 01:34:41 +02:00
jubnl a438652a50 fix(trips): preserve day content when trip date range changes
Rewrites generateDays to remap days positionally by day_number instead
of matching by date identity. Previously any date range shift with no
overlap would cascade-delete all day_assignments, day_notes, and
day_accommodations.

New behaviour:
- Shift/partial overlap: existing days remapped to new dates in order
- Shrink: overflow days become dateless (date=NULL) instead of deleted,
  preserving all child data for manual reassignment
- Grow: existing days kept, new empty days appended
- Clear dates: all days nullified, content intact

Also fixes a UNIQUE(trip_id, day_number) collision that would occur when
spare dateless days remained after growing into a partially-dateless trip
(maxAssigned base was wrong).

Closes #646
2026-04-15 01:28:53 +02:00
Julien G. a8899a551b Merge pull request #655 from mauriceboe/fix/journey-settings-mobile-buttons
fix(journey): resolve mobile settings dialog issues on iOS PWA
2026-04-15 00:48:11 +02:00
jubnl f7da46c785 fix(journey): resolve mobile settings dialog issues on iOS PWA
- Add flex-wrap to settings footer so delete button stays visible when
  translated labels (Dutch, German, French) overflow the single row
- Replace no-op pb-safe class with env(safe-area-inset-bottom) inline
  style so dialog clears the iOS home indicator on iPhone

Fixes #648, #649
2026-04-15 00:33:22 +02:00
Julien G. 14b305c600 Merge pull request #654 from mauriceboe/fix/pwa-offline-session-and-file-downloads
fix(pwa): account for safe-area-inset-top in OfflineBanner so it's visible on phone PWA
2026-04-15 00:15:22 +02:00
jubnl be71425bb7 fix(pwa): account for safe-area-inset-top in OfflineBanner so it's visible on iOS PWA 2026-04-15 00:09:25 +02:00
Julien G. cf4052307d Merge pull request #653 from mauriceboe/fix/pwa-offline-session-and-file-downloads
fix(offline): complete offline data coverage after initial PWA implementation
2026-04-14 23:57:03 +02:00
jubnl 4e3b27c712 fix(offline): cache accommodations, trip members, tags, and categories for full offline support 2026-04-14 23:50:52 +02:00
jubnl 85d72c831d fix(offline): route reservations, budget, files, and FilesPage loads through repo layer 2026-04-14 23:40:49 +02:00
jubnl bb3543efa6 fix(offline): load trips from Dexie on dashboard when offline; fix offline tab i18n key 2026-04-14 23:34:28 +02:00
Julien G. 0e70857d78 Merge pull request #652 from mauriceboe/fix/pwa-offline-session-and-file-downloads
feat(pwa): real offline mode for TREK
2026-04-14 23:21:40 +02:00
jubnl d3b5ca451b fix(sync): monotonic createdAt in mutationQueue to prevent FIFO race on fast CI 2026-04-14 23:16:32 +02:00
jubnl b194e8317d feat(pwa): implement real offline mode with IndexedDB sync
Add genuine offline read/write capability for trips:

- Dexie IndexedDB schema (trips, places, packing, todo, budget,
  reservations, files, mutationQueue, syncMeta, blobCache)
- Repo layer for all domains: offline reads from Dexie, writes
  optimistically to Dexie and enqueue mutations for later replay
- Mutation queue with UUID idempotency keys (X-Idempotency-Key),
  FIFO flush, temp-ID reconciliation on 2xx, fail-and-continue on 4xx
- Trip sync manager: caches all trips with end_date >= today or null,
  auto-evicts 7d after end_date, fetches bundle endpoint in one request
- Map tile prefetcher: bbox from place coords, zooms 10-16, 50MB cap,
  warms SW cache via fetch
- Sync triggers: network online → flush + syncAll; WS reconnect →
  flush only (rate-limiter safe); visibilitychange/30s → flush only
- WS remoteEventHandler writes through to Dexie on every event
- Server idempotency middleware + idempotency_keys table (migration 100,
  24h TTL nightly cleanup)
- GET /api/trips/:id/bundle endpoint for efficient single-request sync
- OfflineBanner component: amber (offline) / blue (syncing) / hidden
- OfflineTab in Settings: cached trip list, re-sync and clear actions
- usePendingMutations hook for per-item pending indicators

Closes #505 #541
2026-04-14 23:04:25 +02:00
Isaias Tavares bb8783d217 Merge branch 'dev' into feat/login-language-detection-dropdown 2026-04-14 17:07:18 -03:00
jubnl 8c7567faf3 fix(pwa): fix offline session redirect and file download auth (#505 #541)
**#541 — File downloads broken in PWA standalone mode**
Replace getAuthUrl + window.open pattern with blob-based fetch using
credentials:include. The old approach minted a 60s single-use ephemeral
token then called window.open, which handed the URL to the system browser
on Android/iOS — losing the PWA cookie jar and producing "invalid or
expired token". The new approach fetches the file directly inside the
PWA WebView as a blob URL, so no auth handoff occurs.

New helper client/src/utils/fileDownload.ts with downloadFile and openFile.
Updated FileManager, ReservationsPanel, ReservationModal, PlaceInspector,
CollabNotes.

Security hardening in fileDownload.ts:
- assertRelativeUrl() guard prevents credentials being sent to external hosts
- openFile() checks blob.type against a safe-inline allowlist; HTML, SVG and
  other script-capable MIME types are forced to download instead of being
  opened inline, preventing same-origin XSS via blob URLs
- resp.ok check covers all non-2xx responses, not just 401

**#505 — PWA offline session lost on reload**
Wrap authStore with Zustand persist middleware, serializing only
{user, isAuthenticated} to localStorage key trek_auth_snapshot.
maps_api_key is intentionally excluded from the snapshot.

On cold start with no network: persist hydrates isAuthenticated:true,
App.tsx clears isLoading and calls loadUser({silent:true}), ProtectedRoute
renders the dashboard immediately. The network error from loadUser leaves
isAuthenticated intact so no login redirect occurs.

On 401 or logout: store state is cleared, persist writes
{isAuthenticated:false} — stale snapshot does not grant offline access
after session expiry.
2026-04-14 21:48:25 +02:00
Julien G. 1268d3e7b1 Merge pull request #632 from tiquis0290/bug/synology-thumbnail
fix: currently synology thumbnails resolve to error
2026-04-14 20:57:50 +02:00
Julien G. 80e1574c26 Merge pull request #643 from tiquis0290/fix/synology-adding-photos
fix: pagination in synology
2026-04-14 20:57:27 +02:00
Maurice 9cbe20cbde Merge pull request #647 from mauriceboe/fix/session-14042026-b
Journey Bug Fixes #2
2026-04-14 20:53:38 +02:00
Maurice fc6430d5ad Fix AddonManager test for provider sub-toggles under Journey addon
- Add journey addon to mock data so providers render under it
- Update toggle count assertion (journey + 2 providers = 3)
2026-04-14 20:47:30 +02:00
Maurice d6aa18c063 Fix pagination error handling and album scroll leak in provider picker (#644)
- Stop pagination on fetch error (set hasMore=false on non-ok response or catch)
- Set hasMore=false when loading album photos (albums load all at once)
- Hide ScrollTrigger when viewing album photos to prevent timeline photo leak
2026-04-14 20:37:25 +02:00
Maurice 563b338ee3 Fix journey settings dialog not scrollable on mobile (#626)
- Prevent background scroll-through with overscroll-contain and touch event handling
- Use bottom-sheet style on mobile (rounded-t, items-end) for better reachability
- Add extra bottom padding for mobile navbar safe area
- Close dialog when tapping overlay background
2026-04-14 20:35:12 +02:00
Maurice 5ea4095beb Fix content divider placed above paragraph instead of below (#624)
- Change divider from line-prefix action to insert action at cursor position
- Divider now inserts after the cursor with proper spacing
2026-04-14 20:31:47 +02:00
Maurice 81d3d6cc7d Fix local photos showing wrong provider label in gallery (#625)
- Guard provider badge with truthy check to handle null/undefined provider
- Use explicit provider name matching instead of binary immich/synology fallback
2026-04-14 20:30:16 +02:00
Maurice e695e0f62d Move memories providers under Journey addon in admin settings (#629)
- Remove memories providers from trip addons section
- Show Immich/Synology as sub-items under the Journey global addon
- Same pattern as bag tracking under packing list
2026-04-14 20:27:44 +02:00
Maurice 00e96baf0e Fix Stadia Maps 401 on journey and atlas maps (#640)
- Add referrerPolicy to JourneyMap TileLayer (matching trip planner behavior)
- Add referrerPolicy to AtlasPage TileLayer (same issue)
- Stadia Maps requires the referrer header for domain validation
2026-04-14 20:21:57 +02:00
Maurice 1a3407a218 Add show more/less button for long journal entries (#623)
- Show "Show more" button on both mobile and desktop when entry text is clamped
- Add "Show less" button when expanded to collapse back
- Add useTranslation hook to ExpandableStory component
- Add i18n keys common.showMore and common.showLess for all 14 languages
2026-04-14 20:17:52 +02:00
Maurice efeff0ba9e Add upload loading indicator for journey photos (#622)
- Show spinner and "Uploading..." text on photo upload button in entry editor
- Show spinner on gallery view upload button during upload
- Disable upload buttons while upload is in progress
- Add i18n key journey.editor.uploading for all 14 languages
2026-04-14 20:12:15 +02:00
Maurice b3571f391a Fix skeleton entry deletion and add hide suggestions toggle (#619)
- Revert filled skeleton entries back to skeleton on delete instead of permanently removing them
- Add per-user hide_skeletons preference on journey_contributors (migration 99)
- Add PATCH /journeys/:id/preferences endpoint for toggling skeleton visibility
- Add Eye/EyeOff toggle button with custom tooltip in journey detail header
- Filter skeleton entries from timeline when hidden
- Add i18n keys for all 14 languages
2026-04-14 19:58:13 +02:00
Marek Maslowski 65931a1777 fix pagination in synology 2026-04-14 19:03:31 +02:00
Marek Maslowski d04a4bcbf8 fix for test suit 2026-04-14 17:45:51 +02:00
Marek Maslowski 1d4f18bdf9 adding test 2026-04-14 17:40:40 +02:00
Julien G. bb160a4010 Merge pull request #639 from mauriceboe/fix/537-notifications-bugs
fix(notifications): fix SMTP error surfacing, webhook button label, backup timestamp
2026-04-14 16:26:33 +02:00
jubnl ff2b33d83b Merge remote-tracking branch 'origin/fix/537-notifications-bugs' into fix/537-notifications-bugs 2026-04-14 16:21:34 +02:00
jubnl 6a23118342 fix(notifications): fix SMTP error surfacing, webhook button label, backup timestamp
- testSmtp now surfaces real nodemailer error instead of generic 'SMTP not configured' on send failure
- admin webhook test button uses correct i18n key (was showing 'Test-E-Mail senden' in all languages)
- backup created_at uses stat.mtime instead of unreliable stat.birthtime on Linux
2026-04-14 16:20:52 +02:00
jubnl 13af757ad1 fix(notifications): fix SMTP error surfacing, webhook button label, backup timestamp
- testSmtp now surfaces real nodemailer error instead of generic 'SMTP not configured' on send failure
- admin webhook test button uses correct i18n key (was showing 'Test-E-Mail senden' in all languages)
- backup created_at uses stat.mtime instead of unreliable stat.birthtime on Linux
2026-04-14 16:14:58 +02:00
Julien G. bae24ad4af Merge pull request #638 from mauriceboe/fix/596-place-notes-ui
fix(places): add notes field to place edit form
2026-04-14 16:00:50 +02:00
jubnl f60e611577 fix(places): fix notes type and display in inspector
Add missing notes (and other fields) to client Place type so the field
is correctly typed when hydrating the edit form. Fix PlaceInspector to
show description and notes as separate blocks so notes are no longer
hidden when a place also has a description.
2026-04-14 15:50:59 +02:00
jubnl 5b99efce06 fix(places): add notes textarea to place edit form (#596)
Notes field was writable via MCP but had no UI input in PlaceFormModal.
2026-04-14 15:38:39 +02:00
Julien G. eb8ec8d793 Merge pull request #637 from mauriceboe/fix/595-pdf-non-transport-reservations
fix(pdf): render restaurant/event/tour/other reservations in trip PDF
2026-04-14 15:33:10 +02:00
Maurice f4b07422ac Merge pull request #636 from mauriceboe/fix/session-14042026
Fix journey map OSM warning, sidebar re-render & migration 98 ambiguous column
2026-04-14 15:31:08 +02:00
jubnl 137ae27cb8 fix(pdf): render restaurant/event/tour/other reservations in trip PDF
Resolves #595. The PDF builder filtered reservations through a transport-only
allow-list, silently dropping all non-transport types. Replace the allow-list
with a single hotel exclusion (hotel is already covered by the accommodations
block) so every other reservation type now appears in the daily itinerary.

Add per-type icon and accent colour matching the existing ReservationsPanel
palette, and per-type subtitle builders (party size, venue, operator) plus a
generic location line for future use.
2026-04-14 15:27:25 +02:00
Maurice d3eab7d973 Fix journey map OSM warning (#627) and sidebar re-render on tab switch (#610)
- Enable attributionControl and add OSM attribution to JourneyMap TileLayer
- Memoize sidebar map entries array to prevent unnecessary map rebuilds
- Use stable callback reference for onMarkerClick
2026-04-14 15:24:29 +02:00
Julien G. bf2c6d35b5 Merge pull request #635 from mauriceboe/fix/atlas-nominatim-throttle
fix(atlas): shared Nominatim throttle, background region fill, fetch timeout
2026-04-14 15:13:46 +02:00
jubnl 0a408c21ac fix(tests): restore native AbortController for undici fetch compatibility
jsdom replaces globalThis.AbortController with its own implementation;
Node.js undici-based fetch validates signals via instanceof against the
native AbortSignal, causing fetch to throw before MSW could intercept.

Fix via custom Vitest environment (tests/environment/jsdom-native-abort.ts)
that captures native AbortController/AbortSignal before jsdom patches them
and restores them after jsdom setup.

Also updates JournalBody test 004 to match component behaviour (headings
rendered as <p>) and removes debug console.log statements.
2026-04-14 15:08:55 +02:00
jubnl 98340aa855 fix(tests): fix remaining 3 immich test failures
IMMICH-057: use two-step trek_photos/trip_photos insert (same fix
as SYNO-035) to avoid missing asset_id column error.

IMMICH-061: mock regex /\/api\/albums$/ did not match the ?shared=true
variant; updated to /\/api\/albums(\?.*)?$/ so both owned and shared
album requests resolve correctly.

IMMICH-090: /search route only fetched a single page; implement
internal pagination loop (max 20 pages) accumulating all assets
before responding, which is what the test and the feature require.
2026-04-14 13:57:38 +02:00
jubnl 714e2ad703 fix(tests): update test helpers and assertions for migration-98 photo schema
trek_photos is now the central registry; trip_photos and journey_photos
reference it via photo_id FK. Updated all affected test helpers and
direct-SQL assertions to join trek_photos instead of querying stale
columns (asset_id, provider, owner_id) on the leaf tables.

Also fix ATLAS-UNIT-019: getVisitedRegions now fires background geocoding
and returns immediately, so the test must call it twice — once to trigger
the fill, once after advancing fake timers to read cached results.
2026-04-14 13:54:48 +02:00
jubnl aa32b1f372 fix(migrations): qualify provider column in trip_photos JOIN (migration 98)
Both trip_photos (alias tp) and trek_photos (alias tkp) have a provider
column. Using the bare identifier 'provider' in the JOIN condition was
ambiguous and caused SQLite to throw SQLITE_ERROR, failing migration 98
and taking down the entire test suite setup.

Fix: introduce providerJoinExpr = 'tp.provider' when the legacy
trip_photos table already carries a provider column, used only in the
two-table JOIN. The single-table INSERT keeps the unqualified form.
2026-04-14 13:39:28 +02:00
jubnl 375ae53566 fix(atlas): shared Nominatim throttle, background region fill, fetch timeout
- Extract throttleNominatim() so reverseGeocodeCountry and
  reverseGeocodeRegion share the same lastNominatimCall state.
  Concurrent /stats + /regions no longer interleave requests
  faster than 1 req/s, closing the remaining 429 path from #576.
- getVisitedRegions now returns cached data immediately and fills
  uncached places in a fire-and-forget background loop. Eliminates
  the N×1.1s response time that caused 504s behind reverse proxies
  (likely root cause of #493). geocodingInFlight set prevents
  double-enqueuing on concurrent page loads.
- Add AbortSignal.timeout(10_000) to both Nominatim fetch calls so
  a hung upstream no longer stalls the endpoint indefinitely.
- Unify User-Agent header in reverseGeocodeRegion to match policy.
2026-04-14 13:29:14 +02:00
Marek Maslowski f686902cd3 adding default value of small when getting thumbnail 2026-04-14 11:22:20 +02:00