|
|
|
|
@ -85,12 +85,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
void registerEvents() {
|
|
|
|
|
chatHubConnection.on("OnUpdateUserStatusAsync", changeStatus);
|
|
|
|
|
// chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
|
|
|
|
|
// hubConnection.on("OnSeenChatUserAsync", onChatSeen);
|
|
|
|
|
chatHubConnection.on("OnSubmitChatAsync", OnSubmitChatAsync);
|
|
|
|
|
chatHubConnection.on("OnUserTypingAsync", onUserTyping);
|
|
|
|
|
chatHubConnection.on("OnUserCountAsync", userCountAsync);
|
|
|
|
|
// hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
|
|
|
|
|
// chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
|
|
|
|
|
chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
|
|
|
|
|
chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
|
|
|
|
|
print("Alll Registered");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void getUserRecentChats() async {
|
|
|
|
|
@ -107,9 +108,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
if (favUList.response != null && recentChat.response != null) {
|
|
|
|
|
favUsersList = favUList.response!;
|
|
|
|
|
favUsersList.sort(
|
|
|
|
|
(ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(
|
|
|
|
|
b.userName!.toLowerCase(),
|
|
|
|
|
),
|
|
|
|
|
(ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()),
|
|
|
|
|
);
|
|
|
|
|
for (dynamic user in recentChat.response!) {
|
|
|
|
|
for (dynamic favUser in favUList.response!) {
|
|
|
|
|
@ -230,16 +229,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
Future<dynamic> uploadAttachments(String userId, File file) async {
|
|
|
|
|
dynamic result;
|
|
|
|
|
try {
|
|
|
|
|
StreamedResponse response = await ChatApiClient().uploadMedia(userId, file);
|
|
|
|
|
if (response.statusCode == 200) {
|
|
|
|
|
result = jsonDecode(await response.stream.bytesToString());
|
|
|
|
|
Object? response = await ChatApiClient().uploadMedia(userId, file);
|
|
|
|
|
if (response != null) {
|
|
|
|
|
result = response;
|
|
|
|
|
} else {
|
|
|
|
|
result = [];
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -365,6 +363,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
ChatUser(
|
|
|
|
|
id: data.first.currentUserId,
|
|
|
|
|
userName: data.first.currentUserName,
|
|
|
|
|
email: data.first.currentUserEmail,
|
|
|
|
|
unreadMessageCount: 0,
|
|
|
|
|
isImageLoading: false,
|
|
|
|
|
image: chatImages!.first.profilePicture ?? "",
|
|
|
|
|
@ -404,6 +403,28 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnSubmitChatAsync(List<Object?>? parameters) {
|
|
|
|
|
logger.d(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!),
|
|
|
|
|
@ -454,6 +475,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
return 2;
|
|
|
|
|
case ".rar":
|
|
|
|
|
return 2;
|
|
|
|
|
case ".aac":
|
|
|
|
|
return 13;
|
|
|
|
|
case ".mp3":
|
|
|
|
|
return 14;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@ -487,6 +512,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
return "application/octet-stream";
|
|
|
|
|
case ".rar":
|
|
|
|
|
return "application/octet-stream";
|
|
|
|
|
case ".aac":
|
|
|
|
|
return "audio/aac";
|
|
|
|
|
case ".mp3":
|
|
|
|
|
return "audio/mp3";
|
|
|
|
|
default:
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
@ -501,11 +530,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
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,
|
|
|
|
|
chatEventId: chatEventId,
|
|
|
|
|
chatSource: 1,
|
|
|
|
|
contant: msg,
|
|
|
|
|
@ -530,7 +561,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
: null,
|
|
|
|
|
image: image,
|
|
|
|
|
isImageLoaded: isImageLoaded,
|
|
|
|
|
voice: voice,
|
|
|
|
|
);
|
|
|
|
|
print("Model data---------------------------");
|
|
|
|
|
logger.d(data.toJson());
|
|
|
|
|
userChatHistory.insert(0, data);
|
|
|
|
|
isFileSelected = false;
|
|
|
|
|
isMsgReply = false;
|
|
|
|
|
@ -569,9 +603,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
isReply: false,
|
|
|
|
|
isImageLoaded: true,
|
|
|
|
|
image: selectedFile.readAsBytesSync());
|
|
|
|
|
} // normal attachemnt msg
|
|
|
|
|
}
|
|
|
|
|
if (!isFileSelected && isMsgReply) {
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print("Normal Text To Text Reply");
|
|
|
|
|
}
|
|
|
|
|
if (message.text == null || message.text.isEmpty) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
@ -723,6 +759,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
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";
|
|
|
|
|
}
|
|
|
|
|
@ -889,6 +929,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
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);
|
|
|
|
|
@ -956,11 +997,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void userTypingInvoke({required int currentUser, required int reciptUser}) async {
|
|
|
|
|
logger.d([reciptUser, currentUser]);
|
|
|
|
|
await chatHubConnection.invoke("UserTypingAsync", args: [reciptUser, currentUser]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Audio Recoding Work
|
|
|
|
|
// Audio Recoding Work
|
|
|
|
|
Timer? _timer;
|
|
|
|
|
int _recodeDuration = 0;
|
|
|
|
|
bool isRecoding = false;
|
|
|
|
|
@ -972,13 +1012,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
late RecorderController recorderController;
|
|
|
|
|
late PlayerController playerController;
|
|
|
|
|
|
|
|
|
|
//////// Audio Recoding Work ////////////////////
|
|
|
|
|
//////// 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()
|
|
|
|
|
@ -986,6 +1031,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
..androidOutputFormat = AndroidOutputFormat.mpeg4
|
|
|
|
|
..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
|
|
|
|
|
..sampleRate = 6000
|
|
|
|
|
..updateFrequency = const Duration(milliseconds: 100)
|
|
|
|
|
..bitRate = 18000;
|
|
|
|
|
playerController = PlayerController();
|
|
|
|
|
}
|
|
|
|
|
@ -1014,13 +1060,21 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _startTimer() {
|
|
|
|
|
Future<void> _startTimer() async {
|
|
|
|
|
_timer?.cancel();
|
|
|
|
|
_timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
|
|
|
|
|
_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 {
|
|
|
|
|
@ -1030,27 +1084,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
path = await recorderController.stop(false);
|
|
|
|
|
File file = File(path!);
|
|
|
|
|
file.readAsBytesSync();
|
|
|
|
|
path = file.path;
|
|
|
|
|
await playerController.preparePlayer(file.path, 1.0);
|
|
|
|
|
// var tempDuration = _recodeDuration;
|
|
|
|
|
// _recodeDuration = tempDuration;
|
|
|
|
|
_timer?.cancel();
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void resumeRecoding() {
|
|
|
|
|
isPause = false;
|
|
|
|
|
isPlaying = false;
|
|
|
|
|
isRecoding = true;
|
|
|
|
|
recorderController.record(path);
|
|
|
|
|
_startTimer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> deleteRecoding() async {
|
|
|
|
|
_recodeDuration = 0;
|
|
|
|
|
_timer?.cancel();
|
|
|
|
|
// path = await recorderController.stop(true);
|
|
|
|
|
recorderController.reset();
|
|
|
|
|
print(path);
|
|
|
|
|
recorderController.stop(true);
|
|
|
|
|
if (path != null && path!.isNotEmpty) {
|
|
|
|
|
File delFile = File(path!);
|
|
|
|
|
double fileSizeInKB = delFile.lengthSync() / 1024;
|
|
|
|
|
@ -1095,8 +1138,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sendVoiceMessage(BuildContext context, {required int targetUserId, required int userStatus, required String userEmail, required String targetUserName}) async {
|
|
|
|
|
//recorderController.pause();
|
|
|
|
|
if (!isPause) {
|
|
|
|
|
path = await recorderController.stop(false);
|
|
|
|
|
}
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print(path);
|
|
|
|
|
}
|
|
|
|
|
@ -1110,17 +1154,156 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile);
|
|
|
|
|
logger.d(value);
|
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
|
logger.d(voiceFile.path!.split("/").last);
|
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
|
// sendChatToServer(
|
|
|
|
|
// chatEventId: 2,
|
|
|
|
|
// fileTypeId: getFileType(ext.toString()),
|
|
|
|
|
// targetUserId: targetUserId,
|
|
|
|
|
// targetUserName: targetUserName,
|
|
|
|
|
// isAttachment: true,
|
|
|
|
|
// chatReplyId: null,
|
|
|
|
|
// isReply: false,
|
|
|
|
|
// isImageLoaded: true,
|
|
|
|
|
// image: voiceFile.readAsBytesSync());
|
|
|
|
|
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: false,
|
|
|
|
|
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);
|
|
|
|
|
logger.d(path);
|
|
|
|
|
File file = File(path!);
|
|
|
|
|
file.readAsBytesSync();
|
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
|
await playerController.preparePlayer(file.path, 1.0);
|
|
|
|
|
notifyListeners();
|
|
|
|
|
playerController.startPlayer(finishMode: FinishMode.pause);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
Utils.showToast("Cannot open file.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
// );
|
|
|
|
|
}
|
|
|
|
|
|