refactor: voice_*-Prefs hinter VoicePrefs-Fassade in settings_prefs (M2 storage-Leitplanke, gleiche Keys/Semantik)
This commit is contained in:
+18
@@ -1392,3 +1392,21 @@
|
|||||||
2026-07-06 12:44 [Edit] C:\Users\nordm\pyramid - Kopie\docs\PC_TESTPLAN.md
|
2026-07-06 12:44 [Edit] C:\Users\nordm\pyramid - Kopie\docs\PC_TESTPLAN.md
|
||||||
2026-07-06 12:44 [Edit] C:\Users\nordm\pyramid - Kopie\ROADMAP.md
|
2026-07-06 12:44 [Edit] C:\Users\nordm\pyramid - Kopie\ROADMAP.md
|
||||||
2026-07-06 12:45 [Edit] C:\Users\nordm\pyramid - Kopie\PROGRESS.md
|
2026-07-06 12:45 [Edit] C:\Users\nordm\pyramid - Kopie\PROGRESS.md
|
||||||
|
2026-07-06 16:58 [Edit] C:\Users\nordm\pyramid - Kopie\docs\PC_TESTPLAN.md
|
||||||
|
2026-07-06 16:59 [Edit] C:\Users\nordm\pyramid - Kopie\PROGRESS.md
|
||||||
|
2026-07-06 17:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart
|
||||||
|
2026-07-06 17:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart
|
||||||
|
2026-07-06 17:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\settings_prefs.dart
|
||||||
|
2026-07-06 17:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call_signaling\voip_manager.dart
|
||||||
|
2026-07-06 17:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call_signaling\voip_manager.dart
|
||||||
|
2026-07-06 17:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\voice_channel\livekit_call_manager.dart
|
||||||
|
2026-07-06 17:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call_signaling\voip_manager.dart
|
||||||
|
2026-07-06 17:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\voice_channel\livekit_call_manager.dart
|
||||||
|
2026-07-06 17:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings\settings_voice.dart
|
||||||
|
2026-07-06 17:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings\settings_voice.dart
|
||||||
|
2026-07-06 17:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings\settings_voice.dart
|
||||||
|
2026-07-06 17:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings\settings_voice.dart
|
||||||
|
2026-07-06 17:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings\settings_voice.dart
|
||||||
|
2026-07-06 17:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings\settings_voice.dart
|
||||||
|
2026-07-06 17:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings\settings_voice.dart
|
||||||
|
2026-07-06 17:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart
|
||||||
|
|||||||
@@ -90,6 +90,56 @@ final privacyReadReceiptsProvider =
|
|||||||
final privacyTypingProvider =
|
final privacyTypingProvider =
|
||||||
StateNotifierProvider<BoolPref, bool>((ref) => BoolPref('privacy_typing', true));
|
StateNotifierProvider<BoolPref, bool>((ref) => BoolPref('privacy_typing', true));
|
||||||
|
|
||||||
|
// ── Voice preferences ────────────────────────────────────────────────────────
|
||||||
|
// Geschrieben von der Settings-Voice-Sektion, gelesen von den Call-Modulen
|
||||||
|
// (call_signaling, voice_channel). Die historischen voice_*-Keys bleiben
|
||||||
|
// unverändert, damit bestehende Nutzer-Einstellungen erhalten bleiben.
|
||||||
|
|
||||||
|
class VoicePrefs {
|
||||||
|
VoicePrefs._();
|
||||||
|
|
||||||
|
static const _kMic = 'voice_mic_device';
|
||||||
|
static const _kSpeaker = 'voice_speaker_device';
|
||||||
|
static const _kCamera = 'voice_camera_device';
|
||||||
|
static const _kOutputVolume = 'voice_output_volume';
|
||||||
|
|
||||||
|
static Future<double> loadOutputVolume() async {
|
||||||
|
final p = await SharedPreferences.getInstance();
|
||||||
|
return p.getDouble(_kOutputVolume) ?? 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> saveOutputVolume(double v) async {
|
||||||
|
final p = await SharedPreferences.getInstance();
|
||||||
|
await p.setDouble(_kOutputVolume, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gewählte Geräte-IDs; null = kein Pref gesetzt (System-Standard nutzen).
|
||||||
|
static Future<({String? mic, String? speaker, String? camera})>
|
||||||
|
loadDevices() async {
|
||||||
|
final p = await SharedPreferences.getInstance();
|
||||||
|
return (
|
||||||
|
mic: p.getString(_kMic),
|
||||||
|
speaker: p.getString(_kSpeaker),
|
||||||
|
camera: p.getString(_kCamera),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> saveMic(String? deviceId) => _saveDevice(_kMic, deviceId);
|
||||||
|
static Future<void> saveSpeaker(String? deviceId) =>
|
||||||
|
_saveDevice(_kSpeaker, deviceId);
|
||||||
|
static Future<void> saveCamera(String? deviceId) =>
|
||||||
|
_saveDevice(_kCamera, deviceId);
|
||||||
|
|
||||||
|
static Future<void> _saveDevice(String key, String? deviceId) async {
|
||||||
|
final p = await SharedPreferences.getInstance();
|
||||||
|
if (deviceId == null || deviceId.isEmpty) {
|
||||||
|
await p.remove(key);
|
||||||
|
} else {
|
||||||
|
await p.setString(key, deviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Theme persistence helpers ────────────────────────────────────────────────
|
// ── Theme persistence helpers ────────────────────────────────────────────────
|
||||||
|
|
||||||
Future<void> saveThemePrefs({
|
Future<void> saveThemePrefs({
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
|
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:webrtc_interface/webrtc_interface.dart';
|
import 'package:webrtc_interface/webrtc_interface.dart';
|
||||||
import 'package:pyramid/core/ice_servers.dart';
|
import 'package:pyramid/core/ice_servers.dart';
|
||||||
|
import 'package:pyramid/core/settings_prefs.dart';
|
||||||
import 'package:pyramid/features/call_signaling/call_signaling_service.dart';
|
import 'package:pyramid/features/call_signaling/call_signaling_service.dart';
|
||||||
import 'package:pyramid/widgets/screen_share_picker.dart';
|
import 'package:pyramid/widgets/screen_share_picker.dart';
|
||||||
|
|
||||||
@@ -272,8 +272,7 @@ class PyramidVoipManager extends CallSignalingService
|
|||||||
var v = value;
|
var v = value;
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
try {
|
try {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
v = await VoicePrefs.loadOutputVolume();
|
||||||
v = prefs.getDouble('voice_output_volume') ?? 1.0;
|
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
v = 1.0;
|
v = 1.0;
|
||||||
}
|
}
|
||||||
@@ -467,10 +466,10 @@ class MediaDevicesWrapper extends MediaDevices {
|
|||||||
// In den Einstellungen gewählte Geräte (voice_*_device Prefs) anwenden —
|
// In den Einstellungen gewählte Geräte (voice_*_device Prefs) anwenden —
|
||||||
// nur wenn kein Screenshare-Source gesetzt ist (sonst nicht anfassen).
|
// nur wenn kein Screenshare-Source gesetzt ist (sonst nicht anfassen).
|
||||||
try {
|
try {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final devicePrefs = await VoicePrefs.loadDevices();
|
||||||
final mic = prefs.getString('voice_mic_device');
|
final mic = devicePrefs.mic;
|
||||||
final cam = prefs.getString('voice_camera_device');
|
final cam = devicePrefs.camera;
|
||||||
final speaker = prefs.getString('voice_speaker_device');
|
final speaker = devicePrefs.speaker;
|
||||||
if (mic != null &&
|
if (mic != null &&
|
||||||
improvedConstraints['audio'] != null &&
|
improvedConstraints['audio'] != null &&
|
||||||
improvedConstraints['audio'] != false) {
|
improvedConstraints['audio'] != false) {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import 'package:livekit_client/livekit_client.dart';
|
|||||||
import 'package:matrix/matrix.dart' hide Room;
|
import 'package:matrix/matrix.dart' hide Room;
|
||||||
import 'package:pyramid/core/ice_servers.dart';
|
import 'package:pyramid/core/ice_servers.dart';
|
||||||
import 'package:pyramid/core/livekit_token.dart';
|
import 'package:pyramid/core/livekit_token.dart';
|
||||||
|
import 'package:pyramid/core/settings_prefs.dart';
|
||||||
import 'package:pyramid/features/voice_channel/voice_channel_service.dart';
|
import 'package:pyramid/features/voice_channel/voice_channel_service.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
const _kVoicePresenceType = 'io.pyramid.voice.presence';
|
const _kVoicePresenceType = 'io.pyramid.voice.presence';
|
||||||
|
|
||||||
@@ -260,11 +260,11 @@ class LiveKitCallManager extends VoiceChannelService {
|
|||||||
String? prefMic, prefSpeaker, prefCam;
|
String? prefMic, prefSpeaker, prefCam;
|
||||||
var deviceIds = <String>{};
|
var deviceIds = <String>{};
|
||||||
try {
|
try {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
_outputVolume = await VoicePrefs.loadOutputVolume();
|
||||||
_outputVolume = prefs.getDouble('voice_output_volume') ?? 1.0;
|
final devicePrefs = await VoicePrefs.loadDevices();
|
||||||
prefMic = prefs.getString('voice_mic_device');
|
prefMic = devicePrefs.mic;
|
||||||
prefSpeaker = prefs.getString('voice_speaker_device');
|
prefSpeaker = devicePrefs.speaker;
|
||||||
prefCam = prefs.getString('voice_camera_device');
|
prefCam = devicePrefs.camera;
|
||||||
final devices = await rtc.navigator.mediaDevices.enumerateDevices();
|
final devices = await rtc.navigator.mediaDevices.enumerateDevices();
|
||||||
deviceIds = devices.map((d) => d.deviceId).toSet();
|
deviceIds = devices.map((d) => d.deviceId).toSet();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -19,11 +19,6 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
|||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
String? _loadError;
|
String? _loadError;
|
||||||
|
|
||||||
static const _kMic = 'voice_mic_device';
|
|
||||||
static const _kSpeaker = 'voice_speaker_device';
|
|
||||||
static const _kCamera = 'voice_camera_device';
|
|
||||||
static const _kOutputVolume = 'voice_output_volume';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -31,7 +26,8 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _init() async {
|
Future<void> _init() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final devicePrefs = await VoicePrefs.loadDevices();
|
||||||
|
final outputVolume = await VoicePrefs.loadOutputVolume();
|
||||||
List<MediaDeviceInfo> devices = [];
|
List<MediaDeviceInfo> devices = [];
|
||||||
String? loadError;
|
String? loadError;
|
||||||
try {
|
try {
|
||||||
@@ -76,10 +72,10 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
|||||||
_audioInputs = devices.where((d) => d.kind?.toLowerCase() == 'audioinput').toList();
|
_audioInputs = devices.where((d) => d.kind?.toLowerCase() == 'audioinput').toList();
|
||||||
_audioOutputs = devices.where((d) => d.kind?.toLowerCase() == 'audiooutput').toList();
|
_audioOutputs = devices.where((d) => d.kind?.toLowerCase() == 'audiooutput').toList();
|
||||||
_videoInputs = devices.where((d) => d.kind?.toLowerCase() == 'videoinput').toList();
|
_videoInputs = devices.where((d) => d.kind?.toLowerCase() == 'videoinput').toList();
|
||||||
_selectedMic = prefs.getString(_kMic);
|
_selectedMic = devicePrefs.mic;
|
||||||
_selectedSpeaker = prefs.getString(_kSpeaker);
|
_selectedSpeaker = devicePrefs.speaker;
|
||||||
_selectedCamera = prefs.getString(_kCamera);
|
_selectedCamera = devicePrefs.camera;
|
||||||
_outputVolume = prefs.getDouble(_kOutputVolume) ?? 1.0;
|
_outputVolume = outputVolume;
|
||||||
_loadError = loadError;
|
_loadError = loadError;
|
||||||
_loading = false;
|
_loading = false;
|
||||||
});
|
});
|
||||||
@@ -87,8 +83,7 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
|||||||
|
|
||||||
Future<void> _setOutputVolume(double v) async {
|
Future<void> _setOutputVolume(double v) async {
|
||||||
setState(() => _outputVolume = v);
|
setState(() => _outputVolume = v);
|
||||||
final prefs = await SharedPreferences.getInstance();
|
await VoicePrefs.saveOutputVolume(v);
|
||||||
await prefs.setDouble(_kOutputVolume, v);
|
|
||||||
// Live auf laufende Calls anwenden (über die Modul-Fassaden).
|
// Live auf laufende Calls anwenden (über die Modul-Fassaden).
|
||||||
ref.read(voiceChannelProvider).setOutputVolume(v).catchError((_) {});
|
ref.read(voiceChannelProvider).setOutputVolume(v).catchError((_) {});
|
||||||
try {
|
try {
|
||||||
@@ -96,15 +91,6 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
|||||||
} catch (_) {} // Instanz existiert evtl. noch nicht
|
} catch (_) {} // Instanz existiert evtl. noch nicht
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _save(String key, String? value) async {
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
await prefs.remove(key);
|
|
||||||
} else {
|
|
||||||
await prefs.setString(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _deviceDropdown({
|
Widget _deviceDropdown({
|
||||||
required List<MediaDeviceInfo> devices,
|
required List<MediaDeviceInfo> devices,
|
||||||
required String? selected,
|
required String? selected,
|
||||||
@@ -227,7 +213,7 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
|||||||
icon: Icons.mic_rounded,
|
icon: Icons.mic_rounded,
|
||||||
onChanged: (v) {
|
onChanged: (v) {
|
||||||
setState(() => _selectedMic = v);
|
setState(() => _selectedMic = v);
|
||||||
_save(_kMic, v);
|
VoicePrefs.saveMic(v);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -243,7 +229,7 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
|||||||
icon: Icons.volume_up_rounded,
|
icon: Icons.volume_up_rounded,
|
||||||
onChanged: (v) {
|
onChanged: (v) {
|
||||||
setState(() => _selectedSpeaker = v);
|
setState(() => _selectedSpeaker = v);
|
||||||
_save(_kSpeaker, v);
|
VoicePrefs.saveSpeaker(v);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -259,7 +245,7 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
|||||||
icon: Icons.videocam_rounded,
|
icon: Icons.videocam_rounded,
|
||||||
onChanged: (v) {
|
onChanged: (v) {
|
||||||
setState(() => _selectedCamera = v);
|
setState(() => _selectedCamera = v);
|
||||||
_save(_kCamera, v);
|
VoicePrefs.saveCamera(v);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import 'package:pyramid/widgets/banner_crop_dialog.dart';
|
|||||||
import 'package:pyramid/widgets/hover_region.dart';
|
import 'package:pyramid/widgets/hover_region.dart';
|
||||||
import 'package:pyramid/widgets/mxc_image.dart';
|
import 'package:pyramid/widgets/mxc_image.dart';
|
||||||
import 'package:pyramid/widgets/pyramid_loader.dart';
|
import 'package:pyramid/widgets/pyramid_loader.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
part 'settings/settings_shared.dart';
|
part 'settings/settings_shared.dart';
|
||||||
part 'settings/settings_profile.dart';
|
part 'settings/settings_profile.dart';
|
||||||
|
|||||||
Reference in New Issue
Block a user