Merge branch 'master' into development_haroon

# Conflicts:
#	lib/classes/consts.dart
#	lib/widgets/app_bar_widget.dart
fatima
haroon amjad 2 years ago
commit 03c488c663

2
.gitignore vendored

@ -34,7 +34,6 @@ pubspec.lock
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
@ -46,3 +45,4 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
/ios/

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="21.279" height="22.831" viewBox="0 0 21.279 22.831">
<path id="Path_4751" data-name="Path 4751" d="M19.767,15.891c-1.379-1.18-2.779-1.894-4.141-.716l-.813.712c-.6.517-1.7,2.931-5.98-1.99S7.1,8.215,7.7,7.7l.818-.713c1.355-1.181.844-2.667-.134-4.2l-.59-.927C6.809.34,5.739-.662,4.381.517l-.734.642A6.892,6.892,0,0,0,.96,5.719c-.49,3.241,1.056,6.953,4.6,11.026s7,6.121,10.281,6.085a6.91,6.91,0,0,0,4.888-2.024l.737-.642c1.355-1.178.513-2.377-.867-3.559Z" transform="translate(-0.872 0)" fill="#2bb8a6"/>
</svg>

After

Width:  |  Height:  |  Size: 557 B

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="27.826" height="17.898" viewBox="0 0 27.826 17.898">
<g id="video-call" transform="translate(-10 -18)">
<rect id="Rectangle_17475" data-name="Rectangle 17475" width="21.057" height="17.898" rx="3" transform="translate(10 18)" fill="#2bb8a6"/>
<path id="Path_4752" data-name="Path 4752" d="M50.692,21.633V34.282a.635.635,0,0,1-.316.55.622.622,0,0,1-.316.082.638.638,0,0,1-.316-.082L45,32.1V23.815l4.743-2.732a.66.66,0,0,1,.632,0A.635.635,0,0,1,50.692,21.633Z" transform="translate(-12.866 -1.104)" fill="#2bb8a6"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 585 B

@ -44,6 +44,8 @@
<string>This App requires access to your location to mark your attendance.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to for call.</string>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>

