♻️ Trying out the new built-in webrtc
This commit is contained in:
@@ -10,7 +10,7 @@ import 'package:island/widgets/chat/call_participant_tile.dart';
|
||||
import 'package:island/widgets/content/sheet.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:livekit_client/livekit_client.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
class CallControlsBar extends HookConsumerWidget {
|
||||
const CallControlsBar({super.key});
|
||||
@@ -194,9 +194,16 @@ class CallControlsBar extends HookConsumerWidget {
|
||||
String deviceType,
|
||||
) async {
|
||||
try {
|
||||
final devices = await Hardware.instance.enumerateDevices(
|
||||
type: deviceType,
|
||||
);
|
||||
final devices = await navigator.mediaDevices.enumerateDevices();
|
||||
final filteredDevices =
|
||||
devices.where((device) {
|
||||
if (deviceType == 'videoinput') {
|
||||
return device.kind == 'videoinput';
|
||||
} else if (deviceType == 'audioinput') {
|
||||
return device.kind == 'audioinput';
|
||||
}
|
||||
return false;
|
||||
}).toList();
|
||||
|
||||
if (!context.mounted) return;
|
||||
|
||||
@@ -209,9 +216,9 @@ class CallControlsBar extends HookConsumerWidget {
|
||||
? 'selectCamera'.tr()
|
||||
: 'selectMicrophone'.tr(),
|
||||
child: ListView.builder(
|
||||
itemCount: devices.length,
|
||||
itemCount: filteredDevices.length,
|
||||
itemBuilder: (context, index) {
|
||||
final device = devices[index];
|
||||
final device = filteredDevices[index];
|
||||
return ListTile(
|
||||
title: Text(
|
||||
device.label.isNotEmpty
|
||||
@@ -236,35 +243,12 @@ class CallControlsBar extends HookConsumerWidget {
|
||||
Future<void> _switchDevice(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
MediaDevice device,
|
||||
MediaDeviceInfo device,
|
||||
String deviceType,
|
||||
) async {
|
||||
try {
|
||||
final callNotifier = ref.read(callNotifierProvider.notifier);
|
||||
|
||||
if (deviceType == 'videoinput') {
|
||||
// Switch camera device
|
||||
final localParticipant = callNotifier.room?.localParticipant;
|
||||
final videoTrack =
|
||||
localParticipant?.videoTrackPublications.firstOrNull?.track;
|
||||
|
||||
if (videoTrack is LocalVideoTrack) {
|
||||
await videoTrack.switchCamera(device.deviceId);
|
||||
}
|
||||
} else if (deviceType == 'audioinput') {
|
||||
// Switch microphone device
|
||||
final localParticipant = callNotifier.room?.localParticipant;
|
||||
final audioTrack =
|
||||
localParticipant?.audioTrackPublications.firstOrNull?.track;
|
||||
|
||||
if (audioTrack is LocalAudioTrack) {
|
||||
// For audio devices, we need to restart the track with new device
|
||||
await audioTrack.restartTrack(
|
||||
AudioCaptureOptions(deviceId: device.deviceId),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement device switching for WebRTC
|
||||
// This would require restarting the media stream with the new device
|
||||
if (context.mounted) {
|
||||
showSnackBar(
|
||||
'switchedTo'.tr(
|
||||
@@ -289,31 +273,9 @@ class CallOverlayBar extends HookConsumerWidget {
|
||||
if (!callState.isConnected) return const SizedBox.shrink();
|
||||
|
||||
final lastSpeaker =
|
||||
callNotifier.participants
|
||||
.where(
|
||||
(element) => element.remoteParticipant.lastSpokeAt != null,
|
||||
)
|
||||
.isEmpty
|
||||
callNotifier.participants.isNotEmpty
|
||||
? callNotifier.participants.first
|
||||
: callNotifier.participants
|
||||
.where(
|
||||
(element) => element.remoteParticipant.lastSpokeAt != null,
|
||||
)
|
||||
.fold(
|
||||
callNotifier.participants.first,
|
||||
(value, element) =>
|
||||
element.remoteParticipant.lastSpokeAt != null &&
|
||||
(value.remoteParticipant.lastSpokeAt == null ||
|
||||
element.remoteParticipant.lastSpokeAt!
|
||||
.compareTo(
|
||||
value
|
||||
.remoteParticipant
|
||||
.lastSpokeAt!,
|
||||
) >
|
||||
0)
|
||||
? element
|
||||
: value,
|
||||
);
|
||||
: null;
|
||||
|
||||
final actionButtonStyle = ButtonStyle(
|
||||
minimumSize: const MaterialStatePropertyAll(Size(24, 24)),
|
||||
@@ -330,17 +292,16 @@ class CallOverlayBar extends HookConsumerWidget {
|
||||
children: [
|
||||
Builder(
|
||||
builder: (context) {
|
||||
if (callNotifier.localParticipant == null) {
|
||||
return CircularProgressIndicator().center();
|
||||
if (lastSpeaker == null) {
|
||||
return const CircularProgressIndicator();
|
||||
}
|
||||
return SizedBox(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child:
|
||||
SpeakingRippleAvatar(
|
||||
live: lastSpeaker,
|
||||
size: 36,
|
||||
).center(),
|
||||
child: SpeakingRippleAvatar(
|
||||
live: lastSpeaker,
|
||||
size: 36,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -348,7 +309,9 @@ class CallOverlayBar extends HookConsumerWidget {
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('@${lastSpeaker.participant.identity}').bold(),
|
||||
Text(
|
||||
'@${lastSpeaker?.participant.identity ?? 'Unknown'}',
|
||||
),
|
||||
Text(
|
||||
formatDuration(callState.duration),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
|
||||
Reference in New Issue
Block a user