You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mohemm-flutter-app/lib/api/chat/chat_provider_model.dart

694 lines
24 KiB
Dart

3 years ago
import 'dart:async';
import 'dart:convert';
import 'dart:io';
3 years ago
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart';
3 years ago
import 'package:logger/logger.dart' as L;
import 'package:logging/logging.dart';
import 'package:mohem_flutter_app/api/api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/consts.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart';
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:signalr_netcore/signalr_client.dart';
import 'package:uuid/uuid.dart';
class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
3 years ago
ScrollController scrollController = ScrollController();
TextEditingController message = TextEditingController();
TextEditingController search = TextEditingController();
List<SingleUserChatModel> userChatHistory = [];
List<ChatUser>? pChatHistory, searchedChats;
late HubConnection hubConnection;
L.Logger logger = L.Logger();
bool hubConInitialized = false;
3 years ago
bool isLoading = true;
bool isChatScreenActive = false;
late File selectedFile;
bool isFileSelected = false;
String sFileType = "";
bool isMsgReply = false;
List<SingleUserChatModel> repliedMsg = [];
List<ChatUser> favUsersList = [];
int paginationVal = 0;
3 years ago
//Scroll
bool _firstAutoscrollExecuted = false;
bool _shouldAutoscroll = false;
Future<void> getUserAutoLoginToken() async {
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin",
{
"employeeNumber": int.parse(
AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG"
},
);
login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(
response.body,
);
if (userLoginResponse.response != null) {
hubConInitialized = true;
AppState().setchatUserDetails = userLoginResponse;
await buildHubConnection();
} else {
Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr");
return;
}
}
Future<List<ChatUser>?> getChatMemberFromSearch(String sName, int cUserId) async {
Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSearchMember}$sName/$cUserId",
token: AppState().chatDetails!.response!.token,
);
return searchUserJsonModel(response.body);
}
List<ChatUser> searchUserJsonModel(String str) => List<ChatUser>.from(json.decode(str).map((x) => ChatUser.fromJson(x)));
void getUserRecentChats() async {
Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}",
token: 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,
);
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;
}
}
}
}
3 years ago
pChatHistory = recentChat.response == null ? [] : recentChat.response;
if (pChatHistory != null) pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
searchedChats = pChatHistory;
isLoading = false;
notifyListeners();
}
Future GetUserChatHistoryNotDeliveredAsync(int userId) async {
await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]);
return "";
}
void getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async {
isLoading = true;
if (isNewChat) userChatHistory = [];
if (!loadMore) paginationVal = 0;
isChatScreenActive = true;
Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal",
token: AppState().chatDetails!.response!.token,
);
if (response.statusCode == 204) {
if (isNewChat) {
userChatHistory = [];
} else if (loadMore) {
// userChatHistory = [];
Utils.showToast("No More Data To Load");
}
} else {
if (loadMore) {
List<SingleUserChatModel> temp = getSingleUserChatModel(response.body).reversed.toList();
userChatHistory.addAll(temp);
} else {
3 years ago
userChatHistory = getSingleUserChatModel(response.body).reversed.toList();
}
}
isLoading = false;
await GetUserChatHistoryNotDeliveredAsync(senderUID);
notifyListeners();
}
void updateUserChatHistoryStatusAsync(List data) {
hubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]);
}
List<SingleUserChatModel> getSingleUserChatModel(String str) => List<SingleUserChatModel>.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x)));
ChatUserModel userToList(String str) => ChatUserModel.fromJson(json.decode(str));
Future<dynamic> uploadAttachments(String userId, File file) async {
dynamic result;
dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}'));
request.fields.addAll({'userId': userId, 'fileSource': '1'});
request.files.add(await MultipartFile.fromPath('files', file.path));
request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'});
try {
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
result = jsonDecode(await response.stream.bytesToString());
} else {
result = [];
}
} catch (e) {
if (kDebugMode) {
print(e);
}
}
;
return result;
}
Future<void> buildHubConnection() async {
HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
hubConnection = HubConnectionBuilder()
.withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
.withAutomaticReconnect(
retryDelays: <int>[2000, 5000, 10000, 20000],
)
.configureLogging(
Logger("Loggin"),
)
.build();
hubConnection.onclose(
({Exception? error}) {},
);
hubConnection.onreconnecting(
({Exception? error}) {},
);
hubConnection.onreconnected(
({String? connectionId}) {},
);
if (hubConnection.state != HubConnectionState.Connected) {
await hubConnection.start();
hubConnection.on("OnUpdateUserStatusAsync", changeStatus);
hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
3 years ago
// hubConnection.on("OnSeenChatUserAsync", onChatSeen);
//hubConnection.on("OnUserTypingAsync", onUserTyping);
hubConnection.on("OnUserCountAsync", userCountAsync);
hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
}
}
void updateUserChatStatus(List<Object?>? args) {
dynamic items = args!.toList();
for (dynamic cItem in items[0]) {
for (SingleUserChatModel chat in userChatHistory) {
if (chat.userChatHistoryId.toString() == cItem["userChatHistoryId"].toString()) {
chat.isSeen = cItem["isSeen"];
chat.isDelivered = cItem["isDelivered"];
notifyListeners();
}
}
}
}
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"]) {
// user.userStatus = items.first["userStatus"];
// }
// }
// notifyListeners();
}
void userCountAsync(List<Object?>? args) {
3 years ago
dynamic items = args!.toList();
// logger.d(items);
//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) {
3 years ago
dynamic items = args!.toList();
print("---------------------------------Update Chat History Windows Async -------------------------------------");
logger.d(items);
// for (var user in searchedChats!) {
// if (user.id == items.first["id"]) {
// user.userStatus = items.first["userStatus"];
// }
// }
// notifyListeners();
}
void chatNotDelivered(List<Object?>? args) {
3 years ago
dynamic items = args!.toList();
for (dynamic item in items[0]) {
dynamic data = [
{
"userChatHistoryId": item["userChatHistoryId"],
"TargetUserId": item["targetUserId"],
"isDelivered": true,
"isSeen": true,
}
];
updateUserChatHistoryStatusAsync(data);
3 years ago
}
3 years ago
logger.d(items);
// for (var user in searchedChats!) {
// if (user.id == items.first["id"]) {
// user.userStatus = items.first["userStatus"];
// }
// }
3 years ago
// notifyListeners();2
}
void changeStatus(List<Object?>? args) {
3 years ago
if (kDebugMode) {
// print("================= Status Online // Offline ====================");
}
3 years ago
dynamic items = args!.toList();
3 years ago
// logger.d(items);
for (ChatUser user in searchedChats!) {
if (user.id == items.first["id"]) {
user.userStatus = items.first["userStatus"];
}
}
notifyListeners();
}
void filter(String value) async {
List<ChatUser>? tmp = [];
if (value.isEmpty || value == "") {
tmp = pChatHistory;
} else {
for (ChatUser element in pChatHistory!) {
if (element.userName!.toLowerCase().contains(value.toLowerCase())) {
tmp.add(element);
}
}
}
searchedChats = tmp;
notifyListeners();
}
Future<void> onMsgReceived(List<Object?>? parameters) async {
3 years ago
print("msg Received");
List<SingleUserChatModel> data = [];
List<SingleUserChatModel> temp = [];
for (dynamic msg in parameters!) {
data = getSingleUserChatModel(jsonEncode(msg));
temp = getSingleUserChatModel(jsonEncode(msg));
data.first.targetUserId = temp.first.currentUserId;
data.first.targetUserName = temp.first.currentUserName;
data.first.currentUserId = temp.first.targetUserId;
data.first.currentUserName = temp.first.targetUserName;
}
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;
// }
// });
logger.d(jsonEncode(data));
var list = [
{
"userChatHistoryId": data.first.userChatHistoryId,
"TargetUserId": data.first.targetUserId,
"isDelivered": true,
"isSeen": isChatScreenActive ? true : false,
}
];
updateUserChatHistoryStatusAsync(list);
notifyListeners();
3 years ago
// if (isChatScreenActive) scrollToBottom();
}
void onUserTyping(List<Object?>? 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?;
Future.delayed(
const Duration(seconds: 2),
() {
user.isTyping = false;
notifyListeners();
},
);
}
}
notifyListeners();
}
int getFileType(String value) {
switch (value) {
case ".pdf":
return 1;
case ".png":
return 3;
case ".txt":
return 5;
case ".jpg":
return 12;
case ".jpeg":
return 4;
case ".xls":
return 7;
case ".xlsx":
return 7;
case ".doc":
return 6;
case ".docx":
return 6;
case ".ppt":
return 8;
case ".pptx":
return 8;
case ".zip":
return 2;
case ".rar":
return 2;
default:
return 0;
}
}
3 years ago
String getFileTypeDescription(String value) {
switch (value) {
case ".pdf":
return "application/pdf";
case ".png":
return "image/png";
case ".txt":
return "text/plain";
case ".jpg":
return "image/jpg";
case ".jpeg":
return "image/jpeg";
case ".ppt":
return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
case ".pptx":
return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
case ".doc":
return "application/vnd.openxmlformats-officedocument.wordprocessingm";
case ".docx":
return "application/vnd.openxmlformats-officedocument.wordprocessingm";
case ".xls":
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
case ".xlsx":
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
case ".zip":
return "application/octet-stream";
case ".rar":
return "application/octet-stream";
default:
return "";
}
}
Future<void> sendChatToServer(
3 years ago
{required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async {
Uuid uuid = const Uuid();
SingleUserChatModel data = SingleUserChatModel(
chatEventId: chatEventId,
chatSource: 1,
3 years ago
contant: message.text,
contantNo: uuid.v4(),
conversationId: uuid.v4(),
createdDate: DateTime.now(),
currentUserId: AppState().chatDetails!.response!.id,
currentUserName: AppState().chatDetails!.response!.userName,
targetUserId: targetUserId,
targetUserName: targetUserName,
isReplied: false,
fileTypeId: fileTypeId,
userChatReplyResponse: isReply ? UserChatReplyResponse.fromJson(repliedMsg.first.toJson()) : null,
fileTypeResponse: isAttachment
? FileTypeResponse(
fileTypeId: fileTypeId,
fileTypeName: getFileType(getFileExtension(selectedFile.path).toString()),
fileKind: getFileExtension(selectedFile.path),
fileName: selectedFile.path.split("/").last,
fileTypeDescription: getFileTypeDescription(getFileExtension(selectedFile.path).toString()),
)
: null,
);
3 years ago
userChatHistory.insert(0, data);
isFileSelected = false;
isMsgReply = false;
sFileType = "";
message.clear();
notifyListeners();
3 years ago
String chatData =
'{"contant":"$msg","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()}"}';
3 years ago
await hubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]);
}
3 years ago
void sendChatMessage(int targetUserId, String targetUserName, BuildContext context) async {
dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId);
3 years ago
if (contain.isEmpty) {
searchedChats!.add(
ChatUser(
id: targetUserId,
userName: targetUserName,
),
);
notifyListeners();
}
if (!isFileSelected && !isMsgReply) {
logger.d("Normal Text Message");
if (message.text == null || message.text.isEmpty) {
return;
}
sendChatToServer(chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: false, chatReplyId: null, isReply: false);
}
if (isFileSelected && !isMsgReply) {
3 years ago
Utils.showLoading(context);
logger.d("Normal Attachment Message");
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile);
String? ext = getFileExtension(selectedFile.path);
3 years ago
Utils.hideLoading(context);
sendChatToServer(chatEventId: 2, fileTypeId: getFileType(ext.toString()), targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: true, chatReplyId: null, isReply: false);
}
if (!isFileSelected && isMsgReply) {
logger.d("Normal Text Message With Reply");
if (message.text == null || message.text.isEmpty) {
return;
}
sendChatToServer(
chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, chatReplyId: repliedMsg.first.userChatHistoryId, isAttachment: false, isReply: true);
}
if (isFileSelected && isMsgReply) {
logger.d("Attachment Message With Reply");
Utils.showLoading(context);
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile);
String? ext = getFileExtension(selectedFile.path);
Utils.hideLoading(context);
sendChatToServer(
chatEventId: 2,
fileTypeId: getFileType(ext.toString()),
targetUserId: targetUserId,
targetUserName: targetUserName,
isAttachment: true,
chatReplyId: repliedMsg.first.userChatHistoryId,
isReply: true,
);
}
}
void selectImageToUpload(BuildContext context) {
ImageOptions.showImageOptionsNew(context, true, (String image, File file) async {
if (checkFileSize(file.path)) {
selectedFile = file;
isFileSelected = true;
sFileType = getFileExtension(file.path)!;
message.text = file.path.split("/").last;
Navigator.of(context).pop();
} else {
Utils.showToast("Max 1 mb size is allowed to upload");
}
notifyListeners();
});
}
void removeAttachment() {
isFileSelected = false;
sFileType = "";
message.text = '';
notifyListeners();
}
String? getFileExtension(String fileName) {
try {
return "." + fileName.split('.').last;
} catch (e) {
return null;
}
}
bool checkFileSize(String path) {
int fileSizeLimit = 1024;
File f = File(path);
double fileSizeInKB = f.lengthSync() / 1024;
double fileSizeInMB = fileSizeInKB / 1024;
if (fileSizeInKB > fileSizeLimit) {
return false;
} else {
return true;
}
}
String getType(String type) {
switch (type) {
case ".pdf":
return "assets/images/pdf.svg";
case ".png":
return "assets/images/png.svg";
case ".txt":
return "assets/icons/chat/txt.svg";
case ".jpg":
return "assets/images/jpg.svg";
case ".jpeg":
return "assets/images/jpg.svg";
case ".xls":
return "assets/icons/chat/xls.svg";
case ".xlsx":
return "assets/icons/chat/xls.svg";
case ".doc":
return "assets/icons/chat/doc.svg";
case ".docx":
return "assets/icons/chat/doc.svg";
case ".ppt":
return "assets/icons/chat/ppt.svg";
case ".pptx":
return "assets/icons/chat/ppt.svg";
case ".zip":
return "assets/icons/chat/zip.svg";
case ".rar":
return "assets/icons/chat/zip.svg";
default:
return "assets/images/thumb.svg";
}
}
void chatReply(SingleUserChatModel data) {
repliedMsg = [];
data.isReplied = true;
isMsgReply = true;
repliedMsg.add(data);
notifyListeners();
}
void closeMe() {
repliedMsg = [];
isMsgReply = false;
notifyListeners();
}
String dateFormte(DateTime data) {
DateFormat f = DateFormat('hh:mm a dd MMM yyyy');
f.format(data);
return f.format(data);
}
Future<void> favoriteUser({required int userID, required int targetUserID}) async {
Response response =
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 (ChatUser user in searchedChats!) {
if (user.id == favoriteChatUser.response!.targetUserId!) {
user.isFav = favoriteChatUser.response!.isFav;
favUsersList.add(user);
}
}
}
notifyListeners();
}
Future<void> unFavoriteUser({required int userID, required int targetUserID}) async {
Response response = await ApiClient()
.postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/deleteFavUser", {"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!) {
if (user.id == favoriteChatUser.response!.targetUserId!) {
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();
}
3 years ago
void clearAll() {
searchedChats = pChatHistory;
search.clear();
isChatScreenActive = false;
paginationVal = 0;
message.text = '';
isFileSelected = false;
repliedMsg = [];
sFileType = "";
}
3 years ago
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,
);
}
3 years ago
void msgScroll() {
scrollController.animateTo(
scrollController.position.minScrollExtent - 100,
duration: const Duration(milliseconds: 500),
curve: Curves.easeIn,
);
}
}