From b6ee5552f0d9121c3bf22464b4de4a5f90480c75 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sat, 30 May 2026 23:22:44 +0200 Subject: [PATCH] fix(app): Dateimanager Einzel-Download landet jetzt im Downloads-Ordner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: '⬇ Download' im Dateimanager schickte file_request raus, aber kein SettingsScreen-Handler nahm das file_response auf. ChatScreen fing es zwar global ab, versuchte aber nur Chat-Bubble-Attachments zu patchen — kein Match, also passierte sichtbar nichts. Fix: Handler in SettingsScreen fuer file_response mit requestId-Praefix 'single-' (aus bulkDownload-1-Datei-Pfad). Schreibt nach RNFS.DownloadDirectoryPath, mit Suffix-Inkrement bei Namens-Konflikt damit nichts ueberschrieben wird. Multi-Datei-Download (ZIP) lief schon ueber file_zip_response, unangetastet. --- android/src/screens/SettingsScreen.tsx | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/android/src/screens/SettingsScreen.tsx b/android/src/screens/SettingsScreen.tsx index ece93c4..4e1774e 100644 --- a/android/src/screens/SettingsScreen.tsx +++ b/android/src/screens/SettingsScreen.tsx @@ -497,6 +497,49 @@ const SettingsScreen: React.FC = () => { })(); } + // Datei-Manager: Einzel-Datei-Download. ChatScreen subscribet auch auf + // file_response — der versucht aber nur Chat-Bubble-Attachments zu + // patchen und macht nix wenn die requestId nicht zu einer Nachricht + // passt. Hier behandeln wir die Manager-initiierten Downloads + // (requestId-Praefix 'single-' aus bulkDownload). Schreibt nach + // ~/Download/ wie der ZIP-Pfad. + if (message.type === ('file_response' as any)) { + const p: any = message.payload || {}; + const reqId = (p.requestId as string) || ''; + if (!reqId.startsWith('single-')) return; // nicht unsere Anfrage + if (p.error) { + ToastAndroid.show('Download fehlgeschlagen: ' + p.error, ToastAndroid.LONG); + return; + } + const b64 = (p.base64 as string) || ''; + if (!b64) return; + const fileName = (p.name as string) || + (p.serverPath as string || '').split('/').pop() || + 'aria-download'; + (async () => { + try { + const dir = RNFS.DownloadDirectoryPath; + const filePath = `${dir}/${fileName}`; + // Falls Datei schon existiert: Suffix anhaengen damit nichts + // ueberschrieben wird. + let target = filePath; + let i = 1; + while (await RNFS.exists(target)) { + const dot = fileName.lastIndexOf('.'); + const base = dot > 0 ? fileName.slice(0, dot) : fileName; + const ext = dot > 0 ? fileName.slice(dot) : ''; + target = `${dir}/${base} (${i})${ext}`; + i++; + } + await RNFS.writeFile(target, b64, 'base64'); + const sizeKb = Math.round(((b64.length * 0.75)) / 1024); + ToastAndroid.show(`Gespeichert: ${target.split('/').pop()} (${sizeKb} KB)`, ToastAndroid.LONG); + } catch (e: any) { + ToastAndroid.show('Speichern fehlgeschlagen: ' + e.message, ToastAndroid.LONG); + } + })(); + } + // Voice wurde gespeichert → Liste neu laden + ggf. auswaehlen if (message.type === ('xtts_voice_saved' as any)) { const name = (message.payload as any).name as string;