import { Modal, View, Text, FlatList, TouchableOpacity, ActivityIndicator, Dimensions, } from 'react-native'; import { Image } from 'expo-image'; import { Ionicons } from '@expo/vector-icons'; import { useTranslation } from 'react-i18next'; /** * MediaLightbox — Vollbild-Carousel über geteilte Chat-Bilder. * * Wird an ZWEI Stellen gerendert (siehe dm.tsx): einmal am Screen-Root für Taps * auf Bilder im Chatverlauf, einmal genested INNERHALB des Info-Sheets * (FormSheet ist ein RN-Modal). Nur die genestete Instanz liegt zuverlässig * ÜBER dem Sheet — deshalb steuert `visible` pro Kontext, welche aktiv ist. * So bleibt das Info-Sheet beim Bild-Öffnen erhalten (kein Kontextwechsel * zurück zur DM). * * Kein async Seitenverhältnis: das Bild füllt eine FIXE Vollbild-Box mit * contentFit="contain". Dadurch entfällt der frühere Quadrat→Echtmaß-Sprung * ("Zucken"), der durch onLoad-gesetzte Ratios entstand. */ export function MediaLightbox({ visible, images, index, onIndexChange, onClose, onSave, saving, }: { visible: boolean; images: string[]; index: number; onIndexChange: (i: number) => void; onClose: () => void; onSave: (uri: string) => void; saving: boolean; }) { const { t } = useTranslation(); const win = Dimensions.get('window'); return ( ({ length: win.width, offset: win.width * i, index: i })} keyExtractor={(u, i) => `${i}-${u}`} onMomentumScrollEnd={(e) => onIndexChange(Math.round(e.nativeEvent.contentOffset.x / win.width)) } renderItem={({ item }) => ( {/* Fixe Vollbild-Box + contain → stabil, kein Re-Layout-Sprung. */} )} /> {/* Zähler "2 / 6" — nur bei mehreren Bildern */} {images.length > 1 && ( {index + 1} / {images.length} )} {/* Sichern (aktuelles Bild) */} images[index] && onSave(images[index])} disabled={saving} activeOpacity={0.7} > {saving ? ( ) : ( )} {t('chat.save')} ); }