@ -7,6 +7,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart';
import 'package:logger/logger.dart' as L;
import 'package:logging/logging.dart';
import 'package:mohem_flutter_app/api/api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/consts.dart';
@ -27,6 +28,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List<ChatUser>? pChatHistory, searchedChats;
late HubConnection hubConnection;
L.Logger logger = L.Logger();
bool hubConInitialized = false;
bool isLoading = true;
bool isChatScreenActive = false;
@ -43,13 +45,27 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
bool _shouldAutoscroll = false;
Future<void> getUserAutoLoginToken() async {
String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString();
//userName
Response response =
await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}user/desktopuserlogin", {"userName": userName, "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", "loginType": 2});
login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(response.body);
AppState().setchatUserDetails = userLoginResponse;
await buildHubConnection();
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin",
{
"employeeNumber": int.parse(
AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG"
},
);
login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(
response.body,
);
if (userLoginResponse.response != null) {
hubConInitialized = true;
AppState().setchatUserDetails = userLoginResponse;
await buildHubConnection();
} else {
Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr");
return;
}
}
Future<List<ChatUser>?> getChatMemberFromSearch(String sName, int cUserId) async {
@ -93,8 +109,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
notifyListeners();
}
void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async {
Future GetUserChatHistoryNotDeliveredAsync(int userId) async {
await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]);
return "";
}
void getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async {
isLoading = true;
if (isNewChat) userChatHistory = [];
if (!loadMore) paginationVal = 0;
isChatScreenActive = true;
Response response = await ApiClient().getJsonForResponse(
@ -117,9 +139,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
}
isLoading = false;
await GetUserChatHistoryNotDeliveredAsync(senderUID);
notifyListeners();
}
void updateUserChatHistoryStatusAsync(List data) {
hubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]);
}
List<SingleUserChatModel> getSingleUserChatModel(String str) => List<SingleUserChatModel>.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x)));
ChatUserModel userToList(String str) => ChatUserModel.fromJson(json.decode(str));
@ -151,8 +178,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
hubConnection = HubConnectionBuilder()
.withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
.withAutomaticReconnect(
retryDelays: <int>[2000, 5000, 10000, 20000],
).build();
retryDelays: <int>[2000, 5000, 10000, 20000],
)
.configureLogging(
Logger("Loggin"),
)
.build();
hubConnection.onclose(
({Exception? error}) {},
);
@ -169,7 +200,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
// hubConnection.on("OnSeenChatUserAsync", onChatSeen);
//hubConnection.on("OnUserTypingAsync", onUserTyping);
// hubConnection.on("OnUserCountAsync", userCountAsync);
hubConnection.on("OnUserCountAsync", userCountAsync);
hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
@ -203,6 +234,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void userCountAsync(List<Object?>? args) {
dynamic items = args!.toList();
// logger.d(items);
//logger.d("---------------------------------User Count Async -------------------------------------");
//logger.d(items);
// for (var user in searchedChats!) {
@ -215,9 +247,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void updateChatHistoryWindow(List<Object?>? args) {
dynamic items = args!.toList();
if (kDebugMode) {
print("---------------------------------Update Chat History Windows Async -------------------------------------");
}
print("---------------------------------Update Chat History Windows Async -------------------------------------");
logger.d(items);
// for (var user in searchedChats!) {
// if (user.id == items.first["id"]) {
@ -229,8 +259,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void chatNotDelivered(List<Object?>? args) {
dynamic items = args!.toList();
if (kDebugMode) {
print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------");
for (dynamic item in items[0]) {
dynamic data = [
{
"userChatHistoryId": item["userChatHistoryId"],
"TargetUserId": item["targetUserId"],
"isDelivered": true,
"isSeen": true,
}
];
updateUserChatHistoryStatusAsync(data);
}
logger.d(items);
// for (var user in searchedChats!) {
@ -271,7 +309,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
Future<void> onMsgReceived(List<Object?>? parameters) async {
print("msg Received");
List<SingleUserChatModel> data = [];
List<SingleUserChatModel> temp = [];
for (dynamic msg in parameters!) {
@ -289,6 +326,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
// element.unreadMessageCount = val! + 1;
// }
// });
var list = [
{
"userChatHistoryId": data.first.userChatHistoryId,
"TargetUserId": data.first.targetUserId,
"isDelivered": true,
"isSeen": isChatScreenActive ? true : false,
}
];
updateUserChatHistoryStatusAsync(list);
notifyListeners();
// if (isChatScreenActive) scrollToBottom();
}
@ -380,7 +428,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
Future<void> sendChatToServer(
{required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async {
Uuid uuid = const Uuid();
String msg = message.text;
var msg = message.text;
SingleUserChatModel data = SingleUserChatModel(
chatEventId: chatEventId,
chatSource: 1,

@ -1,10 +1,12 @@
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart';
import 'package:mohem_flutter_app/api/api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/consts.dart';
import 'package:mohem_flutter_app/classes/date_uitl.dart';
import 'package:mohem_flutter_app/models/chat/chat_count_conversation_model.dart';
import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart';
import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart';
import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart';
@ -15,7 +17,6 @@ import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:uuid/uuid.dart';
class DashboardApiClient {
static final DashboardApiClient _instance = DashboardApiClient._internal();
@ -178,4 +179,11 @@ class DashboardApiClient {
return responseData;
}, url, postParams);
}
Future<ChatUnreadCovnCountModel> getChatCount() async {
Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}user/unreadconversationcount/${AppState().getUserName}",
);
return chatUnreadCovnCountModelFromJson(response.body);
}
}

@ -1,7 +1,7 @@
class ApiConsts {
//static String baseUrl = "http://10.200.204.20:2801/"; // Local server
// static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server
static String baseUrl = "https://hmgwebservices.com"; // Live server
static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server
//static String baseUrl = "https://hmgwebservices.com"; // Live server
static String baseUrlServices = baseUrl + "/Services/"; // server
// static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server
static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/";

@ -0,0 +1,37 @@
//
// Generated file. Do not edit.
//
// ignore_for_file: directives_ordering
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: depend_on_referenced_packages
import 'package:file_picker/_internal/file_picker_web.dart';
import 'package:firebase_core_web/firebase_core_web.dart';
import 'package:firebase_messaging_web/firebase_messaging_web.dart';
import 'package:fluttertoast/fluttertoast_web.dart';
import 'package:geolocator_web/geolocator_web.dart';
import 'package:google_maps_flutter_web/google_maps_flutter_web.dart';
import 'package:image_picker_for_web/image_picker_for_web.dart';
import 'package:shared_preferences_web/shared_preferences_web.dart';
import 'package:url_launcher_web/url_launcher_web.dart';
import 'package:video_player_web/video_player_web.dart';
import 'package:wakelock_web/wakelock_web.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
// ignore: public_member_api_docs
void registerPlugins(Registrar registrar) {
FilePickerWeb.registerWith(registrar);
FirebaseCoreWeb.registerWith(registrar);
FirebaseMessagingWeb.registerWith(registrar);
FluttertoastWebPlugin.registerWith(registrar);
GeolocatorPlugin.registerWith(registrar);
GoogleMapsPlugin.registerWith(registrar);
ImagePickerPlugin.registerWith(registrar);
SharedPreferencesPlugin.registerWith(registrar);
UrlLauncherPlugin.registerWith(registrar);
VideoPlayerPlugin.registerWith(registrar);
WakelockWeb.registerWith(registrar);
registrar.registerMessageHandler();
}

@ -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,25 @@
import 'dart:convert';
ChatUnreadCovnCountModel chatUnreadCovnCountModelFromJson(String str) => ChatUnreadCovnCountModel.fromJson(json.decode(str));
String chatUnreadCovnCountModelToJson(ChatUnreadCovnCountModel data) => json.encode(data.toJson());
class ChatUnreadCovnCountModel {
ChatUnreadCovnCountModel({
this.singleChatCount,
this.groupChatCount,
});
int? singleChatCount;
int? groupChatCount;
factory ChatUnreadCovnCountModel.fromJson(Map<String, dynamic> json) => ChatUnreadCovnCountModel(
singleChatCount: json["singleChatCount"] == null ? null : json["singleChatCount"],
groupChatCount: json["groupChatCount"] == null ? null : json["groupChatCount"],
);
Map<String, dynamic> toJson() => {
"singleChatCount": singleChatCount == null ? null : singleChatCount,
"groupChatCount": groupChatCount == null ? null : groupChatCount,
};
}

@ -1,4 +1,3 @@
import 'dart:convert';
UserAutoLoginModel userAutoLoginModelFromJson(String str) => UserAutoLoginModel.fromJson(json.decode(str));
@ -7,22 +6,22 @@ String userAutoLoginModelToJson(UserAutoLoginModel data) => json.encode(data.toJ
class UserAutoLoginModel {
UserAutoLoginModel({
this.response,
this.response,
this.errorResponses,
});
Response? response;
dynamic? errorResponses;
List<ErrorResponse>? errorResponses;
factory UserAutoLoginModel.fromJson(Map<String, dynamic> json) => UserAutoLoginModel(
response: json["response"] == null ? null : Response.fromJson(json["response"]),
errorResponses: json["errorResponses"],
);
response: json["response"] == null ? null : Response.fromJson(json["response"]),
errorResponses: json["errorResponses"] == null ? null : List<ErrorResponse>.from(json["errorResponses"].map((x) => ErrorResponse.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"response": response == null ? null : response!.toJson(),
"errorResponses": errorResponses,
};
"response": response == null ? null : response!.toJson(),
"errorResponses": errorResponses == null ? null : List<dynamic>.from(errorResponses!.map((x) => x.toJson())),
};
}
class Response {
@ -51,28 +50,48 @@ class Response {
String? encryptedUserName;
factory Response.fromJson(Map<String, dynamic> json) => Response(
id: json["id"] == null ? null : json["id"],
userName: json["userName"] == null ? null : json["userName"],
email: json["email"] == null ? null : json["email"],
phone: json["phone"] == null ? null : json["phone"],
title: json["title"] == null ? null : json["title"],
token: json["token"] == null ? null : json["token"],
isDomainUser: json["isDomainUser"] == null ? null : json["isDomainUser"],
isActiveCode: json["isActiveCode"] == null ? null : json["isActiveCode"],
encryptedUserId: json["encryptedUserId"] == null ? null : json["encryptedUserId"],
encryptedUserName: json["encryptedUserName"] == null ? null : json["encryptedUserName"],
);
id: json["id"] == null ? null : json["id"],
userName: json["userName"] == null ? null : json["userName"],
email: json["email"] == null ? null : json["email"],
phone: json["phone"] == null ? null : json["phone"],
title: json["title"] == null ? null : json["title"],
token: json["token"] == null ? null : json["token"],
isDomainUser: json["isDomainUser"] == null ? null : json["isDomainUser"],
isActiveCode: json["isActiveCode"] == null ? null : json["isActiveCode"],
encryptedUserId: json["encryptedUserId"] == null ? null : json["encryptedUserId"],
encryptedUserName: json["encryptedUserName"] == null ? null : json["encryptedUserName"],
);
Map<String, dynamic> toJson() => {
"id": id == null ? null : id,
"userName": userName == null ? null : userName,
"email": email == null ? null : email,
"phone": phone == null ? null : phone,
"title": title == null ? null : title,
"token": token == null ? null : token,
"isDomainUser": isDomainUser == null ? null : isDomainUser,
"isActiveCode": isActiveCode == null ? null : isActiveCode,
"encryptedUserId": encryptedUserId == null ? null : encryptedUserId,
"encryptedUserName": encryptedUserName == null ? null : encryptedUserName,
};
}
class ErrorResponse {
ErrorResponse({
this.fieldName,
this.message,
});
String? fieldName;
String? message;
factory ErrorResponse.fromJson(Map<String, dynamic> json) => ErrorResponse(
fieldName: json["fieldName"] == null ? null : json["fieldName"],
message: json["message"] == null ? null : json["message"],
);
Map<String, dynamic> toJson() => {
"id": id == null ? null : id,
"userName": userName == null ? null : userName,
"email": email == null ? null : email,
"phone": phone == null ? null : phone,
"title": title == null ? null : title,
"token": token == null ? null : token,
"isDomainUser": isDomainUser == null ? null : isDomainUser,
"isActiveCode": isActiveCode == null ? null : isActiveCode,
"encryptedUserId": encryptedUserId == null ? null : encryptedUserId,
"encryptedUserName": encryptedUserName == null ? null : encryptedUserName,
};
"fieldName": fieldName == null ? null : fieldName,
"message": message == null ? null : message,
};
}

@ -7,6 +7,7 @@ import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/chat_count_conversation_model.dart';
import 'package:mohem_flutter_app/models/dashboard/drawer_menu_item_model.dart';
import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart';
import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart';
@ -34,6 +35,10 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
bool isWorkListLoading = true;
int workListCounter = 0;
//Chat
bool isChatCounterLoding = true;
int chatUConvCounter = 0;
//Misssing Swipe
bool isMissingSwipeLoading = true;
int missingSwipeCounter = 0;
@ -91,6 +96,9 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
accrualList = null;
leaveBalanceAccrual = null;
isChatCounterLoding = true;
chatUConvCounter = 0;
ticketBalance = 0;
isServicesMenusLoading = true;
homeMenus = null;
@ -266,7 +274,18 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
return res;
}
void fetchChatCounts() async {
try {
ChatUnreadCovnCountModel response = await DashboardApiClient().getChatCount();
chatUConvCounter = response.singleChatCount!;
isChatCounterLoding = false;
notifyListeners();
} catch (ex) {
logger.wtf(ex);
notifyListeners();
Utils.handleException(ex, null, null);
}
}
void notify() {
notifyListeners();

@ -0,0 +1,379 @@
import 'dart:ui';
import 'package:camera/camera.dart';
import 'package:flutter/material.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
_animationController!.dispose();
// 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,
),
),
],
);
}
}

