Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.8 KiB
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.mdAbschnitt 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:
- Call-Schicht: Singletons + ChangeNotifier hinter den Fassaden.
LiveKitCallManager.instance(static final Singleton,features/voice_channel/livekit_call_manager.dart:17) undPyramidVoipManager._instance(nullable static,features/call_signaling/voip_manager.dart:17; konstruiert im Kompositions-Punktcore/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 pernotifyListeners()grob-granular publiziert. - Voice-UI-Zustand außerhalb des Moduls:
activeVoiceRoomIdProviderundvoiceParticipantsProviderliegen incore/app_state.dart(Kopplungspunkt laut Ist-Analyse), werden aber von Rooms-Panel und Mini-Call-Widget gesetzt/gelesen und gehören fachlich insvoice_channel-Modul (Join-Zustand + Presence sind Modulsache). MediaCache.instance(core/media_cache.dart:19): reines Singleton, direkt vonwidgets/mxc_image.dartbenutzt. Kein UI-Zustand, nur Cache – geringer Schaden, leicht hinter einenProvider<MediaCache>zu legen.- Push/Notifications: modul-globale Mutable-Zustände in
core/notification_service.dart(_windowsNotifs-Map, Plugin-Globals) und direkteSharedPreferences-Zugriffe inbackground_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.dartenthä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)
- [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). - [GESPERRT bis Klick-Test]
activeVoiceRoomIdProvider+voiceParticipantsProviderinsvoice_channel-Modul umziehen (zusammen mitkVoicePresenceType). Mechanisch klein, aber Call-Pfad-nah – sinnvoll im selben Zug wie Schritt 1. - [frei]
MediaCachehinterProvider<MediaCache>und die.instance-Zugriffe inmxc_image.dartaufrefumstellen – risikoarm, jederzeit möglich, guter Lückenfüller. - [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).