Chat Call UI

fatima
Aamir Muhammad 2 years ago
parent 0508f6c393
commit 68939f6256

@ -0,0 +1,117 @@
class IncomingCallData {
String? callerID;
String? receiverID;
String? msgID;
String? notfID;
String? notificationForeground;
String? count;
String? message;
String? appointmentNo;
String? title;
String? projectID;
String? notificationType;
String? background;
String? doctorname;
String? clinicname;
String? speciality;
String? appointmentdate;
String? appointmenttime;
String? type;
String? sessionId;
String? identity;
String? name;
String? videoUrl;
String? picture;
String? token;
String? isCall;
String? sound;
String? server;
String? isWebRTC;
IncomingCallData(
{this.msgID,
this.notfID,
this.notificationForeground,
this.count,
this.message,
this.appointmentNo,
this.title,
this.projectID,
this.notificationType,
this.background,
this.doctorname,
this.clinicname,
this.speciality,
this.appointmentdate,
this.appointmenttime,
this.type,
this.sessionId,
this.identity,
this.name,
this.videoUrl,
this.picture,
this.isCall,
this.sound});
IncomingCallData.fromJson(Map<String, dynamic> json) {
callerID = json['callerID'];
receiverID = json['PatientID'];
msgID = json['msgID'];
notfID = json['notfID'];
notificationForeground = json['notification_foreground'];
count = json['count'];
message = json['message'];
appointmentNo = json['AppointmentNo'];
title = json['title'];
projectID = json['ProjectID'];
notificationType = json['NotificationType'];
background = json['background'];
doctorname = json['doctorname'];
clinicname = json['clinicname'];
speciality = json['speciality'];
appointmentdate = json['appointmentdate'];
appointmenttime = json['appointmenttime'];
type = json['type'];
sessionId = json['session_id'];
token = json['token'];
identity = json['identity'];
name = json['name'];
videoUrl = json['videoUrl'];
picture = json['picture'];
isCall = json['is_call'];
sound = json['sound'];
server = json['server'];
isWebRTC = json['is_webrtc'] ?? "true";
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = Map<String, dynamic>();
data['msgID'] = this.msgID;
data['notfID'] = this.notfID;
data['notification_foreground'] = this.notificationForeground;
data['count'] = this.count;
data['message'] = this.message;
data['AppointmentNo'] = this.appointmentNo;
data['title'] = this.title;
data['ProjectID'] = this.projectID;
data['NotificationType'] = this.notificationType;
data['background'] = this.background;
data['doctorname'] = this.doctorname;
data['clinicname'] = this.clinicname;
data['speciality'] = this.speciality;
data['appointmentdate'] = this.appointmentdate;
data['appointmenttime'] = this.appointmenttime;
data['type'] = this.type;
data['session_id'] = this.sessionId;
data['token'] = this.token;
data['identity'] = this.identity;
data['name'] = this.name;
data['videoUrl'] = this.videoUrl;
data['picture'] = this.picture;
data['is_call'] = this.isCall;
data['sound'] = this.sound;
data['server'] = this.server;
data['is_webrtc'] = this.isWebRTC;
return data;
}
}

