import * as FileSystem from 'expo-file-system/legacy'; const logFileUri = FileSystem.documentDirectory + 'app_logs.txt'; // Queue to serialize file operations and prevent race conditions const logQueue: string[] = []; let isWriting = false; const processLogQueue = async () => { if (isWriting) return; isWriting = true; while (logQueue.length > 0) { const logLine = logQueue.shift(); if (!logLine) continue; try { if (logFileUri) { const fileInfo = await FileSystem.getInfoAsync(logFileUri); if (!fileInfo.exists) { await FileSystem.writeAsStringAsync(logFileUri, '', { encoding: FileSystem.EncodingType.UTF8 }); } const current = await FileSystem.readAsStringAsync(logFileUri, { encoding: FileSystem.EncodingType.UTF8 }); let newContent = current + logLine; if (newContent.length > 100000) { newContent = newContent.slice(-100000); } await FileSystem.writeAsStringAsync(logFileUri, newContent, { encoding: FileSystem.EncodingType.UTF8 }); } } catch (e) { console.warn('Failed to write to log file:', e); } } isWriting = false; }; const waitForQueueDrain = async () => { while (isWriting || logQueue.length > 0) { await new Promise(resolve => setTimeout(resolve, 50)); } }; const enqueueWrite = async (logLine: string) => { logQueue.push(logLine); processLogQueue(); // Intentionally unawaited to run in background }; export const logger = { log: async (message: string) => { const timestamp = new Date().toISOString(); const logLine = `[INFO] ${timestamp}: ${message}\n`; console.log(logLine.trim()); return enqueueWrite(logLine); }, error: async (message: string, error?: any) => { const timestamp = new Date().toISOString(); let errorString = ''; if (error) { if (error instanceof Error) { errorString = `\n Name: ${error.name}\n Message: ${error.message}\n Stack: ${error.stack}`; } else if (typeof error === 'object') { errorString = `\n Object: ${JSON.stringify(error)}`; } else { errorString = `\n Value: ${String(error)}`; } } const logLine = `[ERROR] ${timestamp}: ${message}${errorString}\n`; console.error(logLine.trim()); return enqueueWrite(logLine); }, readLogs: async (): Promise => { try { // Wait for pending writes to finish await waitForQueueDrain(); isWriting = true; // lock the queue while reading try { const fileInfo = await FileSystem.getInfoAsync(logFileUri); if (!fileInfo.exists) return 'Keine Logs vorhanden.'; return await FileSystem.readAsStringAsync(logFileUri, { encoding: FileSystem.EncodingType.UTF8 }); } finally { isWriting = false; processLogQueue(); } } catch (e) { return `Fehler beim Lesen der Logs: ${e}`; } }, clearLogs: async () => { await waitForQueueDrain(); isWriting = true; // lock the queue while clearing try { await FileSystem.deleteAsync(logFileUri, { idempotent: true }); } catch (e) { console.warn('Failed to clear logs:', e); } finally { isWriting = false; processLogQueue(); } } };