Merge branch 'development_aamir' into 'master'

Chat Fixes & Fav

See merge request Cloud_Solution/mohemm-flutter-app!55
merge-requests/56/merge
haroon amjad 3 years ago
commit f8b6dcb970

@ -498,5 +498,8 @@
"verification": "تَحَقّق", "verification": "تَحَقّق",
"resend": "إعادة إرسال", "resend": "إعادة إرسال",
"codeExpire": "انتهت صلاحية رمز التحقق", "codeExpire": "انتهت صلاحية رمز التحقق",
"typeheretoreply": "اكتب هنا للرد" "typeheretoreply": "اكتب هنا للرد",
"favorite" : "أُفضله",
"searchfromchat": "البحث من الدردشة"
} }

@ -498,5 +498,8 @@
"resend": "Resend", "resend": "Resend",
"codeExpire": "The verification code has been expired", "codeExpire": "The verification code has been expired",
"allQuestionsCorrect": "You have answered all questions correct", "allQuestionsCorrect": "You have answered all questions correct",
"typeheretoreply": "Type here to reply" "typeheretoreply": "Type here to reply",
"favorite" : "My Favorite",
"searchfromchat": "Search from chat"
} }

@ -383,7 +383,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Mohemm; INFOPLIST_KEY_CFBundleDisplayName = Mohemm;
@ -520,7 +520,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Mohemm; INFOPLIST_KEY_CFBundleDisplayName = Mohemm;
@ -549,7 +549,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Mohemm; INFOPLIST_KEY_CFBundleDisplayName = Mohemm;