@ -0,0 +1,379 @@
import 'dart:ui';
import 'package:camera/camera.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/models/chat/call.dart';
class IncomingCall extends StatefulWidget {
IncomingCallData incomingCallData;
bool? isVideoCall;
IncomingCall({Key? key, required this.incomingCallData, this.isVideoCall}) : super(key: key);
@override
_IncomingCallState createState() => _IncomingCallState();
}
class _IncomingCallState extends State<IncomingCall> with SingleTickerProviderStateMixin {
AnimationController? _animationController;
CameraController? _controller;
Future<void>? _initializeControllerFuture;
bool isCameraReady = false;
@override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: const Duration(
milliseconds: 500,
),
);
//_runAnimation();
// connectSignaling();
WidgetsBinding.instance.addPostFrameCallback(
(_) => _runAnimation(),
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Stack(
alignment: FractionalOffset.center,
children: <Widget>[
if (widget.isVideoCall!)
Positioned.fill(
child: AspectRatio(
aspectRatio: _controller!.value.aspectRatio,
child: CameraPreview(
_controller!,
),
),
),
Positioned.fill(
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Container(
decoration: BoxDecoration(
color: MyColors.grey57Color.withOpacity(
0.7,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
margin: const EdgeInsets.all(21.0),
child: Row(
children: <Widget>[
Image.asset(
"assets/images/logos/main_mohemm_logo.png",
height: 70,
width: 70,
),
Container(
margin: const EdgeInsets.only(
left: 10.0,
right: 10.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const <Widget>[
Text(
"Aamir Saleem Ahmad",
style: TextStyle(
fontSize: 21,
fontWeight: FontWeight.bold,
color: MyColors.white,
letterSpacing: -1.26,
height: 23 / 12,
),
),
Text(
"Calling...",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(
0xffC6C6C6,
),
letterSpacing: -0.48,
height: 23 / 24,
),
),
SizedBox(
height: 2,
),
],
),
),
],
),
),
// Container(
// margin: const EdgeInsets.all(21.0),
// width: MediaQuery.of(context).size.width,
// decoration: cardRadius(15.0, color: MyColors.black, elevation: null),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisSize: MainAxisSize.min,
// children: [
// Container(
// padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 6.0),
// child: Text(
// "TranslationBase.of(context).appoInfo",
// style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.white, letterSpacing: -0.64, height: 23 / 12),
// ),
// ),
// Container(
// padding: const EdgeInsets.only(left: 16.0, right: 16.0),
// child: Text(
// "widget.incomingCallData.appointmentdate + widget.incomingCallData.appointmenttime",
// style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600),
// ),
// ),
// Container(
// padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 21.0),
// child: Text(
// "widget.incomingCallData.clinicname",
// style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600),
// ),
// ),
// ],
// ),
// ),
const Spacer(),
Container(
margin: const EdgeInsets.only(
bottom: 70.0,
left: 49,
right: 49,
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RotationTransition(
turns: Tween(
begin: 0.0,
end: -.1,
)
.chain(
CurveTween(
curve: Curves.elasticIn,
),
)
.animate(
_animationController!,
),
child: RawMaterialButton(
onPressed: () {
_submit();
},
elevation: 2.0,
fillColor: MyColors.green2DColor,
padding: const EdgeInsets.all(
15.0,
),
shape: const CircleBorder(),
child: const Icon(
Icons.call,
color: MyColors.white,
size: 35.0,
),
),
),
RawMaterialButton(
onPressed: () {
backToHome();
},
elevation: 2.0,
fillColor: MyColors.redA3Color,
padding: const EdgeInsets.all(
15.0,
),
shape: const CircleBorder(),
child: const Icon(
Icons.call_end,
color: MyColors.white,
size: 35.0,
),
),
],
),
),
],
),
),
),
),
),
],
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
void _runAnimation() async {
List<CameraDescription> cameras = await availableCameras();
CameraDescription firstCamera = cameras[1];
_controller = CameraController(
firstCamera,
ResolutionPreset.medium,
);
_initializeControllerFuture = _controller!.initialize();
setState(() {});
// setAudioFile();
for (int i = 0; i < 100; i++) {
await _animationController!.forward();
await _animationController!.reverse();
}
}
Future<void> _submit() async {
try {
// backToHome();
// final roomModel = RoomModel(name: widget.incomingCallData.name, token: widget.incomingCallData.sessionId, identity: widget.incomingCallData.identity);
await _controller?.dispose();
// changeCallStatusAPI(4);
// if (_session != null && _signaling != null) {
// await Navigator.of(context).pushReplacement(
// MaterialPageRoute(
// // fullscreenDialog: true,
// builder: (BuildContext context) {
// // if (widget.incomingCallData.isWebRTC == "true") {
// return StartVideoCall(signaling: _signaling, session: _session);
//
// // else {
// // return OpenTokConnectCallPage(apiKey: OPENTOK_API_KEY, sessionId: widget.incomingCallData.sessionId, token: widget.incomingCallData.token);
// // }
//
// // return VideoCallWebPage(receiverId: widget.incomingCallData.receiverID, callerId: widget.incomingCallData.callerID); // Web WebRTC VideoCall
//
// // return CallHomePage(receiverId: widget.incomingCallData.receiverID, callerId: widget.incomingCallData.callerID); // App WebRTC VideoCall
// },
// ),
// );
// } else {
// // Invalid Params/Data
// Utils.showToast("Failed to establish connection with server");
// }
} catch (err) {
print(err);
// await PlatformExceptionAlertDialog(
// exception: err,
// ).show(context);
Utils.showToast(err.toString());
}
}
// void changeCallStatusAPI(int sessionStatus) {
// LiveCareService service = new LiveCareService();
// service.endCallAPI(widget.incomingCallData.sessionId, sessionStatus, context).then((res) {}).catchError((err) {
// print(err);
// });
// }
void backToHome() async {
// final connected = await signaling.declineCall(widget.incomingCallData.callerID, widget.incomingCallData.receiverID);
// LandingPage.isOpenCallPage = false;
// _signaling
// player.stop();
// changeCallStatusAPI(3);
// _signaling.bye(_session, callRejected: true);
// _signaling.callDisconnected(_session, callRejected: true);
Navigator.of(context).pop();
}
//
// void disposeAudioResources() async {
// await player.dispose();
// }
//
// void setAudioFile() async {
// player.stop();
// await player.setVolume(1.0); // full volume
// try {
// await player.setAsset('assets/sounds/ring_60Sec.mp3').then((value) {
// player.setLoopMode(LoopMode.one); // loop ring sound
// player.play();
// }).catchError((err) {
// print("Error: $err");
// });
// } catch (e) {
// print("Error: $e");
// }
// }
//
// void connectSignaling({@required bool iAmCaller = false}) async {
// print("----------------- + Signaling Connection Started ---------------------------");
// var caller = widget.incomingCallData.callerID;
// var receiver = widget.incomingCallData.receiverID;
// var host = widget.incomingCallData.server;
//
// var selfRole = iAmCaller ? "Caller" : "Receiver";
// var selfId = iAmCaller ? caller : receiver;
// var selfUser = SocketUser(id: selfId, name: "$selfRole-$selfId", userAgent: DeviceInfo.userAgent, moreInfo: {});
//
// var remoteRole = !iAmCaller ? "Caller" : "Receiver";
// var remoteId = !iAmCaller ? caller : receiver;
// var remoteUser = SocketUser(id: remoteId, name: "$remoteRole-$remoteId", userAgent: DeviceInfo.userAgent, moreInfo: {});
//
// var sessionId = "$caller-$receiver";
// _session = SessionOneToOne(id: sessionId, local_user: selfUser, remote_user: remoteUser);
//
// _signaling = Signaling(host, session: _session);
// await _signaling.connect();
//
// if (_signaling.state == SignalingState.Open) {
// return;
// }
// }
BoxDecoration cardRadius(double radius, {required Color color, double? elevation}) {
return BoxDecoration(
shape: BoxShape.rectangle,
color: color ?? Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(radius),
),
boxShadow: <BoxShadow>[
BoxShadow(
color: const Color(
0xff000000,
).withOpacity(
.05,
),
//spreadRadius: 5,
blurRadius: elevation ?? 27,
offset: const Offset(
-2,
3,
),
),
],
);
}
}

@ -9,6 +9,8 @@ import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/chat/call.dart';
import 'package:mohem_flutter_app/ui/chat/call/chat_call_screen.dart';
import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
@ -16,15 +18,18 @@ import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:swipe_to/swipe_to.dart';
class ChatDetailScreen extends StatelessWidget {
class ChatDetailScreen extends StatefulWidget {
// ignore: prefer_const_constructors_in_immutables
ChatDetailScreen({Key? key}) : super(key: key);
dynamic userDetails;
@override
State<ChatDetailScreen> createState() => _ChatDetailScreenState();
}
class _ChatDetailScreenState extends State<ChatDetailScreen> {
dynamic userDetails;
late ChatProviderModel data;
final RefreshController _refreshController = RefreshController(initialRefresh: false);
final RefreshController _rc = RefreshController(initialRefresh: false);
void getMoreChat() async {
if (userDetails != null) {
@ -32,19 +37,54 @@ class ChatDetailScreen extends StatelessWidget {
data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false);
}
await Future.delayed(const Duration(milliseconds: 1000));
_refreshController.loadComplete();
_rc.loadComplete();
}
@override
Widget build(BuildContext context) {
userDetails = ModalRoute.of(context)!.settings.arguments;
void initState() {
super.initState();
data = Provider.of<ChatProviderModel>(context, listen: false);
if (userDetails != null)
data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: false, isNewChat: userDetails["isNewChat"]);
data.scrollController.addListener(data.scrollListener);
data.getSingleUserChatHistory(
senderUID: AppState().chatDetails!.response!.id.toString(),
receiverUID: userDetails["targetUser"].id,
loadMore: false,
isNewChat: userDetails["isNewChat"],
);
//data.scrollController.addListener(data.scrollListener);
}
@override
Widget build(BuildContext context) {
userDetails = ModalRoute.of(context)!.settings.arguments;
return Scaffold(
backgroundColor: const Color(0xFFF8F8F8),
appBar: AppBarWidget(context, title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, image: userDetails["targetUser"].image),
appBar: AppBarWidget(context,
title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach,
showHomeButton: false,
image: userDetails["targetUser"].image,
actions: [
IconButton(
onPressed: () {
makeCall("AUDIO");
},
icon: SvgPicture.asset(
"assets/images/call.svg",
width: 25,
height: 25,
),
),
IconButton(
onPressed: () {
makeCall("VIDEO");
},
icon: SvgPicture.asset(
"assets/images/call.svg",
width: 25,
height: 25,
),
),
]),
body: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return (m.isLoading
@ -62,7 +102,7 @@ class ChatDetailScreen extends StatelessWidget {
header: const MaterialClassicHeader(
color: MyColors.gradiantEndColor,
),
controller: _refreshController,
controller: _rc,
reverse: true,
child: ListView.builder(
controller: m.scrollController,
@ -136,11 +176,11 @@ class ChatDetailScreen extends StatelessWidget {
margin: EdgeInsets.zero,
elevation: 0,
child: Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20, top: 20, bottom: 0),
padding: const EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 0),
child: Card(
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0),
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
child: Container(
@ -267,4 +307,54 @@ class ChatDetailScreen extends StatelessWidget {
),
);
}
void makeCall(String callType) async {
// final server = await SelectionDialog(
// context,
// title: "Select Server",
// items: ["https://livecareturn.hmg.com:8086", "https://104.197.179.1:8086"]
// ).show();
Map<String, String> json = {
"callerID": "9920",
"PatientID": "1231755",
"msgID": "123",
"notfID": "123",
"notification_foreground": "true",
"count": "1",
"message": "Doctor is calling ",
"AppointmentNo": "123",
"title": "Rayyan Hospital",
"ProjectID": "123",
"NotificationType": "10",
"background": "1",
"doctorname": "Dr Sulaiman Al Habib",
"clinicname": "ENT Clinic",
"speciality": "Speciality",
"appointmentdate": "Sun, 15th Dec, 2019",
"appointmenttime": "09:00",
"type": "video",
"session_id":
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0LTE1OTg3NzQ1MDYiLCJpc3MiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0Iiwic3ViIjoiQUNhYWQ1YTNmOGM2NGZhNjczNTY3NTYxNTc0N2YyNmMyYiIsImV4cCI6MTU5ODc3ODEwNiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiSGFyb29uMSIsInZpZGVvIjp7InJvb20iOiJTbWFsbERhaWx5U3RhbmR1cCJ9fX0.7XUS5uMQQJfkrBZu9EjQ6STL6R7iXkso6BtO1HmrQKk",
"identity": "Haroon1",
"name": "SmallDailyStandup",
"videoUrl": "video",
"picture": "video",
"is_call": "true",
"is_webrtc": "true",
// "server": "https://192.168.8.163:8086",
"server": "https://livecareturn.hmg.com:8086",
};
IncomingCallData incomingCallData = IncomingCallData.fromJson(json);
await Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => IncomingCall(
incomingCallData: incomingCallData,
isVideoCall: callType == "VIDEO" ? true : false,
),
),
);
}
}

@ -7,11 +7,7 @@ import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
AppBar AppBarWidget(BuildContext context,
{required String title,
bool showHomeButton = true,
bool showNotificationButton = false,
bool showMemberButton = false,
String? image}) {
{required String title, bool showHomeButton = true, bool showNotificationButton = false, bool showMemberButton = false, String? image, bool, List<Widget>? actions}) {
return AppBar(
leadingWidth: 0,
// leading: GestureDetector(
@ -24,17 +20,16 @@ AppBar AppBarWidget(BuildContext context,
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap:
Feedback.wrapForTap(() => Navigator.maybePop(context), context),
child:
const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context),
child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
),
4.width,
if (image != null) SvgPicture.asset(
image,
height: 40,
width: 40,
),
if (image != null)
SvgPicture.asset(
image,
height: 40,
width: 40,
),
if (image != null) 14.width,
title.toText24(color: MyColors.darkTextColor, isBold: true).expanded,
],
@ -46,8 +41,7 @@ AppBar AppBarWidget(BuildContext context,
if (showHomeButton)
IconButton(
onPressed: () {
Navigator.popUntil(
context, ModalRoute.withName(AppRoutes.dashboard));
Navigator.popUntil(context, ModalRoute.withName(AppRoutes.dashboard));
},
icon: const Icon(Icons.home, color: MyColors.darkIconColor),
),
@ -65,6 +59,9 @@ AppBar AppBarWidget(BuildContext context,
},
icon: const Icon(Icons.people, color: MyColors.textMixColor),
),
...actions??[]
],
);
}

@ -91,6 +91,8 @@ dependencies:
signalr_netcore: ^1.3.3
logging: ^1.0.1
swipe_to: ^1.0.2
flutter_webrtc: ^0.9.16
camera: ^0.10.0+4

Loading…
Cancel
Save