From 77a759f06a14c334a5c5bb17f381f95e098c0d1f Mon Sep 17 00:00:00 2001 From: zsw Date: Fri, 27 Sep 2024 15:41:45 +0800 Subject: [PATCH 1/3] message type --- lib/im/SocketClient.dart | 61 +++++++++++++++++++++++++++++------- lib/im/database/message.dart | 38 +++------------------- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/lib/im/SocketClient.dart b/lib/im/SocketClient.dart index 757e808e..1ea16362 100644 --- a/lib/im/SocketClient.dart +++ b/lib/im/SocketClient.dart @@ -11,6 +11,8 @@ import 'package:huixiang/im/database/message.dart'; import 'package:huixiang/im/out/auth.pb.dart'; import 'package:huixiang/im/out/message.pb.dart'; import 'package:huixiang/main.dart'; +import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SocketClient { @@ -42,20 +44,19 @@ class SocketClient { MsgData dataResult = MsgData.fromBuffer(proto.body); print('收到来自:${dataResult.from},消息内容: ${utf8.decode(dataResult.data)} '); - Map messageMap = createMessage(userId, dataResult.data, msgType: dataResult.type.value, userId: dataResult.from); - - if (callbacks[dataResult.from] != null) { - messageMap["state"] = 1; - } - hxDatabase.insert(messageMap).then((value) { - messageMap["id"] = value; - Message message = Message.fromJson(messageMap); + receiveInsertMessage(dataResult).then((messageMap) { if (callbacks[dataResult.from] != null) { - callbacks[dataResult.from].call(message); /// user conversation callback + messageMap["state"] = 1; } - callbacks[userId]?.call(message); /// user self conversation list callback + hxDatabase.insert(messageMap).then((value) { + messageMap["id"] = value; + Message message = Message.fromJson(messageMap); + if (callbacks[dataResult.from] != null) { + callbacks[dataResult.from].call(message); /// user conversation callback + } + callbacks[userId]?.call(message); /// user self conversation list callback + }); }); - }, onError: (Object error, StackTrace stackTrace) { debugPrint("socket-listen-error: $error, stackTrace: $stackTrace"); showDebugToast("socket-listen-error: $error, stackTrace: $stackTrace"); @@ -75,6 +76,42 @@ class SocketClient { }); } + Future> receiveInsertMessage(MsgData dataResult) async { + String content = ""; + String attach = ""; + Uint8List dataBytes = dataResult.data; + MsgType type = MsgType.values[dataResult.type.value]; + if (type == MsgType.TEXT) { + content = utf8.decode(dataBytes); + } else if (type == MsgType.IMAGE || type == MsgType.VIDEO) { + Map result = await ImageGallerySaver.saveImage( + dataBytes, + isReturnImagePathOfIOS: true, + ); + bool isSuccess = result["isSuccess"] != null && result["isSuccess"]; + if (isSuccess) { + attach = result["filePath"]; + } + } else if (type == MsgType.AUDIO) { + Directory dir = await getTemporaryDirectory(); + File file = File("${dir.path}/hx_${DateTime.now().millisecondsSinceEpoch}.wav"); + try { + IOSink ioSink = file.openWrite(); + ioSink.write(dataBytes); + ioSink.close(); + attach = file.path; + } catch (e) { + debugPrint("${file.path} write fail"); + } + } else { + content = "暂不支持的消息格式"; + } + + Map messageMap = createMessage(userId, content, attach: attach, msgType: type.value, fromId: dataResult.from); + + return messageMap; + } + showDebugToast(text) { if (kDebugMode) { SmartDialog.showToast(text, alignment: Alignment.center); @@ -172,7 +209,7 @@ class SocketClient { } Future sendMessage(String toId, String content) async { - Map message = createSendMessage(toId, content, userId: userId); + Map message = createMessage(toId, content, fromId: userId); message["state"] = 1; int id = await hxDatabase.insert(message).catchError((error) { debugPrint("insertMessage: $error"); diff --git a/lib/im/database/message.dart b/lib/im/database/message.dart index 0ff06e5f..32b19389 100644 --- a/lib/im/database/message.dart +++ b/lib/im/database/message.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; @@ -7,6 +8,7 @@ import 'package:flutter/cupertino.dart'; import 'package:huixiang/im/out/message.pb.dart'; import 'package:huixiang/im/out/message.pbenum.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:path_provider/path_provider.dart'; class Message { int id; @@ -64,10 +66,10 @@ class Message { }; } -createSendMessage(var toId, String content, {String attach, int msgType, userId, replyId}) { +createMessage(var toId, String content, {String attach, int msgType, fromId, replyId}) { return { - "conversationId": conversationId(userId, toId), - "fromId": userId, + "conversationId": conversationId(fromId, toId), + "fromId": fromId, "toId": toId, "replyId": replyId, "content": content, @@ -79,36 +81,6 @@ createSendMessage(var toId, String content, {String attach, int msgType, userId, }; } -createMessage(var toId, Uint8List dataBytes, {String attach, int msgType, userId, replyId}) { - String content = ""; - MsgType type = MsgType.values[msgType]; - if (type == MsgType.TEXT) { - content = utf8.decode(dataBytes); - } - if (type == MsgType.IMAGE || type == MsgType.AUDIO || type == MsgType.VIDEO) { - Map result = ImageGallerySaver.saveImage( - dataBytes, - isReturnImagePathOfIOS: true, - ); - bool isSuccess = result["isSuccess"] != null && result["isSuccess"]; - if (isSuccess) { - attach = result["filePath"]; - } - } - - return { - "conversationId": conversationId(userId, toId), - "fromId": userId, - "toId": toId, - "replyId": replyId, - "content": content, - "attach": attach, - "msgType": msgType ?? 1, - "time": "${DateTime.now().millisecondsSinceEpoch}", - "state": 0, - "isDelete": 0 - }; -} conversationId(tid, fid) { num itid = num.parse(tid); From 5f279c87cf7973dfc11a4fcc63521354756a5cc6 Mon Sep 17 00:00:00 2001 From: zsw Date: Fri, 27 Sep 2024 16:36:33 +0800 Subject: [PATCH 2/3] message type --- lib/im/SocketClient.dart | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/im/SocketClient.dart b/lib/im/SocketClient.dart index 1ea16362..c4d3821e 100644 --- a/lib/im/SocketClient.dart +++ b/lib/im/SocketClient.dart @@ -208,8 +208,8 @@ class SocketClient { } } - Future sendMessage(String toId, String content) async { - Map message = createMessage(toId, content, fromId: userId); + Future sendMessage(String toId, String content, {String attach, int msgType, replyId}) async { + Map message = createMessage(toId, content, fromId: userId, attach: attach, msgType: msgType, replyId: replyId); message["state"] = 1; int id = await hxDatabase.insert(message).catchError((error) { debugPrint("insertMessage: $error"); @@ -223,8 +223,19 @@ class SocketClient { return Message.fromJson(message); } message["id"] = id; - Uint8List data = utf8.encode(content); - MsgData msgData = MsgData(to: toId, from: userId, type: MsgType.TEXT, data: data); + + MsgType type = MsgType.values[msgType]; + Uint8List data; + if (type == MsgType.TEXT) { + data = utf8.encode(content); + } else if (type == MsgType.IMAGE || type == MsgType.VIDEO || type == MsgType.AUDIO) { + File file = File(attach); + data = await file.readAsBytes(); + } else { + data = utf8.encode(content); + } + + MsgData msgData = MsgData(to: toId, from: userId, type: type, data: data); final proto2 = Proto(5, 1, msgData.writeToBuffer()); try { _socket.add(proto2.toBytes()); @@ -239,6 +250,8 @@ class SocketClient { return Message.fromJson(message); } + + checkSocket() { if (_socket == null) { reconnect(); From e5c2d32436d1c4638937c8fd03fe809b917e0912 Mon Sep 17 00:00:00 2001 From: zsw Date: Fri, 27 Sep 2024 17:23:27 +0800 Subject: [PATCH 3/3] message type --- lib/im/SocketClient.dart | 26 ++++--- lib/im/chat_details_page.dart | 131 ++++++++++++++++++++++++---------- 2 files changed, 109 insertions(+), 48 deletions(-) diff --git a/lib/im/SocketClient.dart b/lib/im/SocketClient.dart index c4d3821e..6709938d 100644 --- a/lib/im/SocketClient.dart +++ b/lib/im/SocketClient.dart @@ -209,6 +209,21 @@ class SocketClient { } Future sendMessage(String toId, String content, {String attach, int msgType, replyId}) async { + + MsgType type = MsgType.values[msgType]; + Uint8List data; + if (type == MsgType.TEXT) { + data = utf8.encode(content); + } else if (type == MsgType.IMAGE || type == MsgType.VIDEO || type == MsgType.AUDIO) { + File file = File(attach); + Directory dir = await getTemporaryDirectory(); + File newFile = await file.copy("${dir.path}/hx_${DateTime.now().millisecondsSinceEpoch}.${file.path.split(".")[1]}"); + data = await file.readAsBytes(); + attach = newFile.path; + } else { + data = utf8.encode(content); + } + Map message = createMessage(toId, content, fromId: userId, attach: attach, msgType: msgType, replyId: replyId); message["state"] = 1; int id = await hxDatabase.insert(message).catchError((error) { @@ -224,17 +239,6 @@ class SocketClient { } message["id"] = id; - MsgType type = MsgType.values[msgType]; - Uint8List data; - if (type == MsgType.TEXT) { - data = utf8.encode(content); - } else if (type == MsgType.IMAGE || type == MsgType.VIDEO || type == MsgType.AUDIO) { - File file = File(attach); - data = await file.readAsBytes(); - } else { - data = utf8.encode(content); - } - MsgData msgData = MsgData(to: toId, from: userId, type: type, data: data); final proto2 = Proto(5, 1, msgData.writeToBuffer()); try { diff --git a/lib/im/chat_details_page.dart b/lib/im/chat_details_page.dart index 66a9486a..51822d5b 100644 --- a/lib/im/chat_details_page.dart +++ b/lib/im/chat_details_page.dart @@ -312,6 +312,12 @@ class _ChatDetailsPage extends State } else { dynamicType = 2; } + + List filePath = mediaPaths.map((e) => e.path).toList(); + filePath.forEach((path) { + socketClient.sendMessage(_toUser.mid, "", attach: path, msgType: galleryMode == GalleryMode.image ? 2 : 4); + }); + } setState(() {}); } @@ -428,6 +434,7 @@ class _ChatDetailsPage extends State Widget chatDetailsItem(position) { bool isSelf = messages[position].fromId == selfUserId; bool isText = messages[position].msgType == 1; + bool isImage = messages[position].msgType == 2; return Container( padding: EdgeInsets.only( top: 16.h, @@ -570,11 +577,13 @@ class _ChatDetailsPage extends State GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { - Navigator.of(context).pushNamed('/router/personal_page', - arguments: { - "memberId": _toUser?.mid ?? "", - "inletType": 1 - }); + Navigator.of(context).pushNamed( + '/router/personal_page', + arguments: { + "memberId": _toUser?.mid ?? "", + "inletType": 1 + }, + ); }, child: MImage( _toUser.avatar, @@ -584,7 +593,8 @@ class _ChatDetailsPage extends State fit: BoxFit.cover, errorSrc: "assets/image/default_1.webp", fadeSrc: "assets/image/default_1.webp", - )), + ), + ), SizedBox( width: 12.w, ), @@ -807,30 +817,26 @@ class _ChatDetailsPage extends State fit: BoxFit.cover, errorSrc: "assets/image/default_1.webp", fadeSrc: "assets/image/default_1.webp", - )), + ), + ), ], ), ), /// not self image 图片 - if (!isSelf && !isText) + if (!isSelf && isImage) Padding( padding: EdgeInsets.only(left: 17.w, right: 39.w, top: 20.h), child: Row( children: [ - // MImage( - // "", - // isCircle: true, - // width: 44, - // height: 44, - // fit: BoxFit.cover, - // errorSrc: "assets/image/default_1.webp", - // fadeSrc: "assets/image/default_1.webp", - // ), - Image.asset( - "assets/image/fuka_zj.webp", - height: 44.h, - width: 44.h, + MImage( + userInfo?.headimg ?? "", + isCircle: true, + width: 44, + height: 44, + fit: BoxFit.cover, + errorSrc: "assets/image/default_1.webp", + fadeSrc: "assets/image/default_1.webp", ), SizedBox( width: 12.w, @@ -847,24 +853,74 @@ class _ChatDetailsPage extends State offset: Offset(0, 4), blurRadius: 4, spreadRadius: 0, - ) + ), ], ), child: GestureDetector( onLongPress: () { setState(() {}); }, - child: Image.asset( - "assets/image/icon_guide_4.webp", + child: Image.file( + File(messages[position].attach), width: 180.h, height: 200.h, fit: BoxFit.fill, ), - ))), + ), + ), + ), + Spacer(), + ], + ), + ), + + /// self image 图片 + if (isSelf && isImage) + Padding( + padding: EdgeInsets.only(left: 39.w, right: 17.w, top: 20.h), + child: Row( + children: [ + Spacer(), Expanded( - flex: 1, - child: Container(), - ) + flex: 3, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + color: Color(0xFFFFFFFF), + boxShadow: [ + BoxShadow( + color: Color(0xFFA8A3A3).withAlpha(12), + offset: Offset(0, 4), + blurRadius: 4, + spreadRadius: 0, + ), + ], + ), + child: GestureDetector( + onLongPress: () { + setState(() {}); + }, + child: Image.file( + File(messages[position].attach), + width: 180.h, + height: 200.h, + fit: BoxFit.fill, + ), + ), + ), + ), + SizedBox( + width: 12.w, + ), + MImage( + userInfo?.headimg ?? "", + isCircle: true, + width: 44, + height: 44, + fit: BoxFit.cover, + errorSrc: "assets/image/default_1.webp", + fadeSrc: "assets/image/default_1.webp", + ), ], ), ), @@ -922,8 +978,7 @@ class _ChatDetailsPage extends State if (commentText.trim() == "") { return; } - socketClient - .sendMessage(_toUser.mid, commentText) + socketClient.sendMessage(_toUser.mid, commentText) .then((value) { Message message = value; messages.insert(0, message); @@ -962,14 +1017,15 @@ class _ChatDetailsPage extends State "assets/image/icon_chat_emo.webp", height: 26.h, width: 26.h, - )), + ), + ), ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { - // _onMoreTap(); - // jumpToBottom(); - SmartDialog.showToast("暂不支持", alignment: Alignment.center); + _onMoreTap(); + jumpToBottom(); + // SmartDialog.showToast("暂不支持", alignment: Alignment.center); }, child: Container( padding: EdgeInsets.only(left: 8.w, right: 19.w), @@ -1123,13 +1179,14 @@ class _ChatDetailsPage extends State ), ), ], - )), + ), + ), ], - ) + ), ], ), ), - ) + ), ], ), );