together_mobile/lib/utils/ws_receive_callback.dart

458 lines
13 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import '/database/box_type.dart';
import '/database/hive_database.dart';
import '/models/apply_list_model.dart';
import '/models/contact_model.dart';
import '/models/init_get_it.dart';
import '/models/route_state_model.dart';
import '/models/user_model.dart';
import '/models/websocket_model.dart';
import '/notification_api.dart';
import '/request/message.dart';
const int chunkSize = 1024 * 1024 * 2;
Future<void> receiveFriendMsg(
Map<String, dynamic> msg,
bool isShowNotification,
) async {
print('=================收到了好友信息事件==================');
print(msg);
print('=======================================');
String senderId = msg['senderId'] as String;
Box<ChatSetting> chatSettingBox = Hive.box<ChatSetting>('chat_setting');
Box<MessageT> messageTBox = await HiveDatabase.openMessageBox(senderId);
Box<int> msgIndexBox = await Hive.openBox<int>('msg_index_$senderId');
ChatSetting? chatSetting = chatSettingBox.get(senderId);
DateTime dateTime = DateTime.parse(msg['dateTime'] as String);
if (chatSetting == null) {
chatSettingBox.put(
senderId,
ChatSetting(
senderId,
0,
false,
true,
false,
dateTime,
1,
),
);
} else if (msgIndexBox.get(msg['msgId'] as String) != null) {
return;
} else {
chatSetting.isOpen = true;
chatSetting.latestDateTime = dateTime;
chatSetting.unreadCount++;
chatSettingBox.put(senderId, chatSetting);
}
List<String> attachments = List.from(msg['attachments']);
final DateTime now = DateTime.parse(msg['dateTime'] as String);
for (var attachment in attachments) {
Box<AttachmentProgress> apr =
Hive.box<AttachmentProgress>('attachment_receive');
apr.put(attachment, AttachmentProgress(0, 1000, 0, true, false));
}
messageTBox.add(
MessageT(
msg['msgId'] as String,
senderId,
msg['text'],
msg['type'],
now,
msg['isShowTime'],
attachments,
),
);
if (!isShowNotification) {
return;
}
String name = getIt.get<Contact>().friends[senderId]!.friendRemark.isEmpty
? getIt.get<ContactAccountProfile>().friends[senderId]!.nickname
: getIt.get<Contact>().friends[senderId]!.friendRemark;
String routeName = getIt.get<RouteState>().currentPathName;
String avatar = getIt.get<ContactAccountProfile>().friends[senderId]!.avatar;
if (!getIt.get<RouteState>().isVisible) {
NotificationAPI.showMessageNotifications(
senderId: senderId,
name: name,
avatar: avatar,
text: msg['text'] as String,
);
} else if (routeName == 'Message') {
if (!getIt.get<RouteState>().query.containsValue(senderId)) {
NotificationAPI.showMessageNotifications(
senderId: senderId,
name: name,
avatar: avatar,
text: msg['text'] as String,
);
}
} else if (routeName != 'Chat') {
NotificationAPI.showMessageNotifications(
senderId: senderId,
name: name,
avatar: avatar,
text: msg['text'] as String,
);
}
}
void receiveApplyFriend(Map<String, dynamic> msg) {
print('=================收到了申请好友事件==================');
print(msg);
print('=======================================');
getIt.get<ApplyList>().addJson(msg);
}
void receiveFriendAdded(Map<String, dynamic> msg) {
print('=================收到了申请好友通过事件==================');
print(msg);
print('=======================================');
getIt.get<Contact>().addFriend(msg['friendId'], msg['setting']);
getIt
.get<ContactAccountProfile>()
.addFriendAccountProfile(msg['friendId'], msg['accountProfile']);
}
void receiveFriendDeleted(Map<String, dynamic> msg) {
print('=================收到了解除好友事件==================');
print(msg);
print('=======================================');
getIt.get<Contact>().removeFriend(msg['friendId']);
getIt.get<ContactAccountProfile>().removeFriend(msg['friendId']);
}
void receiveGroupChatCreation(Map<String, dynamic> msg) {
print('=================收到了群聊邀请事件==================');
print(msg);
print('=======================================');
String groupChatId = msg['groupChat']['id'];
getIt.get<Contact>().addGroupChat(groupChatId);
getIt.get<ContactAccountProfile>().addGroupChatProfile(groupChatId, msg);
}
void receiveGroupChatMsg(
Map<String, dynamic> msg,
bool isShowNotification,
) async {
print('=================收到了群聊信息事件==================');
print(msg);
print('=======================================');
String senderId = msg['senderId'] as String;
String groupChatId = msg['groupChatId'] as String;
Box<ChatSetting> chatSettingBox = Hive.box<ChatSetting>('chat_setting');
Box<MessageT> messageTBox = await HiveDatabase.openMessageBox(groupChatId);
Box<int> msgIndexBox = await Hive.openBox('msg_index_$groupChatId');
ChatSetting? chatSetting = chatSettingBox.get(groupChatId);
DateTime dateTime = DateTime.parse(msg['dateTime'] as String);
getIt.get<ContactAccountProfile>().addGroupChatMemberProfile(
groupChatId,
msg['senderId'],
{
'avatar': msg['avatar'],
'nickname': msg['nickname'],
'remarkInGroupChat': msg['remarkInGroupChat'],
},
);
if (chatSetting == null) {
chatSettingBox.put(
groupChatId,
ChatSetting(
groupChatId,
1,
false,
true,
false,
dateTime,
1,
),
);
} else if (msgIndexBox.get(msg['msgId'] as String) != null) {
return;
} else {
chatSetting.isOpen = true;
chatSetting.latestDateTime = dateTime;
chatSetting.unreadCount++;
chatSettingBox.put(groupChatId, chatSetting);
}
List<String> attachments = List.from(msg['attachments']);
final DateTime now = DateTime.parse(msg['dateTime'] as String);
for (var attachment in attachments) {
Box<AttachmentProgress> apr =
Hive.box<AttachmentProgress>('attachment_receive');
apr.put(attachment, AttachmentProgress(0, 1000, 0, true, false));
}
messageTBox.add(
MessageT(
msg['msgId'] as String,
senderId,
msg['text'],
msg['type'],
now,
msg['isShowTime'],
attachments,
),
);
if (!isShowNotification) {
return;
}
String avatar =
getIt.get<ContactAccountProfile>().groupChats[groupChatId]!.avatar;
late String name;
if (getIt.get<Contact>().friends.containsKey(senderId)) {
if (getIt.get<Contact>().friends[senderId]!.friendRemark.isNotEmpty) {
name = getIt.get<Contact>().friends[senderId]!.friendRemark;
} else if ((msg['remarkInGroupChat'] as String).isNotEmpty) {
name = msg['remarkInGroupChat'];
} else {
name = msg['nickname'];
}
} else {
name = (msg['remarkInGroupChat'] as String).isNotEmpty
? msg['remarkInGroupChat']
: msg['nickname'];
}
String routeName = getIt.get<RouteState>().currentPathName;
if (!getIt.get<RouteState>().isVisible) {
NotificationAPI.showMessageNotifications(
senderId: senderId,
name: name,
avatar: avatar,
text: msg['text'] as String,
groupChatId: groupChatId,
);
} else if (routeName == 'Message') {
if (!getIt.get<RouteState>().query.containsValue(groupChatId)) {
NotificationAPI.showMessageNotifications(
senderId: senderId,
name: name,
avatar: avatar,
text: msg['text'] as String,
groupChatId: groupChatId,
);
}
} else if (routeName != 'Chat') {
NotificationAPI.showMessageNotifications(
senderId: senderId,
name: name,
avatar: avatar,
text: msg['text'] as String,
groupChatId: groupChatId,
);
}
}
void receiveChatImages(Map<String, dynamic> msg) async {
print('=================收到了聊天图片事件==================');
// // print(msg);
print('=======================================');
String chatImageDir = getIt.get<UserProfile>().baseImageDir;
String filename = msg['filename'];
String filePath = '$chatImageDir/$filename';
File file = File(filePath);
if (await file.exists()) {
return;
}
late Box<AttachmentProgress> aprBox;
try {
aprBox = Hive.box<AttachmentProgress>('attachment_receive');
} catch (_) {
aprBox = await Hive.openBox<AttachmentProgress>('attachment_receive');
}
String dirTime = filename.split('/')[0];
Directory dir = Directory('$chatImageDir/$dirTime');
if (!(await dir.exists())) {
await dir.create(recursive: true);
}
int totalChunkNum = msg['totalChunkNum'] as int;
if (totalChunkNum == 1) {
await file.writeAsBytes(List<int>.from(msg['bytes']));
await Future.delayed(
const Duration(milliseconds: 200),
() {
aprBox.put(
filename,
AttachmentProgress(1, 1, 1.0, true, false),
);
},
);
return;
}
File tempFile = File('$chatImageDir/${msg['tempFilename']}');
AttachmentProgress? ap = aprBox.get(filename);
if (!(await tempFile.exists())) {
await tempFile.create(recursive: true);
await tempFile.writeAsBytes(List<int>.from(msg['bytes']));
}
if (ap == null) {
aprBox.put(
filename,
AttachmentProgress(
1,
totalChunkNum,
1 / totalChunkNum,
true,
false,
),
);
} else {
ap.hasChunkNum += 1;
ap.progress = ap.hasChunkNum / totalChunkNum;
ap.isValid = true;
List<File> tempFiles = List.generate(
totalChunkNum,
(index) {
String tempFilePath =
'$chatImageDir/temp/$filename-$totalChunkNum-$index';
return File(tempFilePath);
},
);
// assemble chunks when all the chunks are arrived
if (tempFiles.every((element) => element.existsSync())) {
final openedFile = file.openWrite(mode: FileMode.append);
for (var i = 0; i < totalChunkNum; i++) {
Uint8List bytes = await tempFiles[i].readAsBytes();
openedFile.add(bytes);
await tempFiles[i].delete();
}
openedFile.close();
ap.hasChunkNum = totalChunkNum;
ap.progress = 1.0;
ap.isValid = true;
}
aprBox.put(filename, ap);
}
}
Future<void> receivePullChatImage(Map<String, dynamic> msg) async {
print('=================收到了拉取图片请求==================');
print(msg);
print('=======================================');
String baseImageDir = getIt.get<UserProfile>().baseImageDir;
Map<String, dynamic> sentMsg = {
'event': 'chat-image',
'senderId': getIt.get<UserAccount>().id,
};
if (msg['chatType'] == 0) {
sentMsg['receiverId'] = msg['receiverId'];
} else {
sentMsg['receiverIds'] = msg['receiverIds'];
}
for (var filename in msg['attachments']) {
File file = File('$baseImageDir/$filename');
int fileSize = await file.length();
int totalChunkNum = (fileSize / chunkSize).ceil();
int start = 0;
int end = fileSize >= chunkSize ? start + chunkSize : start + fileSize;
List<int> bytes = [];
await file.openRead(start, end).forEach((element) => bytes.addAll(element));
sentMsg['filename'] = filename;
sentMsg['totalChunkNum'] = totalChunkNum;
sentMsg['tempFilename'] = 'temp/$filename-$totalChunkNum-0';
sentMsg['currentChunkNum'] = 0;
sentMsg['bytes'] = bytes;
await uploadChatAttachment(sentMsg);
getIt.get<WebSocketManager>().addSendImageTimer(filename, totalChunkNum);
}
}
Future<void> receiveCheckChatImage(Map<String, dynamic> msg) async {
print('=================收到了服务端确认收到图片事件==================');
// print(msg);
print('=======================================');
int nextChunkNum = msg['currentChunkNum'] + 1;
int totalChunkNum = msg['totalChunkNum'];
String baseImageDir = getIt.get<UserProfile>().baseImageDir;
String filename = msg['filename'];
Box<AttachmentProgress> asBox =
Hive.box<AttachmentProgress>('attachment_send');
AttachmentProgress aps = asBox.get(filename)!;
getIt.get<WebSocketManager>().removeSendImageTimer(filename);
aps.hasChunkNum += 1;
aps.progress = aps.hasChunkNum / aps.totalChunkNum;
asBox.put(filename, aps);
// print(aps.hasChunkNum);
// print(aps.totalChunkNum);
// print('已发送了: ${aps.progress}');
if (nextChunkNum == totalChunkNum) {
return;
}
// Start to send next chunk
int start = nextChunkNum * chunkSize;
File file = File('$baseImageDir/$filename');
List<int> bytes = [];
if (nextChunkNum + 1 == totalChunkNum) {
await file
.openRead(start)
.forEach((element) => bytes.addAll(element));
} else {
await file
.openRead(start, start + chunkSize)
.forEach((element) => bytes.addAll(element));
}
Map<String, dynamic> sentMsg = {
'event': 'chat-image',
'senderId': getIt.get<UserAccount>().id,
};
if (msg['chatType'] == 0) {
sentMsg['receiverId'] = msg['receiverId'];
} else {
sentMsg['receiverIds'] = msg['receiverIds'];
}
sentMsg['filename'] = filename;
sentMsg['totalChunkNum'] = totalChunkNum;
sentMsg['tempFilename'] = 'temp/$filename-$totalChunkNum-$nextChunkNum';
sentMsg['currentChunkNum'] = nextChunkNum;
sentMsg['bytes'] = bytes;
uploadChatAttachment(sentMsg);
getIt.get<WebSocketManager>().addSendImageTimer(filename, totalChunkNum);
}