@ -1,11 +1,12 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:logging/logging.dart'; import 'package:logger/logger.dart' as L;
import 'package:mohem_flutter_app/api/api_client.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/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/consts.dart';
@ -15,17 +16,18 @@ import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.da
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as login; import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as login;
import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav;
import 'package:mohem_flutter_app/widgets/image_picker.dart'; import 'package:mohem_flutter_app/widgets/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:signalr_netcore/signalr_client.dart'; import 'package:signalr_netcore/signalr_client.dart';
import 'package:logger/logger.dart' as L;
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
ScrollController scrollController = ScrollController();
TextEditingController message = TextEditingController();
TextEditingController search = TextEditingController();
List<SingleUserChatModel> userChatHistory = []; List<SingleUserChatModel> userChatHistory = [];
List<ChatUser>? pChatHistory, searchedChats; List<ChatUser>? pChatHistory, searchedChats;
late HubConnection hubConnection; late HubConnection hubConnection;
L.Logger logger = L.Logger(); L.Logger logger = L.Logger();
TextEditingController message = TextEditingController();
bool isLoading = true; bool isLoading = true;
bool isChatScreenActive = false; bool isChatScreenActive = false;
late File selectedFile; late File selectedFile;
@ -33,8 +35,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
String sFileType = ""; String sFileType = "";
bool isMsgReply = false; bool isMsgReply = false;
List<SingleUserChatModel> repliedMsg = []; List<SingleUserChatModel> repliedMsg = [];
List<ChatUser> favUsersList = [];
int paginationVal = 0; int paginationVal = 0;
//Scroll
bool _firstAutoscrollExecuted = false;
bool _shouldAutoscroll = false;
Future<void> getUserAutoLoginToken() async { Future<void> getUserAutoLoginToken() async {
String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString(); String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString();
Response response = Response response =
@ -59,51 +66,52 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}", "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}",
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
logger.d(AppState().chatDetails!.response!.token);
ChatUserModel recentChat = userToList(response.body); ChatUserModel recentChat = userToList(response.body);
Response favRes = await ApiClient().getJsonForResponse( Response favRes = await ApiClient().getJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}", "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}",
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
print("============================== Fav Response ====================================="); ChatUserModel favUList = userToList(favRes.body);
ChatUserModel favUsersList = userToList(favRes.body); if (favUList.response != null) {
for (var user in recentChat.response!) { favUsersList = favUList.response!;
for (var favUser in favUsersList.response!) { favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
logger.d(favUser.isFav); for (dynamic user in recentChat.response!) {
if (user.id == favUser.id) { for (dynamic favUser in favUList.response!) {
user.isFav = favUser.isFav; if (user.id == favUser.id) {
user.isFav = favUser.isFav;
}
} }
} }
} }
pChatHistory = recentChat.response; pChatHistory = recentChat.response;
pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
searchedChats = pChatHistory; searchedChats = pChatHistory;
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();
} }
void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore}) async { void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async {
isLoading = true; isLoading = true;
if (!loadMore) paginationVal = 0; if (!loadMore) paginationVal = 0;
logger.d(paginationVal);
isChatScreenActive = true; isChatScreenActive = true;
Response response = await ApiClient().getJsonForResponse( Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal",
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
logger.d(response.body);
if (response.statusCode == 204) { if (response.statusCode == 204) {
if (!loadMore) userChatHistory = []; if (isNewChat) {
Utils.showToast("No More Data To Load"); userChatHistory = [];
} else if (loadMore) {
// userChatHistory = [];
Utils.showToast("No More Data To Load");
}
} else { } else {
if (loadMore) { if (loadMore) {
List<SingleUserChatModel> temp = getSingleUserChatModel(response.body); List<SingleUserChatModel> temp = getSingleUserChatModel(response.body).reversed.toList();
userChatHistory.insertAll(0, temp); userChatHistory.addAll(temp);
} else { } else {
userChatHistory = getSingleUserChatModel(response.body); userChatHistory = getSingleUserChatModel(response.body).reversed.toList();
} }
} }
isLoading = false; isLoading = false;
@ -127,19 +135,22 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} else { } else {
result = []; result = [];
} }
} catch (e) {} } catch (e) {
if (kDebugMode) {
print(e);
}
}
;
return result; return result;
} }
Future<void> buildHubConnection() async { Future<void> buildHubConnection() async {
HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
hubConnection = await HubConnectionBuilder() hubConnection = HubConnectionBuilder()
.withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
.withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]) .withAutomaticReconnect(
.configureLogging( retryDelays: <int>[2000, 5000, 10000, 20000],
Logger("Logs Enabled"), ).build();
)
.build();
hubConnection.onclose( hubConnection.onclose(
({Exception? error}) {}, ({Exception? error}) {},
); );
@ -153,24 +164,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
await hubConnection.start(); await hubConnection.start();
hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnUpdateUserStatusAsync", changeStatus);
hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
// hubConnection.on("OnSeenChatUserAsync", onChatSeen);
hubConnection.on("OnUserTypingAsync", onUserTyping); //hubConnection.on("OnUserTypingAsync", onUserTyping);
// hubConnection.on("OnUserCountAsync", userCountAsync); // hubConnection.on("OnUserCountAsync", userCountAsync);
// hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
} else {
hubConnection.on("OnUpdateUserStatusAsync", changeStatus);
hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
hubConnection.on("OnUserTypingAsync", onUserTyping);
// hubConnection.on("OnUserCountAsync", userCountAsync);
// hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
// hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
} }
isLoading = false;
notifyListeners();
} }
void updateUserChatStatus(List<Object?>? args) { void updateUserChatStatus(List<Object?>? args) {
@ -178,7 +179,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
for (dynamic cItem in items[0]) { for (dynamic cItem in items[0]) {
for (SingleUserChatModel chat in userChatHistory) { for (SingleUserChatModel chat in userChatHistory) {
if (chat.userChatHistoryId.toString() == cItem["userChatHistoryId"].toString()) { if (chat.userChatHistoryId.toString() == cItem["userChatHistoryId"].toString()) {
logger.d(jsonEncode(chat));
chat.isSeen = cItem["isSeen"]; chat.isSeen = cItem["isSeen"];
chat.isDelivered = cItem["isDelivered"]; chat.isDelivered = cItem["isDelivered"];
notifyListeners(); notifyListeners();
@ -187,9 +187,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} }
} }
void userCountAsync(List<Object?>? args) { void onChatSeen(List<Object?>? args) {
List items = args!.toList(); dynamic items = args!.toList();
print("---------------------------------User Count Async -------------------------------------"); logger.d("---------------------------------Chat Seen -------------------------------------");
logger.d(items); logger.d(items);
// for (var user in searchedChats!) { // for (var user in searchedChats!) {
// if (user.id == items.first["id"]) { // if (user.id == items.first["id"]) {
@ -199,9 +199,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
// notifyListeners(); // notifyListeners();
} }
void userCountAsync(List<Object?>? args) {
dynamic items = args!.toList();
//logger.d("---------------------------------User Count Async -------------------------------------");
//logger.d(items);
// for (var user in searchedChats!) {
// if (user.id == items.first["id"]) {
// user.userStatus = items.first["userStatus"];
// }
// }
// notifyListeners();
}
void updateChatHistoryWindow(List<Object?>? args) { void updateChatHistoryWindow(List<Object?>? args) {
List items = args!.toList(); dynamic items = args!.toList();
print("---------------------------------Update Chat History Windows Async -------------------------------------"); if (kDebugMode) {
print("---------------------------------Update Chat History Windows Async -------------------------------------");
}
logger.d(items); logger.d(items);
// for (var user in searchedChats!) { // for (var user in searchedChats!) {
// if (user.id == items.first["id"]) { // if (user.id == items.first["id"]) {
@ -212,20 +226,24 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} }
void chatNotDelivered(List<Object?>? args) { void chatNotDelivered(List<Object?>? args) {
List items = args!.toList(); dynamic items = args!.toList();
print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------"); if (kDebugMode) {
print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------");
}
logger.d(items); logger.d(items);
// for (var user in searchedChats!) { // for (var user in searchedChats!) {
// if (user.id == items.first["id"]) { // if (user.id == items.first["id"]) {
// user.userStatus = items.first["userStatus"]; // user.userStatus = items.first["userStatus"];
// } // }
// } // }
// notifyListeners(); // notifyListeners();2
} }
void changeStatus(List<Object?>? args) { void changeStatus(List<Object?>? args) {
// print("================= Status Online // Offline ===================="); if (kDebugMode) {
List items = args!.toList(); // print("================= Status Online // Offline ====================");
}
dynamic items = args!.toList();
// logger.d(items); // logger.d(items);
for (ChatUser user in searchedChats!) { for (ChatUser user in searchedChats!) {
if (user.id == items.first["id"]) { if (user.id == items.first["id"]) {
@ -251,6 +269,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} }
Future<void> onMsgReceived(List<Object?>? parameters) async { Future<void> onMsgReceived(List<Object?>? parameters) async {
print("msg Received");
List<SingleUserChatModel> data = []; List<SingleUserChatModel> data = [];
List<SingleUserChatModel> temp = []; List<SingleUserChatModel> temp = [];
for (dynamic msg in parameters!) { for (dynamic msg in parameters!) {
@ -261,15 +280,20 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
data.first.currentUserId = temp.first.targetUserId; data.first.currentUserId = temp.first.targetUserId;
data.first.currentUserName = temp.first.targetUserName; data.first.currentUserName = temp.first.targetUserName;
} }
userChatHistory.add(data.first); userChatHistory.insert(0, data.first);
// searchedChats!.forEach((element) {
// if (element.id == data.first.currentUserId) {
// var val = element.unreadMessageCount == null ? 0 : element.unreadMessageCount;
// element.unreadMessageCount = val! + 1;
// }
// });
notifyListeners(); notifyListeners();
logger.d(isChatScreenActive); // if (isChatScreenActive) scrollToBottom();
// if (isChatScreenActive) scrollDown();
} }
void onUserTyping(List<Object?>? parameters) { void onUserTyping(List<Object?>? parameters) {
print("==================== Typing Active =================="); // print("==================== Typing Active ==================");
logger.d(parameters); // logger.d(parameters);
for (ChatUser user in searchedChats!) { for (ChatUser user in searchedChats!) {
if (user.id == parameters![1] && parameters[0] == true) { if (user.id == parameters![1] && parameters[0] == true) {
user.isTyping = parameters[0] as bool?; user.isTyping = parameters[0] as bool?;
@ -351,15 +375,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} }
} }
// void scrollDown() {
// scrollController.animateTo(
// scrollController.position.maxScrollExtent + 100,
// curve: Curves.easeOut,
// duration: const Duration(milliseconds: 300),
// );
// notifyListeners();
// }
Future<void> sendChatToServer( Future<void> sendChatToServer(
{required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async {
Uuid uuid = const Uuid(); Uuid uuid = const Uuid();
@ -390,7 +405,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
String chatData = String chatData =
'{"contant":"${message.text}","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}'; '{"contant":"${message.text}","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}';
await hubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]); await hubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]);
userChatHistory.add(data);
userChatHistory.insert(0, data);
isFileSelected = false; isFileSelected = false;
isMsgReply = false; isMsgReply = false;
sFileType = ""; sFileType = "";
@ -537,7 +554,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} }
String dateFormte(DateTime data) { String dateFormte(DateTime data) {
DateFormat f = new DateFormat('hh:mm a dd MMM yyyy'); DateFormat f = DateFormat('hh:mm a dd MMM yyyy');
f.format(data); f.format(data);
return f.format(data); return f.format(data);
} }
@ -547,9 +564,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token); await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token);
fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
if (favoriteChatUser.response != null) { if (favoriteChatUser.response != null) {
for (var user in searchedChats!) { for (ChatUser user in searchedChats!) {
if (user.id == favoriteChatUser.response!.targetUserId!) { if (user.id == favoriteChatUser.response!.targetUserId!) {
user.isFav = favoriteChatUser.response!.isFav; user.isFav = favoriteChatUser.response!.isFav;
favUsersList.add(user);
} }
} }
} }
@ -566,16 +584,56 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
user.isFav = favoriteChatUser.response!.isFav; user.isFav = favoriteChatUser.response!.isFav;
} }
} }
favUsersList.removeWhere((ChatUser element) => element.id == targetUserID);
} }
notifyListeners(); notifyListeners();
} }
void clearSelections() { void clearSelections() {
searchedChats = pChatHistory;
search.clear();
isChatScreenActive = false; isChatScreenActive = false;
paginationVal = 0; paginationVal = 0;
message.text = ''; message.text = '';
isFileSelected = false; isFileSelected = false;
repliedMsg = []; repliedMsg = [];
sFileType = ""; sFileType = "";
notifyListeners();
}
void clearAll() {
searchedChats = pChatHistory;
search.clear();
isChatScreenActive = false;
paginationVal = 0;
message.text = '';
isFileSelected = false;
repliedMsg = [];
sFileType = "";
}
void scrollListener() {
_firstAutoscrollExecuted = true;
if (scrollController.hasClients && scrollController.position.pixels == scrollController.position.maxScrollExtent) {
_shouldAutoscroll = true;
} else {
_shouldAutoscroll = false;
}
}
void scrollToBottom() {
scrollController.animateTo(
scrollController.position.maxScrollExtent + 100,
duration: const Duration(milliseconds: 500),
curve: Curves.easeIn,
);
}
void msgScroll() {
scrollController.animateTo(
scrollController.position.minScrollExtent - 100,
duration: const Duration(milliseconds: 500),
curve: Curves.easeIn,
);
} }
} }

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

