fix(chat): Cache leer + Datei-Tap → Auto-Re-Download statt Fehlertoast

Stefan: nach App-Cache-Leeren in Settings tippt er auf eine Datei im
Chat oder im memorySaved-Anhang → "Oeffnen fehlgeschlagen" Toast,
aber kein Re-Download. Datei hing als Geister-uri im State (RNFS-Cache
weg, State-attachment.uri zeigt noch auf den entfernten Pfad).

Fix in beiden Tap-Handlern (item.attachments im normalen Chat +
memorySaved.attachments via localUri):

1. RNFS.exists(localPath) pruefen
2. Wenn ja → openFileWithIntent
3. Wenn nein:
   - State bereinigen (uri/localUri auf undefined setzen, UI zeigt
     dann "tippen zum Laden")
   - Toast "Cache leer — lade nach..."
   - file_request via RVS triggern
   - autoOpenPaths-Marker setzen, sodass file_response → Datei
     speichern + automatisch oeffnen

Bilder-Branch hatte schon onError-Handler (Image-Komponente meldet
self) — der ist unveraendert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 16:14:56 +02:00
parent 5b28a065c0
commit d27fcaf342
+42 -14
View File
@@ -1375,17 +1375,30 @@ const ChatScreen: React.FC = () => {
<TouchableOpacity <TouchableOpacity
key={`${item.id}-att-${idx}`} key={`${item.id}-att-${idx}`}
style={styles.memoryAttachmentRow} style={styles.memoryAttachmentRow}
onPress={() => { onPress={async () => {
if (!a.path) return; if (!a.path) return;
if (a.localUri) { if (a.localUri) {
if (isImage) setFullscreenImage(a.localUri); const localPath = a.localUri.replace(/^file:\/\//, '');
else openFileWithIntent(a.localUri.replace(/^file:\/\//, ''), a.mime || ''); const exists = await RNFS.exists(localPath).catch(() => false);
} else { if (exists) {
// Datei via Bridge nachladen — file_response hat den if (isImage) setFullscreenImage(a.localUri);
// memorySaved-Match-Path und cached + zeigt direkt else openFileWithIntent(localPath, a.mime || '');
autoOpenPaths.current.add(a.path); return;
rvs.send('file_request' as any, { serverPath: a.path, requestId: `memAtt_${item.id}_${idx}` }); }
// Cache weg → localUri leeren + neu laden
setMessages(prev => prev.map(mm => mm.id === item.id && mm.memorySaved
? { ...mm, memorySaved: { ...mm.memorySaved,
attachments: mm.memorySaved.attachments?.map(x =>
x.path === a.path ? { ...x, localUri: undefined } : x) } }
: mm));
if (Platform.OS === 'android') {
ToastAndroid.show('Cache leer — lade nach...', ToastAndroid.SHORT);
}
} }
// Datei via Bridge nachladen — file_response hat den
// memorySaved-Match-Path und cached + zeigt direkt
autoOpenPaths.current.add(a.path);
rvs.send('file_request' as any, { serverPath: a.path, requestId: `memAtt_${item.id}_${idx}` });
}} }}
> >
<Text style={styles.memoryAttachmentIcon}>{icon}</Text> <Text style={styles.memoryAttachmentIcon}>{icon}</Text>
@@ -1489,17 +1502,32 @@ const ChatScreen: React.FC = () => {
) : ( ) : (
<TouchableOpacity <TouchableOpacity
style={styles.attachmentFile} style={styles.attachmentFile}
onPress={() => { onPress={async () => {
// Lokal vorhanden \u2192 direkt mit System-Intent oeffnen // Lokal vorhanden? Cache koennte geleert worden sein \u2014
// Datei-Existenz pruefen bevor wir den Intent feuern.
if (att.uri) { if (att.uri) {
openFileWithIntent(att.uri.replace(/^file:\/\//, ''), att.mimeType || ''); const localPath = att.uri.replace(/^file:\/\//, '');
return; const exists = await RNFS.exists(localPath).catch(() => false);
if (exists) {
openFileWithIntent(localPath, att.mimeType || '');
return;
}
// Cache weg \u2192 uri im State leeren damit UI "tippen zum Laden" zeigt
setMessages(prev => prev.map(m => m.id === item.id
? { ...m, attachments: m.attachments?.map(a =>
a.serverPath === att.serverPath ? { ...a, uri: undefined } : a) }
: m));
if (Platform.OS === 'android') {
ToastAndroid.show('Cache leer \u2014 lade nach...', ToastAndroid.SHORT);
}
} }
// Sonst: file_request \u2192 bei file_response wird die Datei // Re-Download via file_request \u2192 bei file_response wird die
// gespeichert UND geoeffnet (autoOpenPaths-Tracking). // Datei gespeichert UND geoeffnet (autoOpenPaths-Tracking).
if (att.serverPath) { if (att.serverPath) {
autoOpenPaths.current.add(att.serverPath); autoOpenPaths.current.add(att.serverPath);
rvs.send('file_request' as any, { serverPath: att.serverPath, requestId: item.id }); rvs.send('file_request' as any, { serverPath: att.serverPath, requestId: item.id });
} else if (Platform.OS === 'android') {
ToastAndroid.show('Datei kann nicht nachgeladen werden (kein serverPath)', ToastAndroid.LONG);
} }
}} }}
> >