Browse Source

Merge remote-tracking branch 'origin/wr_202303' into wr_202303

wr_202303
wurong 4 months ago
parent
commit
c5ed90325e
  1. 84
      lib/im/SocketClient.dart
  2. 131
      lib/im/chat_details_page.dart
  3. 38
      lib/im/database/message.dart

84
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<String, dynamic> 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<Map<String, dynamic>> 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<String, dynamic> 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<String, dynamic> messageMap = createMessage(userId, content, attach: attach, msgType: type.value, fromId: dataResult.from);
return messageMap;
}
showDebugToast(text) {
if (kDebugMode) {
SmartDialog.showToast(text, alignment: Alignment.center);
@ -171,8 +208,23 @@ class SocketClient {
}
}
Future<Message> sendMessage(String toId, String content) async {
Map<String, dynamic> message = createSendMessage(toId, content, userId: userId);
Future<Message> 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<String, dynamic> 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");
@ -186,8 +238,8 @@ 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);
MsgData msgData = MsgData(to: toId, from: userId, type: type, data: data);
final proto2 = Proto(5, 1, msgData.writeToBuffer());
try {
_socket.add(proto2.toBytes());
@ -202,6 +254,8 @@ class SocketClient {
return Message.fromJson(message);
}
checkSocket() {
if (_socket == null) {
reconnect();

131
lib/im/chat_details_page.dart

@ -312,6 +312,12 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
} else {
dynamicType = 2;
}
List<String> 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<ChatDetailsPage>
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<ChatDetailsPage>
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<ChatDetailsPage>
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<ChatDetailsPage>
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<ChatDetailsPage>
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<ChatDetailsPage>
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<ChatDetailsPage>
"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<ChatDetailsPage>
),
),
],
)),
),
),
],
)
),
],
),
),
)
),
],
),
);

38
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 <String, dynamic>{
"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<String, dynamic> result = ImageGallerySaver.saveImage(
dataBytes,
isReturnImagePathOfIOS: true,
);
bool isSuccess = result["isSuccess"] != null && result["isSuccess"];
if (isSuccess) {
attach = result["filePath"];
}
}
return <String, dynamic>{
"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);

Loading…
Cancel
Save