@ -5,6 +5,7 @@ import 'package:mohem_flutter_app/ui/attendance/vacation_rule_screen.dart';
import 'package:mohem_flutter_app/ui/bottom_sheets/attendence_details_bottom_sheet.dart'; import 'package:mohem_flutter_app/ui/bottom_sheets/attendence_details_bottom_sheet.dart';
import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
import 'package:mohem_flutter_app/ui/chat/chat_home.dart'; import 'package:mohem_flutter_app/ui/chat/chat_home.dart';
import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart';
import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart';
@ -177,6 +178,7 @@ class AppRoutes {
//Chat //Chat
static const String chat = "/chat"; static const String chat = "/chat";
static const String chatDetailed = "/chatDetailed"; static const String chatDetailed = "/chatDetailed";
static const String chatFavoriteUsers = "/chatFavoriteUsers";
//Marathon //Marathon
static const String marathonIntroScreen = "/marathonIntroScreen"; static const String marathonIntroScreen = "/marathonIntroScreen";
@ -287,8 +289,9 @@ class AppRoutes {
changePassword: (BuildContext context) => ChangePasswordScreen(), changePassword: (BuildContext context) => ChangePasswordScreen(),
//Chat //Chat
chat: (BuildContext context) => ChatHomeScreen(), chat: (BuildContext context) => ChatHome(),
chatDetailed: (BuildContext context) => ChatDetailScreen(), chatDetailed: (BuildContext context) => ChatDetailScreen(),
chatFavoriteUsers: (BuildContext context) => ChatFavoriteUsersScreen(),
// Marathon // Marathon
marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(), marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(),

@ -514,7 +514,9 @@ class CodegenLoader extends AssetLoader{
"verification": "تَحَقّق", "verification": "تَحَقّق",
"resend": "إعادة إرسال", "resend": "إعادة إرسال",
"codeExpire": "انتهت صلاحية رمز التحقق", "codeExpire": "انتهت صلاحية رمز التحقق",
"typeheretoreply": "اكتب هنا للرد" "typeheretoreply": "اكتب هنا للرد",
"favorite": "أُفضله",
"searchfromchat": "البحث من الدردشة"
}; };
static const Map<String,dynamic> en_US = { static const Map<String,dynamic> en_US = {
"mohemm": "Mohemm", "mohemm": "Mohemm",
@ -1016,7 +1018,9 @@ static const Map<String,dynamic> en_US = {
"resend": "Resend", "resend": "Resend",
"codeExpire": "The verification code has been expired", "codeExpire": "The verification code has been expired",
"allQuestionsCorrect": "You have answered all questions correct", "allQuestionsCorrect": "You have answered all questions correct",
"typeheretoreply": "Type here to reply" "typeheretoreply": "Type here to reply",
"favorite": "My Favorite",
"searchfromchat": "Search from chat"
}; };
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
} }

