feat: Immich photo integration — Photos addon with sharing, filters, lightbox

- Immich connection per user (Settings → Immich URL + API Key)
- Photos addon (admin-toggleable, trip tab)
- Manual photo selection from Immich library (date filter + all photos)
- Photo sharing with consent popup, per-photo privacy toggle
- Lightbox with liquid glass EXIF info panel (camera, lens, location, settings)
- Location filter + date sort in gallery
- WebSocket live sync when photos are added/removed/shared
- Proxy endpoints for thumbnails and originals with token auth
This commit is contained in:
Maurice
2026-03-29 20:12:47 +02:00
parent 02b907e764
commit 9f8075171d
16 changed files with 1361 additions and 17 deletions
+28 -2
View File
@@ -380,8 +380,8 @@ const ar: Record<string, string | { name: string; category: string }[]> = {
// Addons
'admin.addons.title': 'الإضافات',
'admin.addons.subtitle': 'فعّل أو عطّل الميزات لتخصيص تجربة TREK.',
'admin.addons.catalog.memories.name': 'الذكريات',
'admin.addons.catalog.memories.description': 'ألبومات صور مشتركة لكل رحلة',
'admin.addons.catalog.memories.name': 'صور (Immich)',
'admin.addons.catalog.memories.description': 'شارك صور رحلتك عبر Immich',
'admin.addons.catalog.packing.name': 'التعبئة',
'admin.addons.catalog.packing.description': 'قوائم تحقق لإعداد أمتعتك لكل رحلة',
'admin.addons.catalog.budget.name': 'الميزانية',
@@ -1118,6 +1118,32 @@ const ar: Record<string, string | { name: string; category: string }[]> = {
'day.editAccommodation': 'تعديل الإقامة',
'day.reservations': 'الحجوزات',
// Memories / Immich
'memories.title': 'صور',
'memories.notConnected': 'Immich غير متصل',
'memories.notConnectedHint': 'قم بتوصيل Immich في الإعدادات لعرض صور رحلتك هنا.',
'memories.noDates': 'أضف تواريخ لرحلتك لتحميل الصور.',
'memories.noPhotos': 'لم يتم العثور على صور',
'memories.noPhotosHint': 'لم يتم العثور على صور في Immich لفترة هذه الرحلة.',
'memories.photosFound': 'صور',
'memories.fromOthers': 'من آخرين',
'memories.sharePhotos': 'مشاركة الصور',
'memories.sharing': 'مشترك',
'memories.reviewTitle': 'مراجعة صورك',
'memories.reviewHint': 'انقر على الصور لاستبعادها من المشاركة.',
'memories.shareCount': 'مشاركة {count} صور',
'memories.immichUrl': 'عنوان خادم Immich',
'memories.immichApiKey': 'مفتاح API',
'memories.testConnection': 'اختبار الاتصال',
'memories.connected': 'متصل',
'memories.disconnected': 'غير متصل',
'memories.connectionSuccess': 'تم الاتصال بـ Immich',
'memories.connectionError': 'تعذر الاتصال بـ Immich',
'memories.saved': 'تم حفظ إعدادات Immich',
'memories.oldest': 'الأقدم أولاً',
'memories.newest': 'الأحدث أولاً',
'memories.allLocations': 'جميع المواقع',
// Collab Addon
'collab.tabs.chat': 'الدردشة',
'collab.tabs.notes': 'الملاحظات',
+50 -1
View File
@@ -388,6 +388,8 @@ const de: Record<string, string | { name: string; category: string }[]> = {
'admin.addons.catalog.atlas.description': 'Weltkarte mit besuchten Ländern und Reisestatistiken',
'admin.addons.catalog.collab.name': 'Collab',
'admin.addons.catalog.collab.description': 'Echtzeit-Notizen, Umfragen und Chat für die Reiseplanung',
'admin.addons.catalog.memories.name': 'Fotos (Immich)',
'admin.addons.catalog.memories.description': 'Reisefotos über deine Immich-Instanz teilen',
'admin.addons.subtitleBefore': 'Aktiviere oder deaktiviere Funktionen, um ',
'admin.addons.subtitleAfter': ' nach deinen Wünschen anzupassen.',
'admin.addons.enabled': 'Aktiviert',
@@ -475,7 +477,15 @@ const de: Record<string, string | { name: string; category: string }[]> = {
'vacay.remaining': 'Rest',
'vacay.carriedOver': 'aus {year}',
'vacay.blockWeekends': 'Wochenenden sperren',
'vacay.blockWeekendsHint': 'Verhindert Urlaubseinträge an Samstagen und Sonntagen',
'vacay.blockWeekendsHint': 'Verhindert Urlaubseinträge an Wochenendtagen',
'vacay.weekendDays': 'Wochenendtage',
'vacay.mon': 'Mo',
'vacay.tue': 'Di',
'vacay.wed': 'Mi',
'vacay.thu': 'Do',
'vacay.fri': 'Fr',
'vacay.sat': 'Sa',
'vacay.sun': 'So',
'vacay.publicHolidays': 'Feiertage',
'vacay.publicHolidaysHint': 'Feiertage im Kalender markieren',
'vacay.selectCountry': 'Land wählen',
@@ -1112,6 +1122,45 @@ const de: Record<string, string | { name: string; category: string }[]> = {
'day.editAccommodation': 'Unterkunft bearbeiten',
'day.reservations': 'Reservierungen',
// Photos / Immich
'memories.title': 'Fotos',
'memories.notConnected': 'Immich nicht verbunden',
'memories.notConnectedHint': 'Verbinde deine Immich-Instanz in den Einstellungen, um deine Reisefotos hier zu sehen.',
'memories.noDates': 'Füge Daten zu deiner Reise hinzu, um Fotos zu laden.',
'memories.noPhotos': 'Keine Fotos gefunden',
'memories.noPhotosHint': 'Keine Fotos in Immich für den Zeitraum dieser Reise gefunden.',
'memories.photosFound': 'Fotos',
'memories.fromOthers': 'von anderen',
'memories.sharePhotos': 'Fotos teilen',
'memories.sharing': 'Wird geteilt',
'memories.reviewTitle': 'Deine Fotos prüfen',
'memories.reviewHint': 'Klicke auf Fotos, um sie vom Teilen auszuschließen.',
'memories.shareCount': '{count} Fotos teilen',
'memories.immichUrl': 'Immich Server URL',
'memories.immichApiKey': 'API-Schlüssel',
'memories.testConnection': 'Verbindung testen',
'memories.connected': 'Verbunden',
'memories.disconnected': 'Nicht verbunden',
'memories.connectionSuccess': 'Verbindung zu Immich hergestellt',
'memories.connectionError': 'Verbindung zu Immich fehlgeschlagen',
'memories.saved': 'Immich-Einstellungen gespeichert',
'memories.addPhotos': 'Fotos hinzufügen',
'memories.selectPhotos': 'Fotos aus Immich auswählen',
'memories.selectHint': 'Tippe auf Fotos um sie auszuwählen.',
'memories.selected': 'ausgewählt',
'memories.addSelected': '{count} Fotos hinzufügen',
'memories.alreadyAdded': 'Hinzugefügt',
'memories.private': 'Privat',
'memories.stopSharing': 'Nicht mehr teilen',
'memories.oldest': 'Älteste zuerst',
'memories.newest': 'Neueste zuerst',
'memories.allLocations': 'Alle Orte',
'memories.tripDates': 'Trip-Zeitraum',
'memories.allPhotos': 'Alle Fotos',
'memories.confirmShareTitle': 'Mit Reisebegleitern teilen?',
'memories.confirmShareHint': '{count} Fotos werden für alle Mitglieder dieses Trips sichtbar. Du kannst einzelne Fotos nachträglich auf privat setzen.',
'memories.confirmShareButton': 'Fotos teilen',
// Collab Addon
'collab.tabs.chat': 'Chat',
'collab.tabs.notes': 'Notizen',
+50 -1
View File
@@ -388,6 +388,8 @@ const en: Record<string, string | { name: string; category: string }[]> = {
'admin.addons.catalog.atlas.description': 'World map with visited countries and travel stats',
'admin.addons.catalog.collab.name': 'Collab',
'admin.addons.catalog.collab.description': 'Real-time notes, polls, and chat for trip planning',
'admin.addons.catalog.memories.name': 'Photos (Immich)',
'admin.addons.catalog.memories.description': 'Share trip photos via your Immich instance',
'admin.addons.subtitleBefore': 'Enable or disable features to customize your ',
'admin.addons.subtitleAfter': ' experience.',
'admin.addons.enabled': 'Enabled',
@@ -475,7 +477,15 @@ const en: Record<string, string | { name: string; category: string }[]> = {
'vacay.remaining': 'Left',
'vacay.carriedOver': 'from {year}',
'vacay.blockWeekends': 'Block Weekends',
'vacay.blockWeekendsHint': 'Prevent vacation entries on Saturdays and Sundays',
'vacay.blockWeekendsHint': 'Prevent vacation entries on weekend days',
'vacay.weekendDays': 'Weekend days',
'vacay.mon': 'Mon',
'vacay.tue': 'Tue',
'vacay.wed': 'Wed',
'vacay.thu': 'Thu',
'vacay.fri': 'Fri',
'vacay.sat': 'Sat',
'vacay.sun': 'Sun',
'vacay.publicHolidays': 'Public Holidays',
'vacay.publicHolidaysHint': 'Mark public holidays in the calendar',
'vacay.selectCountry': 'Select country',
@@ -1112,6 +1122,45 @@ const en: Record<string, string | { name: string; category: string }[]> = {
'day.editAccommodation': 'Edit accommodation',
'day.reservations': 'Reservations',
// Photos / Immich
'memories.title': 'Photos',
'memories.notConnected': 'Immich not connected',
'memories.notConnectedHint': 'Connect your Immich instance in Settings to see your trip photos here.',
'memories.noDates': 'Add dates to your trip to load photos.',
'memories.noPhotos': 'No photos found',
'memories.noPhotosHint': 'No photos found in Immich for this trip\'s date range.',
'memories.photosFound': 'photos',
'memories.fromOthers': 'from others',
'memories.sharePhotos': 'Share photos',
'memories.sharing': 'Sharing',
'memories.reviewTitle': 'Review your photos',
'memories.reviewHint': 'Click photos to exclude them from sharing.',
'memories.shareCount': 'Share {count} photos',
'memories.immichUrl': 'Immich Server URL',
'memories.immichApiKey': 'API Key',
'memories.testConnection': 'Test connection',
'memories.connected': 'Connected',
'memories.disconnected': 'Not connected',
'memories.connectionSuccess': 'Connected to Immich',
'memories.connectionError': 'Could not connect to Immich',
'memories.saved': 'Immich settings saved',
'memories.addPhotos': 'Add photos',
'memories.selectPhotos': 'Select photos from Immich',
'memories.selectHint': 'Tap photos to select them.',
'memories.selected': 'selected',
'memories.addSelected': 'Add {count} photos',
'memories.alreadyAdded': 'Added',
'memories.private': 'Private',
'memories.stopSharing': 'Stop sharing',
'memories.oldest': 'Oldest first',
'memories.newest': 'Newest first',
'memories.allLocations': 'All locations',
'memories.tripDates': 'Trip dates',
'memories.allPhotos': 'All photos',
'memories.confirmShareTitle': 'Share with trip members?',
'memories.confirmShareHint': '{count} photos will be visible to all members of this trip. You can make individual photos private later.',
'memories.confirmShareButton': 'Share photos',
// Collab Addon
'collab.tabs.chat': 'Chat',
'collab.tabs.notes': 'Notes',
+28 -2
View File
@@ -945,8 +945,8 @@ const es: Record<string, string> = {
'photos.linkPlace': 'Vincular lugar',
'photos.noPlace': 'Sin lugar',
'photos.uploadN': 'Subida de {n} foto(s)',
'admin.addons.catalog.memories.name': 'Recuerdos',
'admin.addons.catalog.memories.description': 'Álbumes de fotos compartidos para cada viaje',
'admin.addons.catalog.memories.name': 'Fotos (Immich)',
'admin.addons.catalog.memories.description': 'Comparte fotos de viaje a través de tu instancia de Immich',
'admin.addons.catalog.packing.name': 'Equipaje',
'admin.addons.catalog.packing.description': 'Prepara tu equipaje con listas de comprobación para cada viaje',
'admin.addons.catalog.budget.name': 'Presupuesto',
@@ -1065,6 +1065,32 @@ const es: Record<string, string> = {
'day.editAccommodation': 'Editar alojamiento',
'day.reservations': 'Reservas',
// Memories / Immich
'memories.title': 'Fotos',
'memories.notConnected': 'Immich no conectado',
'memories.notConnectedHint': 'Conecta tu instancia de Immich en Ajustes para ver tus fotos de viaje aquí.',
'memories.noDates': 'Añade fechas a tu viaje para cargar fotos.',
'memories.noPhotos': 'No se encontraron fotos',
'memories.noPhotosHint': 'No se encontraron fotos en Immich para el rango de fechas de este viaje.',
'memories.photosFound': 'fotos',
'memories.fromOthers': 'de otros',
'memories.sharePhotos': 'Compartir fotos',
'memories.sharing': 'Compartiendo',
'memories.reviewTitle': 'Revisar tus fotos',
'memories.reviewHint': 'Haz clic en las fotos para excluirlas de compartir.',
'memories.shareCount': 'Compartir {count} fotos',
'memories.immichUrl': 'URL del servidor Immich',
'memories.immichApiKey': 'Clave API',
'memories.testConnection': 'Probar conexión',
'memories.connected': 'Conectado',
'memories.disconnected': 'No conectado',
'memories.connectionSuccess': 'Conectado a Immich',
'memories.connectionError': 'No se pudo conectar a Immich',
'memories.saved': 'Configuración de Immich guardada',
'memories.oldest': 'Más antiguas',
'memories.newest': 'Más recientes',
'memories.allLocations': 'Todas las ubicaciones',
// Collab Addon
'collab.tabs.chat': 'Mensajes',
'collab.tabs.notes': 'Notas',
+28 -2
View File
@@ -373,8 +373,8 @@ const fr: Record<string, string> = {
'admin.tabs.addons': 'Extensions',
'admin.addons.title': 'Extensions',
'admin.addons.subtitle': 'Activez ou désactivez des fonctionnalités pour personnaliser votre expérience TREK.',
'admin.addons.catalog.memories.name': 'Souvenirs',
'admin.addons.catalog.memories.description': 'Albums photo partagés pour chaque voyage',
'admin.addons.catalog.memories.name': 'Photos (Immich)',
'admin.addons.catalog.memories.description': 'Partagez vos photos de voyage via votre instance Immich',
'admin.addons.catalog.packing.name': 'Bagages',
'admin.addons.catalog.packing.description': 'Listes de contrôle pour préparer vos bagages pour chaque voyage',
'admin.addons.catalog.budget.name': 'Budget',
@@ -1111,6 +1111,32 @@ const fr: Record<string, string> = {
'day.editAccommodation': 'Modifier l\'hébergement',
'day.reservations': 'Réservations',
// Memories / Immich
'memories.title': 'Photos',
'memories.notConnected': 'Immich non connecté',
'memories.notConnectedHint': 'Connectez votre instance Immich dans les paramètres pour voir vos photos de voyage ici.',
'memories.noDates': 'Ajoutez des dates à votre voyage pour charger les photos.',
'memories.noPhotos': 'Aucune photo trouvée',
'memories.noPhotosHint': 'Aucune photo trouvée dans Immich pour la période de ce voyage.',
'memories.photosFound': 'photos',
'memories.fromOthers': 'd\'autres',
'memories.sharePhotos': 'Partager les photos',
'memories.sharing': 'Partagé',
'memories.reviewTitle': 'Vérifier vos photos',
'memories.reviewHint': 'Cliquez sur les photos pour les exclure du partage.',
'memories.shareCount': 'Partager {count} photos',
'memories.immichUrl': 'URL du serveur Immich',
'memories.immichApiKey': 'Clé API',
'memories.testConnection': 'Tester la connexion',
'memories.connected': 'Connecté',
'memories.disconnected': 'Non connecté',
'memories.connectionSuccess': 'Connecté à Immich',
'memories.connectionError': 'Impossible de se connecter à Immich',
'memories.saved': 'Paramètres Immich enregistrés',
'memories.oldest': 'Plus anciennes',
'memories.newest': 'Plus récentes',
'memories.allLocations': 'Tous les lieux',
// Collab Addon
'collab.tabs.chat': 'Chat',
'collab.tabs.notes': 'Notes',
+28 -2
View File
@@ -373,8 +373,8 @@ const nl: Record<string, string> = {
'admin.tabs.addons': 'Add-ons',
'admin.addons.title': 'Add-ons',
'admin.addons.subtitle': 'Schakel functies in of uit om je TREK-ervaring aan te passen.',
'admin.addons.catalog.memories.name': 'Herinneringen',
'admin.addons.catalog.memories.description': 'Gedeelde fotoalbums voor elke reis',
'admin.addons.catalog.memories.name': 'Foto\'s (Immich)',
'admin.addons.catalog.memories.description': 'Deel reisfoto\'s via je Immich-instantie',
'admin.addons.catalog.packing.name': 'Inpakken',
'admin.addons.catalog.packing.description': 'Checklists om je bagage voor elke reis voor te bereiden',
'admin.addons.catalog.budget.name': 'Budget',
@@ -1111,6 +1111,32 @@ const nl: Record<string, string> = {
'day.editAccommodation': 'Accommodatie bewerken',
'day.reservations': 'Reserveringen',
// Memories / Immich
'memories.title': 'Foto\'s',
'memories.notConnected': 'Immich niet verbonden',
'memories.notConnectedHint': 'Verbind je Immich-instantie in Instellingen om je reisfoto\'s hier te zien.',
'memories.noDates': 'Voeg data toe aan je reis om foto\'s te laden.',
'memories.noPhotos': 'Geen foto\'s gevonden',
'memories.noPhotosHint': 'Geen foto\'s gevonden in Immich voor de datumreeks van deze reis.',
'memories.photosFound': 'foto\'s',
'memories.fromOthers': 'van anderen',
'memories.sharePhotos': 'Foto\'s delen',
'memories.sharing': 'Wordt gedeeld',
'memories.reviewTitle': 'Je foto\'s bekijken',
'memories.reviewHint': 'Klik op foto\'s om ze uit te sluiten van delen.',
'memories.shareCount': '{count} foto\'s delen',
'memories.immichUrl': 'Immich Server URL',
'memories.immichApiKey': 'API-sleutel',
'memories.testConnection': 'Verbinding testen',
'memories.connected': 'Verbonden',
'memories.disconnected': 'Niet verbonden',
'memories.connectionSuccess': 'Verbonden met Immich',
'memories.connectionError': 'Kon niet verbinden met Immich',
'memories.saved': 'Immich-instellingen opgeslagen',
'memories.oldest': 'Oudste eerst',
'memories.newest': 'Nieuwste eerst',
'memories.allLocations': 'Alle locaties',
// Collab Addon
'collab.tabs.chat': 'Chat',
'collab.tabs.notes': 'Notities',
+28 -2
View File
@@ -373,8 +373,8 @@ const ru: Record<string, string> = {
'admin.tabs.addons': 'Дополнения',
'admin.addons.title': 'Дополнения',
'admin.addons.subtitle': 'Включайте или отключайте функции для настройки TREK под себя.',
'admin.addons.catalog.memories.name': 'Воспоминания',
'admin.addons.catalog.memories.description': 'Общие фотоальбомы для каждой поездки',
'admin.addons.catalog.memories.name': 'Фото (Immich)',
'admin.addons.catalog.memories.description': 'Делитесь фотографиями из поездок через Immich',
'admin.addons.catalog.packing.name': 'Сборы',
'admin.addons.catalog.packing.description': 'Чек-листы для подготовки багажа к каждой поездке',
'admin.addons.catalog.budget.name': 'Бюджет',
@@ -1111,6 +1111,32 @@ const ru: Record<string, string> = {
'day.editAccommodation': 'Редактировать жильё',
'day.reservations': 'Бронирования',
// Memories / Immich
'memories.title': 'Фото',
'memories.notConnected': 'Immich не подключён',
'memories.notConnectedHint': 'Подключите Immich в настройках, чтобы видеть фотографии из поездок.',
'memories.noDates': 'Добавьте даты поездки для загрузки фотографий.',
'memories.noPhotos': 'Фотографии не найдены',
'memories.noPhotosHint': 'В Immich нет фотографий за период этой поездки.',
'memories.photosFound': 'фото',
'memories.fromOthers': 'от других',
'memories.sharePhotos': 'Поделиться фото',
'memories.sharing': 'Общий доступ',
'memories.reviewTitle': 'Проверьте ваши фото',
'memories.reviewHint': 'Нажмите на фото, чтобы исключить его из общего доступа.',
'memories.shareCount': 'Поделиться ({count} фото)',
'memories.immichUrl': 'URL сервера Immich',
'memories.immichApiKey': 'API-ключ',
'memories.testConnection': 'Проверить подключение',
'memories.connected': 'Подключено',
'memories.disconnected': 'Не подключено',
'memories.connectionSuccess': 'Подключение к Immich установлено',
'memories.connectionError': 'Не удалось подключиться к Immich',
'memories.saved': 'Настройки Immich сохранены',
'memories.oldest': 'Сначала старые',
'memories.newest': 'Сначала новые',
'memories.allLocations': 'Все места',
// Collab Addon
'collab.tabs.chat': 'Чат',
'collab.tabs.notes': 'Заметки',
+28 -2
View File
@@ -373,8 +373,8 @@ const zh: Record<string, string> = {
'admin.tabs.addons': '扩展',
'admin.addons.title': '扩展',
'admin.addons.subtitle': '启用或禁用功能以自定义你的 TREK 体验。',
'admin.addons.catalog.memories.name': '回忆',
'admin.addons.catalog.memories.description': '每次旅行的共享相册',
'admin.addons.catalog.memories.name': '照片 (Immich)',
'admin.addons.catalog.memories.description': '通过 Immich 实例分享旅行照片',
'admin.addons.catalog.packing.name': '行李',
'admin.addons.catalog.packing.description': '每次旅行的行李准备清单',
'admin.addons.catalog.budget.name': '预算',
@@ -1111,6 +1111,32 @@ const zh: Record<string, string> = {
'day.editAccommodation': '编辑住宿',
'day.reservations': '预订',
// Memories / Immich
'memories.title': '照片',
'memories.notConnected': 'Immich 未连接',
'memories.notConnectedHint': '在设置中连接您的 Immich 实例以在此查看旅行照片。',
'memories.noDates': '为旅行添加日期以加载照片。',
'memories.noPhotos': '未找到照片',
'memories.noPhotosHint': 'Immich 中未找到此旅行日期范围内的照片。',
'memories.photosFound': '张照片',
'memories.fromOthers': '来自他人',
'memories.sharePhotos': '分享照片',
'memories.sharing': '分享中',
'memories.reviewTitle': '审查您的照片',
'memories.reviewHint': '点击照片以将其从分享中排除。',
'memories.shareCount': '分享 {count} 张照片',
'memories.immichUrl': 'Immich 服务器地址',
'memories.immichApiKey': 'API 密钥',
'memories.testConnection': '测试连接',
'memories.connected': '已连接',
'memories.disconnected': '未连接',
'memories.connectionSuccess': '已连接到 Immich',
'memories.connectionError': '无法连接到 Immich',
'memories.saved': 'Immich 设置已保存',
'memories.oldest': '最早优先',
'memories.newest': '最新优先',
'memories.allLocations': '所有地点',
// Collab Addon
'collab.tabs.chat': '聊天',
'collab.tabs.notes': '笔记',