Browse Source

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

# Conflicts:
#	lib/im/chat_details_page.dart
#	lib/im/database/hx_database.dart
#	lib/im/im_view/im_page.dart
wr_202303
wurong 4 months ago
parent
commit
0a014a0d65
  1. 46
      lib/constant.dart
  2. 65
      lib/im/chat_details_page.dart
  3. 28
      lib/im/database/hx_database.dart
  4. 1
      lib/im/database/message.dart
  5. 29
      lib/im/im_view/im_page.dart

46
lib/constant.dart

@ -0,0 +1,46 @@
Map<S, List<T>> groupBy<S, T>(Iterable<T> values, S Function(T) key) {
var map = <S, List<T>>{};
for (var element in values) {
(map[key(element)] ??= []).add(element);
}
return map;
}
Map<String, int> groupCount<S, T>(Map<S, List<T>> values) {
var map = <String, int>{};
for (var element in values.keys) {
map["$element"] = values[element]?.length ?? 0;
}
return map;
}
Map<String, T> groupItem<S, T>(Map<S, List<T>> values) {
var map = <String, T>{};
for (var element in values.keys) {
if (values[element] == null) {
continue;
}
map["$element"] = values[element].first;
}
return map;
}
extension ListExtension<S, T> on Iterable<T> {
Map<S, List<T>> lGroupBy(S Function(T) key) {
return groupBy(this, key);
}
}
extension MapExtension<S, T> on Map<S, List<T>> {
Map<String, int> get mGroupCount => groupCount(this);
Map<String, T> get mGroupItem => groupItem(this);
}

65
lib/im/chat_details_page.dart