@ -485,5 +485,7 @@ abstract class LocaleKeys {
static const resend = 'resend'; static const resend = 'resend';
static const codeExpire = 'codeExpire'; static const codeExpire = 'codeExpire';
static const typeheretoreply = 'typeheretoreply'; static const typeheretoreply = 'typeheretoreply';
static const favorite = 'favorite';
static const searchfromchat = 'searchfromchat';
} }

@ -36,7 +36,7 @@ class ChatBubble extends StatelessWidget {
alignment: isCurrentUser ? Alignment.centerRight : Alignment.centerLeft, alignment: isCurrentUser ? Alignment.centerRight : Alignment.centerLeft,
child: DecoratedBox( child: DecoratedBox(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: MyColors.white,
gradient: isCurrentUser gradient: isCurrentUser
? null ? null
: const LinearGradient( : const LinearGradient(
@ -89,7 +89,7 @@ class ChatBubble extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : Colors.white.withOpacity(0.7)), dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7),),
if (isCurrentUser) 5.width, if (isCurrentUser) 5.width,
if (isCurrentUser) if (isCurrentUser)
Icon( Icon(

@ -1,8 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart';
@ -19,30 +17,34 @@ import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:swipe_to/swipe_to.dart'; import 'package:swipe_to/swipe_to.dart';
class ChatDetailScreen extends StatelessWidget { class ChatDetailScreen extends StatelessWidget {
// ignore: prefer_const_constructors_in_immutables
ChatDetailScreen({Key? key}) : super(key: key); ChatDetailScreen({Key? key}) : super(key: key);
dynamic userDetails; dynamic userDetails;
late ChatProviderModel data; late ChatProviderModel data;
ScrollController scrollController = ScrollController();
RefreshController _refreshController = RefreshController(initialRefresh: false);
void getMoreChat() async { final RefreshController _refreshController = RefreshController(initialRefresh: false);
void getMoreChat() async {
if (userDetails != null) { if (userDetails != null) {
data.paginationVal = data.paginationVal + 10; data.paginationVal = data.paginationVal + 10;
data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true); data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false);
} }
await Future.delayed(Duration(milliseconds: 1000)); await Future.delayed(const Duration(milliseconds: 1000));
_refreshController.refreshCompleted(); _refreshController.loadComplete();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
userDetails = ModalRoute.of(context)!.settings.arguments; userDetails = ModalRoute.of(context)!.settings.arguments;
data = Provider.of<ChatProviderModel>(context, listen: false); data = Provider.of<ChatProviderModel>(context, listen: false);
if (userDetails != null) data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: 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);
return Scaffold( return Scaffold(
backgroundColor: const Color(0xFFF8F8F8), backgroundColor: const Color(0xFFF8F8F8),
appBar: AppBarWidget(context, title: userDetails["targetUser"].userName, showHomeButton: false, image: userDetails["targetUser"].image), appBar: AppBarWidget(context, title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, image: userDetails["targetUser"].image),
body: Consumer<ChatProviderModel>( body: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) { builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return (m.isLoading return (m.isLoading
@ -52,18 +54,23 @@ class ChatDetailScreen extends StatelessWidget {
Expanded( Expanded(
flex: 2, flex: 2,
child: SmartRefresher( child: SmartRefresher(
enablePullDown: true, enablePullDown: false,
enablePullUp: false, enablePullUp: true,
onLoading: () {
getMoreChat();
},
header: const MaterialClassicHeader( header: const MaterialClassicHeader(
color: MyColors.gradiantEndColor, color: MyColors.gradiantEndColor,
), ),
controller: _refreshController, controller: _refreshController,
onRefresh: getMoreChat, reverse: true,
child: ListView.builder( child: ListView.builder(
controller: scrollController, controller: m.scrollController,
shrinkWrap: true, shrinkWrap: true,
physics: const BouncingScrollPhysics(),
reverse: true,
itemCount: m.userChatHistory.length, itemCount: m.userChatHistory.length,
padding: EdgeInsets.zero, padding: const EdgeInsets.only(top: 20),
itemBuilder: (BuildContext context, int i) { itemBuilder: (BuildContext context, int i) {
return SwipeTo( return SwipeTo(
iconColor: MyColors.lightGreenColor, iconColor: MyColors.lightGreenColor,
@ -98,7 +105,9 @@ class ChatDetailScreen extends StatelessWidget {
height: 80, height: 80,
color: MyColors.black.withOpacity(0.10), color: MyColors.black.withOpacity(0.10),
child: ListTile( child: ListTile(
title: (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() ? "You" : m.repliedMsg.first.currentUserName.toString()) title: (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString()
? "You"
: m.repliedMsg.first.currentUserName.toString().replaceAll(".", " "))
.toText14(color: MyColors.lightGreenColor), .toText14(color: MyColors.lightGreenColor),
subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.white, maxLine: 2), subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.white, maxLine: 2),
trailing: GestureDetector( trailing: GestureDetector(
@ -138,10 +147,11 @@ class ChatDetailScreen extends StatelessWidget {
height: 200, height: 200,
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: FileImage( image: FileImage(
m.selectedFile, m.selectedFile,
), ),
fit: BoxFit.cover), fit: BoxFit.cover,
),
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(
Radius.circular(0), Radius.circular(0),
), ),

@ -1,224 +1,120 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/api/chat/chat_provider_model.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/classes/colors.dart';
import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.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/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_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/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/ui/chat/chat_home_screen.dart';
import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart';
import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/items_for_sale.dart';
import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/my_posted_ads_fragment.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:sizer/sizer.dart';
class ChatHomeScreen extends StatefulWidget { class ChatHome extends StatefulWidget {
const ChatHomeScreen({Key? key}) : super(key: key); const ChatHome({Key? key}) : super(key: key);
@override @override
State<ChatHomeScreen> createState() => _ChatHomeScreenState(); State<ChatHome> createState() => _ChatHomeState();
} }
class _ChatHomeScreenState extends State<ChatHomeScreen> { class _ChatHomeState extends State<ChatHome> {
TextEditingController search = TextEditingController(); int tabIndex = 0;
PageController controller = PageController();
late ChatProviderModel data; late ChatProviderModel data;
@override @override
void initState() { void initState() {
// TODO: implement initState
super.initState(); super.initState();
data = Provider.of<ChatProviderModel>(context, listen: false); data = Provider.of<ChatProviderModel>(context, listen: false);
data.getUserAutoLoginToken().whenComplete(() { data.getUserAutoLoginToken().then((value) {
data.getUserRecentChats(); data.getUserRecentChats();
}); });
} }
@override @override
void dispose() { void dispose() {
data.clearAll();
data.hubConnection.stop();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: MyColors.white,
appBar: AppBarWidget(context, title: LocaleKeys.mychats.tr(), showHomeButton: false), appBar: AppBarWidget(
body: Consumer<ChatProviderModel>(builder: (BuildContext context, ChatProviderModel m, Widget? child) { context,
return m.isLoading title: LocaleKeys.chat.tr(),
? ChatHomeShimmer() showHomeButton: true,
: ListView( ),
shrinkWrap: true, body: Column(
physics: const AlwaysScrollableScrollPhysics(), children: <Widget>[
children: [ Container(
Padding( padding: const EdgeInsets.only(left: 21, right: 21, top: 16, bottom: 16),
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 20), decoration: const BoxDecoration(
child: TextField( borderRadius: BorderRadius.only(
onChanged: (String val) { bottomLeft: Radius.circular(25),
m.filter(val); bottomRight: Radius.circular(25),
}, ),
decoration: InputDecoration( gradient: LinearGradient(
border: InputBorder.none, transform: GradientRotation(.83),
focusedBorder: InputBorder.none, begin: Alignment.topRight,
enabledBorder: OutlineInputBorder( end: Alignment.bottomLeft,
borderRadius: BorderRadius.circular(5), colors: [
borderSide: const BorderSide( MyColors.gradiantEndColor,
color: Color(0xFFE5E5E5), MyColors.gradiantStartColor,
),
),
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
hintText: "Search from chat",
hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic),
filled: true,
fillColor: const Color(0xFFF7F7F7),
),
),
),
if (m.searchedChats != null)
ListView.separated(
itemCount: m.searchedChats!.length,
padding: const EdgeInsets.only(top: 20),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: ListTile(
leading: Stack(
children: [
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red,
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
),
),
)
],
),
title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor),
// subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor),
trailing: SizedBox(
width: 60,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
if (m.searchedChats![index].unreadMessageCount! > 0)
Flexible(
child: Container(
padding: EdgeInsets.zero,
alignment: Alignment.centerRight,
width: 18,
height: 18,
decoration: const BoxDecoration(
color: MyColors.redColor,
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
child: (m.searchedChats![index].unreadMessageCount!.toString())
.toText10(
color: MyColors.white,
)
.center,
),
),
Flexible(
child: IconButton(
alignment: Alignment.centerRight,
padding: EdgeInsets.zero,
icon: Icon(m.searchedChats![index].isFav! ? Icons.star : Icons.star_border),
color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color,
onPressed: () {
if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!);
if (!m.searchedChats![index].isFav!) m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!);
},
),
)
],
),
),
minVerticalPadding: 0,
onTap: () {
Navigator.pushNamed(
context,
AppRoutes.chatDetailed,
arguments: {"targetUser": m.searchedChats![index]},
).then((value) {
m.clearSelections();
});
},
onLongPress: () {},
),
);
},
separatorBuilder: (BuildContext context, int index) => const Padding(
padding: EdgeInsets.only(right: 10, left: 70),
child: Divider(
color: Color(0xFFE5E5E5),
),
),
),
], ],
); ),
}),
floatingActionButton: FloatingActionButton(
child: Container(
width: 60,
height: 60,
decoration: const BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
transform: GradientRotation(.46),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
), ),
), child: Row(
child: const Icon( children: [myTab(LocaleKeys.mychats.tr(), 0), myTab(LocaleKeys.favorite.tr(), 1)],
Icons.add,
size: 30,
color: MyColors.white,
),
),
onPressed: () async {
showMyBottomSheet(
context,
callBackFunc: () {},
child: SearchEmployeeBottomSheet(
title: LocaleKeys.searchForEmployee.tr(),
apiMode: LocaleKeys.delegate.tr(),
fromChat: true,
onSelectEmployee: (_selectedEmployee) {
setState(() {});
},
), ),
); ),
}, PageView(
controller: controller,
physics: const NeverScrollableScrollPhysics(),
onPageChanged: (int pageIndex) {
setState(() {
tabIndex = pageIndex;
});
},
children: <Widget>[ChatHomeScreen(), ChatFavoriteUsersScreen()],
).expanded,
],
), ),
); );
} }
Widget myTab(String title, int index) {
bool isSelected = (index == tabIndex);
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
title.toText12(color: isSelected ? MyColors.white : MyColors.white.withOpacity(.74), isCenter: true),
4.height,
Container(
height: 8,
width: 8,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isSelected ? MyColors.white : Colors.transparent,
),
).onPress(() {
setState(() {
// showFabOptions = true;
});
})
],
).onPress(() {
controller.jumpToPage(index);
}).expanded;
}
} }

@ -0,0 +1,222 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
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/config/routes.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/widgets/bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart';
class ChatHomeScreen extends StatefulWidget {
@override
State<ChatHomeScreen> createState() => _ChatHomeScreenState();
}
class _ChatHomeScreenState extends State<ChatHomeScreen> {
TextEditingController search = TextEditingController();
@override
void dispose() {
super.dispose();
search.clear();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyColors.white,
body: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return m.isLoading
? ChatHomeShimmer()
: ListView(
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
child: TextField(
controller: m.search,
onChanged: (String val) {
m.filter(val);
},
decoration: InputDecoration(
border: fieldBorder(radius: 5, color: 0xFFE5E5E5),
focusedBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5),
enabledBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5),
contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
hintText: LocaleKeys.searchfromchat.tr(),
hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic),
filled: true,
fillColor: const Color(0xFFF7F7F7),
suffixIcon: m.search.text.isNotEmpty
? IconButton(
onPressed: () {
m.clearSelections();
},
icon: const Icon(
Icons.clear,
size: 22,
),
color: MyColors.redA3Color,
)
: null,
),
),
),
if (m.searchedChats != null)
ListView.separated(
itemCount: m.searchedChats!.length,
padding: const EdgeInsets.only(bottom: 80),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: ListTile(
leading: Stack(
children: <Widget>[
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red,
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
),
),
)
],
),
title: (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor),
// subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor),
trailing: SizedBox(
width: 60,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
if (m.searchedChats![index].unreadMessageCount! > 0)
Flexible(
child: Container(
padding: EdgeInsets.zero,
alignment: Alignment.centerRight,
width: 18,
height: 18,
decoration: const BoxDecoration(
color: MyColors.redColor,
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
child: (m.searchedChats![index].unreadMessageCount!.toString())
.toText10(
color: MyColors.white,
)
.center,
),
),
Flexible(
child: IconButton(
alignment: Alignment.centerRight,
padding: EdgeInsets.zero,
icon: Icon(m.searchedChats![index].isFav! ? Icons.star_sharp : Icons.star_border),
color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color,
onPressed: () {
if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!);
if (!m.searchedChats![index].isFav!) m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!);
},
),
)
],
),
),
minVerticalPadding: 0,
onTap: () {
Navigator.pushNamed(
context,
AppRoutes.chatDetailed,
arguments: {"targetUser": m.searchedChats![index], "isNewChat": false},
).then((Object? value) {
m.clearSelections();
m.notifyListeners();
});
},
),
);
},
separatorBuilder: (BuildContext context, int index) => const Padding(
padding: EdgeInsets.only(right: 10, left: 70),
child: Divider(
color: Color(0xFFE5E5E5),
),
),
),
],
);
},
),
floatingActionButton: FloatingActionButton(
child: Container(
width: 60,
height: 60,
decoration: const BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
transform: GradientRotation(.46),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
),
),
child: const Icon(
Icons.add,
size: 30,
color: MyColors.white,
),
),
onPressed: () async {
showMyBottomSheet(
context,
callBackFunc: () {},
child: SearchEmployeeBottomSheet(
title: LocaleKeys.searchForEmployee.tr(),
apiMode: LocaleKeys.delegate.tr(),
fromChat: true,
onSelectEmployee: (_selectedEmployee) {},
),
);
},
),
);
}
OutlineInputBorder fieldBorder({required double radius, required int color}) {
return OutlineInputBorder(
borderRadius: BorderRadius.circular(radius),
borderSide: BorderSide(
color: Color(color),
),
);
}
}

