main_production_audio_video_call
Sikander Saleem 2 weeks ago
parent e834bf322b
commit 957b6eddea

@ -324,10 +324,18 @@ Future<void> handleDataMessage(Map<String, dynamic> messageData, bool isFromBack
return false; return false;
}(); }();
final moduleId = messageData['moduleId'] as String? ?? messageData['applicationId']?.toString(); String? moduleId = messageData['moduleId'] as String? ?? messageData['applicationId']?.toString();
if (messageData['moduleId'] != null && messageData['moduleId'].toString().isNotEmpty) {
moduleId = messageData['moduleId']?.toString();
} else if (messageData['applicationId'] != null && messageData['applicationId'].toString().isNotEmpty) {
moduleId = messageData['applicationId']?.toString();
}
final referenceId = messageData['referenceId'] as String?; final referenceId = messageData['referenceId'] as String?;
final conversationId = messageData['conversationId'] as String?; final conversationId = messageData['conversationId'] as String?;
print("handleDataMessage:moduleId:$moduleId");
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
Timer? _callTimeoutTimer; Timer? _callTimeoutTimer;
try { try {

@ -158,7 +158,9 @@ import 'modules/cleaner_module/provider/cleaner_provider.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) {
FlutterCallkitIncoming.onBackgroundMessage(onBackgroundMessage); FlutterCallkitIncoming.onBackgroundMessage(onBackgroundMessage);
}
FlutterCallkitIncoming.endAllCalls(); FlutterCallkitIncoming.endAllCalls();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
// HttpOverrides.global = MyHttpOverrides(); // for later use. // HttpOverrides.global = MyHttpOverrides(); // for later use.

@ -15,9 +15,11 @@ import 'call_provider.dart';
class AudioCallPage extends StatefulWidget { class AudioCallPage extends StatefulWidget {
Participants sender; Participants sender;
Participants recipient; Participants recipient;
int moduleId;
int? referenceID;
bool isAccept; bool isAccept;
AudioCallPage({Key? key, required this.sender, required this.recipient, this.isAccept = false}) : super(key: key); AudioCallPage({Key? key, required this.sender, required this.recipient, this.isAccept = false, required this.moduleId, this.referenceID}) : super(key: key);
@override @override
_AudioCallPageState createState() { _AudioCallPageState createState() {
@ -31,7 +33,6 @@ class _AudioCallPageState extends State<AudioCallPage> {
// Participants? participants; // Participants? participants;
String currentStatus = "Connecting...";
bool isDialogOpen = false; bool isDialogOpen = false;
@override @override
@ -54,12 +55,14 @@ class _AudioCallPageState extends State<AudioCallPage> {
} }
callPro.initAudioCallListeners(); callPro.initAudioCallListeners();
if (widget.isAccept) { if (widget.isAccept) {
callPro.acceptCall(widget.sender.employeeNumber ?? "", widget.recipient?.employeeNumber ?? "", false); callPro.acceptCall(widget.sender.employeeNumber ?? "", widget.recipient?.employeeNumber ?? "", false, moduleId: widget.moduleId);
} else { } else {
callPro.startCall(widget.sender.employeeNumber ?? "", widget.recipient?.employeeNumber ?? "", false, null, null, onSuccess: (String msg) { callPro.startCall(widget.sender.employeeNumber ?? "", widget.recipient?.employeeNumber ?? "", false, widget.moduleId, widget.referenceID, onSuccess: (String msg) {
callPro.dispose(); callPro.dispose();
Navigator.pop(context); Navigator.pop(context);
}, onFailed: (String msg) { }, onFailed: (String msg) {
callPro.dispose();
print("isDialogOpen:$isDialogOpen");
if (isDialogOpen) { if (isDialogOpen) {
return; return;
} }
@ -79,7 +82,6 @@ class _AudioCallPageState extends State<AudioCallPage> {
okTitle: "Go Back", okTitle: "Go Back",
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
callPro.dispose();
Navigator.pop(context); Navigator.pop(context);
}), }),
), ),
@ -174,18 +176,29 @@ class _AudioCallPageState extends State<AudioCallPage> {
24.height, 24.height,
InfoTextLabelWidget(label: chatProvider.recipient?.userName ?? "", textStyle: AppTextStyles.heading4.copyWith(fontWeight: FontWeight.w600), color: Colors.white), InfoTextLabelWidget(label: chatProvider.recipient?.userName ?? "", textStyle: AppTextStyles.heading4.copyWith(fontWeight: FontWeight.w600), color: Colors.white),
4.height, 4.height,
InfoTextLabelWidget(label: currentStatus, textStyle: AppTextStyles.heading6, color: Colors.white) Selector<CallProvider, String>(
selector: (_, myModel) => myModel.currentStatus, // Selects only the userName
builder: (_, currentStatus, __) => InfoTextLabelWidget(label: currentStatus, textStyle: AppTextStyles.heading6, color: Colors.white),
),
4.height,
Selector<CallProvider, bool>(
selector: (_, myModel) => myModel.isPeerMuted,
builder: (_, isPeerMuted, __) => isPeerMuted ? InfoTextLabelWidget(label: "Mic Mute", textStyle: AppTextStyles.tinyFont, color: AppColor.red30) : const SizedBox(),
),
], ],
), ),
const Spacer(), const Spacer(),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
callButton("calling/mic_enable", () { Selector<CallProvider, bool>(
selector: (_, myModel) => myModel.isMuted, // Selects only the userName
builder: (_, isMuted, __) => callButton(isMuted ? "calling/mic_disable" : "calling/mic_enable", () {
callPro.toggleMute(); callPro.toggleMute();
}), }),
),
callButton("calling/end_call", () async { callButton("calling/end_call", () async {
callPro.endCall(widget.sender.employeeNumber ?? "", widget.recipient.employeeNumber ?? ""); callPro.endCall(widget.sender.employeeNumber ?? "", widget.recipient.employeeNumber ?? "", moduleId: widget.moduleId);
Navigator.pop(context); Navigator.pop(context);
}, isEndCall: true, size: 68), }, isEndCall: true, size: 68),
callButton("calling/speaker_enable", () {}), callButton("calling/speaker_enable", () {}),

@ -35,6 +35,8 @@ class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
bool isLoading = false; bool isLoading = false;
String currentStatus = "Connecting...";
Future<void> _disposeConnection() async { Future<void> _disposeConnection() async {
try { try {
if (callHubConnection != null) { if (callHubConnection != null) {
@ -216,7 +218,7 @@ class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
String? senderN; String? senderN;
String? recipientN; String? recipientN;
bool? isVideo; bool? isVideo;
int? moduleId; int moduleId = 1004;
int? referenceID; int? referenceID;
Function(String message)? onFailed; Function(String message)? onFailed;
@ -226,27 +228,29 @@ class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
this.senderN = senderN; this.senderN = senderN;
this.recipientN = recipientN; this.recipientN = recipientN;
this.isVideo = isVideo; this.isVideo = isVideo;
this.moduleId = moduleId; // this.moduleId = moduleId;
this.referenceID = referenceID; this.referenceID = referenceID;
this.onFailed = onFailed; this.onFailed = onFailed;
this.onSuccess = onSuccess; this.onSuccess = onSuccess;
invoke(invokeMethod: "CallUserAsync", currentUserID: senderN!, targetUserID: recipientN!, isVideoCall: isVideo!); invoke(invokeMethod: "CallUserAsync", currentUserID: senderN!, targetUserID: recipientN!, isVideoCall: isVideo!, data: [this.moduleId, referenceID]);
} }
void acceptCall(String senderN, String recipientN, bool isVideo) async { void acceptCall(String senderN, String recipientN, bool isVideo, {required int moduleId}) async {
invoke(invokeMethod: "AnswerCallAsync", currentUserID: senderN, targetUserID: recipientN, isVideoCall: isVideo); invoke(invokeMethod: "AnswerCallAsync", currentUserID: senderN, targetUserID: recipientN, isVideoCall: isVideo, data: [this.moduleId]);
} }
Future declineCall(String senderN, String recipientN) async { Future declineCall(String senderN, String recipientN, {required int moduleId}) async {
await invoke(invokeMethod: "CallDeclinedAsync", currentUserID: senderN, targetUserID: recipientN, isVideoCall: false); await invoke(invokeMethod: "CallDeclinedAsync", currentUserID: senderN, targetUserID: recipientN, isVideoCall: false, data: [this.moduleId]);
} }
void endCall(String senderN, String recipientN) { void endCall(String senderN, String recipientN, {required int moduleId}) {
invoke(invokeMethod: "HangUpAsync", currentUserID: senderN, targetUserID: recipientN); invoke(invokeMethod: "HangUpAsync", currentUserID: senderN, targetUserID: recipientN, data: [moduleId]);
} }
void toggleMute() { void toggleMute() async {
invoke(invokeMethod: "AudioToggle", currentUserID: senderN!, targetUserID: recipientN!, isVideoCall: isVideo!); await invoke(invokeMethod: "AudioToggle", currentUserID: senderN!, targetUserID: recipientN!);
isMuted = !isMuted;
notifyListeners();
} }
void checkCall(Map<String, dynamic> message) { void checkCall(Map<String, dynamic> message) {
@ -323,7 +327,7 @@ class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
void onAudioToggle(List<Object?>? params) { void onAudioToggle(List<Object?>? params) {
print("onAudioToggle: $params"); print("onAudioToggle: $params");
isMuted = !isMuted; isPeerMuted = !isPeerMuted;
notifyListeners(); notifyListeners();
} }
@ -335,16 +339,19 @@ class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
Future<void> invoke({required String invokeMethod, required String currentUserID, required String targetUserID, bool isVideoCall = false, var data}) async { Future<void> invoke({required String invokeMethod, required String currentUserID, required String targetUserID, bool isVideoCall = false, var data}) async {
List<Object> args = []; List<Object> args = [];
if (data != null) {
data = data.toString().replaceFirst("[", "").replaceFirst("]", "");
}
if (invokeMethod == "AnswerCallAsync") { if (invokeMethod == "AnswerCallAsync") {
args = [currentUserID, targetUserID]; args = [currentUserID, targetUserID, data];
} else if (invokeMethod == 'CallDeclinedAsync') { } else if (invokeMethod == 'CallDeclinedAsync') {
args = [currentUserID, targetUserID]; args = [currentUserID, targetUserID, data];
} else if (invokeMethod == "CallUserAsync") { } else if (invokeMethod == "CallUserAsync") {
args = [currentUserID, targetUserID, isVideoCall]; args = [currentUserID, targetUserID, isVideoCall];
} else if (invokeMethod == "HangUpAsync") { } else if (invokeMethod == "HangUpAsync") {
args = [currentUserID, targetUserID]; args = [currentUserID, targetUserID, data];
} else if (invokeMethod == "AudioToggle") { } else if (invokeMethod == "AudioToggle") {
args = [currentUserID, targetUserID, isVideoCall]; args = [currentUserID, targetUserID];
} else if (invokeMethod == "IceCandidateAsync") { } else if (invokeMethod == "IceCandidateAsync") {
args = [targetUserID, data]; args = [targetUserID, data];
} else if (invokeMethod == "OfferAsync") { } else if (invokeMethod == "OfferAsync") {
@ -376,6 +383,8 @@ class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
return; return;
} else if (params[0] == 'USER_BUSY') { } else if (params[0] == 'USER_BUSY') {
onFailed?.call("The user is currently busy on another call"); onFailed?.call("The user is currently busy on another call");
} else if (params[0] == 'USER_DECLINE') {
onFailed?.call("Call Declined, User has declined your call.");
} else if (params[0] == 'USER_OFFLINE') { } else if (params[0] == 'USER_OFFLINE') {
onFailed?.call("The user is currently offline"); onFailed?.call("The user is currently offline");
} else { } else {

@ -202,6 +202,18 @@ class _ChatPageState extends State<ChatPage> {
appBar: DefaultAppBar( appBar: DefaultAppBar(
title: widget.title, title: widget.title,
actions: [ actions: [
Selector<ChatProvider, _ChatConnectionState>(
selector: (_, provider) => _ChatConnectionState(
isLoading: provider.chatLoginTokenLoading,
loginResponse: provider.chatLoginResponse,
),
builder: (context, connectionState, child) {
if (!connectionState.isLoading && connectionState.loginResponse == null) {
return SizedBox();
} else {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton( IconButton(
icon: "calling/audio_call_icon".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)), icon: "calling/audio_call_icon".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -230,6 +242,8 @@ class _ChatPageState extends State<ChatPage> {
builder: (_) => AudioCallPage( builder: (_) => AudioCallPage(
sender: Provider.of<ChatProvider>(context, listen: false).sender!, sender: Provider.of<ChatProvider>(context, listen: false).sender!,
recipient: Provider.of<ChatProvider>(context, listen: false).recipient!, recipient: Provider.of<ChatProvider>(context, listen: false).recipient!,
moduleId: widget.moduleId,
referenceID: widget.requestId,
))); )));
} }
}); });
@ -238,6 +252,8 @@ class _ChatPageState extends State<ChatPage> {
builder: (_) => AudioCallPage( builder: (_) => AudioCallPage(
sender: Provider.of<ChatProvider>(context, listen: false).sender!, sender: Provider.of<ChatProvider>(context, listen: false).sender!,
recipient: Provider.of<ChatProvider>(context, listen: false).recipient!, recipient: Provider.of<ChatProvider>(context, listen: false).recipient!,
moduleId: widget.moduleId,
referenceID: widget.requestId,
))); )));
} }
}, },
@ -272,6 +288,10 @@ class _ChatPageState extends State<ChatPage> {
}, },
), ),
], ],
);
}
}),
],
), ),
body: Selector<ChatProvider, _ChatConnectionState>( body: Selector<ChatProvider, _ChatConnectionState>(
selector: (_, provider) => _ChatConnectionState( selector: (_, provider) => _ChatConnectionState(

@ -219,7 +219,7 @@ class _LandPageState extends State<LandPage> {
callingEvents(BuildContext context) { callingEvents(BuildContext context) {
FlutterCallkitIncoming.onEvent.listen((CallEvent? event) { FlutterCallkitIncoming.onEvent.listen((CallEvent? event) {
if (event == null) return; if (event == null) return;
print("callingEvents:$event");
switch (event) { switch (event) {
case CallEventActionCallAccept(:final callKitParams): case CallEventActionCallAccept(:final callKitParams):
_handleCallAccepted(callKitParams); _handleCallAccepted(callKitParams);
@ -236,9 +236,8 @@ class _LandPageState extends State<LandPage> {
case CallEventActionCallStart(): case CallEventActionCallStart():
// TODO: Handle this case. // TODO: Handle this case.
throw UnimplementedError(); throw UnimplementedError();
case CallEventActionCallEnded(): case CallEventActionCallEnded(:final callKitParams):
// TODO: Handle this case. _handleCallEnded(callKitParams);
throw UnimplementedError();
case CallEventActionCallTimeout(): case CallEventActionCallTimeout():
// TODO: Handle this case. // TODO: Handle this case.
throw UnimplementedError(); throw UnimplementedError();
@ -275,11 +274,16 @@ class _LandPageState extends State<LandPage> {
var calPro = Provider.of<CallProvider>(context, listen: false); var calPro = Provider.of<CallProvider>(context, listen: false);
bool isConnected = await calPro.buildHubConnection(callKitParams.extra?["calleeEmployeeNumber"]); bool isConnected = await calPro.buildHubConnection(callKitParams.extra?["calleeEmployeeNumber"]);
if (isConnected) { if (isConnected) {
await calPro.declineCall(callKitParams.extra?["calleeEmployeeNumber"], callKitParams.extra?["callerEmployeeNumber"]); await calPro.declineCall(callKitParams.extra?["calleeEmployeeNumber"], callKitParams.extra?["callerEmployeeNumber"], moduleId: int.parse(callKitParams.extra!["moduleId"]));
calPro.dispose(); calPro.dispose();
} }
} }
Future<void> _handleCallEnded(CallKitParams callKitParams) async {
FlutterCallkitIncoming.endCall(callKitParams.extra?["callId"]);
FlutterCallkitIncoming.endAllCalls();
}
void _handleCallAccepted(CallKitParams callKitParams) { void _handleCallAccepted(CallKitParams callKitParams) {
FlutterCallkitIncoming.endCall(callKitParams.extra?["callId"]); FlutterCallkitIncoming.endCall(callKitParams.extra?["callId"]);
FlutterCallkitIncoming.endAllCalls(); FlutterCallkitIncoming.endAllCalls();
@ -287,6 +291,7 @@ class _LandPageState extends State<LandPage> {
builder: (_) => AudioCallPage( builder: (_) => AudioCallPage(
sender: Participants(employeeNumber: callKitParams.extra?["calleeEmployeeNumber"]), sender: Participants(employeeNumber: callKitParams.extra?["calleeEmployeeNumber"]),
recipient: Participants(employeeNumber: callKitParams.extra?["callerEmployeeNumber"]), recipient: Participants(employeeNumber: callKitParams.extra?["callerEmployeeNumber"]),
moduleId: int.parse(callKitParams.extra!["moduleId"]),
isAccept: true))); isAccept: true)));
} }
} }

Loading…
Cancel
Save