Files
pyramid/docs/M2_STATE_MANAGEMENT.md
Bernd Steckmeister 3300a44c4a docs: State-Management-Doc korrigiert - MediaCache-Umstellung ist NICHT risikoarm (Chat-Timeline haengt dran), zurueckgestellt
Der erste Befund beruhte auf einem durch head-limit abgeschnittenen grep;
message_media.dart (am wenigsten geprueft laut PC_TESTPLAN 3) nutzt den
Cache ebenfalls, inkl. statischem Wrapper ohne ref-Zugang.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 17:52:09 +02:00

96 lines
5.4 KiB
Markdown
Raw Permalink 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, 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<MediaCache>`:**
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 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).