refactor: M2-Call-Pilot – Module call_signaling + voice_channel mit Fassaden (Entscheidung 2)

- CallSignalingService/callSignalingProvider und VoiceChannelService/
  voiceChannelProvider als einzige oeffentliche Schnittstellen
- voip_manager.dart / livekit_call_manager.dart in ihre Module verschoben,
  Logik unangetastet (nur Klassen-Koepfe, @override, Imports, Provider-Namen)
- Alle Konsumenten entkoppelt; Kompositions-Punkt matrix_client.dart als
  dokumentierte Ausnahme. analyze sauber, 29 Tests gruen, Windows-Start ok.
  Call-Klick-/Geraetetest steht aus (PROGRESS.md)
This commit is contained in:
Bernd Steckmeister
2026-07-06 12:42:59 +02:00
parent f64398d3c6
commit 3c7eb9ddca
20 changed files with 383 additions and 53 deletions
+7 -6
View File
@@ -9,9 +9,10 @@ import 'package:pretty_qr_code/pretty_qr_code.dart';
import 'package:pyramid/core/app_state.dart';
import 'package:pyramid/core/matrix_client.dart';
import 'package:pyramid/core/theme.dart';
import 'package:pyramid/core/voip_manager.dart';
import 'package:pyramid/features/auth/bootstrap_dialog.dart';
import 'package:pyramid/features/call/voice_channel.dart';
import 'package:pyramid/features/call_signaling/call_signaling_service.dart';
import 'package:pyramid/features/voice_channel/voice_channel_service.dart';
import 'package:pyramid/features/chat/chat_view.dart';
import 'package:pyramid/features/members/members_panel.dart';
import 'package:pyramid/features/rooms/rooms_panel.dart';
@@ -160,7 +161,7 @@ class _AppShellState extends ConsumerState<AppShell>
// notifyListeners (u.a. Render-Timer im Sekundentakt); ohne Flankenerkennung
// würde der Nutzer permanent zurück in die Call-UI gezwungen und könnte
// sie nie minimieren.
ref.listen(voipStateProvider, (prev, next) {
ref.listen(callSignalingProvider, (prev, next) {
final wasConnected = _wasVoipConnected;
final isConnected = next.currentCall != null &&
next.currentCall!.state == CallState.kConnected;
@@ -172,7 +173,7 @@ class _AppShellState extends ConsumerState<AppShell>
}
});
ref.listen(callStateProvider, (prev, next) {
ref.listen(voiceChannelProvider, (prev, next) {
// Only auto-switch to voice view for video/audio calls, NOT voice channels
// (voice channels should stay in background with a mini bar)
final wasActive = _wasLiveKitActive;
@@ -200,7 +201,7 @@ class _AppShellState extends ConsumerState<AppShell>
final activeModal = ref.watch(activeModalProvider);
final membersOpen = ref.watch(membersPanelOpenProvider);
final innerPt = PyramidTheme.of(context);
final voip = ref.watch(voipStateProvider);
final voip = ref.watch(callSignalingProvider);
final size = MediaQuery.sizeOf(context);
final isMobile = size.width < 900 || size.height < 500;
@@ -332,7 +333,7 @@ class _MobileShell extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final voip = ref.watch(voipStateProvider);
final voip = ref.watch(callSignalingProvider);
Widget body;
if (viewMode == ViewMode.voice) {
@@ -456,7 +457,7 @@ class _NotificationBlockedBanner extends ConsumerWidget {
class _IncomingCallOverlay extends ConsumerWidget {
final CallSession call;
final PyramidVoipManager voip;
final CallSignalingService voip;
final PyramidTheme pt;
const _IncomingCallOverlay({