3300a44c4a
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>
96 lines
5.4 KiB
Markdown
96 lines
5.4 KiB
Markdown
# 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<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 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).
|