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": "تَحَقّق",
"resend": "إعادة إرسال",
"codeExpire": "انتهت صلاحية رمز التحقق",
"typeheretoreply": "اكتب هنا للرد"
"typeheretoreply": "اكتب هنا للرد",
"favorite" : "أُفضله",
"searchfromchat": "البحث من الدردشة"
}

@ -498,5 +498,8 @@
"resend": "Resend",
"codeExpire": "The verification code has been expired",
"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_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 3A359E86ZF;
DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Mohemm;
@ -520,7 +520,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 3A359E86ZF;
DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Mohemm;
@ -549,7 +549,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 3A359E86ZF;
DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Mohemm;

@ -1,11 +1,12 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.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/app_state/app_state.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/make_user_favotire_unfavorite_chat_model.dart' as fav;
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:logger/logger.dart' as L;
import 'package:uuid/uuid.dart';
class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
ScrollController scrollController = ScrollController();
TextEditingController message = TextEditingController();
TextEditingController search = TextEditingController();
List<SingleUserChatModel> userChatHistory = [];
List<ChatUser>? pChatHistory, searchedChats;
late HubConnection hubConnection;
L.Logger logger = L.Logger();
TextEditingController message = TextEditingController();
bool isLoading = true;
bool isChatScreenActive = false;
late File selectedFile;
@ -33,8 +35,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
String sFileType = "";
bool isMsgReply = false;
List<SingleUserChatModel> repliedMsg = [];
List<ChatUser> favUsersList = [];
int paginationVal = 0;
//Scroll
bool _firstAutoscrollExecuted = false;
bool _shouldAutoscroll = false;
Future<void> getUserAutoLoginToken() async {
String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString();
Response response =
@ -59,51 +66,52 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}",
token: AppState().chatDetails!.response!.token,
);
logger.d(AppState().chatDetails!.response!.token);
ChatUserModel recentChat = userToList(response.body);
Response favRes = await ApiClient().getJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}",
token: AppState().chatDetails!.response!.token,
);
print("============================== Fav Response =====================================");
ChatUserModel favUsersList = userToList(favRes.body);
for (var user in recentChat.response!) {
for (var favUser in favUsersList.response!) {
logger.d(favUser.isFav);
ChatUserModel favUList = userToList(favRes.body);
if (favUList.response != null) {
favUsersList = favUList.response!;
favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
for (dynamic user in recentChat.response!) {
for (dynamic favUser in favUList.response!) {
if (user.id == favUser.id) {
user.isFav = favUser.isFav;
}
}
}
}
pChatHistory = recentChat.response;
pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
searchedChats = pChatHistory;
isLoading = false;
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;
if (!loadMore) paginationVal = 0;
logger.d(paginationVal);
isChatScreenActive = true;
Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal",
token: AppState().chatDetails!.response!.token,
);
logger.d(response.body);
if (response.statusCode == 204) {
if (!loadMore) userChatHistory = [];
if (isNewChat) {
userChatHistory = [];
} else if (loadMore) {
// userChatHistory = [];
Utils.showToast("No More Data To Load");
}
} else {
if (loadMore) {
List<SingleUserChatModel> temp = getSingleUserChatModel(response.body);
userChatHistory.insertAll(0, temp);
List<SingleUserChatModel> temp = getSingleUserChatModel(response.body).reversed.toList();
userChatHistory.addAll(temp);
} else {
userChatHistory = getSingleUserChatModel(response.body);
userChatHistory = getSingleUserChatModel(response.body).reversed.toList();
}
}
isLoading = false;
@ -127,19 +135,22 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} else {
result = [];
}
} catch (e) {}
} catch (e) {
if (kDebugMode) {
print(e);
}
}
;
return result;
}
Future<void> buildHubConnection() async {
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)
.withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000])
.configureLogging(
Logger("Logs Enabled"),
)
.build();
.withAutomaticReconnect(
retryDelays: <int>[2000, 5000, 10000, 20000],
).build();
hubConnection.onclose(
({Exception? error}) {},
);
@ -153,24 +164,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
await hubConnection.start();
hubConnection.on("OnUpdateUserStatusAsync", changeStatus);
hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
// hubConnection.on("OnSeenChatUserAsync", onChatSeen);
hubConnection.on("OnUserTypingAsync", onUserTyping);
//hubConnection.on("OnUserTypingAsync", onUserTyping);
// hubConnection.on("OnUserCountAsync", userCountAsync);
// hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
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) {
@ -178,7 +179,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
for (dynamic cItem in items[0]) {
for (SingleUserChatModel chat in userChatHistory) {
if (chat.userChatHistoryId.toString() == cItem["userChatHistoryId"].toString()) {
logger.d(jsonEncode(chat));
chat.isSeen = cItem["isSeen"];
chat.isDelivered = cItem["isDelivered"];
notifyListeners();
@ -187,9 +187,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
}
void userCountAsync(List<Object?>? args) {
List items = args!.toList();
print("---------------------------------User Count Async -------------------------------------");
void onChatSeen(List<Object?>? args) {
dynamic items = args!.toList();
logger.d("---------------------------------Chat Seen -------------------------------------");
logger.d(items);
// for (var user in searchedChats!) {
// if (user.id == items.first["id"]) {
@ -199,9 +199,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
// 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) {
List items = args!.toList();
dynamic items = args!.toList();
if (kDebugMode) {
print("---------------------------------Update Chat History Windows Async -------------------------------------");
}
logger.d(items);
// for (var user in searchedChats!) {
// if (user.id == items.first["id"]) {
@ -212,20 +226,24 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
void chatNotDelivered(List<Object?>? args) {
List items = args!.toList();
dynamic items = args!.toList();
if (kDebugMode) {
print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------");
}
logger.d(items);
// for (var user in searchedChats!) {
// if (user.id == items.first["id"]) {
// user.userStatus = items.first["userStatus"];
// }
// }
// notifyListeners();
// notifyListeners();2
}
void changeStatus(List<Object?>? args) {
if (kDebugMode) {
// print("================= Status Online // Offline ====================");
List items = args!.toList();
}
dynamic items = args!.toList();
// logger.d(items);
for (ChatUser user in searchedChats!) {
if (user.id == items.first["id"]) {
@ -251,6 +269,7 @@ 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!) {
@ -261,15 +280,20 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
data.first.currentUserId = temp.first.targetUserId;
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();
logger.d(isChatScreenActive);
// if (isChatScreenActive) scrollDown();
// if (isChatScreenActive) scrollToBottom();
}
void onUserTyping(List<Object?>? parameters) {
print("==================== Typing Active ==================");
logger.d(parameters);
// print("==================== Typing Active ==================");
// logger.d(parameters);
for (ChatUser user in searchedChats!) {
if (user.id == parameters![1] && parameters[0] == true) {
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(
{required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async {
Uuid uuid = const Uuid();
@ -390,7 +405,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
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()}"}';
await hubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]);
userChatHistory.add(data);
userChatHistory.insert(0, data);
isFileSelected = false;
isMsgReply = false;
sFileType = "";
@ -537,7 +554,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
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);
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);
fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
if (favoriteChatUser.response != null) {
for (var user in searchedChats!) {
for (ChatUser user in searchedChats!) {
if (user.id == favoriteChatUser.response!.targetUserId!) {
user.isFav = favoriteChatUser.response!.isFav;
favUsersList.add(user);
}
}
}
@ -566,11 +584,26 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
user.isFav = favoriteChatUser.response!.isFav;
}
}
favUsersList.removeWhere((ChatUser element) => element.id == targetUserID);
}
notifyListeners();
}
void clearSelections() {
searchedChats = pChatHistory;
search.clear();
isChatScreenActive = false;
paginationVal = 0;
message.text = '';
isFileSelected = false;
repliedMsg = [];
sFileType = "";
notifyListeners();
}
void clearAll() {
searchedChats = pChatHistory;
search.clear();
isChatScreenActive = false;
paginationVal = 0;
message.text = '';
@ -578,4 +611,29 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
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,
);
}
}

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

@ -514,7 +514,9 @@ class CodegenLoader extends AssetLoader{
"verification": "تَحَقّق",
"resend": "إعادة إرسال",
"codeExpire": "انتهت صلاحية رمز التحقق",
"typeheretoreply": "اكتب هنا للرد"
"typeheretoreply": "اكتب هنا للرد",
"favorite": "أُفضله",
"searchfromchat": "البحث من الدردشة"
};
static const Map<String,dynamic> en_US = {
"mohemm": "Mohemm",
@ -1016,7 +1018,9 @@ static const Map<String,dynamic> en_US = {
"resend": "Resend",
"codeExpire": "The verification code has been expired",
"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};
}

@ -485,5 +485,7 @@ abstract class LocaleKeys {
static const resend = 'resend';
static const codeExpire = 'codeExpire';
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,
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: MyColors.white,
gradient: isCurrentUser
? null
: const LinearGradient(
@ -89,7 +89,7 @@ class ChatBubble extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
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)
Icon(

@ -1,8 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
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';
@ -19,30 +17,34 @@ import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:swipe_to/swipe_to.dart';
class ChatDetailScreen extends StatelessWidget {
// ignore: prefer_const_constructors_in_immutables
ChatDetailScreen({Key? key}) : super(key: key);
dynamic userDetails;
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) {
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));
_refreshController.refreshCompleted();
await Future.delayed(const Duration(milliseconds: 1000));
_refreshController.loadComplete();
}
@override
Widget build(BuildContext context) {
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);
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(
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>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return (m.isLoading
@ -52,18 +54,23 @@ class ChatDetailScreen extends StatelessWidget {
Expanded(
flex: 2,
child: SmartRefresher(
enablePullDown: true,
enablePullUp: false,
enablePullDown: false,
enablePullUp: true,
onLoading: () {
getMoreChat();
},
header: const MaterialClassicHeader(
color: MyColors.gradiantEndColor,
),
controller: _refreshController,
onRefresh: getMoreChat,
reverse: true,
child: ListView.builder(
controller: scrollController,
controller: m.scrollController,
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
reverse: true,
itemCount: m.userChatHistory.length,
padding: EdgeInsets.zero,
padding: const EdgeInsets.only(top: 20),
itemBuilder: (BuildContext context, int i) {
return SwipeTo(
iconColor: MyColors.lightGreenColor,
@ -98,7 +105,9 @@ class ChatDetailScreen extends StatelessWidget {
height: 80,
color: MyColors.black.withOpacity(0.10),
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),
subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.white, maxLine: 2),
trailing: GestureDetector(
@ -141,7 +150,8 @@ class ChatDetailScreen extends StatelessWidget {
image: FileImage(
m.selectedFile,
),
fit: BoxFit.cover),
fit: BoxFit.cover,
),
borderRadius: const BorderRadius.all(
Radius.circular(0),
),

@ -1,195 +1,70 @@
import 'dart:convert';
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/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/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/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:sizer/sizer.dart';
class ChatHomeScreen extends StatefulWidget {
const ChatHomeScreen({Key? key}) : super(key: key);
class ChatHome extends StatefulWidget {
const ChatHome({Key? key}) : super(key: key);
@override
State<ChatHomeScreen> createState() => _ChatHomeScreenState();
State<ChatHome> createState() => _ChatHomeState();
}
class _ChatHomeScreenState extends State<ChatHomeScreen> {
TextEditingController search = TextEditingController();
class _ChatHomeState extends State<ChatHome> {
int tabIndex = 0;
PageController controller = PageController();
late ChatProviderModel data;
@override
void initState() {
// TODO: implement initState
super.initState();
data = Provider.of<ChatProviderModel>(context, listen: false);
data.getUserAutoLoginToken().whenComplete(() {
data.getUserAutoLoginToken().then((value) {
data.getUserRecentChats();
});
}
@override
void dispose() {
data.clearAll();
data.hubConnection.stop();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBarWidget(context, title: LocaleKeys.mychats.tr(), showHomeButton: false),
body: Consumer<ChatProviderModel>(builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return m.isLoading
? ChatHomeShimmer()
: ListView(
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 20),
child: TextField(
onChanged: (String val) {
m.filter(val);
},
decoration: InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: const BorderSide(
color: Color(0xFFE5E5E5),
),
),
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),
),
),
),
)
],
backgroundColor: MyColors.white,
appBar: AppBarWidget(
context,
title: LocaleKeys.chat.tr(),
showHomeButton: true,
),
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,
body: Column(
children: <Widget>[
if (m.searchedChats![index].unreadMessageCount! > 0)
Flexible(
child: Container(
padding: EdgeInsets.zero,
alignment: Alignment.centerRight,
width: 18,
height: 18,
Container(
padding: const EdgeInsets.only(left: 21, right: 21, top: 16, bottom: 16),
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!);
},
),
)
],
),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
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),
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
@ -198,27 +73,48 @@ class _ChatHomeScreenState extends State<ChatHomeScreen> {
],
),
),
child: const Icon(
Icons.add,
size: 30,
color: MyColors.white,
child: Row(
children: [myTab(LocaleKeys.mychats.tr(), 0), myTab(LocaleKeys.favorite.tr(), 1)],
),
),
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(
context,
AppRoutes.chatDetailed,
arguments: {"targetUser": chatUsersList![index]},
arguments: {"targetUser": chatUsersList![index], "isNewChat": true},
);
},
onLongPress: () {},

@ -48,7 +48,7 @@ class ImageOptions {
allowedExtensions: ['jpg', 'jpeg ', 'pdf', 'txt', 'docx', 'doc', 'pptx', 'xlsx', 'png', 'rar', 'zip', 'xls'],
);
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