Skip to content

Instantly share code, notes, and snippets.

@DhruvamUnikon
Created June 14, 2024 14:10
Show Gist options
  • Save DhruvamUnikon/6f003179b1942c35c056491e57c276b2 to your computer and use it in GitHub Desktop.
Save DhruvamUnikon/6f003179b1942c35c056491e57c276b2 to your computer and use it in GitHub Desktop.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:go_router/go_router.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:unikon/common_main.dart';
import 'package:unikon/features/post/domain/entity/reaction/short_user_vm.dart';
import 'package:unikon/utils/bottom_sheet/base_bottom_sheet.dart';
import 'package:unikon/utils/dimensions/gaps.dart';
import 'package:unikon/utils/env/environment.dart';
import 'package:unikon/utils/images/constants.dart';
import 'package:unikon/utils/permissions/permission_helper.dart';
import 'package:unikon/utils/router/router_config.dart';
import 'package:unikon/utils/snackbars/overlay_snackbar.dart';
import 'package:unikon/widget_library/buttons/inverse_primary_button.dart';
import 'package:unikon/widget_library/buttons/primary_button.dart';
import 'package:unikon/widget_library/images/base_image.dart';
import 'package:unikon/widget_library/video_call/advanced_video_call_holder.dart';
import 'package:zego_uikit_prebuilt_call/zego_uikit_prebuilt_call.dart';
import 'package:zego_uikit_signaling_plugin/zego_uikit_signaling_plugin.dart';
class CallInvitationController {
CallInvitationController._internal();
static final CallInvitationController instance =
CallInvitationController._internal();
final onCallEndStreamCtrl = StreamController<String>.broadcast();
Future<bool> onCallHangUp() async {
final canHangUp = await CustomBottomSheet.show(
navigatorKey.currentContext!,
const CallCloseBottomSheetWidget(),
);
return (canHangUp != null && canHangUp is bool && canHangUp);
}
}
class ZegoCallInvitation {
/// Step 1
/// Setup navigator key
static void setUpNavigatorKey(GlobalKey<NavigatorState> navigatorKey) {
ZegoUIKitPrebuiltCallInvitationService().setNavigatorKey(navigatorKey);
}
/// Step 2
/// Initialise Calling UI
static void initialiseCalUI(Function onInvitationSetupDone) {
/// call the useSystemCallingUI
ZegoUIKit().initLog().then((value) {
ZegoUIKitPrebuiltCallInvitationService().useSystemCallingUI(
[ZegoUIKitSignalingPlugin()],
);
onInvitationSetupDone();
});
}
/// on App's user login
static Future<void> onUserLogin(String userId, String userName) async {
/// 1.2.1. initialized ZegoUIKitPrebuiltCallInvitationService
/// when app's user is logged in or re-logged in
/// We recommend calling this method as soon as the user logs in to your app.
await ZegoUIKitPrebuiltCallInvitationService().init(
appID: AppEnvironment.instance.zegoAppId /*input your AppID*/,
appSign: AppEnvironment.instance.zegoAppSign /*input your AppSign*/,
userID: 'user_$userId',
userName: userName,
plugins: [ZegoUIKitSignalingPlugin()],
ringtoneConfig: ZegoCallRingtoneConfig(
incomingCallPath: 'assets/sounds/phone_ringing.mp3',
outgoingCallPath: 'assets/sounds/phone_ringing.mp3',
),
notificationConfig: ZegoCallInvitationNotificationConfig(
androidNotificationConfig: ZegoCallAndroidNotificationConfig(
showFullScreen: true,
),
),
events: ZegoUIKitPrebuiltCallEvents(
onHangUpConfirmation: (event, defaultAction) async {
return CallInvitationController.instance.onCallHangUp();
},
onCallEnd: (event, defaultAction) {
defaultAction.call();
CallInvitationController.instance.onCallEndStreamCtrl.add('call-end');
},
),
invitationEvents: ZegoUIKitPrebuiltCallInvitationEvents(
onIncomingCallReceived:
(callId, caller, callType, callees, customData) {
PermissionHelper.requestMultiplePermissions(
permissions: [
Permission.camera,
Permission.microphone,
],
context: navigatorKey.currentContext!,
);
},
onOutgoingCallDeclined: (callId, callee, customData) {
showTopSnackBar(rootScaffoldMessengerKey.currentContext!,
'The User is busy at the moment');
},
onOutgoingCallTimeout: (callId, callee, isVideoCall) {
CallInvitationController.instance.onCallEndStreamCtrl.add('call-end');
},
),
requireConfig: (ZegoCallInvitationData data) {
final isVideoCall = data.type == ZegoCallType.videoCall;
final isGroupCall = data.invitees.length > 1;
late ZegoUIKitPrebuiltCallConfig config;
if (isVideoCall) {
if (isGroupCall) {
config = ZegoUIKitPrebuiltCallConfig.groupVideoCall();
} else {
config = ZegoUIKitPrebuiltCallConfig.oneOnOneVideoCall();
}
} else {
if (isGroupCall) {
config = ZegoUIKitPrebuiltCallConfig.groupVoiceCall();
} else {
config = ZegoUIKitPrebuiltCallConfig.oneOnOneVoiceCall();
}
}
config.layout = ZegoLayout.gallery();
config.foreground = const Center(child: UnikonBrandingStrip());
// When joining using audio call, switch to audio output
// device rather than speaker and turn off camera
if (!isVideoCall) {
config.turnOnMicrophoneWhenJoining = true;
config.turnOnCameraWhenJoining = false;
config.useSpeakerWhenJoining = false;
}
config.audioVideoView = ZegoCallAudioVideoViewConfig(
showCameraStateOnView: false,
showMicrophoneStateOnView: false,
showUserNameOnView: false,
useVideoViewAspectFill: true,
foregroundBuilder: (context, size, user, extraInfo) {
return UserDetailsWidget(
user: ShortUserVM(
id: user?.id ?? '',
userId: user?.id ?? '',
firstName: user?.name ?? '',
lastName: '',
),
);
},
);
return config;
},
);
}
/// on App's user logout
static Future<void> onUserLogout() async {
/// 1.2.2. de-initialization ZegoUIKitPrebuiltCallInvitationService
/// when app's user is logged out
await ZegoUIKitPrebuiltCallInvitationService().uninit();
}
static Future<void> sendCallInvitation(
// Callee user ID
String calleeUserId,
// Callee name
String calleeName,
// call id that you can use to identify the call
String callId,
// call type: video or voice
ZegoCallType callType,
) async {
/// 1.3.1. send call invitation
await ZegoUIKitPrebuiltCallInvitationService().send(
invitees: [
ZegoCallUser('user_$calleeUserId', calleeName),
],
isVideoCall: callType == ZegoCallType.videoCall,
resourceID: 'call_invitation',
callID: callId,
// callID: callId,
);
}
}
class CallCloseBottomSheetWidget extends StatelessWidget {
const CallCloseBottomSheetWidget({super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
g28Box,
BaseImageWidget(
imageUri: ImageConstants.closeIcon,
size: Size(80.sp, 80.sp),
),
g28Box,
Text(
'Are you sure you want to exit?',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 18.sp,
fontFamily: 'Poppins',
fontWeight: FontWeight.w700,
),
),
g12Box,
Text(
'Click confirm to proceed.',
textAlign: TextAlign.center,
style: TextStyle(
color: const Color(0xFFCCCCCC),
fontSize: 14.sp,
fontFamily: 'Roboto',
fontWeight: FontWeight.w400,
),
),
g30Box,
Row(
children: [
Expanded(
child: InversePrimaryBorderedButton(
isLoading: false,
label: 'Cancel',
onPressed: () {
navigatorKey.currentContext!.pop(false);
},
),
),
g16Box,
Expanded(
child: PrimaryButton(
isLoading: false,
label: 'Confirm',
onPressed: () {
navigatorKey.currentContext!.pop(true);
},
),
),
],
),
],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment