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

88 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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).