@ -0,0 +1,470 @@
import 'dart:ui';
import 'package:camera/camera.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/models/chat/call.dart';
class OutGoingCall extends StatefulWidget {
IncomingCallData OutGoingCallData;
bool? isVideoCall;
OutGoingCall({Key? key, required this.OutGoingCallData, this.isVideoCall}) : super(key: key);
@override
_OutGoingCallState createState() => _OutGoingCallState();
}
class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderStateMixin {
AnimationController? _animationController;
CameraController? _controller;
Future<void>? _initializeControllerFuture;
bool isCameraReady = false;
bool isMicOff = false;
bool isLoudSpeaker = false;
bool isCamOff = 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>[
40.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
margin: const EdgeInsets.all(21.0),
child: Container(
margin: const EdgeInsets.only(
left: 10.0,
right: 10.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
SvgPicture.asset(
"assets/images/user.svg",
height: 70,
width: 70,
fit: BoxFit.cover,
),
10.height,
Text(
"Aamir Saleem Ahmad",
style: TextStyle(
fontSize: 21,
fontWeight: FontWeight.bold,
color: MyColors.white,
letterSpacing: -1.26,
height: 23 / 12,
),
),
Text(
"Ringing...",
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.OutGoingCallData.appointmentdate + widget.OutGoingCallData.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.OutGoingCallData.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>[
if (widget.isVideoCall!)
RotationTransition(
turns: Tween(
begin: 0.0,
end: -.1,
)
.chain(
CurveTween(
curve: Curves.elasticIn,
),
)
.animate(
_animationController!,
),
child: RawMaterialButton(
onPressed: () {
_camOff();
},
elevation: 2.0,
fillColor: isCamOff ? MyColors.green2DColor : Colors.grey,
padding: const EdgeInsets.all(
15.0,
),
shape: const CircleBorder(),
child: Icon(
isCamOff ? Icons.videocam_off : Icons.videocam,
color: MyColors.white,
size: 35.0,
),
),
)
else
RotationTransition(
turns: Tween(
begin: 0.0,
end: -.1,
)
.chain(
CurveTween(
curve: Curves.elasticIn,
),
)
.animate(
_animationController!,
),
child: RawMaterialButton(
onPressed: () {
_loudOn();
},
elevation: 2.0,
fillColor: isLoudSpeaker ? MyColors.green2DColor : Colors.grey,
padding: const EdgeInsets.all(
15.0,
),
shape: const CircleBorder(),
child: const Icon(
Icons.volume_up,
color: MyColors.white,
size: 35.0,
),
),
),
RotationTransition(
turns: Tween(
begin: 0.0,
end: -.1,
)
.chain(
CurveTween(
curve: Curves.elasticIn,
),
)
.animate(
_animationController!,
),
child: RawMaterialButton(
onPressed: () {
_micOff();
},
elevation: 2.0,
fillColor: isMicOff ? MyColors.green2DColor : Colors.grey,
padding: const EdgeInsets.all(
15.0,
),
shape: const CircleBorder(),
child: Icon(
isMicOff ? Icons.mic_off : Icons.mic,
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();
}
}
void _micOff() {
setState(() {
isMicOff = !isMicOff;
});
}
void _camOff() {
setState(() {
isCamOff = !isCamOff;
});
}
void _loudOn() {
setState(() {
isLoudSpeaker = !isLoudSpeaker;
});
}
Future<void> _submit() async {
try {
// backToHome();
// final roomModel = RoomModel(name: widget.OutGoingCallData.name, token: widget.OutGoingCallData.sessionId, identity: widget.OutGoingCallData.identity);
await _controller?.dispose();
// changeCallStatusAPI(4);
// if (_session != null && _signaling != null) {
// await Navigator.of(context).pushReplacement(
// MaterialPageRoute(
// // fullscreenDialog: true,
// builder: (BuildContext context) {
// // if (widget.OutGoingCallData.isWebRTC == "true") {
// return StartVideoCall(signaling: _signaling, session: _session);
//
// // else {
// // return OpenTokConnectCallPage(apiKey: OPENTOK_API_KEY, sessionId: widget.OutGoingCallData.sessionId, token: widget.OutGoingCallData.token);
// // }
//
// // return VideoCallWebPage(receiverId: widget.OutGoingCallData.receiverID, callerId: widget.OutGoingCallData.callerID); // Web WebRTC VideoCall
//
// // return CallHomePage(receiverId: widget.OutGoingCallData.receiverID, callerId: widget.OutGoingCallData.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.OutGoingCallData.sessionId, sessionStatus, context).then((res) {}).catchError((err) {
// print(err);
// });
// }
void backToHome() async {
// final connected = await signaling.declineCall(widget.OutGoingCallData.callerID, widget.OutGoingCallData.receiverID);
// LandingPage.isOpenCallPage = false;
// _signaling
_animationController!.dispose();
// 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.OutGoingCallData.callerID;
// var receiver = widget.OutGoingCallData.receiverID;
// var host = widget.OutGoingCallData.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,
),
),
],
);
}
}

@ -91,12 +91,12 @@ class ChatBubble extends StatelessWidget {
children: [
dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7),),
if (isCurrentUser) 5.width,
if (isCurrentUser)
Icon(
isDelivered ? Icons.done_all : Icons.done_all,
color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor,
size: 14,
),
// if (isCurrentUser)
// Icon(
// isDelivered ? Icons.done_all : Icons.done_all,
// color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor,
// size: 14,
// ),
],
),
],

@ -6,9 +6,12 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.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_outgoing_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,23 +19,36 @@ 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) {
data.paginationVal = data.paginationVal + 10;
data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false);
if (userDetails != null)
data.getSingleUserChatHistory(
senderUID: AppState().chatDetails!.response!.id!.toInt(),
receiverUID: userDetails["targetUser"].id,
loadMore: true,
isNewChat: false,
);
}
await Future.delayed(const Duration(milliseconds: 1000));
_refreshController.loadComplete();
await Future.delayed(
const Duration(
milliseconds: 1000,
),
);
_rc.loadComplete();
}
@override
@ -40,11 +56,42 @@ class ChatDetailScreen extends StatelessWidget {
userDetails = ModalRoute.of(context)!.settings.arguments;
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!.toInt(),
receiverUID: userDetails["targetUser"].id,
loadMore: false,
isNewChat: userDetails["isNewChat"],
);
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/icons/chat/call.svg",
width: 22,
height: 22,
),
),
IconButton(
onPressed: () {
makeCall("VIDEO");
},
icon: SvgPicture.asset(
"assets/icons/chat/video_call.svg",
width: 20,
height: 20,
),
),
10.width,
]),
body: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return (m.isLoading
@ -62,7 +109,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 +183,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 +314,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) => OutGoingCall(
isVideoCall: callType == "VIDEO" ? true : false,
OutGoingCallData: incomingCallData,
),
),
);
}
}

