fix websocket reconnect bug and accept unreceived msgs
parent
be64a626ce
commit
9a730d68e5
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
},
|
||||
);
|
||||
},
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue