trim mobile labels in journey picker + guard JourneyMap flyTo

- mobile-shorten 'Alle Fotos' → 'Alle' in MemoriesPanel picker and the
  Journey ProviderPicker filter tabs (four tabs no longer wrap)
- mobile-shorten 'Datum wählen' → 'Datum' in the entry-editor DatePicker
  placeholder
- guard JourneyMap.tsx flyTo: getZoom() throws "Set map center and zoom
  first" when activeMarkerId arrives before fitBounds has set a view —
  wrap in try/catch and fall back to setView.
This commit is contained in:
Maurice
2026-04-18 19:28:19 +02:00
parent 4974013995
commit a3f52ebd7b
3 changed files with 26 additions and 7 deletions
+8 -2
View File
@@ -269,8 +269,14 @@ const JourneyMap = forwardRef<JourneyMapHandle, Props>(function JourneyMap(
const timer = setTimeout(() => {
highlightMarker(activeMarkerId)
const marker = markersRef.current.get(activeMarkerId)
if (marker && mapRef.current) {
mapRef.current.flyTo(marker.getLatLng(), Math.max(mapRef.current.getZoom(), 12), { duration: 0.5 })
if (!marker || !mapRef.current) return
// fitBounds may still be pending when this fires — getZoom() throws
// "Set map center and zoom first" until the map has a view. Guard it.
try {
const currentZoom = mapRef.current.getZoom()
mapRef.current.flyTo(marker.getLatLng(), Math.max(currentZoom, 12), { duration: 0.5 })
} catch {
mapRef.current.setView(marker.getLatLng(), 12)
}
}, 50)
return () => clearTimeout(timer)
@@ -582,7 +582,8 @@ export default function MemoriesPanel({ tripId, startDate, endDate }: MemoriesPa
borderColor: !pickerDateFilter ? 'var(--text-primary)' : 'var(--border-primary)',
color: !pickerDateFilter ? 'var(--bg-primary)' : 'var(--text-muted)',
}}>
{t('memories.allPhotos')}
<span className="hidden sm:inline">{t('memories.allPhotos')}</span>
<span className="sm:hidden">{t('common.all')}</span>
</button>
</div>
{selectedIds.size > 0 && (
+16 -4
View File
@@ -1734,7 +1734,7 @@ function ProviderPicker({ provider, userId, entries, trips, existingAssetIds, on
{[
{ id: 'trip' as const, label: t('journey.picker.tripPeriod') },
{ id: 'custom' as const, label: t('journey.picker.dateRange') },
{ id: 'all' as const, label: t('journey.picker.allPhotos') },
{ id: 'all' as const, label: t('journey.picker.allPhotos'), short: t('common.all') },
{ id: 'album' as const, label: t('journey.picker.albums') },
].map(f => (
<button
@@ -1746,7 +1746,12 @@ function ProviderPicker({ provider, userId, entries, trips, existingAssetIds, on
: 'text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800'
}`}
>
{f.label}
{f.short ? (
<>
<span className="hidden sm:inline">{f.label}</span>
<span className="sm:hidden">{f.short}</span>
</>
) : f.label}
</button>
))}
</div>
@@ -2023,7 +2028,7 @@ function DatePicker({ value, onChange, tripDates }: {
for (let i = 0; i < firstDow; i++) cells.push(null)
for (let d = 1; d <= daysInMonth; d++) cells.push(d)
const formatted = value ? new Date(value + 'T00:00:00').toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }) : t('journey.picker.selectDate')
const formatted = value ? new Date(value + 'T00:00:00').toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }) : null
return (
<div className="relative">
@@ -2032,7 +2037,14 @@ function DatePicker({ value, onChange, tripDates }: {
onClick={() => setOpen(!open)}
className="w-full px-3 py-2 border border-zinc-200 dark:border-zinc-700 rounded-lg text-[13px] bg-white dark:bg-zinc-800 text-zinc-900 dark:text-white text-left flex items-center justify-between"
>
<span>{formatted}</span>
{formatted ? (
<span>{formatted}</span>
) : (
<span>
<span className="hidden sm:inline">{t('journey.picker.selectDate')}</span>
<span className="sm:hidden">{t('common.date')}</span>
</span>
)}
<Calendar size={13} className="text-zinc-400" />
</button>