@ -1,6 +1,9 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
@ -33,13 +36,18 @@ class _ChatHomeState extends State<ChatHome> {
data = Provider.of<ChatProviderModel>(context, listen: false);
data.getUserAutoLoginToken().then((value) {
data.getUserRecentChats();
// var datae = [int.parse(AppState().memberInformationList!.eMPLOYEENUMBER.toString())];
// data.hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [int.parse(AppState().memberInformationList!.eMPLOYEENUMBER.toString())]);
});
}
@override
void dispose() {
data.clearAll();
data.hubConnection.stop();
if (data.hubConInitialized) {
data.hubConnection.stop();
}
super.dispose();
}

@ -71,6 +71,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
data.fetchLeaveTicketBalance(context, DateTime.now());
data.fetchMenuEntries();
data.getCategoryOffersListAPI(context);
data.fetchChatCounts();
_refreshController.refreshCompleted();
}
@ -268,7 +269,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
).onPress(() {
showMyBottomSheet(
context,
callBackFunc: (){},
callBackFunc: () {},
child: MarkAttendanceWidget(model, isFromDashboard: true),
);
}),
@ -469,10 +470,32 @@ class _DashboardScreenState extends State<DashboardScreen> {
label: LocaleKeys.itemsForSale.tr(),
),
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/chat/chat.svg",
color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
icon: Stack(
alignment: Alignment.centerLeft,
children: [
SvgPicture.asset(
"assets/icons/chat/chat.svg",
color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
Consumer<DashboardProviderModel>(
builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) {
if (data.chatUConvCounter == 0) {
return const SizedBox();
}
return Positioned(
right: 0,
top: 0,
child: Container(
padding: const EdgeInsets.only(left: 4, right: 4),
alignment: Alignment.center,
decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)),
child: data.chatUConvCounter.toString().toText10(color: Colors.white),
),
);
},
),
],
),
label: LocaleKeys.chat.tr(),
),
],

