didvan-app/lib/views/direct/direct_state.dart

234 lines
6.2 KiB
Dart

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<MessageData> messages = [];
late final int typeId;
final Map<String, List<int>> dailyMessages = {};
final List<int> deletionQueue = [];
String? text;
NewsAttachment? replyNews;
RadarAttachment? replyRadar;
File? recordedFile;
Uint8List? recordedFileBytes;
int? audioDuration;
String? path;
bool isRecording = false;
Future<void> 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<void> 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<void> 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<void> 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();
}
}
}
}