@ -17,8 +17,6 @@ import 'package:shared_preferences/shared_preferences.dart';
import '../../community/release_dynamic.dart'; import '../../community/release_dynamic.dart';
import '../../generated/l10n.dart'; import '../../generated/l10n.dart';
import '../../utils/font_weight.dart'; import '../../utils/font_weight.dart';
import '../retrofit/data/im_user_list.dart';
import '../view_widget/custom_image.dart';
import 'im_view/on_chat_message.dart'; import 'im_view/on_chat_message.dart';
import 'im_view/on_chat_msg_instance.dart'; import 'im_view/on_chat_msg_instance.dart';
@ -72,7 +70,6 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
socketClient.addCallback(_toUser.mid, (Message message) { socketClient.addCallback(_toUser.mid, (Message message) {
messages.add(message); messages.add(message);
refreshState(); refreshState();
}); });
refreshState(); refreshState();
@ -155,7 +152,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
commentFocus.removeListener(_focusNodeListener); commentFocus.removeListener(_focusNodeListener);
socketClient.removeCallback(_toUser.mid); socketClient.removeCallback(toUserId);
} }
@ -251,7 +248,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
// resizeToAvoidBottomInset: false, // resizeToAvoidBottomInset: false,
backgroundColor: Color(0xFFF6F6F6), backgroundColor: Color(0xFFF6F6F6),
appBar: MyAppBar( appBar: MyAppBar(
title: _toUser.nickname, title: "哈哈哈哈",
titleColor: Color(0xFF0D0D0D), titleColor: Color(0xFF0D0D0D),
titleSize: 17.sp, titleSize: 17.sp,
leading: true, leading: true,
@ -368,7 +365,6 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
height: 16.h, height: 16.h,
), ),
if (copyIndex == 1) if (copyIndex == 1)
///
Stack( Stack(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
children: [ children: [
@ -458,14 +454,19 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
padding: EdgeInsets.only(left: 17.w, right: 39.w), padding: EdgeInsets.only(left: 17.w, right: 39.w),
child: Row( child: Row(
children: [ children: [
MImage( // MImage(
_toUser.avatar, // "",
isCircle: true, // isCircle: true,
// width: 44,
// height: 44,
// fit: BoxFit.cover,
// errorSrc: "assets/image/default_user.webp",
// fadeSrc: "assets/image/default_user.webp",
// ),
Image.asset(
"assets/image/fuka_zj.webp",
height: 44.h, height: 44.h,
width: 44.h, width: 44.h,
fit: BoxFit.cover,
errorSrc: "assets/image/default_1.webp",
fadeSrc: "assets/image/default_1.webp",
), ),
SizedBox( SizedBox(
width: 12.w, width: 12.w,
@ -655,14 +656,19 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
SizedBox( SizedBox(
width: 12.w, width: 12.w,
), ),
MImage( // MImage(
"", // "",
isCircle: true, // isCircle: true,
height: 44.h, // width: 44,
width: 44.h, // height: 44,
fit: BoxFit.cover, // fit: BoxFit.cover,
errorSrc: "assets/image/default_1.webp", // errorSrc: "assets/image/default_user.webp",
fadeSrc: "assets/image/default_1.webp", // fadeSrc: "assets/image/default_user.webp",
// ),
Image.asset(
"assets/image/fuka_zj.webp",
height: 44,
width: 44,
), ),
], ],
), ),
@ -674,14 +680,19 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
padding: EdgeInsets.only(left: 17.w, right: 39.w, top: 20.h), padding: EdgeInsets.only(left: 17.w, right: 39.w, top: 20.h),
child: Row( child: Row(
children: [ children: [
MImage( // MImage(
_toUser.avatar, // "",
isCircle: true, // isCircle: true,
// width: 44,
// height: 44,
// fit: BoxFit.cover,
// errorSrc: "assets/image/default_user.webp",
// fadeSrc: "assets/image/default_user.webp",
// ),
Image.asset(
"assets/image/fuka_zj.webp",
height: 44.h, height: 44.h,
width: 44.h, width: 44.h,
fit: BoxFit.cover,
errorSrc: "assets/image/default_1.webp",
fadeSrc: "assets/image/default_1.webp",
), ),
SizedBox( SizedBox(
width: 12.w, width: 12.w,
@ -773,7 +784,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
if (commentText.trim() == "") { if (commentText.trim() == "") {
return; return;
} }
socketClient.sendMessage(_toUser.mid, commentText).then((value) { socketClient.sendMessage(toUserId, commentText).then((value) {
Message message = value; Message message = value;
messages.insert(0, message); messages.insert(0, message);
chatController.clear(); chatController.clear();

28
lib/im/database/hx_database.dart

@ -45,11 +45,11 @@ class HxDatabase {
List<Message> messages = List<Message> messages =
await db.rawQuery(sql, [userId, userId]).then((value) { await db.rawQuery(sql, [userId, userId]).then((value) {
return value.map((e) { return value.map((e) {
debugPrint("Message: ${e}"); debugPrint("Message: $e");
return Message.fromJson(e); return Message.fromJson(e);
}).toList(); }).toList();
}, onError: (error) { }, onError: (error) {
debugPrint("Messageerror: $error"); debugPrint("Message_error: $error");
}); });
return (messages?.isNotEmpty ?? false) ? messages.first : null; return (messages?.isNotEmpty ?? false) ? messages.first : null;
} }
@ -83,6 +83,22 @@ class HxDatabase {
}); });
} }
Future<Map<String, int>> messageUnreadCount(List<String> userIds, String selfUserId) async {
if (db == null) {
return Future.value({});
}
List<Message> messages = await db.query(
"Message",
where: 'fromId IN (?) AND toId = ? AND state = 0 AND isDelete = 0',
whereArgs: []..addAll(userIds)..add(selfUserId)
).then((value) {
return value.map((e) => Message.fromJson(e)).toList();
}, onError: (error) {
debugPrint("Message-error: $error");
});
return messages.lGroupBy((p)=> p.fromId).mGroupCount;
}
Future<List<Map>> queryListAll() { Future<List<Map>> queryListAll() {
if (db == null) { if (db == null) {
return Future.value(); return Future.value();
@ -111,7 +127,13 @@ class HxDatabase {
debugPrint("Message_insert: $message"); debugPrint("Message_insert: $message");
return db.insert("Message", message); return db.insert("Message", message);
} }
/// update message read state
readMessage(String selfUserId, String userId) {
if (db == null) {
return Future.value(<Message>[]);
}
db.update("Message", {"state": 1}, where: "fromId = ? AND toId = ? AND state = 0 AND isDelete = 0", whereArgs: [userId, selfUserId]);
}
Future<int> insertOrUpdateImUser(Map imUserMap) async { Future<int> insertOrUpdateImUser(Map imUserMap) async {
if (db == null) { if (db == null) {
return Future.value(0); return Future.value(0);

1
lib/im/database/message.dart

@ -16,6 +16,7 @@ class Message {
String time; String time;
/// 0 unread, 1 read, 2
int state; int state;
int isDelete; int isDelete;

29
lib/im/im_view/im_page.dart

@ -88,6 +88,8 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
List<String> userIds = []; List<String> userIds = [];
Map<String, Message> lastMessageMap = {}; Map<String, Message> lastMessageMap = {};
Stream streamSubscription; Stream streamSubscription;
Map<String, int> unreadCountMap = {};
Stream streamSubscription ;
loadMessageList() async { loadMessageList() async {
SharedPreferences shared = await SharedPreferences.getInstance(); SharedPreferences shared = await SharedPreferences.getInstance();
@ -120,9 +122,10 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
.map((e) => e.toId != userId ? e.toId : e.fromId) .map((e) => e.toId != userId ? e.toId : e.fromId)
.toSet() .toSet()
.where((element) => element != userId) .where((element) => element != userId)
.toList(); // .toList();
List<ImUserList> contacts = (await hxDatabase.queryImUser(userIds)) ?? []; List<ImUserList> contacts = (await hxDatabase.queryImUser(userIds)) ?? [];
unreadCountMap = await hxDatabase.messageUnreadCount(userIds, userId);
if (contacts.isNotEmpty) imUserList = groupBy(contacts, (p0) => p0.mid); if (contacts.isNotEmpty) imUserList = groupBy(contacts, (p0) => p0.mid);
lastMessageMap = lastMessageMap =
@ -138,15 +141,19 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
Message message = await hxDatabase.lastMessage(userId); Message message = await hxDatabase.lastMessage(userId);
if (message != null) { if (message != null) {
lastMessageMap[userId] = message; lastMessageMap[userId] = message;
refreshState();
} }
} }
Map<S, T> groupBy<S, T>(Iterable<T> values, S Function(T) key) { void updateUnreadCount() async {
var map = <S, T>{}; SharedPreferences shared = await SharedPreferences.getInstance();
for (var element in values) { String userId = shared.getString("userId");
map[key(element)] ??= element; unreadCountMap = await hxDatabase.messageUnreadCount(userIds, userId);
} refreshState();
return map; }
refreshState() {
if (mounted) setState(() {});
} }
// queryMessage() async { // queryMessage() async {
@ -195,8 +202,9 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
token: value.getString("token"), token: value.getString("token"),
); );
} }
BaseData<List<MsgStats>> baseData = BaseData<List<MsgStats>> baseData = await apiService.stats().catchError((onError) {
await apiService.stats().catchError((onError) {}); debugPrint("stats.error: $onError");
});
if (baseData != null && baseData.isSuccess) { if (baseData != null && baseData.isSuccess) {
setState(() { setState(() {
msgNumber.forEach((key, value) { msgNumber.forEach((key, value) {
@ -302,8 +310,7 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
Navigator.of(context) Navigator.of(context)
.pushNamed('/router/chat_friend_group') .pushNamed('/router/chat_friend_group').then((value) {
.then((value) {
_refresh(); _refresh();
}); });
}, },

Loading…
Cancel
Save