2024-06-01 12:18:25 +00:00
|
|
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:get/get.dart';
|
|
|
|
import 'package:livekit_client/livekit_client.dart';
|
|
|
|
import 'package:solian/exts.dart';
|
|
|
|
import 'package:solian/models/call.dart';
|
|
|
|
import 'package:solian/models/channel.dart';
|
|
|
|
import 'package:solian/providers/auth.dart';
|
2024-07-23 17:17:41 +00:00
|
|
|
import 'package:solian/providers/call.dart';
|
2024-06-01 12:18:25 +00:00
|
|
|
|
|
|
|
class ChatCallPrejoinPopup extends StatefulWidget {
|
|
|
|
final Call ongoingCall;
|
|
|
|
final Channel channel;
|
2024-08-19 17:19:18 +00:00
|
|
|
final Function onJoin;
|
2024-06-01 12:18:25 +00:00
|
|
|
|
|
|
|
const ChatCallPrejoinPopup({
|
|
|
|
super.key,
|
|
|
|
required this.ongoingCall,
|
|
|
|
required this.channel,
|
2024-08-19 17:19:18 +00:00
|
|
|
required this.onJoin,
|
2024-06-01 12:18:25 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<ChatCallPrejoinPopup> createState() => _ChatCallPrejoinPopupState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _ChatCallPrejoinPopupState extends State<ChatCallPrejoinPopup> {
|
|
|
|
bool _isBusy = false;
|
|
|
|
|
2024-08-19 17:10:15 +00:00
|
|
|
void _performJoin() async {
|
2024-06-01 12:18:25 +00:00
|
|
|
final AuthProvider auth = Get.find();
|
2024-08-19 17:10:15 +00:00
|
|
|
final ChatCallProvider call = Get.find();
|
2024-07-24 17:18:47 +00:00
|
|
|
if (auth.isAuthorized.isFalse) return;
|
2024-06-01 12:18:25 +00:00
|
|
|
|
|
|
|
setState(() => _isBusy = true);
|
|
|
|
|
2024-08-19 17:10:15 +00:00
|
|
|
call.setCall(widget.ongoingCall, widget.channel);
|
|
|
|
call.isBusy.value = true;
|
2024-06-01 12:18:25 +00:00
|
|
|
|
|
|
|
try {
|
2024-08-19 17:10:15 +00:00
|
|
|
final resp = await call.getRoomToken();
|
2024-06-01 12:18:25 +00:00
|
|
|
final token = resp.$1;
|
|
|
|
final endpoint = resp.$2;
|
|
|
|
|
2024-08-19 17:10:15 +00:00
|
|
|
call.initRoom();
|
|
|
|
call.setupRoomListeners(
|
2024-06-01 12:18:25 +00:00
|
|
|
onDisconnected: (reason) {
|
|
|
|
context.showSnackbar(
|
|
|
|
'callDisconnected'.trParams({'reason': reason.toString()}),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2024-08-19 17:10:15 +00:00
|
|
|
call.joinRoom(endpoint, token);
|
2024-06-01 12:18:25 +00:00
|
|
|
|
2024-08-19 17:10:15 +00:00
|
|
|
Navigator.pop(context);
|
2024-06-01 12:18:25 +00:00
|
|
|
} catch (e) {
|
|
|
|
context.showErrorDialog(e);
|
|
|
|
}
|
|
|
|
|
2024-08-19 17:19:18 +00:00
|
|
|
widget.onJoin();
|
2024-06-01 12:18:25 +00:00
|
|
|
setState(() => _isBusy = false);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
2024-08-19 17:10:15 +00:00
|
|
|
final ChatCallProvider call = Get.find();
|
|
|
|
call.checkPermissions().then((_) {
|
|
|
|
call.initHardware();
|
2024-06-01 12:18:25 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
super.initState();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
final ChatCallProvider provider = Get.find();
|
|
|
|
|
|
|
|
return Obx(
|
|
|
|
() => Center(
|
|
|
|
child: Container(
|
|
|
|
constraints: const BoxConstraints(maxWidth: 320),
|
|
|
|
child: Column(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
children: [
|
|
|
|
Text('callMicrophone'.tr),
|
|
|
|
Switch(
|
|
|
|
value: provider.enableAudio.value,
|
|
|
|
onChanged: null,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
).paddingOnly(bottom: 5),
|
|
|
|
DropdownButtonHideUnderline(
|
|
|
|
child: DropdownButton2<MediaDevice>(
|
|
|
|
isExpanded: true,
|
|
|
|
disabledHint: Text('callMicrophoneDisabled'.tr),
|
|
|
|
hint: Text('callMicrophoneSelect'.tr),
|
|
|
|
items: provider.enableAudio.value
|
|
|
|
? provider.audioInputs
|
|
|
|
.map(
|
|
|
|
(item) => DropdownMenuItem<MediaDevice>(
|
|
|
|
value: item,
|
|
|
|
child: Text(item.label),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.toList()
|
|
|
|
.cast<DropdownMenuItem<MediaDevice>>()
|
|
|
|
: [],
|
|
|
|
value: provider.audioDevice.value,
|
|
|
|
onChanged: (MediaDevice? value) async {
|
|
|
|
if (value != null) {
|
|
|
|
provider.audioDevice.value = value;
|
|
|
|
await provider.changeLocalAudioTrack();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
buttonStyleData: const ButtonStyleData(
|
|
|
|
height: 40,
|
|
|
|
width: 320,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
).paddingOnly(bottom: 25),
|
|
|
|
Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
children: [
|
|
|
|
Text('callCamera'.tr),
|
|
|
|
Switch(
|
|
|
|
value: provider.enableVideo.value,
|
|
|
|
onChanged: (value) => provider.enableVideo.value = value,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
).paddingOnly(bottom: 5),
|
|
|
|
DropdownButtonHideUnderline(
|
|
|
|
child: DropdownButton2<MediaDevice>(
|
|
|
|
isExpanded: true,
|
|
|
|
disabledHint: Text('callCameraDisabled'.tr),
|
|
|
|
hint: Text('callCameraSelect'.tr),
|
|
|
|
items: provider.enableVideo.value
|
|
|
|
? provider.videoInputs
|
|
|
|
.map(
|
|
|
|
(item) => DropdownMenuItem<MediaDevice>(
|
|
|
|
value: item,
|
|
|
|
child: Text(item.label),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.toList()
|
|
|
|
.cast<DropdownMenuItem<MediaDevice>>()
|
|
|
|
: [],
|
|
|
|
value: provider.videoDevice.value,
|
|
|
|
onChanged: (MediaDevice? value) async {
|
|
|
|
if (value != null) {
|
|
|
|
provider.videoDevice.value = value;
|
|
|
|
await provider.changeLocalVideoTrack();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
buttonStyleData: const ButtonStyleData(
|
|
|
|
height: 40,
|
|
|
|
width: 320,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
).paddingOnly(bottom: 25),
|
|
|
|
if (_isBusy)
|
|
|
|
const Center(child: CircularProgressIndicator())
|
|
|
|
else
|
|
|
|
ElevatedButton(
|
|
|
|
style: ElevatedButton.styleFrom(
|
|
|
|
minimumSize: const Size(320, 56),
|
|
|
|
backgroundColor:
|
|
|
|
Theme.of(context).colorScheme.primaryContainer,
|
|
|
|
),
|
2024-08-19 17:10:15 +00:00
|
|
|
onPressed: _isBusy ? null : _performJoin,
|
2024-06-01 12:18:25 +00:00
|
|
|
child: Text('callJoin'.tr),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
Get.find<ChatCallProvider>()
|
|
|
|
..deactivateHardware()
|
|
|
|
..disposeHardware();
|
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
}
|