diff --git a/android/src/screens/SettingsScreen.tsx b/android/src/screens/SettingsScreen.tsx index 8cc34c1..ece93c4 100644 --- a/android/src/screens/SettingsScreen.tsx +++ b/android/src/screens/SettingsScreen.tsx @@ -20,6 +20,7 @@ import { Modal, PermissionsAndroid, useWindowDimensions, + DeviceEventEmitter, } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import RNFS from 'react-native-fs'; @@ -62,7 +63,7 @@ import MemoryBrowser from '../components/MemoryBrowser'; import TriggerBrowser from '../components/TriggerBrowser'; import SkillBrowser from '../components/SkillBrowser'; import OAuthBrowser from '../components/OAuthBrowser'; -import { isVerboseLogging, setVerboseLogging, isDebugLogsToBridge, setDebugLogsToBridge } from '../services/logger'; +import { isVerboseLogging, setVerboseLogging, isDebugLogsToBridge, setDebugLogsToBridge, APP_LOG_EVENT } from '../services/logger'; import { isWakeReadySoundEnabled, setWakeReadySoundEnabled, @@ -388,6 +389,19 @@ const SettingsScreen: React.FC = () => { setConnLog(prev => [...prev.slice(-99), entry]); }); + // Lokale App-Logs (reportAppDebug/Error) im Live-Logs-Tab anzeigen + // — damit Stefan ohne curl direkt in der App sieht was passiert. + const localLogSub = DeviceEventEmitter.addListener(APP_LOG_EVENT, (e: any) => { + const entry: LogEntry = { + id: `applog_${e.ts || Date.now()}_${logIdCounter++}`, + timestamp: e.ts || Date.now(), + source: e.scope || 'app', + message: e.message || '', + level: e.level || 'info', + }; + setLogs(prev => [...prev.slice(-200), entry]); + }); + const unsubMessage = rvs.onMessage((message: RVSMessage) => { if (message.type === 'log') { const entry: LogEntry = { @@ -523,6 +537,7 @@ const SettingsScreen: React.FC = () => { unsubState(); unsubMessage(); unsubLog(); + localLogSub.remove(); }; }, []); diff --git a/android/src/services/logger.ts b/android/src/services/logger.ts index 1a7c509..08aebfc 100644 --- a/android/src/services/logger.ts +++ b/android/src/services/logger.ts @@ -7,9 +7,22 @@ */ import AsyncStorage from '@react-native-async-storage/async-storage'; -import { Platform } from 'react-native'; +import { Platform, DeviceEventEmitter } from 'react-native'; import rvs from './rvs'; +// Lokales Event damit die SettingsScreen Live Logs / Events Tabs +// auch das sehen was die App SELBST loggt (reportAppDebug/Error). +// Bisher gingen die nur via RVS an die Bridge. Lokal sichtbar = Mama- +// tauglich Debug ohne curl. +export const APP_LOG_EVENT = 'AriaLocalAppLog'; + +interface LocalLogEntry { + ts: number; + level: 'info' | 'warn' | 'error'; + scope: string; + message: string; +} + export const VERBOSE_LOGGING_KEY = 'aria_verbose_logging'; // Eigener Toggle fuer Debug-Logs die ueber RVS an die Bridge gehen // (/shared/logs/app.log → Diagnostic /api/app-log). Damit der Default-User @@ -80,9 +93,10 @@ let _reportingInstalled = false; /** Schickt einen App-Fehler via RVS an die Bridge. */ export function reportAppError(ev: AppErrorEvent): void { + const ts = Date.now(); try { rvs.send('app_log' as any, { - ts: Date.now(), + ts, platform: Platform.OS, level: ev.level || 'error', scope: ev.scope, @@ -92,6 +106,14 @@ export function reportAppError(ev: AppErrorEvent): void { } catch { // RVS noch nicht connected — Fehler geht im console weiter. } + // Lokal in den App-Logs-Tab emitten — Errors gehen IMMER durch + // (unabhaengig vom Debug-Toggle). + try { + const entry: LocalLogEntry = { + ts, level: ev.level || 'error', scope: ev.scope, message: ev.message, + }; + DeviceEventEmitter.emit(APP_LOG_EVENT, entry); + } catch {} // Plus lokal: console.error, damit Stefan's adb (wenn doch mal verfuegbar) // den Crash sieht. console.error(`[app-error scope=${ev.scope}]`, ev.message, '\n', ev.stack || ''); @@ -107,15 +129,24 @@ export function reportAppError(ev: AppErrorEvent): void { * (reportAppError) gehen weiterhin IMMER durch. */ export function reportAppDebug(scope: string, message: string): void { if (!_debugLogsToBridge) return; + const ts = Date.now(); + const trimmed = String(message).slice(0, 2000); try { rvs.send('app_log' as any, { - ts: Date.now(), + ts, platform: Platform.OS, level: 'info', scope, - message: String(message).slice(0, 2000), + message: trimmed, }); } catch {} + // Plus lokal in den App-Logs-Tab emitten — damit Stefan in der App + // selbst (Settings → Protokoll → Live Logs) sieht was passiert, + // ohne curl gegen Bridge. + try { + const entry: LocalLogEntry = { ts, level: 'info', scope, message: trimmed }; + DeviceEventEmitter.emit(APP_LOG_EVENT, entry); + } catch {} } /** Installiert einen globalen JS-Error-Handler der ungefangene Errors via