From 63dde6506fc9cf68eaf727e6c79e63a19101d0aa Mon Sep 17 00:00:00 2001 From: duffyduck Date: Fri, 3 Jul 2026 02:07:33 +0200 Subject: [PATCH] fix(projects): Drawer resettet App-Focus nicht mehr (leere Projekte-Ursache) + Zurueck-Button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kernbug: ProjectsBrowser.load() pushte bei JEDEM Drawer-Oeffnen status.active in den App-Focus. Im Multi-Threading hat das Brain keinen globalen active_project-State mehr → status.active ist null → Focus wurde auf Hauptchat zurueckgesetzt. Folge: nach jedem Drawer-Oeffnen landeten alle Nachrichten im Hauptchat, Projekte blieben leer. - ProjectsBrowser: neues Prop currentFocusId (App-Focus = Source-of-Truth). load() uebernimmt nur noch die Projektliste, kein onActiveChanged(status.active) mehr. Highlight (✓ FOCUS) folgt currentFocusId. - ChatScreen: currentFocusId={focusedProjectId} durchgereicht. - ChatScreen: direkter „← Hauptchat"-Button im Focus-Header (nur im Projekt sichtbar) — ein Tap statt Drawer→Hauptchat. Co-Authored-By: Claude Opus 4.8 (1M context) --- android/src/components/ProjectsBrowser.tsx | 18 +++++++++++++++--- android/src/screens/ChatScreen.tsx | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/android/src/components/ProjectsBrowser.tsx b/android/src/components/ProjectsBrowser.tsx index d4a7e0c..007baaf 100644 --- a/android/src/components/ProjectsBrowser.tsx +++ b/android/src/components/ProjectsBrowser.tsx @@ -36,6 +36,12 @@ interface Props { /** Wird gerufen wenn Stefan ein anderes Projekt fokussiert (App-lokale * UI-Entscheidung, wechselt den Chat-Focus). */ onActiveChanged?: (project: Project | null) => void; + /** Der aktuell in der App fokussierte Kontext (App-lokale Source-of-Truth). + * Leer = Hauptchat. Steuert das ✓-FOCUS-Highlight. WICHTIG: der Drawer darf + * den Focus NICHT aus dem Brain-Status ableiten — im Multi-Threading gibt es + * kein globales active_project mehr (status.active ist null), das wuerde den + * Focus bei jedem Drawer-Oeffnen auf Hauptchat zuruecksetzen. */ + currentFocusId?: string; /** Queue-Status pro Kontext (key "__main__" = Hauptchat, sonst project_id). * Wenn geliefert: Status-Dot pro Zeile gerendert. */ queueStatus?: Record; @@ -51,7 +57,7 @@ function _fmtRel(unixSec: number): string { return new Date(unixSec * 1000).toLocaleDateString('de-DE'); } -export const ProjectsBrowser: React.FC = ({ visible = true, onClose, onActiveChanged, queueStatus }) => { +export const ProjectsBrowser: React.FC = ({ visible = true, onClose, onActiveChanged, currentFocusId, queueStatus }) => { const _statusDot = (pid: string) => { const s = queueStatus?.[pid]; if (!s) return { color: '#555570', label: '' }; @@ -80,9 +86,11 @@ export const ProjectsBrowser: React.FC = ({ visible = true, onClose, onAc setLoading(true); setErr(null); brainApi.getProjectStatus() .then(status => { + // NUR die Projektliste + Queue uebernehmen. NICHT status.active in den + // App-Focus pushen — im Multi-Threading ist das Brain-active_project + // bedeutungslos (null), das wuerde den Focus bei jedem Drawer-Oeffnen + // auf Hauptchat zuruecksetzen und alle Nachrichten dort landen lassen. setProjects(status.projects || []); - setActiveId(status.active_id || ''); - onActiveChangedRef.current?.(status.active); }) .catch(e => setErr(String(e?.message || e))) .finally(() => setLoading(false)); @@ -90,6 +98,10 @@ export const ProjectsBrowser: React.FC = ({ visible = true, onClose, onAc useEffect(() => { if (visible) load(); }, [visible, load]); + // Highlight („✓ FOCUS") folgt dem App-Focus (Source-of-Truth), nicht dem + // Brain. switchTo setzt activeId zusaetzlich sofort fuer Instant-Feedback. + useEffect(() => { setActiveId(currentFocusId || ''); }, [currentFocusId]); + // Reload bei RVS-Reconnect — sonst zeigt die Liste den Fast-Fail ewig useEffect(() => { if (!visible) return; diff --git a/android/src/screens/ChatScreen.tsx b/android/src/screens/ChatScreen.tsx index fd377e8..e129c42 100644 --- a/android/src/screens/ChatScreen.tsx +++ b/android/src/screens/ChatScreen.tsx @@ -2607,6 +2607,21 @@ const ChatScreen: React.FC = () => { {dot.label} + {/* Direkter Zurueck-zum-Hauptchat-Button — nur wenn man in einem + Projekt ist. Ein Tap statt Drawer→Hauptchat. */} + {!isMain && ( + setFocusedProjectId('')} + hitSlop={{top:8,bottom:8,left:8,right:8}} + style={{ + marginLeft: 4, paddingHorizontal: 10, paddingVertical: 4, + borderRadius: 12, backgroundColor: 'rgba(255,255,255,0.12)', + flexDirection: 'row', alignItems: 'center', gap: 4, + }} + > + ← Hauptchat + + )} ); @@ -2617,6 +2632,7 @@ const ChatScreen: React.FC = () => { visible={projectsVisible} onClose={() => setProjectsVisible(false)} onActiveChanged={(p) => setFocusedProjectId(p?.id || '')} + currentFocusId={focusedProjectId} queueStatus={queueStatus} />