diff --git a/CHANGES.md b/CHANGES.md index 3d3e200..8db4391 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1424,3 +1424,6 @@ 2026-07-06 17:44 [Edit] C:\Users\nordm\pyramid - Kopie\ROADMAP.md 2026-07-06 17:45 [Edit] C:\Users\nordm\pyramid - Kopie\PROGRESS.md 2026-07-06 17:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-07-06 17:49 [Write] C:\Users\nordm\pyramid - Kopie\docs\M2_STATE_MANAGEMENT.md +2026-07-06 17:49 [Edit] C:\Users\nordm\pyramid - Kopie\ROADMAP.md +2026-07-06 17:49 [Edit] C:\Users\nordm\pyramid - Kopie\PROGRESS.md diff --git a/PROGRESS.md b/PROGRESS.md index d0c3534..5ae950e 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -13,6 +13,34 @@ Schritt (und beim Abbruch mitten im Schritt den Zwischenstand). Format: --- +## 2026-07-06 – State-Management-Ist-Analyse (docs/M2_STATE_MANAGEMENT.md) + toter incomingCallProvider entfernt + +**Erledigt:** Nächster offener M2-Punkt „Einheitliches State-Management" – +nach dem erprobten Vorgehen erst die Analyse, Umsetzung folgt gestaffelt: + +- **`docs/M2_STATE_MANAGEMENT.md` geschrieben:** Repo-weite Bestandsaufnahme + (Riverpod schon dominant, ~50 Provider, keine ValueNotifier/eigenen + StreamController). 4 Misch-Patterns identifiziert und gewichtet: + (1) Call-Singletons + ChangeNotifier hinter den Pilot-Fassaden mit + UI-Zustand IN den Managern, (2) `activeVoiceRoomIdProvider`/ + `voiceParticipantsProvider` liegen in app_state.dart statt im + voice_channel-Modul, (3) `MediaCache.instance`, (4) Push-Globals + (bewusst so, Isolate-Zwang – KEIN Umbau-Kandidat). Zielbild + + Schrittfolge mit klarem Gating: Schritte 1–2 (Call-Pfad) GESPERRT bis + Bernds Klick-Test des Piloten; frei ist nur MediaCache-hinter-Provider. +- **Toter `incomingCallProvider` entfernt (41bcaf2):** einzige Fundstelle + repo-weit war die Definition in app_state.dart – Überbleibsel des + Call-Piloten (Provider ersatzlos in die Module verlegt). analyze sauber, + 29 Tests grün. + +**Offen/Nächster Schritt:** auth_log-Check (Einträge seit 2026-07-06 +17:43). Umsetzbar ohne Bernd wäre noch Schritt 3 aus dem neuen Doc +(MediaCache hinter Provider); Schritte 1–2 erst nach dem Klick-Test. + +**Stolperfallen:** Keine – Analyse + risikofreie Leichen-Entfernung. + +--- + ## 2026-07-06 – auth_log-Check 17:14-Fenster sauber + settings_encryption.dart in 4 part-Dateien geteilt (6128953) **Erledigt:** Dritte PC-Session des Tages. Zuerst der von der Vorsession diff --git a/ROADMAP.md b/ROADMAP.md index 3c35711..15951e3 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -197,6 +197,13 @@ lassen, ohne dass andere Module angefasst werden müssen. herauslösen – kein zweiter ungetesteter Logik-Umbau auf dem heiligen Call-Pfad. - [ ] Einheitliches State-Management (Riverpod konsequent, keine Misch-Patterns) + **Ist-Analyse + Umbauplan liegen in `docs/M2_STATE_MANAGEMENT.md`** + (2026-07-06): Riverpod ist schon dominant (~50 Provider); 4 + Misch-Patterns identifiziert, Schrittfolge definiert. Schritte 1–2 + (Call-Manager-UI-State, Voice-Provider-Umzug) GESPERRT bis Bernds + Klick-Test (PC_TESTPLAN Abschnitt 8); frei: MediaCache hinter + Provider. Push bleibt bewusst wie er ist (Isolate-Zwang). Toter + `incomingCallProvider` bereits entfernt (41bcaf2). - [x] Toten Code & Duplikate entfernen, Ordnerstruktur vereinheitlichen (PROGRESS.md 2026-07-03: `message_bubble.dart` tot entfernt, doppelte `_formatTime` in `message_group.dart` zusammengeführt; alle 6 in der diff --git a/docs/M2_STATE_MANAGEMENT.md b/docs/M2_STATE_MANAGEMENT.md new file mode 100644 index 0000000..9616190 --- /dev/null +++ b/docs/M2_STATE_MANAGEMENT.md @@ -0,0 +1,87 @@ +# 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, direkt von `widgets/mxc_image.dart` benutzt. Kein + UI-Zustand, nur Cache – geringer Schaden, leicht hinter einen + `Provider` 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`** 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 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).