# M2 – Einheitliches State-Management: Ist-Analyse + Umbauplan > **STATUS 2026-07-06: reine Analyse, noch KEIN Umbau.** Grundlage für den > ROADMAP-M2-Punkt „Einheitliches State-Management (Riverpod konsequent, > keine Misch-Patterns)". Die Schritte 1–2 unten betreffen den heiligen > Call-Pfad und sind GESPERRT, bis Bernds Klick-Test des Call-Piloten > (`docs/PC_TESTPLAN.md` Abschnitt 8) grün ist – vorher nur Schritt 3. ## Ist-Stand (repo-weit erhoben, 2026-07-06) Riverpod ist bereits das dominante Muster: rund 50 Provider – `StateProvider` für UI-Zustand, `StreamProvider` auf `client.onSync`, `FutureProvider` (Client, Update-Info), `StateNotifierProvider` für die Prefs-Notifier (`BoolPref`/`StringSetPref` in `core/settings_prefs.dart`). `ValueNotifier`/eigene `StreamController` gibt es NICHT. Lokales `setState` in Widgets für rein ephemeren Zustand (Hover, Dialog-Schritte, Textfelder) ist normales Flutter und zählt hier bewusst NICHT als Misch-Pattern. Gefundene Misch-Patterns, nach Gewicht: 1. **Call-Schicht: Singletons + ChangeNotifier hinter den Fassaden.** `LiveKitCallManager.instance` (static final Singleton, `features/voice_channel/livekit_call_manager.dart:17`) und `PyramidVoipManager._instance` (nullable static, `features/call_signaling/voip_manager.dart:17`; konstruiert im Kompositions-Punkt `core/matrix_client.dart:66–71`). Die Modul-Provider (`voiceChannelProvider`/`callSignalingProvider`) geben nur die Singletons zurück. Das ist die im Pilot BEWUSST gewählte Zwischenform (Verhaltensgleichheit vor Schönheit). Eigentliches Problem: UI-Zustand (Mute-Flags, Teilnehmer, Renderer, Qualitätswahl) lebt mutierbar IN den Managern und wird per `notifyListeners()` grob-granular publiziert. 2. **Voice-UI-Zustand außerhalb des Moduls:** `activeVoiceRoomIdProvider` und `voiceParticipantsProvider` liegen in `core/app_state.dart` (Kopplungspunkt laut Ist-Analyse), werden aber von Rooms-Panel und Mini-Call-Widget gesetzt/gelesen und gehören fachlich ins `voice_channel`-Modul (Join-Zustand + Presence sind Modulsache). 3. **`MediaCache.instance`** (`core/media_cache.dart:19`): reines Singleton, kein UI-Zustand, nur Cache. Nutzer sind `widgets/mxc_image.dart` (7 Stellen, Widgets – leicht umstellbar) UND `features/chat/message/message_media.dart` (7 Stellen, darunter der statische Wrapper `_DocBytesCache` für Dokument-Vorschauen, dessen Aufrufer keinen `ref`-Zugang haben). Eine Umstellung müsste `ref`/die Cache-Instanz durch die statischen Helfer der Chat-Timeline fädeln – und genau dieser Code (Download-/Entschlüsselungs-Fehlerpfade) ist laut PC_TESTPLAN Abschnitt 3 der am wenigsten geprüfte Teil der App. 4. **Push/Notifications:** modul-globale Mutable-Zustände in `core/notification_service.dart` (`_windowsNotifs`-Map, Plugin-Globals) und direkte `SharedPreferences`-Zugriffe in `background_push.dart`/ `fcm_push_service.dart`. Das ist dem Background-Isolate-Zwang geschuldet (siehe Schnitt-Doc Punkt 8 + Memory „Pyramid Push") – **bewusst KEIN Umbau-Kandidat**, nur hier dokumentiert. Bereits erledigt im Zuge dieser Analyse: der seit dem Call-Piloten tote `incomingCallProvider` ist aus `app_state.dart` entfernt (41bcaf2). ## Zielbild - `core/app_state.dart` enthält nur noch ECHTEN App-weiten UI-Zustand (Theme, Layout/Panels, Navigation, Toast, Space-Auswahl) – kein Feature-Fachzustand. - Feature-Zustand lebt im jeweiligen Modul hinter dessen Provider; andere Module lesen ihn NUR über die öffentliche Schnittstelle. - Kein `.instance`-Zugriff über Modulgrenzen; Konstruktion ausschließlich im Kompositions-Punkt bzw. im Provider des Moduls. - ChangeNotifier ist als Übergangsform ok; Endzustand der Call-Module ist ein immutables Zustandsobjekt (z. B. `VoiceChannelState`) pro Modul, das der Provider publiziert, plus Kommando-Methoden auf dem Service (entspricht dem Schnitt-Doc-Entwurf, dort als Stream skizziert). ## Schrittfolge (Reihenfolge = Priorität) 1. **[GESPERRT bis Klick-Test] UI-State aus den Managern herauslösen:** je Call-Modul ein immutables Zustandsobjekt + `Notifier`/ `StateNotifier`, Manager wird interne Implementierung ohne UI-Zustand. Das ist der bereits in PROGRESS.md zurückgestellte Logik-Umbau – NICHT vorher anfangen (heiliger Call-Pfad, ein ungetesteter Umbau liegt schon auf dem Stapel). 2. **[GESPERRT bis Klick-Test] `activeVoiceRoomIdProvider` + `voiceParticipantsProvider` ins `voice_channel`-Modul umziehen** (zusammen mit `kVoicePresenceType`). Mechanisch klein, aber Call-Pfad-nah – sinnvoll im selben Zug wie Schritt 1. 3. **[ZURÜCKGESTELLT] `MediaCache` hinter `Provider`:** Erst als „risikoarm, jederzeit" eingestuft – das stimmte NICHT (Korrektur 2026-07-06, siehe Ist-Stand Punkt 3: auch die Chat-Timeline hängt dran, inkl. statischer Helfer ohne `ref`). Gehört in den Zug des `chat_timeline`-Moduls (Schnitt-Doc Punkt 9) bzw. frühestens nach dem Klick-Test von PC_TESTPLAN Abschnitt 3 – nicht als Lückenfüller. 4. **[kein Umbau] Push/Notifications:** bleibt wie es ist (Isolate-Zwang); nur bei ohnehin anstehenden Push-Arbeiten die Prefs-Zugriffe auf die `Prefs`-Fassade ziehen (Schnitt-Doc Punkt 6). Abhak-Kriterium für den ROADMAP-Punkt: Schritte 1–3 umgesetzt und die Kernflows (Login, Raum, Nachricht, Voice-Join) nach jedem Schritt praktisch geprüft; Punkt 4 braucht nur den Doku-Vermerk (steht hiermit).