@ -0,0 +1,103 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
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/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart';
class ChatFavoriteUsersScreen extends StatelessWidget {
const ChatFavoriteUsersScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyColors.white,
body: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) {
if (m.isLoading) {
return ChatHomeShimmer();
} else {
return m.favUsersList != null && m.favUsersList.isNotEmpty
? ListView.separated(
itemCount: m.favUsersList!.length,
padding: const EdgeInsets.only(top: 20),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: ListTile(
leading: Stack(
children: [
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: m.favUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red,
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
),
),
)
],
),
title: (m.favUsersList![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor),
trailing: IconButton(
alignment: Alignment.centerRight,
padding: EdgeInsets.zero,
icon: Icon(m.favUsersList![index].isFav! ? Icons.star : Icons.star_border),
color: m.favUsersList![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color,
onPressed: () {
if (m.favUsersList![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.favUsersList![index].id!);
},
),
minVerticalPadding: 0,
onTap: () {
Navigator.pushNamed(
context,
AppRoutes.chatDetailed,
arguments: {"targetUser": m.favUsersList![index], "isNewChat": false},
).then(
(Object? value) {
m.clearSelections();
},
);
},
),
);
},
separatorBuilder: (BuildContext context, int index) => const Padding(
padding: EdgeInsets.only(right: 10, left: 70),
child: Divider(
color: Color(
0xFFE5E5E5,
),
),
),
)
: Column(
children: <Widget>[
Utils.getNoDataWidget(context).expanded,
],
);
}
},
),
);
}
}

@ -233,7 +233,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
Navigator.pushNamed( Navigator.pushNamed(
context, context,
AppRoutes.chatDetailed, AppRoutes.chatDetailed,
arguments: {"targetUser": chatUsersList![index]}, arguments: {"targetUser": chatUsersList![index], "isNewChat": true},
); );
}, },
onLongPress: () {}, onLongPress: () {},

@ -48,7 +48,7 @@ class ImageOptions {
allowedExtensions: ['jpg', 'jpeg ', 'pdf', 'txt', 'docx', 'doc', 'pptx', 'xlsx', 'png', 'rar', 'zip', 'xls'], allowedExtensions: ['jpg', 'jpeg ', 'pdf', 'txt', 'docx', 'doc', 'pptx', 'xlsx', 'png', 'rar', 'zip', 'xls'],
); );
List<File> files = result!.paths.map((path) => File(path!)).toList(); List<File> files = result!.paths.map((path) => File(path!)).toList();
image(result!.files.first.path.toString(), files.first); image(result.files.first.path.toString(), files.first);
}, },
), ),
); );

Loading…
Cancel
Save