import 'package:flutter/material.dart'; import 'package:healthcare_user/common/settings.dart'; import 'dart:async'; import 'package:permission_handler/permission_handler.dart'; import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:agora_rtc_engine/rtc_engine.dart' as rtc_engine; import 'package:agora_rtc_engine/rtc_local_view.dart' as rtc_local_view; import 'package:agora_rtc_engine/rtc_remote_view.dart' as rtc_remote_view; class CallPage extends StatefulWidget { final String? channelName; final ClientRole? role; const CallPage({Key? key, this.channelName, this.role}) : super(key: key); @override State createState() => _CallPageState(); } class _CallPageState extends State { final _users = []; final _infoString = []; late RtcEngine _engine; bool muted = false; // Define the muted variable bool viewPanel = true; @override void initState() { super.initState(); initialize(); } @override void dispose() { _users.clear(); _engine.leaveChannel(); _engine.destroy(); super.dispose(); } Future initialize() async { if (appId.isEmpty) { setState(() { _infoString.add('AppId is missing please provide AppId'); _infoString.add('Agora Engine is not starting'); }); return; } _engine = await rtc_engine.RtcEngine.create(appId); await _engine.enableVideo(); await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); await _engine.setClientRole(widget.role!); _addAgoraEventHandler(); VideoEncoderConfiguration configuration = VideoEncoderConfiguration( dimensions: VideoDimensions(width: 1920, height: 1080), ); await _engine.setVideoEncoderConfiguration(configuration); await _engine.joinChannel(token, widget.channelName!, null, 0); } void _addAgoraEventHandler() { _engine.setEventHandler( rtc_engine.RtcEngineEventHandler( error: (code) { setState(() { final info = 'Error: $code'; _infoString.add(info); }); }, joinChannelSuccess: (channel, uid, elapsed) { setState(() { final info = 'Join Channel: $channel, uid:$uid'; _infoString.add(info); }); }, leaveChannel: (stats) { setState(() { _infoString.add('Leave Channel'); _users.clear(); }); }, userJoined: (uid, elapsed) { setState(() { final info = 'User joined: $uid'; _infoString.add(info); _users.add(uid); }); }, userOffline: (uid, elapsed) { setState(() { final info = 'User Offline: $uid'; _infoString.add(info); _users.remove(uid); }); }, firstRemoteVideoFrame: (uid, width, height, elapsed) { setState(() { final info = 'First Remote Video: $uid $width*$height'; _infoString.add(info); _users.remove(uid); }); }, ), ); } Widget _viewRows() { final List list = []; if (widget.role == ClientRole.Broadcaster) { list.add(const rtc_local_view.SurfaceView()); } for (var uid in _users) { list.add(rtc_remote_view.SurfaceView( uid: uid, channelId: widget.channelName!, )); } final views=list; return Column( children: List.generate( views.length, (index) => Expanded( child: views[index], ), ), ); } Widget _toolbar() { if (widget.role == ClientRole.Audience) return SizedBox(); return Container( alignment: Alignment.bottomCenter, padding: const EdgeInsets.symmetric(vertical: 48), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ RawMaterialButton( onPressed: () { setState(() { muted = !muted; }); _engine.muteLocalAudioStream(muted); }, child: Icon( muted ? Icons.mic_off : Icons.mic, color: muted ? Colors.white : Colors.blueAccent, size: 20.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: muted ? Colors.blueAccent : Colors.white, padding: EdgeInsets.all(12.0), ), RawMaterialButton( onPressed: () => Navigator.pop(context), child: Icon( Icons.call_end, color: Colors.white, size: 35.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: Colors.redAccent, padding: EdgeInsets.all(15.0), ), RawMaterialButton( onPressed: () { _engine.switchCamera(); }, child: Icon( Icons.switch_camera, color: Colors.blueAccent, size: 20.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: Colors.white, padding: EdgeInsets.all(12.0), ), ], ), ); } Widget _panel() { return Visibility( visible: viewPanel, child: Container( padding: const EdgeInsets.symmetric(vertical: 48), alignment: Alignment.bottomCenter, child: FractionallySizedBox( heightFactor: 0.5, child: Container( padding: EdgeInsets.symmetric(vertical: 48), child: ListView.builder( reverse: true, itemCount: _infoString.length, itemBuilder:(BuildContext context,int index) { if(_infoString.isEmpty) { return const Text("null"); } return Padding( padding: const EdgeInsets.symmetric(vertical: 3,horizontal: 10), child: Row( mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Container( padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 5), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5) ), child: Text( _infoString[index], style: const TextStyle(color:Colors.blueGrey), ), ), ) ], ), ); }, ), ), ), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("VideoCall"), centerTitle: true, actions: [ IconButton(onPressed:() { setState(() { viewPanel=!viewPanel; }); }, icon: const Icon(Icons.ice_skating)) ], ), backgroundColor: Colors.black, body: Center( child: Stack( children: [ _viewRows(), _panel(), _toolbar(), ] ), ), ); } }