Files
pyramid/docs/M2_STATE_MANAGEMENT.md
T
2026-07-06 17:50:05 +02:00

4.8 KiB
Raw Blame History

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 12 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:6671). 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, direkt von widgets/mxc_image.dart benutzt. Kein UI-Zustand, nur Cache geringer Schaden, leicht hinter einen Provider<MediaCache> zu legen.
  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. [frei] MediaCache hinter Provider<MediaCache> und die .instance-Zugriffe in mxc_image.dart auf ref umstellen risikoarm, jederzeit möglich, guter 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 13 umgesetzt und die Kernflows (Login, Raum, Nachricht, Voice-Join) nach jedem Schritt praktisch geprüft; Punkt 4 braucht nur den Doku-Vermerk (steht hiermit).