@ -6,73 +6,60 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
PreferredSize AppBarWidget(BuildContext context,
{required String title,
bool showHomeButton = true,
bool showNotificationButton = false,
bool showMemberButton = false,
String? image}) {
return PreferredSize(
preferredSize: const Size.fromHeight(57.0),
child: Column(
AppBar AppBarWidget(BuildContext context,
{required String title, bool showHomeButton = true, bool showNotificationButton = false, bool showMemberButton = false, String? image, List<Widget>? actions}) {
return AppBar(
leadingWidth: 0,
// leading: GestureDetector(
// behavior: HitTestBehavior.opaque,
// onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context),
// child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
// ),
//titleSpacing: -1.44,
title: Row(
children: [
AppBar(
leadingWidth: 0,
// leading: GestureDetector(
// behavior: HitTestBehavior.opaque,
// onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context),
// child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
// ),
//titleSpacing: -1.44,
title: Row(
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
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) 14.width,
title.toText24(color: MyColors.darkTextColor, isBold: true).expanded,
],
),
centerTitle: false,
elevation: 0,
backgroundColor: Colors.white,
actions: [
if (showHomeButton)
IconButton(
onPressed: () {
Navigator.popUntil(
context, ModalRoute.withName(AppRoutes.dashboard));
},
icon: const Icon(Icons.home, color: MyColors.darkIconColor),
),
if (showNotificationButton)
IconButton(
onPressed: () {
Navigator.pushNamed(context, AppRoutes.worklistSettings);
},
icon: const Icon(Icons.notifications, color: MyColors.textMixColor),
),
if (showMemberButton)
IconButton(
onPressed: () {
Navigator.pushNamed(context, AppRoutes.subordinateLeave);
},
icon: const Icon(Icons.people, color: MyColors.textMixColor),
),
],
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context),
child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
),
Container(width: double.infinity, height: 1, color: MyColors.lightGreyEFColor),
4.width,
if (image != null)
SvgPicture.asset(
image,
height: 40,
width: 40,
),
if (image != null) 14.width,
title.toText24(color: MyColors.darkTextColor, isBold: true).expanded,
],
),
centerTitle: false,
elevation: 0,
backgroundColor: Colors.white,
actions: [
if (showHomeButton)
IconButton(
onPressed: () {
Navigator.popUntil(context, ModalRoute.withName(AppRoutes.dashboard));
},
icon: const Icon(Icons.home, color: MyColors.darkIconColor),
),
if (showNotificationButton)
IconButton(
onPressed: () {
Navigator.pushNamed(context, AppRoutes.worklistSettings);
},
icon: const Icon(Icons.notifications, color: MyColors.textMixColor),
),
if (showMemberButton)
IconButton(
onPressed: () {
Navigator.pushNamed(context, AppRoutes.subordinateLeave);
},
icon: const Icon(Icons.people, color: MyColors.textMixColor),
),
...actions??[]
],
);
}

@ -236,7 +236,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
arguments: {"targetUser": chatUsersList![index], "isNewChat": true},
);
},
onLongPress: () {},
),
);
},

@ -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