fix websocket reconnect bug and accept unreceived msgs

main
htylight 2023-09-16 11:33:57 +08:00
parent be64a626ce
commit 9a730d68e5
8 changed files with 85 additions and 32 deletions

View File

@ -15,7 +15,6 @@ class HiveDatabase {
if (_isInitialised) {
return;
}
await Hive.close();
List<int> encryptionKeyUint8List = await _getEncryptKey();
@ -74,8 +73,9 @@ class HiveDatabase {
return encryptionKeyUint8List;
}
static void close() {
static Future<void> close() async {
_isInitialised = false;
await Hive.close();
}
}

View File

@ -33,18 +33,18 @@ class WebSocketManager extends ChangeNotifier {
int reconnectTimes = 0;
Duration timeout = const Duration(seconds: 4);
void connect(String userId) {
void connect(String userId, bool isReconnect) {
id = userId;
wsUrl = Uri.parse('ws://10.0.2.2:8000/ws/$id');
wsUrl = Uri.parse('ws://10.0.2.2:8000/ws/$id?is_reconnect=$isReconnect');
channel = WebSocketChannel.connect(wsUrl);
socketStatus = SocketStatus.connected;
print('websocket connected <$channel>');
heartBeatInspect();
if (reconnectTimer != null) {
// reconnectTimer!.cancel();
reconnectTimer!.cancel();
reconnectTimer = null;
reconnectTimes = 0;
}
heartBeatInspect();
channel.stream.listen(onData, onError: onError, onDone: onDone);
}
@ -75,7 +75,7 @@ class WebSocketManager extends ChangeNotifier {
receiveFriendAdded(data);
case 'friend-deleted':
receiveFriendDeleted(data);
case 'friend-chat-image' || 'group-chat-image':
case 'chat-image':
receiveChatImages(data);
case 'group-chat-creation':
receiveGroupChatCreation(data);
@ -142,7 +142,7 @@ class WebSocketManager extends ChangeNotifier {
reconnectTimer = Timer.periodic(timeout, (timer) {
if (reconnectTimes < reconnectCount) {
connect(id);
connect(id, true);
reconnectTimes++;
} else {
print('reconnection times exceed the max times......');
@ -185,6 +185,8 @@ void receiveFriendMsg(Map<String, dynamic> msg) async {
1,
),
);
} else if ((messageTBox.get(msg['msgId'] as String)) != null) {
return;
} else {
chatSetting.isOpen = true;
chatSetting.latestDateTime = dateTime;
@ -193,13 +195,15 @@ void receiveFriendMsg(Map<String, dynamic> msg) async {
}
List<String> attachments = List.from(msg['attachments']);
final DateTime now = DateTime.parse(msg['dateTime'] as String);
messageTBox.add(
messageTBox.put(
msg['msgId'] as String,
MessageT(
senderId,
msg['text'],
msg['type'],
DateTime.parse(msg['dateTime'] as String),
now,
msg['isShowTime'],
attachments,
),
@ -269,10 +273,17 @@ void receiveChatImages(Map<String, dynamic> msg) async {
print(msg);
print('=======================================');
String chatImageDir = getIt.get<UserProfile>().baseImageDir;
File file = await File('$chatImageDir/${msg['filename']}').create(
recursive: true,
);
await file.writeAsBytes(msg['bytes']);
File file = File('$chatImageDir/${msg['filename']}');
if (await file.exists()) {
return;
} else {
await file.create(recursive: true);
await file.writeAsBytes(List<int>.from(msg['bytes']));
}
// File file = await File('$chatImageDir/${msg['filename']}').create(
// recursive: true,
// // );
// await file.writeAsBytes(msg['bytes']);
}
void receiveGroupChatCreation(Map<String, dynamic> msg) {
@ -314,6 +325,8 @@ void receiveGroupChatMsg(Map<String, dynamic> msg) async {
1,
),
);
} else if ((messageTBox.get(msg['msgId'] as String)) != null) {
return;
} else {
chatSetting.isOpen = true;
chatSetting.latestDateTime = dateTime;
@ -322,12 +335,15 @@ void receiveGroupChatMsg(Map<String, dynamic> msg) async {
}
List<String> attachments = List.from(msg['attachments']);
messageTBox.add(
final DateTime now = DateTime.parse(msg['dateTime'] as String);
messageTBox.put(
msg['msgId'] as String,
MessageT(
senderId,
msg['text'],
msg['type'],
DateTime.parse(msg['dateTime'] as String),
now,
msg['isShowTime'],
attachments,
),

View File

@ -31,7 +31,7 @@ class _ChatScreenState extends State<ChatScreen> {
if (!getIt.get<UserProfile>().isInitialised) {
await HiveDatabase.init();
getIt.get<WebSocketManager>().connect(getIt.get<UserAccount>().id);
getIt.get<WebSocketManager>().connect(getIt.get<UserAccount>().id, false);
List<Map<String, dynamic>> res = await Future.wait([
getMyProfile(getIt.get<UserAccount>().id),

View File

@ -72,6 +72,8 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
@override
Widget build(BuildContext context) {
bool isFriend = widget.senderId == widget.contactId;
return Container(
padding: const EdgeInsets.symmetric(
vertical: kDefaultPadding / 2,
@ -91,12 +93,10 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
),
),
Row(
textDirection: widget.senderId == widget.contactId
? TextDirection.ltr
: TextDirection.rtl,
textDirection: isFriend ? TextDirection.ltr : TextDirection.rtl,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.senderId == widget.contactId
isFriend
? getIt
.get<ContactAccountProfile>()
.friends[widget.contactId]!
@ -120,7 +120,7 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
),
Expanded(
child: Column(
crossAxisAlignment: widget.senderId == widget.contactId
crossAxisAlignment: isFriend
? CrossAxisAlignment.start
: CrossAxisAlignment.end,
children: [
@ -129,7 +129,7 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
Container(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
decoration: BoxDecoration(
color: widget.senderId == widget.contactId
color: isFriend
? const Color.fromARGB(255, 241, 241, 241)
: kPrimaryColor,
borderRadius: BorderRadius.circular(10.0),

View File

@ -238,7 +238,11 @@ class _MessageInputBoxState extends State<MessageInputBox> {
attachments.add('$dirTime/${getRandomFilename()}');
}
}
_messageTBox.add(
final String msgId = formatMsgIDFromTime(now);
_messageTBox.put(
msgId,
MessageT(
senderId,
text,
@ -260,6 +264,17 @@ class _MessageInputBoxState extends State<MessageInputBox> {
final msg = {
'type': 'text/multipart',
'msgId': msgId,
'senderId': senderId,
'text': text,
'attachments': attachments,
'dateTime': now.toString(),
'isShowTime': isShowTime,
};
final msg2 = {
'type': 'text/multipart',
'msgId': msgId,
'senderId': senderId,
'text': text,
'attachments': attachments,
@ -270,6 +285,9 @@ class _MessageInputBoxState extends State<MessageInputBox> {
if (widget.chatType == 0) {
msg['event'] = 'friend-chat-msg';
msg['receiverId'] = widget.contactId;
msg2['event'] = 'friend-chat-msg';
msg2['receiverId'] = getIt.get<UserAccount>().id;
// getIt.get<WebSocketManager>().channel.sink.add(json.encode(msg2));
getIt.get<WebSocketManager>().channel.sink.add(json.encode(msg));
if (attachments.isNotEmpty) {
String baseImageDir = getIt.get<UserProfile>().baseImageDir;
@ -411,7 +429,7 @@ Future<List<String>> bytes2json(
encodedJson.add(
json.encode(
{
'event': 'friend-chat-image',
'event': 'chat-image',
'receiverId': args.$2[0],
'filename': args.$3[i],
'bytes': bytes,
@ -422,7 +440,7 @@ Future<List<String>> bytes2json(
encodedJson.add(
json.encode(
{
'event': 'friend-chat-image',
'event': 'chat-image',
'receiverIds': args.$2,
'filename': args.$3[i],
'bytes': bytes,

View File

@ -88,7 +88,7 @@ class _FriendMessageScreenState extends State<FriendMessageScreen> {
ChatSetting? chatSetting =
_chatSettingBox.get(widget.friendId);
// whethe it is a brand new chat
// whether it is a brand new chat
if (chatSetting != null) {
chatSetting.unreadCount = 0;
_chatSettingBox.put(widget.friendId, chatSetting);

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:together_mobile/database/hive_database.dart';
import 'package:together_mobile/models/apply_list_model.dart';
@ -33,11 +34,12 @@ class SettingScreen extends StatelessWidget {
child: TextButton(
onPressed: () async {
await getIt.get<Token>().clear();
// ignore: use_build_context_synchronously
context.go('/welcome');
// ignore: use_build_context_synchronously
Timer(
const Duration(milliseconds: 200),
() {
() async {
getIt.get<WebSocketManager>().disconnect();
getIt.get<UserAccount>().clear();
getIt.get<UserProfile>().clear();
@ -45,7 +47,7 @@ class SettingScreen extends StatelessWidget {
getIt.get<Contact>().clear();
getIt.get<ContactAccountProfile>().clear();
// Hive.deleteFromDisk();
HiveDatabase.close();
await HiveDatabase.close();
},
);
},

View File

@ -82,8 +82,25 @@ String formatMessageDateTime(DateTime dateTime) {
String formatDirTime(DateTime dateTime) {
int year = dateTime.year;
String month =
dateTime.month < 0 ? '0${dateTime.month}' : '${dateTime.month}';
String day = dateTime.day < 0 ? '0${dateTime.day}' : '${dateTime.day}';
dateTime.month < 10 ? '0${dateTime.month}' : '${dateTime.month}';
String day = dateTime.day < 10 ? '0${dateTime.day}' : '${dateTime.day}';
return '$year$month$day';
}
String formatMsgIDFromTime(DateTime dateTime) {
int year = dateTime.year;
String month =
dateTime.month < 10 ? '0${dateTime.month}' : '${dateTime.month}';
String day = dateTime.day < 10 ? '0${dateTime.day}' : '${dateTime.day}';
String hour = dateTime.hour < 10 ? '0${dateTime.hour}' : '${dateTime.hour}';
String minute =
dateTime.minute < 10 ? '0${dateTime.minute}' : '${dateTime.minute}';
String millisecond = dateTime.millisecond >= 100
? '${dateTime.millisecond}'
: dateTime.millisecond < 10
? '0${dateTime.minute}'
: '00${dateTime.minute}';
return '$year$month$day$hour$minute$millisecond';
}