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.
1478 lines
50 KiB
Dart
1478 lines
50 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
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:just_audio/just_audio.dart';
|
|
import 'package:mohem_flutter_app/api/chat/chat_api_client.dart';
|
|
import 'package:mohem_flutter_app/api/my_team/my_team_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/config/routes.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/models/my_team/get_employee_subordinates_list.dart';
|
|
import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
|
|
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';
|
|
import 'package:flutter/material.dart' as Material;
|
|
|
|
class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
ScrollController scrollController = ScrollController();
|
|
|
|
TextEditingController message = TextEditingController();
|
|
TextEditingController search = TextEditingController();
|
|
List<SingleUserChatModel> userChatHistory = [], repliedMsg = [];
|
|
List<ChatUser>? pChatHistory, searchedChats;
|
|
String chatCID = '';
|
|
bool isLoading = true;
|
|
bool isChatScreenActive = false;
|
|
int receiverID = 0;
|
|
late File selectedFile;
|
|
String sFileType = "";
|
|
|
|
List<ChatUser> favUsersList = [];
|
|
int paginationVal = 0;
|
|
int? cTypingUserId = 0;
|
|
bool isTextMsg = false, isReplyMsg = false, isAttachmentMsg = false, isVoiceMsg = false;
|
|
|
|
// 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;
|
|
List<GetEmployeeSubordinatesList> getEmployeeSubordinatesList = [];
|
|
List<ChatUser> teamMembersList = [];
|
|
|
|
Material.TextDirection textDirection = Material.TextDirection.ltr;
|
|
bool isRTL = false;
|
|
String msgText = "";
|
|
|
|
//Chat Home Page Counter
|
|
int chatUConvCounter = 0;
|
|
|
|
/// Search Provider
|
|
List<ChatUser>? chatUsersList = [];
|
|
int pageNo = 1;
|
|
|
|
bool disbaleChatForThisUser = false;
|
|
|
|
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",
|
|
);
|
|
disbaleChatForThisUser = true;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
Future<void> buildHubConnection() async {
|
|
chatHubConnection = await getHubConnection();
|
|
await chatHubConnection.start();
|
|
if (kDebugMode) {
|
|
logger.i("Hub Conn: Startedddddddd");
|
|
}
|
|
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=Desktop&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
|
|
.withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
|
|
return hub;
|
|
}
|
|
|
|
void registerEvents() {
|
|
chatHubConnection.on("OnUpdateUserStatusAsync", changeStatus);
|
|
// 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");
|
|
}
|
|
}
|
|
|
|
Future<void> getUserRecentChats() async {
|
|
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()));
|
|
sort();
|
|
notifyListeners();
|
|
if (searchedChats!.isNotEmpty || favUsersList.isNotEmpty) {
|
|
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) {}
|
|
} 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) {
|
|
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) {
|
|
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) {
|
|
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) {
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
void changeStatus(List<Object?>? args) {
|
|
dynamic items = args!.toList();
|
|
for (ChatUser user in searchedChats!) {
|
|
if (user.id == items.first["id"]) {
|
|
user.userStatus = items.first["userStatus"];
|
|
}
|
|
}
|
|
if (teamMembersList.isNotEmpty) {
|
|
for (ChatUser user in teamMembersList!) {
|
|
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;
|
|
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 (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) {
|
|
List<String> emails = [];
|
|
emails.add(await EmailImageEncryption().encrypt(val: data.first.currentUserEmail!));
|
|
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
|
|
searchedChats!.add(
|
|
ChatUser(
|
|
id: data.first.currentUserId,
|
|
userName: data.first.currentUserName,
|
|
email: data.first.currentUserEmail,
|
|
unreadMessageCount: 0,
|
|
isImageLoading: false,
|
|
image: chatImages!.first.profilePicture ?? "",
|
|
isImageLoaded: true,
|
|
userStatus: 1,
|
|
isTyping: false,
|
|
userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, data.first.currentUserId.toString()),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
setMsgTune();
|
|
if (isChatScreenActive && data.first.currentUserId == receiverID) {
|
|
userChatHistory.insert(0, data.first);
|
|
} else {
|
|
if (searchedChats != null) {
|
|
for (ChatUser user in searchedChats!) {
|
|
if (user.id == data.first.currentUserId) {
|
|
int tempCount = user.unreadMessageCount ?? 0;
|
|
user.unreadMessageCount = tempCount + 1;
|
|
}
|
|
}
|
|
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) {
|
|
print(isChatScreenActive);
|
|
print(receiverID);
|
|
print(isChatScreenActive);
|
|
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;
|
|
}
|
|
}
|
|
|
|
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,
|
|
required bool isImageLoaded,
|
|
String? userEmail,
|
|
int? userStatus,
|
|
File? voiceFile,
|
|
required bool isVoiceAttached}) async {
|
|
Uuid uuid = const Uuid();
|
|
String contentNo = uuid.v4();
|
|
String msg;
|
|
if (isVoiceAttached) {
|
|
msg = voiceFile!.path.split("/").last;
|
|
} else {
|
|
msg = message.text;
|
|
logger.w(msg);
|
|
}
|
|
SingleUserChatModel data = SingleUserChatModel(
|
|
userChatHistoryId: 0,
|
|
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: isVoiceMsg ? getFileExtension(voiceFile!.path).toString() : getFileExtension(selectedFile.path).toString(),
|
|
fileKind: "file",
|
|
fileName: isVoiceMsg ? msg : selectedFile.path.split("/").last,
|
|
fileTypeDescription: isVoiceMsg ? getFileTypeDescription(getFileExtension(voiceFile!.path).toString()) : getFileTypeDescription(getFileExtension(selectedFile.path).toString()),
|
|
)
|
|
: null,
|
|
image: image,
|
|
isImageLoaded: isImageLoaded,
|
|
voice: isVoiceMsg ? voiceFile! : null,
|
|
voiceController: isVoiceMsg ? AudioPlayer() : null);
|
|
if (kDebugMode) {
|
|
logger.i("model data: " + jsonEncode(data));
|
|
}
|
|
userChatHistory.insert(0, data);
|
|
isTextMsg = false;
|
|
isReplyMsg = false;
|
|
isAttachmentMsg = false;
|
|
isVoiceMsg = false;
|
|
sFileType = "";
|
|
message.clear();
|
|
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)]);
|
|
}
|
|
|
|
void sendChatMessage(BuildContext context, {required int targetUserId, required int userStatus, required String userEmail, required String targetUserName}) async {
|
|
if (kDebugMode) {
|
|
print("====================== Values ============================");
|
|
print("Is Text " + isTextMsg.toString());
|
|
print("isReply " + isReplyMsg.toString());
|
|
print("isAttachment " + isAttachmentMsg.toString());
|
|
print("isVoice " + isVoiceMsg.toString());
|
|
}
|
|
//Text
|
|
if (isTextMsg && !isAttachmentMsg && !isVoiceMsg && !isReplyMsg) {
|
|
logger.d("// Normal Text Message");
|
|
if (message.text.isEmpty) {
|
|
return;
|
|
}
|
|
sendChatToServer(
|
|
chatEventId: 1,
|
|
fileTypeId: null,
|
|
targetUserId: targetUserId,
|
|
targetUserName: targetUserName,
|
|
isAttachment: false,
|
|
chatReplyId: null,
|
|
isReply: false,
|
|
isImageLoaded: false,
|
|
image: null,
|
|
isVoiceAttached: false,
|
|
userEmail: userEmail,
|
|
userStatus: userStatus);
|
|
} else if (isTextMsg && !isAttachmentMsg && !isVoiceMsg && isReplyMsg) {
|
|
logger.d("// Text Message as Reply");
|
|
if (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,
|
|
isVoiceAttached: false,
|
|
voiceFile: null,
|
|
userEmail: userEmail,
|
|
userStatus: userStatus);
|
|
}
|
|
// Attachment
|
|
else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) {
|
|
logger.d("// Normal Image Message");
|
|
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: null,
|
|
isReply: false,
|
|
isImageLoaded: true,
|
|
image: selectedFile.readAsBytesSync(),
|
|
isVoiceAttached: false,
|
|
userEmail: userEmail,
|
|
userStatus: userStatus);
|
|
} else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) {
|
|
logger.d("// Image as Reply Msg");
|
|
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(),
|
|
isVoiceAttached: false,
|
|
userEmail: userEmail,
|
|
userStatus: userStatus);
|
|
}
|
|
//Voice
|
|
|
|
else if (!isTextMsg && !isAttachmentMsg && isVoiceMsg && !isReplyMsg) {
|
|
logger.d("// Normal Voice Message");
|
|
|
|
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);
|
|
sendChatToServer(
|
|
chatEventId: 2,
|
|
fileTypeId: getFileType(ext.toString()),
|
|
targetUserId: targetUserId,
|
|
targetUserName: targetUserName,
|
|
chatReplyId: null,
|
|
isAttachment: true,
|
|
isReply: isReplyMsg,
|
|
isImageLoaded: false,
|
|
voiceFile: voiceFile,
|
|
isVoiceAttached: true,
|
|
userEmail: userEmail,
|
|
userStatus: userStatus);
|
|
notifyListeners();
|
|
} else if (!isTextMsg && !isAttachmentMsg && isVoiceMsg && isReplyMsg) {
|
|
logger.d("// Voice as Reply Msg");
|
|
|
|
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);
|
|
sendChatToServer(
|
|
chatEventId: 2,
|
|
fileTypeId: getFileType(ext.toString()),
|
|
targetUserId: targetUserId,
|
|
targetUserName: targetUserName,
|
|
chatReplyId: null,
|
|
isAttachment: true,
|
|
isReply: isReplyMsg,
|
|
isImageLoaded: false,
|
|
voiceFile: voiceFile,
|
|
isVoiceAttached: true,
|
|
userEmail: userEmail,
|
|
userStatus: userStatus);
|
|
notifyListeners();
|
|
}
|
|
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;
|
|
isAttachmentMsg = true;
|
|
isTextMsg = false;
|
|
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() {
|
|
isAttachmentMsg = 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;
|
|
isReplyMsg = true;
|
|
repliedMsg.add(data);
|
|
notifyListeners();
|
|
}
|
|
|
|
void closeMe() {
|
|
repliedMsg = [];
|
|
isReplyMsg = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
String dateFormte(DateTime data) {
|
|
DateFormat f = DateFormat('hh:mm a dd MMM yyyy', "en_US");
|
|
f.format(data);
|
|
return f.format(data);
|
|
}
|
|
|
|
Future<void> favoriteUser({required int userID, required int targetUserID, required bool fromSearch}) 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;
|
|
dynamic contain = favUsersList!.where((ChatUser element) => element.id == favoriteChatUser.response!.targetUserId!);
|
|
if (contain.isEmpty) {
|
|
favUsersList.add(user);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (ChatUser user in chatUsersList!) {
|
|
if (user.id == favoriteChatUser.response!.targetUserId!) {
|
|
user.isFav = favoriteChatUser.response!.isFav;
|
|
dynamic contain = favUsersList!.where((ChatUser element) => element.id == favoriteChatUser.response!.targetUserId!);
|
|
if (contain.isEmpty) {
|
|
favUsersList.add(user);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (fromSearch) {
|
|
for (ChatUser user in favUsersList) {
|
|
if (user.id == targetUserID) {
|
|
user.userLocalDownlaodedImage = null;
|
|
user.isImageLoading = false;
|
|
user.isImageLoaded = false;
|
|
}
|
|
}
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> unFavoriteUser({required int userID, required int targetUserID}) async {
|
|
fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().unFavUser(userID: userID, targetUserID: targetUserID);
|
|
|
|
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,
|
|
);
|
|
}
|
|
|
|
for (ChatUser user in chatUsersList!) {
|
|
if (user.id == favoriteChatUser.response!.targetUserId!) {
|
|
user.isFav = favoriteChatUser.response!.isFav;
|
|
}
|
|
}
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
void clearSelections() {
|
|
searchedChats = pChatHistory;
|
|
search.clear();
|
|
isChatScreenActive = false;
|
|
receiverID = 0;
|
|
paginationVal = 0;
|
|
message.text = '';
|
|
isAttachmentMsg = false;
|
|
repliedMsg = [];
|
|
sFileType = "";
|
|
isReplyMsg = false;
|
|
isTextMsg = false;
|
|
isVoiceMsg = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
void clearAll() {
|
|
searchedChats = pChatHistory;
|
|
search.clear();
|
|
isChatScreenActive = false;
|
|
receiverID = 0;
|
|
paginationVal = 0;
|
|
message.text = '';
|
|
isTextMsg = false;
|
|
isAttachmentMsg = false;
|
|
isVoiceMsg = false;
|
|
isReplyMsg = false;
|
|
repliedMsg = [];
|
|
sFileType = "";
|
|
}
|
|
|
|
void disposeData() {
|
|
if (!disbaleChatForThisUser) {
|
|
search.clear();
|
|
isChatScreenActive = false;
|
|
receiverID = 0;
|
|
paginationVal = 0;
|
|
message.text = '';
|
|
isTextMsg = false;
|
|
isAttachmentMsg = false;
|
|
isVoiceMsg = false;
|
|
isReplyMsg = false;
|
|
repliedMsg = [];
|
|
sFileType = "";
|
|
deleteData();
|
|
favUsersList.clear();
|
|
searchedChats?.clear();
|
|
pChatHistory?.clear();
|
|
chatHubConnection.stop();
|
|
AppState().chatDetails = null;
|
|
}
|
|
}
|
|
|
|
void deleteData() {
|
|
List<ChatUser> exists = [], unique = [];
|
|
if (searchedChats != null) 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void setMsgTune() async {
|
|
JustAudio.AudioPlayer player = JustAudio.AudioPlayer();
|
|
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 "";
|
|
}
|
|
|
|
void userTypingInvoke({required int currentUser, required int reciptUser}) async {
|
|
await chatHubConnection.invoke("UserTypingAsync", args: [reciptUser, currentUser]);
|
|
}
|
|
|
|
//////// 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;
|
|
isVoiceMsg = false;
|
|
recorderController.dispose();
|
|
playerController.dispose();
|
|
}
|
|
|
|
void startRecoding(BuildContext context) async {
|
|
await Permission.microphone.request().then((PermissionStatus status) {
|
|
if (status.isPermanentlyDenied) {
|
|
Utils.confirmDialog(
|
|
context,
|
|
"The app needs microphone access to be able to record audio.",
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
openAppSettings();
|
|
},
|
|
);
|
|
} else if (status.isDenied) {
|
|
Utils.confirmDialog(
|
|
context,
|
|
"The app needs microphone access to be able to record audio.",
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
openAppSettings();
|
|
},
|
|
);
|
|
} else if (status.isGranted) {
|
|
sRecoding();
|
|
} else {
|
|
startRecoding(context);
|
|
}
|
|
});
|
|
}
|
|
|
|
void sRecoding() async {
|
|
isVoiceMsg = true;
|
|
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;
|
|
isVoiceMsg = 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;
|
|
}
|
|
|
|
Future<File> downChatVoice(Uint8List bytes, String ext, SingleUserChatModel data) async {
|
|
File file;
|
|
try {
|
|
String dirPath = '${(await getApplicationDocumentsDirectory()).path}/chat_audios';
|
|
if (!await Directory(dirPath).exists()) {
|
|
await Directory(dirPath).create();
|
|
await File('$dirPath/.nomedia').create();
|
|
}
|
|
file = File("$dirPath/${data.currentUserId}-${data.targetUserId}-${DateTime.now().microsecondsSinceEpoch}" + ext);
|
|
await file.writeAsBytes(bytes);
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print(e);
|
|
}
|
|
file = File("");
|
|
}
|
|
return file;
|
|
}
|
|
|
|
void scrollToMsg(SingleUserChatModel data) {
|
|
if (data.userChatReplyResponse != null && data.userChatReplyResponse!.userChatHistoryId != null) {
|
|
int index = userChatHistory.indexWhere((SingleUserChatModel element) => element.userChatHistoryId == data.userChatReplyResponse!.userChatHistoryId);
|
|
if (index >= 1) {
|
|
double contentSize = scrollController.position.viewportDimension + scrollController.position.maxScrollExtent;
|
|
double target = contentSize * index / userChatHistory.length;
|
|
scrollController.position.animateTo(
|
|
target,
|
|
duration: const Duration(seconds: 1),
|
|
curve: Curves.easeInOut,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> getTeamMembers() async {
|
|
teamMembersList = [];
|
|
isLoading = true;
|
|
if (AppState().getemployeeSubordinatesList.isNotEmpty) {
|
|
getEmployeeSubordinatesList = AppState().getemployeeSubordinatesList;
|
|
for (GetEmployeeSubordinatesList element in getEmployeeSubordinatesList) {
|
|
if (element.eMPLOYEEEMAILADDRESS != null) {
|
|
if (element.eMPLOYEEEMAILADDRESS!.isNotEmpty) {
|
|
teamMembersList.add(
|
|
ChatUser(
|
|
id: int.parse(element.eMPLOYEENUMBER!),
|
|
email: element.eMPLOYEEEMAILADDRESS,
|
|
userName: element.eMPLOYEENAME,
|
|
phone: element.eMPLOYEEMOBILENUMBER,
|
|
userStatus: 0,
|
|
unreadMessageCount: 0,
|
|
isFav: false,
|
|
isTyping: false,
|
|
isImageLoading: false,
|
|
image: element.eMPLOYEEIMAGE ?? "",
|
|
isImageLoaded: element.eMPLOYEEIMAGE == null ? false : true,
|
|
userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null ? null : await downloadImageLocal(element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
getEmployeeSubordinatesList = await MyTeamApiClient().getEmployeeSubordinates("", "", "");
|
|
AppState().setemployeeSubordinatesList = getEmployeeSubordinatesList;
|
|
for (GetEmployeeSubordinatesList element in getEmployeeSubordinatesList) {
|
|
if (element.eMPLOYEEEMAILADDRESS != null) {
|
|
if (element.eMPLOYEEEMAILADDRESS!.isNotEmpty) {
|
|
teamMembersList.add(
|
|
ChatUser(
|
|
id: int.parse(element.eMPLOYEENUMBER!),
|
|
email: element.eMPLOYEEEMAILADDRESS,
|
|
userName: element.eMPLOYEENAME,
|
|
phone: element.eMPLOYEEMOBILENUMBER,
|
|
userStatus: 0,
|
|
unreadMessageCount: 0,
|
|
isFav: false,
|
|
isTyping: false,
|
|
isImageLoading: false,
|
|
image: element.eMPLOYEEIMAGE ?? "",
|
|
isImageLoaded: element.eMPLOYEEIMAGE == null ? false : true,
|
|
userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null ? null : await downloadImageLocal(element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (ChatUser user in searchedChats!) {
|
|
for (ChatUser teamUser in teamMembersList!) {
|
|
if (user.id == teamUser.id) {
|
|
teamUser.userStatus = user.userStatus;
|
|
}
|
|
}
|
|
}
|
|
|
|
isLoading = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
void inputBoxDirection(String val) {
|
|
if (val.isNotEmpty) {
|
|
isTextMsg = true;
|
|
} else {
|
|
isTextMsg = false;
|
|
}
|
|
msgText = val;
|
|
notifyListeners();
|
|
}
|
|
|
|
void onDirectionChange(bool val) {
|
|
isRTL = val;
|
|
notifyListeners();
|
|
}
|
|
|
|
Material.TextDirection getTextDirection(String v) {
|
|
String str = v.trim();
|
|
if (str.isEmpty) return Material.TextDirection.ltr;
|
|
int firstUnit = str.codeUnitAt(0);
|
|
if (firstUnit > 0x0600 && firstUnit < 0x06FF ||
|
|
firstUnit > 0x0750 && firstUnit < 0x077F ||
|
|
firstUnit > 0x07C0 && firstUnit < 0x07EA ||
|
|
firstUnit > 0x0840 && firstUnit < 0x085B ||
|
|
firstUnit > 0x08A0 && firstUnit < 0x08B4 ||
|
|
firstUnit > 0x08E3 && firstUnit < 0x08FF ||
|
|
firstUnit > 0xFB50 && firstUnit < 0xFBB1 ||
|
|
firstUnit > 0xFBD3 && firstUnit < 0xFD3D ||
|
|
firstUnit > 0xFD50 && firstUnit < 0xFD8F ||
|
|
firstUnit > 0xFD92 && firstUnit < 0xFDC7 ||
|
|
firstUnit > 0xFDF0 && firstUnit < 0xFDFC ||
|
|
firstUnit > 0xFE70 && firstUnit < 0xFE74 ||
|
|
firstUnit > 0xFE76 && firstUnit < 0xFEFC ||
|
|
firstUnit > 0x10800 && firstUnit < 0x10805 ||
|
|
firstUnit > 0x1B000 && firstUnit < 0x1B0FF ||
|
|
firstUnit > 0x1D165 && firstUnit < 0x1D169 ||
|
|
firstUnit > 0x1D16D && firstUnit < 0x1D172 ||
|
|
firstUnit > 0x1D17B && firstUnit < 0x1D182 ||
|
|
firstUnit > 0x1D185 && firstUnit < 0x1D18B ||
|
|
firstUnit > 0x1D1AA && firstUnit < 0x1D1AD ||
|
|
firstUnit > 0x1D242 && firstUnit < 0x1D244) {
|
|
return Material.TextDirection.rtl;
|
|
}
|
|
return Material.TextDirection.ltr;
|
|
}
|
|
|
|
void openChatByNoti(BuildContext context) async {
|
|
SingleUserChatModel nUser = SingleUserChatModel();
|
|
Utils.saveStringFromPrefs("isAppOpendByChat", "false");
|
|
if (await Utils.getStringFromPrefs("notificationData") != "null") {
|
|
nUser = SingleUserChatModel.fromJson(jsonDecode(await Utils.getStringFromPrefs("notificationData")));
|
|
Utils.saveStringFromPrefs("notificationData", "null");
|
|
Future.delayed(const Duration(seconds: 2));
|
|
for (ChatUser user in searchedChats!) {
|
|
if (user.id == nUser.targetUserId) {
|
|
Navigator.pushNamed(context, AppRoutes.chatDetailed, arguments: ChatDetailedScreenParams(user, false));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
Utils.saveStringFromPrefs("notificationData", "null");
|
|
}
|
|
}
|