Last active
August 21, 2020 17:00
-
-
Save mulieriq/e1daae4f9f76572a539591e7622b70b2 to your computer and use it in GitHub Desktop.
create call
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class VideoCallPerosnalScreen extends StatefulWidget { | |
/// non-modifiable channel name of the page | |
final String channelName; | |
final String callerid; | |
final String receiverid; | |
/// Creates a call page with given channel name. | |
const VideoCallPerosnalScreen( | |
{Key key, this.callerid, this.receiverid, this.channelName}) | |
: super(key: key); | |
@override | |
_VideoCallPerosnalScreenState createState() { | |
return new _VideoCallPerosnalScreenState(); | |
} | |
} | |
class _VideoCallPerosnalScreenState extends State<VideoCallPerosnalScreen> { | |
static final _sessions = List<VideoSession>(); | |
final _infoStrings = <String>[]; | |
bool muted = false; | |
String username = " Muli"; | |
updateChatroomNumber(number) { | |
return Firestore.instance.collection("videocon").document().setData({ | |
widget.channelName: {"number": number} | |
}); | |
} | |
updateDestroyChatRoom() { | |
return Firestore.instance.collection("videocon").document().delete(); | |
} | |
@override | |
void dispose() { | |
// clean up native views & destroy sdk | |
_sessions.forEach((session) { | |
AgoraRtcEngine.removeNativeView(session.viewId); | |
}); | |
_sessions.clear(); | |
AgoraRtcEngine.leaveChannel(); | |
super.dispose(); | |
} | |
@override | |
void initState() { | |
Wakelock.enable(); | |
super.initState(); | |
// initialize agora sdk | |
initialize(); | |
} | |
void initialize() { | |
if (APP_ID.isEmpty) { | |
setState(() { | |
_infoStrings | |
.add("APP_ID missing, please provide your APP_ID in settings.dart"); | |
_infoStrings.add("Video Engine is not starting"); | |
}); | |
return; | |
} | |
_initAgoraRtcEngine(); | |
_addAgoraEventHandlers(); | |
// use _addRenderView everytime a native video view is needed | |
_addRenderView(0, (viewId) { | |
AgoraRtcEngine.setupLocalVideo(viewId, VideoRenderMode.Hidden); | |
AgoraRtcEngine.startPreview(); | |
// state can access widget directly | |
AgoraRtcEngine.joinChannel(null, widget.channelName, null, 0); | |
}); | |
} | |
/// Create agora sdk instance and initialze | |
Future<void> _initAgoraRtcEngine() async { | |
AgoraRtcEngine.create(APP_ID); | |
AgoraRtcEngine.enableVideo(); | |
} | |
/// Add agora event handlers | |
void _addAgoraEventHandlers() { | |
AgoraRtcEngine.onError = (dynamic code) { | |
setState(() { | |
String info = 'onError: ' + code.toString(); | |
_infoStrings.add(info); | |
}); | |
}; | |
AgoraRtcEngine.onJoinChannelSuccess = | |
(String channel, int uid, int elapsed) { | |
setState(() { | |
String info = 'onJoinChannel: ' + channel + ', uid: ' + uid.toString(); | |
_infoStrings.add(info); | |
}); | |
}; | |
AgoraRtcEngine.onLeaveChannel = () { | |
setState(() { | |
_infoStrings.add('onLeaveChannel'); | |
}); | |
}; | |
AgoraRtcEngine.onUserJoined = (int uid, int elapsed) { | |
setState(() { | |
String info = 'userJoined: ' + uid.toString(); | |
_infoStrings.add(info); | |
_addRenderView(uid, (viewId) { | |
AgoraRtcEngine.setupRemoteVideo(viewId, VideoRenderMode.Hidden, uid); | |
}); | |
}); | |
}; | |
AgoraRtcEngine.onUserOffline = (int uid, int reason) { | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.callerid) | |
.delete() | |
.then((r) { | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.receiverid) | |
.delete(); | |
}); | |
setState(() { | |
String info = 'userOffline: ' + uid.toString(); | |
_infoStrings.add(info); | |
_removeRenderView(uid); | |
}); | |
}; | |
AgoraRtcEngine.onFirstRemoteVideoFrame = | |
(int uid, int width, int height, int elapsed) { | |
setState(() { | |
String info = 'firstRemoteVideo: ' + | |
uid.toString() + | |
' ' + | |
width.toString() + | |
'x' + | |
height.toString(); | |
_infoStrings.add(info); | |
}); | |
}; | |
} | |
/// Create a native view and add a new video session object | |
/// The native viewId can be used to set up local/remote view | |
void _addRenderView(int uid, Function(int viewId) finished) { | |
Widget view = AgoraRtcEngine.createNativeView((viewId) { | |
setState(() { | |
_getVideoSession(uid).viewId = viewId; | |
if (finished != null) { | |
finished(viewId); | |
} | |
}); | |
}); | |
VideoSession session = VideoSession(uid, view); | |
_sessions.add(session); | |
} | |
/// Remove a native view and remove an existing video session object | |
void _removeRenderView(int uid) { | |
VideoSession session = _getVideoSession(uid); | |
if (session != null) { | |
_sessions.remove(session); | |
} | |
AgoraRtcEngine.removeNativeView(session.viewId); | |
} | |
/// Helper function to filter video session with uid | |
VideoSession _getVideoSession(int uid) { | |
return _sessions.firstWhere((session) { | |
return session.uid == uid; | |
}); | |
} | |
/// Helper function to get list of native views | |
List<Widget> _getRenderViews() { | |
return _sessions.map((session) => session.view).toList(); | |
} | |
/// Video view wrapper | |
Widget _videoView( | |
view, | |
) { | |
return Expanded(child: Container(child: view)); | |
} | |
Widget _tvideoView(view, view2) { | |
return Expanded( | |
child: Container( | |
child: Stack( | |
children: <Widget>[ | |
view, | |
Positioned( | |
right: MediaQuery.of(context).size.width * 0.05, | |
bottom: MediaQuery.of(context).size.height * 0.12, | |
child: Row( | |
children: <Widget>[ | |
Container( | |
decoration: BoxDecoration( | |
borderRadius: BorderRadius.all(Radius.circular(50)), | |
), | |
height: MediaQuery.of(context).size.width * 0.5, | |
width: MediaQuery.of(context).size.width * 0.4, | |
child: Card( | |
child: view2, | |
clipBehavior: Clip.hardEdge, | |
) | |
//color: Colors.red, | |
) | |
], | |
)) | |
], | |
))); | |
} | |
Widget _tvideoView2(view, view2, view3) { | |
return Expanded( | |
child: Container( | |
child: Stack( | |
children: <Widget>[ | |
view, | |
Positioned( | |
right: MediaQuery.of(context).size.width * 0.05, | |
bottom: MediaQuery.of(context).size.height * 0.12, | |
child: Row( | |
children: <Widget>[ | |
Container( | |
decoration: BoxDecoration( | |
borderRadius: BorderRadius.all(Radius.circular(50)), | |
), | |
height: MediaQuery.of(context).size.width * 0.5, | |
width: MediaQuery.of(context).size.width * 0.4, | |
child: Card( | |
child: view2, | |
clipBehavior: Clip.hardEdge, | |
) | |
//color: Colors.red, | |
), | |
Container( | |
decoration: BoxDecoration( | |
borderRadius: BorderRadius.all(Radius.circular(50)), | |
), | |
height: MediaQuery.of(context).size.width * 0.5, | |
width: MediaQuery.of(context).size.width * 0.4, | |
child: Card( | |
child: view3, | |
clipBehavior: Clip.hardEdge, | |
) | |
//color: Colors.red, | |
) | |
], | |
)) | |
], | |
))); | |
} | |
/// Video view row wrapper | |
Widget _expandedVideoRow(List<Widget> views) { | |
List<Widget> wrappedViews = views | |
.map((Widget view) => _videoView( | |
view, | |
)) | |
.toList(); | |
return Expanded(child: Row(children: wrappedViews)); | |
} | |
/// Video layout wrapper | |
Widget _viewRows() { | |
List<Widget> views = _getRenderViews(); | |
print(views); | |
print(views.length); | |
switch (views.length) { | |
case 1: | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
// _tviews(views[0])] | |
_videoView(views[0]) | |
], | |
)); | |
case 2: | |
return Container( | |
child: Column( | |
children: <Widget>[_tvideoView(views[1], views[0])], | |
)); | |
case 3: | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
_tvideoView( | |
//view[0] | |
views[2], //index 1 is mine | |
views[1], //index 2 callers | |
) | |
], | |
)); | |
case 4: | |
updateChatroomNumber(4); | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
_expandedVideoRow(views.sublist(0, 2)), | |
_expandedVideoRow(views.sublist(2, 4)) | |
], | |
)); | |
case 5: | |
updateChatroomNumber(5); | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
_expandedVideoRow(views.sublist(0, 2)), | |
_expandedVideoRow(views.sublist(2, 5)) | |
], | |
)); | |
case 6: | |
updateChatroomNumber(6); | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
_expandedVideoRow(views.sublist(0, 2)), | |
_expandedVideoRow(views.sublist(2, 6)) | |
], | |
)); | |
case 7: | |
updateChatroomNumber(7); | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
_expandedVideoRow(views.sublist(0, 2)), | |
_expandedVideoRow(views.sublist(2, 7)) | |
], | |
)); | |
case 8: | |
updateChatroomNumber(8); | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
_expandedVideoRow(views.sublist(0, 2)), | |
_expandedVideoRow(views.sublist(2, 8)) | |
], | |
)); | |
case 9: | |
updateChatroomNumber(9); | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
_expandedVideoRow(views.sublist(0, 2)), | |
_expandedVideoRow(views.sublist(2, 9)) | |
], | |
)); | |
case 10: | |
updateChatroomNumber(10); | |
return Container( | |
child: Column( | |
children: <Widget>[ | |
_expandedVideoRow(views.sublist(0, 2)), | |
_expandedVideoRow(views.sublist(2, 10)) | |
], | |
)); | |
default: | |
} | |
return Container(); | |
} | |
/// Toolbar layout | |
Widget _toolbar() { | |
return Container( | |
alignment: Alignment.bottomCenter, | |
padding: EdgeInsets.symmetric(vertical: 48), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
RawMaterialButton( | |
onPressed: () => _onToggleMute(), | |
child: new Icon( | |
muted ? Icons.mic : Icons.mic_off, | |
color: muted ? Colors.white : Colors.blueAccent, | |
size: 20.0, | |
), | |
shape: new CircleBorder(), | |
elevation: 2.0, | |
fillColor: muted ? Colors.blueAccent : Colors.white, | |
padding: const EdgeInsets.all(12.0), | |
), | |
RawMaterialButton( | |
onPressed: () { | |
return Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.callerid) | |
.delete() | |
.then((r) { | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.receiverid) | |
.delete(); | |
}).then((r) { | |
Navigator.pop(context); | |
}); | |
}, | |
child: new Icon( | |
Icons.call_end, | |
color: Colors.white, | |
size: 35.0, | |
), | |
shape: new CircleBorder(), | |
elevation: 2.0, | |
fillColor: Colors.redAccent, | |
padding: const EdgeInsets.all(15.0), | |
), | |
RawMaterialButton( | |
onPressed: () => _onSwitchCamera(), | |
child: new Icon( | |
Icons.switch_camera, | |
color: Colors.blueAccent, | |
size: 20.0, | |
), | |
shape: new CircleBorder(), | |
elevation: 2.0, | |
fillColor: Colors.white, | |
padding: const EdgeInsets.all(12.0), | |
) | |
], | |
), | |
); | |
} | |
/// Info panel to show logs | |
Widget _panel() { | |
return Container( | |
padding: 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: _infoStrings.length, | |
itemBuilder: (BuildContext context, int index) { | |
if (_infoStrings.length == 0) { | |
return null; | |
} | |
return Padding( | |
padding: | |
EdgeInsets.symmetric(vertical: 3, horizontal: 10), | |
child: Row(mainAxisSize: MainAxisSize.min, children: [ | |
Flexible( | |
child: Container( | |
padding: EdgeInsets.symmetric( | |
vertical: 2, horizontal: 5), | |
decoration: BoxDecoration( | |
//color: Colors.yellowAccent, | |
borderRadius: BorderRadius.circular(5)), | |
child: Text(_infoStrings[index], | |
style: | |
TextStyle(color: Colors.blueGrey)))) | |
])); | |
})), | |
)); | |
} | |
void _onCallEnd(BuildContext context) { | |
dispose(); | |
Navigator.pop(context); | |
//dispose(); | |
} | |
void _onToggleMute() { | |
setState(() { | |
muted = !muted; | |
}); | |
AgoraRtcEngine.muteLocalAudioStream(muted); | |
} | |
void _onSwitchCamera() { | |
AgoraRtcEngine.switchCamera(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
// appBar: AppBar( | |
// title: Text('Conference Room'), | |
// ), | |
backgroundColor: Colors.black, | |
body: Center( | |
child: Stack( | |
children: <Widget>[_viewRows(), /* _panel(),*/ _toolbar()], | |
))); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class VoiceCallPage extends StatefulWidget { | |
final String callid; | |
final String receiverid; | |
final String callerid; | |
final String callername; | |
final String callerphoto; | |
final String channelName; | |
VoiceCallPage( | |
{this.callerid, | |
this.callername, | |
this.channelName, | |
this.callid, | |
this.receiverid, | |
this.callerphoto}); | |
@override | |
_VoiceCallPageState createState() => _VoiceCallPageState(); | |
} | |
class _VoiceCallPageState extends State<VoiceCallPage> { | |
String getTimerTime(int start) { | |
int minutes = (start ~/ 60); | |
String sMinute = ''; | |
if (minutes.toString().length == 1) { | |
sMinute = '0' + minutes.toString(); | |
} else | |
sMinute = minutes.toString(); | |
int seconds = (start % 60); | |
String sSeconds = ''; | |
if (seconds.toString().length == 1) { | |
sSeconds = '0' + seconds.toString(); | |
} else | |
sSeconds = seconds.toString(); | |
return sMinute + ':' + sSeconds; | |
} | |
@override | |
void initState() { | |
super.initState(); | |
FlutterRingtonePlayer.playRingtone(); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
FlutterRingtonePlayer.stop(); | |
} | |
handleCameraAndMic() async { | |
await PermissionHandler().requestPermissions( | |
[PermissionGroup.camera, PermissionGroup.microphone]); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Color(0xff172630), | |
body: SafeArea( | |
child: Container( | |
height: MediaQuery.of(context).size.height, | |
width: MediaQuery.of(context).size.width, | |
decoration: BoxDecoration( | |
color: Color(0xff172630), | |
), | |
padding: EdgeInsets.all(50.0), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.start, | |
mainAxisSize: MainAxisSize.max, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: <Widget>[ | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.01, | |
), | |
Text( | |
'Incoming Video Call', | |
style: TextStyle( | |
color: Colors.white, | |
fontWeight: FontWeight.w300, | |
fontSize: 15), | |
), | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.02, | |
), | |
Text( | |
'${widget.callername}', | |
style: TextStyle( | |
color: Colors.white, | |
fontWeight: FontWeight.w900, | |
fontSize: 20), | |
), | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.03, | |
), | |
SizedBox( | |
height: 20.0, | |
), | |
CircleAvatar( | |
radius: MediaQuery.of(context).size.width * 0.25, | |
// backgroundImage: | |
child: CachedNetworkImage( | |
imageBuilder: (context, imageProvider) => Container( | |
width: MediaQuery.of(context).size.width * 0.5, | |
height: MediaQuery.of(context).size.width * 0.5, | |
decoration: BoxDecoration( | |
shape: BoxShape.circle, | |
image: DecorationImage( | |
image: imageProvider, fit: BoxFit.cover), | |
), | |
), | |
// fit: BoxFit.cover, | |
fadeInCurve: Curves.easeInOutCirc, | |
fadeInDuration: Duration(seconds: 2), | |
fadeOutCurve: Curves.easeInOutCirc, | |
fadeOutDuration: Duration(seconds: 2), | |
imageUrl: widget.callerphoto == null | |
? "lib/assets/mcculogo.png" | |
: widget.callerphoto, | |
useOldImageOnUrlChange: true, | |
placeholder: (context, url) => Icon(Icons.person), | |
errorWidget: (context, url, error) => Image.asset( | |
"lib/assets/mcculogo.png", | |
fit: BoxFit.cover, | |
)), | |
// NetworkImage( | |
// snapshot.data.documents[i] | |
// .data['userImage']), | |
), | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.15, | |
), | |
Row( | |
mainAxisSize: MainAxisSize.max, | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: <Widget>[ | |
FunctionalButton( | |
title: 'Receive', | |
color: Colors.green, | |
icon: Icons.videocam, | |
onPressed: () { | |
FlutterRingtonePlayer.stop(); | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.callerid) | |
.updateData({"received_by_recepient": true}).then( | |
(r) { | |
handleCameraAndMic(); | |
Navigator.push( | |
context, | |
CupertinoPageRoute( | |
builder: (context) => VideoCallPerosnalScreen( | |
callerid: widget.callerid, | |
receiverid: widget.receiverid, | |
channelName: widget.channelName, | |
))); | |
}); | |
///place instance to callers db | |
// Firestore.instance | |
// .collection("personalvideocalls") | |
// .document(widget.callerid) | |
// .collection(widget.receiverid) | |
// .document(widget.callid) | |
// .updateData({ | |
// "received_by_recepient": true, | |
// } //) | |
// ).then((r) { | |
// Firestore.instance | |
// .collection("personalvideocalls") | |
// .document(widget.receiverid) | |
// .collection(widget.callerid) | |
// .document(widget.callid) | |
// .updateData( | |
// {"received_by_recepient": true}, | |
// ).then((r) async { | |
// // update input validation | |
// // await for camera and mic permissions before pushing video page | |
// //await _handleCameraAndMic(); | |
// // push video page with given channel name | |
// Navigator.push( | |
// context, | |
// CupertinoPageRoute( | |
// builder: (context) => new CallPage( | |
// channelName: widget.channelName, | |
// ))); | |
// }); | |
// }); | |
}, | |
), | |
FunctionalButton( | |
title: 'End', | |
color: Colors.red, | |
icon: Icons.videocam_off, | |
onPressed: () { | |
///place instance to callers db | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.receiverid) | |
.delete(); | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.callerid) | |
.delete(); | |
FlutterRingtonePlayer.stop(); | |
// Navigator.pop(context); | |
}, | |
), | |
], | |
), | |
// FloatingActionButton( | |
// onPressed: () { | |
// Navigator.pop(context); | |
// }, | |
// elevation: 50.0, | |
// shape: CircleBorder(side: BorderSide(color: Colors.red)), | |
// mini: false, | |
// child: Icon( | |
// Icons.call_end, | |
// color: Colors.red, | |
// ), | |
// backgroundColor: Colors.red[100], | |
// ), | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.02, | |
), | |
// Text( | |
// "Waiting Time : ${_timmer}", | |
// style: TextStyle( | |
// color: Colors.red, | |
// fontWeight: FontWeight.w300, | |
// fontSize: 15), | |
// ), | |
], | |
), | |
), | |
), | |
); | |
} | |
} | |
class FunctionalButton extends StatefulWidget { | |
final title; | |
final icon; | |
final color; | |
final Function() onPressed; | |
const FunctionalButton( | |
{Key key, this.title, this.color, this.icon, this.onPressed}) | |
: super(key: key); | |
@override | |
_FunctionalButtonState createState() => _FunctionalButtonState(); | |
} | |
class _FunctionalButtonState extends State<FunctionalButton> { | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
mainAxisAlignment: MainAxisAlignment.start, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
mainAxisSize: MainAxisSize.min, | |
children: <Widget>[ | |
RawMaterialButton( | |
onPressed: widget.onPressed, | |
splashColor: Colors.red, | |
fillColor: Colors.white, | |
elevation: 10.0, | |
shape: CircleBorder(), | |
child: Padding( | |
padding: const EdgeInsets.all(15.0), | |
child: Icon( | |
widget.icon, | |
size: 30.0, | |
color: widget.color, | |
), | |
), | |
), | |
Container( | |
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0), | |
child: Text( | |
widget.title, | |
style: TextStyle(fontSize: 15.0, color: Colors.white), | |
), | |
) | |
], | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var channelid = generateChannelid() { | |
return Random().nextInt(1000).toString(); | |
} | |
placeVideoCall() { | |
///place instance to callers db | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.senderId) | |
// .collection(widget.receiverid) | |
.setData({ | |
"callerId": null, | |
"callerDeleteId": widget.senderId, | |
"callerName": widget.senderName, | |
"callerImage": widget.senderImage, | |
"iscaller": true, // used to identify who s placing the call | |
"callingChannel": channelid, | |
"receiverId": widget.receiverid, | |
"receiverName": widget.receverName, | |
"receiverImage": widget.receiverImage, | |
"received_by_recepient": | |
false, //used to determine if the receiver picked the call | |
"outgoing": true, //haitumiki sawa ..to show he made the call | |
"time": DateTime.now().millisecondsSinceEpoch.toString(), | |
}).then((r) { | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.receiverid) | |
//.collection(widget.senderId) | |
.setData({ | |
"callerId": widget.senderId, | |
"callerDeleteId": widget.senderId, | |
"callerName": widget.senderName, | |
"callerImage": widget.senderImage, | |
"iscaller": false, | |
"callingChannel": channelid, | |
"receiverId": widget.receiverid, | |
"receiverName": widget.receverName, | |
"receiverImage": widget.receiverImage, | |
"received_by_recepient": false, //kwa receiver this haitumiki | |
"incoming": true, | |
"time": DateTime.now().millisecondsSinceEpoch.toString(), | |
}).then((r) { | |
}); | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class OutgoingVideoCall extends StatefulWidget { | |
final String recipientid; | |
final String recipientname; | |
final String recipientphoto; | |
final String channelName; | |
OutgoingVideoCall( | |
{this.recipientid, | |
this.recipientname, | |
this.channelName, | |
this.recipientphoto}); | |
@override | |
_OutgoingVideoCallState createState() => _OutgoingVideoCallState(); | |
} | |
class _OutgoingVideoCallState extends State<OutgoingVideoCall> { | |
Timer _timmerInstance; | |
int _start = 0; | |
String _timmer = ''; | |
void startTimmer() { | |
var oneSec = Duration(seconds: 1); | |
_timmerInstance = Timer.periodic( | |
oneSec, | |
(Timer timer) => setState(() { | |
if (_start < 0) { | |
_timmerInstance.cancel(); | |
} else { | |
_start = _start + 1; | |
_timmer = getTimerTime(_start); | |
} | |
})); | |
} | |
String getTimerTime(int start) { | |
int minutes = (start ~/ 60); | |
String sMinute = ''; | |
if (minutes.toString().length == 1) { | |
sMinute = '0' + minutes.toString(); | |
} else | |
sMinute = minutes.toString(); | |
int seconds = (start % 60); | |
String sSeconds = ''; | |
if (seconds.toString().length == 1) { | |
sSeconds = '0' + seconds.toString(); | |
} else | |
sSeconds = seconds.toString(); | |
return sMinute + ':' + sSeconds; | |
} | |
@override | |
void initState() { | |
super.initState(); | |
startTimmer(); | |
// Ringtone.play(); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
_timmerInstance.cancel(); | |
FlutterRingtonePlayer.stop(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return ScopedModelDescendant<Scoped>( | |
builder: (BuildContext context, Widget child, Scoped model) { | |
return ReceiverLayout( | |
scaffold: Scaffold( | |
backgroundColor: Color(0xff172630), | |
body: SafeArea( | |
child: Container( | |
height: MediaQuery.of(context).size.height, | |
width: MediaQuery.of(context).size.width, | |
decoration: BoxDecoration( | |
color: Color(0xff172630), | |
), | |
padding: EdgeInsets.all(50.0), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.start, | |
mainAxisSize: MainAxisSize.max, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: <Widget>[ | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.01, | |
), | |
Text( | |
'Outgoing Video Call', | |
style: TextStyle( | |
color: Colors.white, | |
fontWeight: FontWeight.w300, | |
fontSize: 15), | |
), | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.02, | |
), | |
Text( | |
'${widget.recipientname}', | |
style: TextStyle( | |
color: Colors.white, | |
fontWeight: FontWeight.w900, | |
fontSize: 20), | |
), | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.03, | |
), | |
SizedBox( | |
height: 20.0, | |
), | |
CircleAvatar( | |
radius: MediaQuery.of(context).size.width * 0.25, | |
// backgroundImage: | |
child: CachedNetworkImage( | |
imageBuilder: (context, imageProvider) => Container( | |
width: MediaQuery.of(context).size.width * 0.5, | |
height: MediaQuery.of(context).size.width * 0.5, | |
decoration: BoxDecoration( | |
shape: BoxShape.circle, | |
image: DecorationImage( | |
image: imageProvider, fit: BoxFit.cover), | |
), | |
), | |
// fit: BoxFit.cover, | |
fadeInCurve: Curves.easeInOutCirc, | |
fadeInDuration: Duration(seconds: 2), | |
fadeOutCurve: Curves.easeInOutCirc, | |
fadeOutDuration: Duration(seconds: 2), | |
imageUrl: widget.recipientphoto == null | |
? "lib/assets/mcculogo.png" | |
: widget.recipientphoto, | |
useOldImageOnUrlChange: true, | |
placeholder: (context, url) => Icon(Icons.person), | |
errorWidget: (context, url, error) => Image.asset( | |
"lib/assets/mcculogo.png", | |
fit: BoxFit.cover, | |
)), | |
), | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.15, | |
), | |
FloatingActionButton( | |
onPressed: () { | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(model.userId) | |
.delete() | |
.then((r) { | |
Firestore.instance | |
.collection("personalvideocalls") | |
.document(widget.recipientid) | |
.delete(); | |
}); | |
FlutterRingtonePlayer.stop(); | |
// Navigator.pop(context); | |
}, | |
elevation: 50.0, | |
shape: CircleBorder(side: BorderSide(color: Colors.red)), | |
mini: false, | |
child: Icon( | |
Icons.call_end, | |
color: Colors.red, | |
), | |
backgroundColor: Colors.red[100], | |
), | |
SizedBox( | |
height: MediaQuery.of(context).size.height * 0.02, | |
), | |
], | |
), | |
), | |
), | |
), | |
); | |
}); | |
} | |
} | |
class FunctionalButton extends StatefulWidget { | |
final title; | |
final icon; | |
final color; | |
final Function() onPressed; | |
const FunctionalButton( | |
{Key key, this.title, this.color, this.icon, this.onPressed}) | |
: super(key: key); | |
@override | |
_FunctionalButtonState createState() => _FunctionalButtonState(); | |
} | |
class _FunctionalButtonState extends State<FunctionalButton> { | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
mainAxisAlignment: MainAxisAlignment.start, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
mainAxisSize: MainAxisSize.min, | |
children: <Widget>[ | |
RawMaterialButton( | |
onPressed: widget.onPressed, | |
splashColor: Colors.red, | |
fillColor: Colors.white, | |
elevation: 10.0, | |
shape: CircleBorder(), | |
child: Padding( | |
padding: const EdgeInsets.all(15.0), | |
child: Icon( | |
widget.icon, | |
size: 30.0, | |
color: widget.color, | |
), | |
), | |
), | |
Container( | |
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0), | |
child: Text( | |
widget.title, | |
style: TextStyle(fontSize: 15.0, color: Colors.white), | |
), | |
) | |
], | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment