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/provider/chat_provider_model.dart

1325 lines
44 KiB
Dart

3 years ago
import 'dart:async';
import 'dart:convert';
import 'dart:io';
3 years ago
import 'dart:typed_data';
3 years ago
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart';
import 'package:just_audio/just_audio.dart' as JustAudio;
import 'package:mohem_flutter_app/api/chat/chat_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/encryption.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/chat_user_image_model.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 userLoginToken;
import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav;
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/widgets/image_picker.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:signalr_netcore/hub_connection.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;
String chatCID = '';
bool isLoading = true;
bool isChatScreenActive = false;
int receiverID = 0;
late File selectedFile;
bool isFileSelected = false;
String sFileType = "";
bool isMsgReply = false;
List<SingleUserChatModel> repliedMsg = [];
List<ChatUser> favUsersList = [];
int paginationVal = 0;
bool currentUserTyping = false;
int? cTypingUserId = 0;
3 years ago
//Chat Home Page Counter
int chatUConvCounter = 0;
Future<void> getUserAutoLoginToken() async {
userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken();
if (userLoginResponse.response != null) {
AppState().setchatUserDetails = userLoginResponse;
} else {
AppState().setchatUserDetails = userLoginResponse;
Utils.showToast(
userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr",
);
}
}
Future<void> buildHubConnection() async {
chatHubConnection = await getHubConnection();
await chatHubConnection.start();
if (kDebugMode) {
logger.i("Hub Conn: Startedddddddd");
}
3 years ago
chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
chatHubConnection.on("OnGetChatConversationCount", onNewChatConversion);
}
Future<HubConnection> getHubConnection() async {
HubConnection hub;
HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
hub = HubConnectionBuilder()
.withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
.withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
return hub;
}
void registerEvents() {
chatHubConnection.on("OnUpdateUserStatusAsync", changeStatus);
3 years ago
// chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
chatHubConnection.on("OnSubmitChatAsync", OnSubmitChatAsync);
chatHubConnection.on("OnUserTypingAsync", onUserTyping);
chatHubConnection.on("OnUserCountAsync", userCountAsync);
// chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
if (kDebugMode) {
logger.i("All listeners registered");
}
}
void getUserRecentChats() async {
if (chatHubConnection.state != HubConnectionState.Connected) {
getUserAutoLoginToken().whenComplete(() async {
await buildHubConnection();
getUserRecentChats();
});
return;
}
ChatUserModel recentChat = await ChatApiClient().getRecentChats();
ChatUserModel favUList = await ChatApiClient().getFavUsers();
if (favUList.response != null && recentChat.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;
await invokeUserChatHistoryNotDeliveredAsync(
userId: int.parse(
AppState().chatDetails!.response!.id.toString(),
),
);
3 years ago
sort();
notifyListeners();
if (searchedChats!.isNotEmpty || favUsersList.isNotEmpty) {
3 years ago
getUserImages();
}
}
Future invokeUserChatHistoryNotDeliveredAsync({required int userId}) async {
await chatHubConnection.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;
receiverID = receiverUID;
Response response = await ChatApiClient().getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal);
if (response.statusCode == 204) {
if (isNewChat) {
userChatHistory = [];
} else if (loadMore) {
Utils.showToast("No More Data To Load");
}
} else {
if (loadMore) {
List<SingleUserChatModel> temp = getSingleUserChatModel(response.body).reversed.toList();
userChatHistory.addAll(temp);
} else {
userChatHistory = getSingleUserChatModel(response.body).reversed.toList();
}
}
isLoading = false;
notifyListeners();
if (isChatScreenActive && receiverUID == receiverID) {
markRead(userChatHistory, receiverUID);
}
generateConvId();
}
void generateConvId() async {
Uuid uuid = const Uuid();
chatCID = uuid.v4();
}
void markRead(List<SingleUserChatModel> data, int receiverID) {
if (data != null) {
for (SingleUserChatModel element in data!) {
if (AppState().chatDetails!.response!.id! == element.targetUserId) {
if (element.isSeen != null) {
if (!element.isSeen!) {
element.isSeen = true;
dynamic data = [
{
"userChatHistoryId": element.userChatHistoryId,
"TargetUserId": element.currentUserId == receiverID ? element.currentUserId : element.targetUserId,
"isDelivered": true,
"isSeen": true,
}
];
updateUserChatHistoryStatusAsync(data);
notifyListeners();
}
}
for (ChatUser element in searchedChats!) {
if (element.id == receiverID) {
element.unreadMessageCount = 0;
chatUConvCounter = 0;
}
}
}
}
notifyListeners();
}
}
void updateUserChatHistoryStatusAsync(List data) {
try {
chatHubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]);
} catch (e) {
throw e;
}
}
void updateUserChatHistoryOnMsg(List data) {
try {
chatHubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]);
} catch (e) {
throw e;
}
}
List<SingleUserChatModel> getSingleUserChatModel(String str) => List<SingleUserChatModel>.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x)));
Future<dynamic> uploadAttachments(String userId, File file) async {
dynamic result;
try {
Object? response = await ChatApiClient().uploadMedia(userId, file);
if (response != null) {
result = response;
} else {
result = [];
}
} catch (e) {
throw e;
}
return result;
}
void updateUserChatStatus(List<Object?>? args) {
dynamic items = args!.toList();
for (var cItem in items[0]) {
for (SingleUserChatModel chat in userChatHistory) {
if (cItem["contantNo"].toString() == chat.contantNo.toString()) {
chat.isSeen = cItem["isSeen"];
chat.isDelivered = cItem["isDelivered"];
}
}
}
notifyListeners();
}
void onChatSeen(List<Object?>? args) {
dynamic items = args!.toList();
// 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();
if (kDebugMode) {
logger.i("---------------------------------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]) {
for (ChatUser element in searchedChats!) {
if (element.id == item["currentUserId"]) {
int? val = element.unreadMessageCount ?? 0;
element.unreadMessageCount = val! + 1;
}
}
3 years ago
}
notifyListeners();
}
void changeStatus(List<Object?>? args) {
3 years ago
dynamic items = args!.toList();
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 {
List<SingleUserChatModel> data = [], 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;
3 years ago
data.first.targetUserEmail = temp.first.currentUserEmail;
data.first.currentUserId = temp.first.targetUserId;
data.first.currentUserName = temp.first.targetUserName;
3 years ago
data.first.currentUserEmail = temp.first.targetUserEmail;
if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) {
data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg");
}
if (data.first.userChatReplyResponse != null) {
if (data.first.fileTypeResponse != null) {
if (data.first.userChatReplyResponse!.fileTypeId == 12 || data.first.userChatReplyResponse!.fileTypeId == 4 || data.first.userChatReplyResponse!.fileTypeId == 3) {
data.first.userChatReplyResponse!.image =
await ChatApiClient().downloadURL(fileName: data.first.userChatReplyResponse!.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg");
data.first.userChatReplyResponse!.isImageLoaded = true;
}
}
}
}
if (searchedChats != null) {
dynamic contain = searchedChats!.where((ChatUser element) => element.id == data.first.currentUserId);
if (contain.isEmpty) {
3 years ago
List<String> emails = [];
emails.add(await EmailImageEncryption().encrypt(val: data.first.currentUserEmail!));
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
searchedChats!.add(
ChatUser(
3 years ago
id: data.first.currentUserId,
userName: data.first.currentUserName,
email: data.first.currentUserEmail,
3 years ago
unreadMessageCount: 0,
isImageLoading: false,
image: chatImages!.first.profilePicture ?? "",
isImageLoaded: true,
userStatus: 1,
isTyping: false,
userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, data.first.currentUserId.toString()),
),
);
}
3 years ago
}
3 years ago
setMsgTune();
if (isChatScreenActive && data.first.currentUserId == receiverID) {
userChatHistory.insert(0, data.first);
3 years ago
} else {
if (searchedChats != null) {
for (ChatUser user in searchedChats!) {
if (user.id == data.first.currentUserId) {
int tempCount = user.unreadMessageCount ?? 0;
user.unreadMessageCount = tempCount + 1;
}
}
3 years ago
sort();
}
}
List<Object> list = [
{
"userChatHistoryId": data.first.userChatHistoryId,
"TargetUserId": temp.first.targetUserId,
"isDelivered": true,
"isSeen": isChatScreenActive && data.first.currentUserId == receiverID ? true : false
}
];
updateUserChatHistoryOnMsg(list);
invokeChatCounter(userId: AppState().chatDetails!.response!.id!);
notifyListeners();
}
void OnSubmitChatAsync(List<Object?>? parameters) {
logger.i(parameters);
List<SingleUserChatModel> data = [], 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.targetUserEmail = temp.first.currentUserEmail;
data.first.currentUserId = temp.first.targetUserId;
data.first.currentUserName = temp.first.targetUserName;
data.first.currentUserEmail = temp.first.targetUserEmail;
}
if (isChatScreenActive && data.first.currentUserId == receiverID) {
int index = userChatHistory.indexWhere((SingleUserChatModel element) => element.userChatHistoryId == 0);
logger.d(index);
userChatHistory[index] = data.first;
}
notifyListeners();
}
void sort() {
searchedChats!.sort(
(ChatUser a, ChatUser b) => b.unreadMessageCount!.compareTo(a.unreadMessageCount!),
);
}
void onUserTyping(List<Object?>? 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;
case ".aac":
return 13;
case ".mp3":
return 14;
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";
case ".aac":
return "audio/aac";
case ".mp3":
return "audio/mp3";
default:
return "";
}
}
Future<void> sendChatToServer(
{required int chatEventId,
required fileTypeId,
required int targetUserId,
required String targetUserName,
required chatReplyId,
required bool isAttachment,
required bool isReply,
Uint8List? image,
Uint8List? voice,
required bool isImageLoaded}) async {
Uuid uuid = const Uuid();
String contentNo = uuid.v4();
String msg = message.text;
SingleUserChatModel data = SingleUserChatModel(
userChatHistoryId: 0,
3 years ago
chatEventId: chatEventId,
chatSource: 1,
contant: msg,
contantNo: contentNo,
conversationId: chatCID,
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: getFileExtension(selectedFile.path).toString(),
fileKind: "file",
3 years ago
fileName: selectedFile.path.split("/").last,
fileTypeDescription: getFileTypeDescription(getFileExtension(selectedFile.path).toString()),
)
: null,
image: image,
isImageLoaded: isImageLoaded,
voice: voice,
3 years ago
);
if (kDebugMode) {
logger.i("model data: " + jsonEncode(data));
}
3 years ago
userChatHistory.insert(0, data);
isFileSelected = false;
isMsgReply = false;
sFileType = "";
message.clear();
notifyListeners();
3 years ago
String chatData =
'{"contant":"$msg","contantNo":"$contentNo","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"$chatCID"}';
await chatHubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]);
}
3 years ago
void sendChatMessage(BuildContext context, {required int targetUserId, required int userStatus, required String userEmail, required String targetUserName}) async {
if (!isFileSelected && !isMsgReply) {
if (kDebugMode) {
print("Normal Text Msg");
}
if (message.text == null || message.text.isEmpty) {
return;
}
sendChatToServer(
chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: false, chatReplyId: null, isReply: false, isImageLoaded: false, image: null);
}
if (isFileSelected && !isMsgReply) {
if (kDebugMode) {
logger.i("Normal Attachment Msg");
}
3 years ago
Utils.showLoading(context);
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,
isImageLoaded: true,
image: selectedFile.readAsBytesSync());
}
if (!isFileSelected && isMsgReply) {
if (kDebugMode) {
print("Normal Text To Text 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,
isImageLoaded: repliedMsg.first.isImageLoaded!,
image: repliedMsg.first.image);
} // reply msg over image && normal
if (isFileSelected && isMsgReply) {
if (kDebugMode) {
print("Reply With File");
}
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,
isImageLoaded: true,
image: selectedFile.readAsBytesSync());
}
if (searchedChats != null) {
dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId);
if (contain.isEmpty) {
List<String> emails = [];
emails.add(await EmailImageEncryption().encrypt(val: userEmail));
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
searchedChats!.add(
ChatUser(
id: targetUserId,
userName: targetUserName,
unreadMessageCount: 0,
email: userEmail,
isImageLoading: false,
image: chatImages.first.profilePicture ?? "",
isImageLoaded: true,
isTyping: false,
isFav: false,
userStatus: userStatus,
userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()),
),
);
notifyListeners();
}
} else {
List<String> emails = [];
emails.add(await EmailImageEncryption().encrypt(val: userEmail));
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
searchedChats!.add(
ChatUser(
id: targetUserId,
userName: targetUserName,
unreadMessageCount: 0,
email: userEmail,
isImageLoading: false,
image: chatImages.first.profilePicture ?? "",
isImageLoaded: true,
isTyping: false,
isFav: false,
userStatus: userStatus,
userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()),
),
);
notifyListeners();
}
}
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 {
if (kDebugMode) {
logger.i("ext: " + "." + fileName.split('.').last);
}
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";
case ".aac":
return "assets/icons/chat/aac.svg";
case ".mp3":
return "assets/icons/chat/zip.mp3";
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 {
fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().favUser(userID: userID, targetUserID: targetUserID);
if (favoriteChatUser.response != null) {
for (ChatUser user in searchedChats!) {
if (user.id == favoriteChatUser.response!.targetUserId!) {
user.isFav = favoriteChatUser.response!.isFav;
3 years ago
dynamic contain = favUsersList!.where((ChatUser element) => element.id == favoriteChatUser.response!.targetUserId!);
if (contain.isEmpty) {
favUsersList.add(user);
}
}
}
}
notifyListeners();
}
Future<void> unFavoriteUser({required int userID, required int targetUserID}) async {
fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().unFavUser(userID: userID, targetUserID: targetUserID);
3 years ago
if (favoriteChatUser.response != null) {
for (ChatUser user in searchedChats!) {
if (user.id == favoriteChatUser.response!.targetUserId!) {
user.isFav = favoriteChatUser.response!.isFav;
}
}
favUsersList.removeWhere(
(ChatUser element) => element.id == targetUserID,
);
}
3 years ago
notifyListeners();
}
void clearSelections() {
searchedChats = pChatHistory;
search.clear();
isChatScreenActive = false;
receiverID = 0;
paginationVal = 0;
message.text = '';
isFileSelected = false;
repliedMsg = [];
sFileType = "";
3 years ago
isMsgReply = false;
notifyListeners();
}
3 years ago
void clearAll() {
searchedChats = pChatHistory;
search.clear();
isChatScreenActive = false;
receiverID = 0;
paginationVal = 0;
message.text = '';
isFileSelected = false;
repliedMsg = [];
sFileType = "";
}
3 years ago
void disposeData() {
search.clear();
isChatScreenActive = false;
receiverID = 0;
paginationVal = 0;
message.text = '';
isFileSelected = false;
repliedMsg = [];
sFileType = "";
deleteData();
favUsersList.clear();
searchedChats!.clear();
pChatHistory!.clear();
chatHubConnection.stop();
AppState().chatDetails = null;
}
void deleteData() {
List<ChatUser> exists = [], unique = [];
exists.addAll(searchedChats!);
exists.addAll(favUsersList!);
Map<String, ChatUser> profileMap = {};
for (ChatUser item in exists) {
profileMap[item.email!] = item;
}
unique = profileMap.values.toList();
for (ChatUser element in unique!) {
deleteFile(element.id.toString());
}
}
void getUserImages() async {
List<String> emails = [];
List<ChatUser> exists = [], unique = [];
exists.addAll(searchedChats!);
exists.addAll(favUsersList!);
Map<String, ChatUser> profileMap = {};
for (ChatUser item in exists) {
profileMap[item.email!] = item;
}
unique = profileMap.values.toList();
for (ChatUser element in unique!) {
emails.add(await EmailImageEncryption().encrypt(val: element.email!));
}
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
for (ChatUser user in searchedChats!) {
for (ChatUserImageModel uImage in chatImages) {
if (user.email == uImage.email) {
user.image = uImage.profilePicture ?? "";
user.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, user.id.toString());
user.isImageLoading = false;
user.isImageLoaded = true;
}
}
}
for (ChatUser favUser in favUsersList) {
for (ChatUserImageModel uImage in chatImages) {
if (favUser.email == uImage.email) {
favUser.image = uImage.profilePicture ?? "";
favUser.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, favUser.id.toString());
favUser.isImageLoading = false;
favUser.isImageLoaded = true;
}
}
}
3 years ago
notifyListeners();
}
Future<File?> downloadImageLocal(String? encodedBytes, String userID) async {
File? myfile;
if (encodedBytes == null) {
return myfile;
} else {
await deleteFile(userID);
Uint8List decodedBytes = base64Decode(encodedBytes);
Directory appDocumentsDirectory = await getApplicationDocumentsDirectory();
String dirPath = '${appDocumentsDirectory.path}/chat_images';
if (!await Directory(dirPath).exists()) {
await Directory(dirPath).create();
await File('$dirPath/.nomedia').create();
}
late File imageFile = File("$dirPath/$userID.jpg");
imageFile.writeAsBytesSync(decodedBytes);
return imageFile;
}
}
Future deleteFile(String userID) async {
Directory appDocumentsDirectory = await getApplicationDocumentsDirectory();
String dirPath = '${appDocumentsDirectory.path}/chat_images';
late File imageFile = File('$dirPath/$userID.jpg');
if (await imageFile.exists()) {
await imageFile.delete();
}
}
Future<String> downChatMedia(Uint8List bytes, String ext) async {
String dir = (await getApplicationDocumentsDirectory()).path;
File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
await file.writeAsBytes(bytes);
return file.path;
}
3 years ago
void setMsgTune() async {
JustAudio.AudioPlayer player = JustAudio.AudioPlayer();
3 years ago
await player.setVolume(1.0);
String audioAsset = "";
if (Platform.isAndroid) {
audioAsset = "assets/audio/pulse_tone_android.mp3";
} else {
audioAsset = "assets/audio/pulse_tune_ios.caf";
}
try {
await player.setAsset(audioAsset);
await player.load();
player.play();
} catch (e) {
print("Error: $e");
}
}
Future<void> getChatMedia(BuildContext context, {required String fileName, required String fileTypeName, required int fileTypeID}) async {
Utils.showLoading(context);
if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) {
Uint8List encodedString = await ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: getFileTypeDescription(fileTypeName));
try {
String path = await downChatMedia(encodedString, fileTypeName ?? "");
Utils.hideLoading(context);
OpenFile.open(path);
} catch (e) {
Utils.showToast("Cannot open file.");
}
}
}
void onNewChatConversion(List<Object?>? params) {
dynamic items = params!.toList();
chatUConvCounter = items[0]["singleChatCount"] ?? 0;
notifyListeners();
}
Future invokeChatCounter({required int userId}) async {
await chatHubConnection.invoke("GetChatCounversationCount", args: [userId]);
return "";
}
3 years ago
void userTypingInvoke({required int currentUser, required int reciptUser}) async {
await chatHubConnection.invoke("UserTypingAsync", args: [reciptUser, currentUser]);
}
// Audio Recoding Work
Timer? _timer;
int _recodeDuration = 0;
bool isRecoding = false;
bool isPause = false;
bool isPlaying = false;
String? path;
String? musicFile;
late Directory appDirectory;
late RecorderController recorderController;
late PlayerController playerController;
//////// Audio Recoding Work ////////////////////
Future<void> initAudio({required int receiverId}) async {
// final dir = Directory((Platform.isAndroid
// ? await getExternalStorageDirectory() //FOR ANDROID
// : await getApplicationSupportDirectory() //FOR IOS
// )!
appDirectory = await getApplicationDocumentsDirectory();
String dirPath = '${appDirectory.path}/chat_audios';
if (!await Directory(dirPath).exists()) {
await Directory(dirPath).create();
await File('$dirPath/.nomedia').create();
}
path = "$dirPath/${AppState().chatDetails!.response!.id}-$receiverID-${DateTime.now().microsecondsSinceEpoch}.aac";
recorderController = RecorderController()
..androidEncoder = AndroidEncoder.aac
..androidOutputFormat = AndroidOutputFormat.mpeg4
..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
..sampleRate = 6000
..updateFrequency = const Duration(milliseconds: 100)
..bitRate = 18000;
playerController = PlayerController();
}
void disposeAudio() {
isRecoding = false;
isPlaying = false;
isPause = false;
recorderController.dispose();
playerController.dispose();
}
void startRecoding() async {
PermissionStatus status = await Permission.microphone.request();
if (status.isDenied == true) {
startRecoding();
} else {
recorderController.reset();
await recorderController.record(path);
_recodeDuration = 0;
_startTimer();
isRecoding = !isRecoding;
notifyListeners();
}
}
Future<void> _startTimer() async {
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 1), (Timer t) async {
_recodeDuration++;
if (_recodeDuration <= 59) {
applyCounter();
} else {
pauseRecoding();
}
});
}
void applyCounter() {
buildTimer();
notifyListeners();
}
Future<void> pauseRecoding() async {
isPause = true;
isPlaying = true;
recorderController.pause();
path = await recorderController.stop(false);
File file = File(path!);
file.readAsBytesSync();
path = file.path;
await playerController.preparePlayer(file.path, 1.0);
_timer?.cancel();
notifyListeners();
}
Future<void> deleteRecoding() async {
_recodeDuration = 0;
_timer?.cancel();
if (path == null) {
path = await recorderController.stop(true);
} else {
await recorderController.stop(true);
}
if (path != null && path!.isNotEmpty) {
File delFile = File(path!);
double fileSizeInKB = delFile.lengthSync() / 1024;
double fileSizeInMB = fileSizeInKB / 1024;
if (kDebugMode) {
debugPrint("Deleted file size: ${delFile.lengthSync()}");
debugPrint("Deleted file size in KB: " + fileSizeInKB.toString());
debugPrint("Deleted file size in MB: " + fileSizeInMB.toString());
}
if (await delFile.exists()) {
delFile.delete();
}
isPause = false;
isRecoding = false;
isPlaying = false;
notifyListeners();
}
}
String buildTimer() {
String minutes = _formatNum(_recodeDuration ~/ 60);
String seconds = _formatNum(_recodeDuration % 60);
return '$minutes : $seconds';
}
String _formatNum(int number) {
String numberStr = number.toString();
if (number < 10) {
numberStr = '0' + numberStr;
}
return numberStr;
}
void playRecoding() async {
isPlaying = true;
await playerController.startPlayer(finishMode: FinishMode.pause);
}
void playOrPause() async {
playerController.playerState == PlayerState.playing ? await playerController.pausePlayer() : playRecoding();
notifyListeners();
}
void sendVoiceMessage(BuildContext context, {required int targetUserId, required int userStatus, required String userEmail, required String targetUserName}) async {
if (!isPause) {
path = await recorderController.stop(false);
}
if (kDebugMode) {
logger.i("path:" + path!);
}
File voiceFile = File(path!);
voiceFile.readAsBytesSync();
_timer?.cancel();
isPause = false;
isPlaying = false;
isRecoding = false;
Utils.showLoading(context);
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile);
String? ext = getFileExtension(voiceFile.path);
Utils.hideLoading(context);
sendVoiceMessageToServer(
msgText: voiceFile.path!.split("/").last,
chatEventId: 2,
fileTypeId: getFileType(ext.toString()),
targetUserId: targetUserId,
targetUserName: targetUserName,
isVoiceAttached: true,
voice: voiceFile.readAsBytesSync(),
userEmail: userEmail,
userStatus: userStatus,
chatReplyId: null,
isAttachment: true,
isReply: isMsgReply,
voicFile: voiceFile,
);
notifyListeners();
}
Future<void> sendVoiceMessageToServer(
{String? msgText,
int? chatEventId,
int? fileTypeId,
int? targetUserId,
String? targetUserName,
bool? isVoiceAttached,
Uint8List? voice,
String? userEmail,
int? userStatus,
bool? isReply,
bool? isAttachment,
int? chatReplyId,
File? voicFile}) async {
Uuid uuid = const Uuid();
String contentNo = uuid.v4();
String msg = msgText!;
SingleUserChatModel data = SingleUserChatModel(
chatEventId: chatEventId,
chatSource: 1,
contant: msg,
contantNo: contentNo,
conversationId: chatCID,
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: getFileExtension(voicFile!.path).toString(),
fileKind: "file",
fileName: msgText,
fileTypeDescription: getFileTypeDescription(getFileExtension(voicFile!.path).toString()),
)
: null,
image: null,
isImageLoaded: false,
voice: voice,
);
userChatHistory.insert(0, data);
notifyListeners();
String chatData =
'{"contant":"$msg","contantNo":"$contentNo","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"$chatCID"}';
await chatHubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]);
if (searchedChats != null) {
dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId);
if (contain.isEmpty) {
List<String> emails = [];
emails.add(await EmailImageEncryption().encrypt(val: userEmail!));
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
searchedChats!.add(
ChatUser(
id: targetUserId,
userName: targetUserName,
unreadMessageCount: 0,
email: userEmail,
isImageLoading: false,
image: chatImages.first.profilePicture ?? "",
isImageLoaded: true,
isTyping: false,
isFav: false,
userStatus: userStatus,
userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()),
),
);
notifyListeners();
}
} else {
List<String> emails = [];
emails.add(await EmailImageEncryption().encrypt(val: userEmail!));
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
searchedChats!.add(
ChatUser(
id: targetUserId,
userName: targetUserName,
unreadMessageCount: 0,
email: userEmail,
isImageLoading: false,
image: chatImages.first.profilePicture ?? "",
isImageLoaded: true,
isTyping: false,
isFav: false,
userStatus: userStatus,
userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()),
),
);
notifyListeners();
}
}
void playVoice(
BuildContext context, {
required SingleUserChatModel data,
}) async {
Utils.showLoading(context);
Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? ""));
try {
String path = await downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data);
File file = File(path!);
file.readAsBytesSync();
Utils.hideLoading(context);
3 years ago
await data.voiceController!.preparePlayer(file.path, 1.0);
data.voiceController!.startPlayer(finishMode: FinishMode.pause);
notifyListeners();
} catch (e) {
Utils.showToast("Cannot open file.");
}
}
3 years ago
void stopPlaying(BuildContext context, {required SingleUserChatModel data}) async {
await data.voiceController!.pausePlayer();
3 years ago
notifyListeners();
}
Future<String> downChatVoice(Uint8List bytes, String ext, SingleUserChatModel data) async {
String dirPath = '${(await getApplicationDocumentsDirectory()).path}/chat_audios';
if (!await Directory(dirPath).exists()) {
await Directory(dirPath).create();
await File('$dirPath/.nomedia').create();
}
File file = File("$dirPath/${data.currentUserId}-${data.targetUserId}-${DateTime.now().microsecondsSinceEpoch}." + ext);
await file.writeAsBytes(bytes);
return file.path;
}
// data.scrollController.animateTo(
// data.scrollController.position.maxScrollExtent,
// duration: const Duration(milliseconds: 100),
// curve: Curves.easeOut,
// );
}