import 'dart:io'; import 'package:didvan/models/enums.dart'; import 'package:didvan/models/message_data/message_data.dart'; import 'package:didvan/models/message_data/news_attachment.dart'; import 'package:didvan/models/message_data/radar_attachment.dart'; import 'package:didvan/providers/core.dart'; import 'package:didvan/services/media/media.dart'; import 'package:didvan/services/media/voice.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/network/request_helper.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_vibrate/flutter_vibrate.dart'; import 'package:http/http.dart' as http; import 'package:path_provider/path_provider.dart'; import 'package:record/record.dart'; class DirectState extends CoreProvier { final _recorder = AudioRecorder(); final List messages = []; late final int typeId; final Map> dailyMessages = {}; final List deletionQueue = []; String? text; NewsAttachment? replyNews; RadarAttachment? replyRadar; File? recordedFile; Uint8List? recordedFileBytes; int? audioDuration; String? path; bool isRecording = false; Future getMessages() async { appState = AppState.busy; final RequestService service = RequestService(RequestHelper.direct(typeId)); await service.httpGet(); if (service.isSuccess) { messages.clear(); final messageDatas = service.result['messages']; for (var i = 0; i < messageDatas.length; i++) { messages.add(MessageData.fromJson(messageDatas[i])); _addToDailyGrouped(messages.last); } appState = AppState.idle; return; } appState = AppState.failed; } void deleteRecordedFile() { recordedFile!.delete(); recordedFile = null; notifyListeners(); update(); } Future startRecording() async { text = null; await _recorder.hasPermission(); if (!kIsWeb) { Vibrate.feedback(FeedbackType.medium); } isRecording = true; Directory? tempDir; if (!kIsWeb) { tempDir = await getDownloadsDirectory(); } _recorder.start(const RecordConfig(), path: kIsWeb ? '' : '${tempDir!.path}/${DateTime.now().millisecondsSinceEpoch ~/ 1000}.m4a'); notifyListeners(); } Future stopRecording({required bool sendImidiately}) async { path = await _recorder.stop(); isRecording = false; if (path == null) { notifyListeners(); return; } if (kIsWeb) { final Uri audioUri = Uri.parse(path!); final http.Response audioResponse = await http.get(audioUri); recordedFileBytes = audioResponse.bodyBytes; } else { recordedFile = File(path!); } if (sendImidiately) { await sendMessage(); } else { notifyListeners(); } } void delete() { for (var i = 0; i < deletionQueue.length; i++) { final service = RequestService( RequestHelper.deleteDirect(typeId, deletionQueue[i]), ); service.delete(); messages.removeWhere((element) => element.id == deletionQueue[i]); } deletionQueue.clear(); notifyListeners(); } void _addToDailyGrouped(MessageData message) { String createdAt = message.createdAt.replaceAll('T', ' ').split(' ').first; if (!dailyMessages.containsKey(createdAt)) { dailyMessages.addAll({ createdAt: [message.id] }); } else { dailyMessages[createdAt]!.add(message.id); } } Future sendMessage() async { if ((text == null || text!.isEmpty) && (recordedFile == null && recordedFileBytes == null)) return; MediaService.audioPlayer.stop(); final body = {}; if (text != null) { body.addAll({'text': text}); } if (replyRadar != null) { body.addAll({'radarId': replyRadar!.id}); } if (replyNews != null) { body.addAll({'newsId': replyNews!.id}); } if (replyNews != null) { body.addAll({'newsId': replyNews!.id}); } if (path != null) { final duration = await VoiceService.getDuration(src: path!); if (duration != null) { body.addAll({'duration': duration.inSeconds.toString()}); } } final uploadFile = recordedFile; final uploadFileBytes = recordedFileBytes; text = null; recordedFile = null; recordedFileBytes = null; replyRadar = null; replyNews = null; path = null; notifyListeners(); final service = RequestService(RequestHelper.sendDirectMessage(typeId), body: body); if (uploadFile == null && uploadFileBytes == null) { await service.post(); if (service.isSuccess) { final message = service.result['message']; messages.insert(0, MessageData.fromJson(message)); dailyMessages.clear(); for (var i = 0; i < messages.length; i++) { _addToDailyGrouped(messages[i]); } } } else { messages.insert( 0, MessageData( id: 0, writedByAdmin: false, readed: false, createdAt: DateTime.now().subtract(const Duration(minutes: 210)).toString(), text: text, audio: path, audioFile: uploadFile, radar: replyRadar, news: replyNews, audioDuration: audioDuration, ), ); dailyMessages.clear(); for (var i = 0; i < messages.length; i++) { _addToDailyGrouped(messages[i]); } if (kIsWeb) { await service.multipartBytes( file: uploadFileBytes!, method: 'POST', fieldName: 'audio', fileName: 'voice-message', mediaExtension: 'm4a', mediaFormat: 'audio', ); } else { await service.multipart( file: Platform.isIOS ? File(uploadFile!.path.replaceAll('file://', '')) : uploadFile, method: 'POST', fieldName: 'audio', fileName: 'voice-message', mediaExtension: 'm4a', mediaFormat: 'audio', ); } if (service.isSuccess) { final message = service.result['message']; final m = MessageData.fromJson(message); messages[0] = m; update(); } } } }