Browse Source

add message conversationId; conversion list refresh sort; message list align top

wr_202303
zsw 4 months ago
parent
commit
51ec8411de
  1. 29
      lib/im/chat_details_page.dart
  2. 48
      lib/im/database/hx_database.dart
  3. 18
      lib/im/database/message.dart
  4. 308
      lib/im/im_view/im_page.dart

29
lib/im/chat_details_page.dart

@ -4,6 +4,7 @@ import 'dart:ui';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -66,6 +67,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
int copyIndex = 0; int copyIndex = 0;
String selfUserId = ""; String selfUserId = "";
ImUser _toUser; ImUser _toUser;
String conversation ;
@override @override
void onMessage(txt) { void onMessage(txt) {
@ -77,14 +79,16 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
int page = 0; int page = 0;
loadMessageList() async { loadMessageList() async {
ImUser imUser = await hxDatabase.queryImUserById(_toUser.mid); selfUserId = (await SharedPreferences.getInstance()).getString("userId");
conversation = conversationId(selfUserId, _toUser.mid);
ImUser imUser = await hxDatabase.queryImUserById(conversation);
if (imUser == null) { if (imUser == null) {
await hxDatabase.insertOrUpdateImUser(_toUser.toJson()); await hxDatabase.insertOrUpdateImUser(_toUser.toJson());
} }
selfUserId = (await SharedPreferences.getInstance()).getString("userId");
// unread msg 2 read state // unread msg 2 read state
await hxDatabase.readMessage(selfUserId, _toUser.mid); await hxDatabase.readMessage(conversation);
await refresh(); await refresh();
socketClient.addCallback(_toUser.mid, (Message message) { socketClient.addCallback(_toUser.mid, (Message message) {
@ -100,7 +104,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
Future refresh() async { Future refresh() async {
List<Message> messagePage = List<Message> messagePage =
await hxDatabase.queryUList(_toUser.mid, page: page + 1, pageSize: 10); await hxDatabase.queryUList(conversation, page: page + 1, pageSize: 10);
page += 1; page += 1;
if (page == 1) { if (page == 1) {
messages = messagePage; messages = messagePage;
@ -118,7 +122,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
} }
Future messageShowTime() async { Future messageShowTime() async {
List<Message> messagePages = await hxDatabase.queryTList(_toUser.mid); List<Message> messagePages = await hxDatabase.queryTList(conversation);
for (var value in messages) { for (var value in messages) {
Message message = messagePages.firstWhere((element) => value.id == element.id, orElse: () => null); Message message = messagePages.firstWhere((element) => value.id == element.id, orElse: () => null);
value.showTime = message != null; value.showTime = message != null;
@ -318,7 +322,6 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
// setState(() {}); // setState(() {});
} }
} }
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () { onTap: () {
@ -372,9 +375,6 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
footer: CustomFooter( footer: CustomFooter(
loadStyle: LoadStyle.ShowWhenLoading, loadStyle: LoadStyle.ShowWhenLoading,
builder: (BuildContext context, LoadStatus mode) { builder: (BuildContext context, LoadStatus mode) {
// return (messages.length == 0)
// ? Container()
// : MyFooter(mode);
return SizedBox(); return SizedBox();
}, },
), ),
@ -384,10 +384,13 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
refreshState(); refreshState();
}); });
}, },
child: SingleChildScrollView( child: Container(
alignment: Alignment.topCenter,
child: SingleChildScrollView(
physics: BouncingScrollPhysics(), physics: BouncingScrollPhysics(),
controller: scrollController, controller: scrollController,
child: chatDetailsList(), child: chatDetailsList(),
),
), ),
), ),
flex: 1, flex: 1,
@ -403,11 +406,12 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
/// ///
Widget chatDetailsList() { Widget chatDetailsList() {
return Container( return Container(
margin: EdgeInsets.only(bottom: 48.h), alignment: Alignment.topCenter,
child: ListView.builder( child: ListView.builder(
itemCount: messages.length, itemCount: messages.length,
shrinkWrap: true, shrinkWrap: true,
reverse: true, reverse: true,
padding: EdgeInsets.zero,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, position) { itemBuilder: (context, position) {
return GestureDetector( return GestureDetector(
@ -430,7 +434,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
bool isText = messages[position].msgType == 1; bool isText = messages[position].msgType == 1;
return Container( return Container(
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: 32.h, top: 16.h,
bottom: 16.h,
), ),
child: Column( child: Column(
children: [ children: [

48
lib/im/database/hx_database.dart

@ -22,7 +22,7 @@ class HxDatabase {
await openDatabase(databaseName, version: 2, await openDatabase(databaseName, version: 2,
onCreate: (Database db, int version) async { onCreate: (Database db, int version) async {
db.execute( db.execute(
'CREATE TABLE IF NOT EXISTS `Message` (`id` INTEGER, `fromId` VARCHAR(20), `toId` VARCHAR(20), `replyId` VARCHAR(20), `content` TEXT, `attach` TEXT, `msgType` INTEGER, `time` VARCHAR(20), `state` INTEGER, `isDelete` INTEGER, PRIMARY KEY (`id`))'); 'CREATE TABLE IF NOT EXISTS `Message` (`id` INTEGER, `conversationId` VARCHAR(40), `fromId` VARCHAR(20), `toId` VARCHAR(20), `replyId` VARCHAR(20), `content` TEXT, `attach` TEXT, `msgType` INTEGER, `time` VARCHAR(20), `state` INTEGER, `isDelete` INTEGER, PRIMARY KEY (`id`))');
db.execute( db.execute(
'CREATE TABLE IF NOT EXISTS `ImUser` (`id` INTEGER, `mid` VARCHAR(20), `nickname` VARCHAR(20), `avatar` VARCHAR(200), `phone` VARCHAR(200), `isDelete` INTEGER, `isTop` INTEGER, PRIMARY KEY (`id`))'); 'CREATE TABLE IF NOT EXISTS `ImUser` (`id` INTEGER, `mid` VARCHAR(20), `nickname` VARCHAR(20), `avatar` VARCHAR(200), `phone` VARCHAR(200), `isDelete` INTEGER, `isTop` INTEGER, PRIMARY KEY (`id`))');
}, onConfigure: (database) async { }, onConfigure: (database) async {
@ -49,12 +49,12 @@ class HxDatabase {
} }
} }
Future<Message> lastMessage(String userId) async { Future<Message> lastMessage(String conversationId) async {
await _dbIsOpen(); await _dbIsOpen();
String sql = String sql =
'SELECT * FROM Message WHERE toId = ? OR fromId = ? ORDER BY time DESC LIMIT 1'; 'SELECT * FROM Message WHERE conversationId = ? ORDER BY time DESC LIMIT 1';
List<Message> messages = List<Message> messages =
await db.rawQuery(sql, [userId, userId]).then((value) { await db.rawQuery(sql, [conversationId]).then((value) {
return value.map((e) { return value.map((e) {
debugPrint("Message: $e"); debugPrint("Message: $e");
return Message.fromJson(e); return Message.fromJson(e);
@ -72,56 +72,54 @@ class HxDatabase {
WHERE ROWID IN ( WHERE ROWID IN (
SELECT ROWID SELECT ROWID
FROM ( FROM (
SELECT ROWID, `fromId`, `toId`, MAX(`time`) AS max_time SELECT ROWID, conversationId, MAX(`time`) AS max_time
FROM `Message` FROM `Message`
GROUP BY `fromId` || '_' || `toId`, `toId` || '_' || `fromId` GROUP BY conversationId
) AS grouped_messages ) AS grouped_messages
WHERE max_time = ( WHERE max_time = (
SELECT MAX(`time`) SELECT MAX(`time`)
FROM `Message` FROM `Message`
WHERE (`fromId` = grouped_messages.`fromId` AND `toId` = grouped_messages.`toId`) WHERE conversationId = grouped_messages.conversationId
OR (`fromId` = grouped_messages.`toId` AND `toId` = grouped_messages.`fromId`)
) )
) )
ORDER BY `time` DESC;'''; ORDER BY `time` DESC;''';
return db.rawQuery(sql).then((value) { return db.rawQuery(sql).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("MessageError: $error");
}); });
} }
Future<List<Message>> queryUList(userId, {int page = 1, int pageSize = 10}) async{ Future<List<Message>> queryUList(conversationId, {int page = 1, int pageSize = 10}) async{
await _dbIsOpen(); await _dbIsOpen();
int start = (page - 1) * pageSize; int start = (page - 1) * pageSize;
String sql = String sql = 'SELECT * FROM Message WHERE conversationId = ? ORDER BY time DESC LIMIT ?, ?';
'SELECT * FROM Message WHERE toId = ? OR fromId = ? ORDER BY time DESC LIMIT ?, ?'; return db.rawQuery(sql, [conversationId, start, pageSize]).then((value) {
return db.rawQuery(sql, [userId, userId, start, pageSize]).then((value) {
return value.map((e) => Message.fromJson(e)).toList(); return value.map((e) => Message.fromJson(e)).toList();
}, onError: (error) { }, onError: (error) {
debugPrint("Messageerror: $error"); debugPrint("Messageerror: $error");
}); });
} }
Future<List<Message>> queryTList(userId) async{ Future<List<Message>> queryTList(conversationId) async{
await _dbIsOpen(); await _dbIsOpen();
String sql = 'SELECT *, time / 300000 * 300000 AS time_interval FROM Message WHERE toId = ? OR fromId = ? GROUP BY time_interval ORDER BY time DESC'; String sql = 'SELECT *, time / 300000 * 300000 AS time_interval FROM Message WHERE conversationId = ? GROUP BY time_interval ORDER BY time DESC';
return db.rawQuery(sql, [userId, userId]).then((value) { return db.rawQuery(sql, [conversationId]).then((value) {
return value.map((e) => Message.fromJson(e)).toList(); return value.map((e) => Message.fromJson(e)).toList();
}, onError: (error) { }, onError: (error) {
debugPrint("Messageerror: $error"); debugPrint("Messageerror: $error");
}); });
} }
Future<Map<String, int>> messageUnreadCount(List<String> userIds, String selfUserId) async { Future<Map<String, int>> messageUnreadCount(List<String> conversationIds) async {
await _dbIsOpen(); await _dbIsOpen();
String userStr = userIds.join(","); String userStr = conversationIds.join(",");
debugPrint("userStr: $userStr"); debugPrint("userStr: $userStr");
List<Message> messages = await db.rawQuery( List<Message> messages = await db.rawQuery(
"SELECT * FROM Message WHERE fromId IN ($userStr) AND toId = $selfUserId AND state = 0 AND isDelete = 0", "SELECT * FROM Message WHERE `conversationId` IN ($userStr) AND state = 0 AND isDelete = 0",
).then((value) { ).then((value) {
return value.map((e) => Message.fromJson(e)).toList(); return value.map((e) => Message.fromJson(e)).toList();
}, onError: (error) { }, onError: (error) {
@ -136,8 +134,8 @@ class HxDatabase {
return db.rawQuery(sql); return db.rawQuery(sql);
} }
Future<int> deleteByUser(String userId) async { Future<int> deleteByUser(String conversationId) async {
return db.delete("Message",where: "fromId = ? OR toId = ?", whereArgs: [userId, userId]); return db.delete("Message",where: "conversationId = ?", whereArgs: [conversationId]);
} }
Future<int> deleteAll() async { Future<int> deleteAll() async {
@ -158,11 +156,11 @@ class HxDatabase {
} }
/// update message read state /// update message read state
readMessage(String selfUserId, String userId) async{ readMessage(String conversationId) async{
await _dbIsOpen(); await _dbIsOpen();
db.update("Message", {"state": 1}, db.update("Message", {"state": 1},
where: "fromId = ? AND toId = ? AND state = 0 AND isDelete = 0", where: "conversationId = ? AND state = 0 AND isDelete = 0",
whereArgs: [userId, selfUserId]); whereArgs: [conversationId]);
} }
Future<int> insertOrUpdateImUser(Map imUserMap) async { Future<int> insertOrUpdateImUser(Map imUserMap) async {

18
lib/im/database/message.dart

@ -1,7 +1,11 @@
import 'dart:math';
class Message { class Message {
int id; int id;
String conversationId;
String fromId; String fromId;
String toId; String toId;
@ -23,10 +27,11 @@ class Message {
bool showTime = false; bool showTime = false;
Message(this.id, this.fromId, this.toId, this.replyId, this.content, this.attach, this.msgType, this.time, this.state, this.isDelete); Message(this.id, this.conversationId, this.fromId, this.toId, this.replyId, this.content, this.attach, this.msgType, this.time, this.state, this.isDelete);
factory Message.fromJson(Map<String, dynamic> json) => Message( factory Message.fromJson(Map<String, dynamic> json) => Message(
json["id"], json["id"],
json["conversationId"],
json["fromId"], json["fromId"],
json["toId"], json["toId"],
json["replyId"], json["replyId"],
@ -39,6 +44,7 @@ class Message {
Map<String, dynamic> toJson() => <String, dynamic>{ Map<String, dynamic> toJson() => <String, dynamic>{
"id": id, "id": id,
"conversationId": conversationId,
"fromId": fromId, "fromId": fromId,
"toId": toId, "toId": toId,
"replyId": replyId, "replyId": replyId,
@ -53,6 +59,7 @@ class Message {
createMessage(var toId, String content, {String attach, int msgType, userId, replyId}) { createMessage(var toId, String content, {String attach, int msgType, userId, replyId}) {
return <String, dynamic>{ return <String, dynamic>{
"conversationId": conversationId(userId, toId),
"fromId": userId, "fromId": userId,
"toId": toId, "toId": toId,
"replyId": replyId, "replyId": replyId,
@ -64,3 +71,12 @@ createMessage(var toId, String content, {String attach, int msgType, userId, rep
"isDelete": 0 "isDelete": 0
}; };
} }
conversationId(tid, fid) {
num itid = num.parse(tid);
num ifid = num.parse(fid);
if (itid > ifid) {
return "$ifid-$itid";
}
return "$itid-$ifid";
}

308
lib/im/im_view/im_page.dart

@ -43,11 +43,12 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
"6": 0, "6": 0,
}; };
int state = 0; int state = 0;
List<String> userIds = []; List<String> conversationIds = [];
Map<String, Message> lastMessageMap = {}; Map<String, Message> lastMessageMap = {};
Map<String, int> unreadCountMap = {}; Map<String, int> unreadCountMap = {};
Map<String, ImUser> contactMap = {}; Map<String, ImUser> contactMap = {};
int insertIndex = 0; int insertIndex = 0;
String selfUserId;
@override @override
void onMessage(txt) { void onMessage(txt) {
@ -77,14 +78,14 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
initSocketClient() async { initSocketClient() async {
SharedPreferences shared = await SharedPreferences.getInstance(); SharedPreferences shared = await SharedPreferences.getInstance();
String userId = shared.getString("userId"); selfUserId = shared.getString("userId");
socketClient.addCallback(userId, (Message message) { socketClient.addCallback(selfUserId, (Message message) {
if (userIds.contains(message.fromId)) { if (conversationIds.contains(message.conversationId)) {
userIds.remove(message.fromId); conversationIds.remove(message.conversationId);
} }
userIds.insert(insertIndex, message.fromId); conversationIds.insert(insertIndex, message.conversationId);
lastMessageMap[message.fromId] = message; lastMessageMap[message.conversationId] = message;
listenerRefresh(message); listenerRefresh(message);
}); });
@ -99,12 +100,9 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
} }
listenerRefresh(Message message) async { listenerRefresh(Message message) async {
SharedPreferences shared = await SharedPreferences.getInstance();
String userId = shared.getString("userId");
await sortConversation(lastMessageMap); await sortConversation(lastMessageMap);
await queryUnreadCount(userIds, userId); await queryUnreadCount(conversationId);
debugPrint("messages_records : ${message.toJson()}"); debugPrint("messages_records : ${message.toJson()}");
if (contactMap[message.fromId] == null) { if (contactMap[message.fromId] == null) {
@ -115,38 +113,35 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
} }
loadMessageList() async { loadMessageList() async {
SharedPreferences shared = await SharedPreferences.getInstance();
String userId = shared.getString("userId");
messages = await hxDatabase.queryList(); messages = await hxDatabase.queryList();
lastMessageMap = messages.lGroupBy((p0) => p0.toId != userId ? p0.toId : p0.fromId).mGroupItem(key: (p1) => num.parse(p1.time)); lastMessageMap = messages.lGroupBy((p0) => p0.conversationId).mGroupItem(key: (p1) => num.parse(p1.time));
await sortConversation(lastMessageMap); await queryImUserInfo(messages.map((e) => e.toId != selfUserId ? e.toId : e.fromId).toList());
await queryUnreadCount(userIds, userId); await sortConversation(lastMessageMap);
await queryImUserInfo(userIds); await queryUnreadCount(conversationIds);
refreshState(); refreshState();
} }
/// update conversation by time sort /// update conversation by time sort
sortConversation(lastMessageMap) async { sortConversation(lastMessageMap) async {
SharedPreferences shared = await SharedPreferences.getInstance();
String userId = shared.getString("userId");
List<Message> sortMessages = lastMessageMap.values.toList(); List<Message> sortMessages = lastMessageMap.values.toList();
sortMessages.sort((a, b) => (num.parse(b.time)).compareTo(num.parse(a.time))); sortMessages.sort((a, b) => (num.parse(b.time)).compareTo(num.parse(a.time)));
userIds = sortMessages conversationIds = sortMessages
.map((e) => e.toId != userId ? e.toId : e.fromId) .map((e) => e.conversationId)
.toSet() .toSet()
.where((element) => element != userId)
.toList(); .toList();
conversationIds.forEach((element) {
debugPrint("conversationIds: ${element}");
});
} }
/// update conversation unreadcount /// update conversation unreadcount
queryUnreadCount(userIds, userId) async { queryUnreadCount(conversationId) async {
unreadCountMap = await hxDatabase.messageUnreadCount(userIds, userId); unreadCountMap = await hxDatabase.messageUnreadCount(conversationId);
debugPrint("unreadCount: $unreadCountMap");
} }
/// update imuser info by mids /// update imuser info by mids
@ -162,33 +157,31 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
return; return;
} }
} }
contactMap = contacts.lGroupBy((p0) => p0.mid).mGroupItem(); contactMap = contacts.lGroupBy((p0) => conversationId(p0.mid, selfUserId)).mGroupItem();
List<String> topUserIds = [],notTopUserIds = []; List<String> topConversationIds = [],notTopUserIds = [];
contactMap.forEach((key, value) { contactMap.forEach((key, value) {
if(value.isTop == 1) if(value.isTop == 1)
topUserIds.add(key); topConversationIds.add(key);
else else
notTopUserIds.add(key); notTopUserIds.add(key);
}); });
insertIndex = topUserIds.length; insertIndex = topConversationIds.length;
this.userIds = topUserIds..addAll(notTopUserIds); this.conversationIds = topConversationIds..addAll(notTopUserIds);
} }
/// update one conversation last message ,and update conversation sort /// update one conversation last message ,and update conversation sort
void updateLastMessage(String userId) async { void updateLastMessage(String conversationId) async {
Message message = await hxDatabase.lastMessage(userId); Message message = await hxDatabase.lastMessage(conversationId);
debugPrint("lastmessage: $userId ${message.content} ${message.toJson()}"); debugPrint("lastmessage: $conversationId ${message.content} ${message.toJson()}");
if (message != null) { if (message != null) {
lastMessageMap[userId] = message; lastMessageMap[conversationId] = message;
await sortConversation(lastMessageMap); await sortConversation(lastMessageMap);
refreshState(); refreshState();
} }
} }
void updateUnreadCount() async { void updateUnreadCount() async {
SharedPreferences shared = await SharedPreferences.getInstance(); unreadCountMap = await hxDatabase.messageUnreadCount(conversationIds);
String userId = shared.getString("userId");
unreadCountMap = await hxDatabase.messageUnreadCount(userIds, userId);
refreshState(); refreshState();
} }
@ -216,8 +209,8 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
await hxDatabase.insertOrUpdateImUser(element.toJson()); await hxDatabase.insertOrUpdateImUser(element.toJson());
}); });
baseData.data.forEach((element) { baseData.data.forEach((element) {
if (contactMap[element.mid] == null) { if (contactMap[conversationId(element.mid, selfUserId)] == null) {
contactMap[element.mid] = element; contactMap[conversationId(element.mid, selfUserId)] = element;
} }
}); });
refreshState(); refreshState();
@ -233,93 +226,89 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Color(0xFFFFFFFF), backgroundColor: Color(0xFFFFFFFF),
body: SmartRefresher( body: Container(
enablePullDown: true, decoration: BoxDecoration(
enablePullUp: false, gradient: LinearGradient(
header: MyHeader(), begin: Alignment.topCenter,
physics: BouncingScrollPhysics(), end: Alignment.bottomCenter,
footer: CustomFooter( colors: [
loadStyle: LoadStyle.ShowWhenLoading, Color(0xFFD9FFDE),
builder: (BuildContext context, LoadStatus mode) { Color(0xFFD9FFDE),
return (messages.length == 0) ? Container() : MyFooter(mode); Color(0xFFFFFFFF),
}, Color(0xFFFFFFFF),
],
stops: [0, 0.2, 0.4, 1],
),
), ),
controller: _refreshController, child: SmartRefresher(
onRefresh: _refresh, enablePullDown: true,
onLoading: () { enablePullUp: false,
_refresh(); header: MyHeader(),
}, physics: BouncingScrollPhysics(),
child: Container( footer: CustomFooter(
// color: Colors.white, loadStyle: LoadStyle.ShowWhenLoading,
decoration: BoxDecoration( builder: (BuildContext context, LoadStatus mode) {
gradient: LinearGradient( return (messages.length == 0) ? Container() : MyFooter(mode);
begin: Alignment.topCenter, },
end: Alignment.bottomCenter,
colors: [
Color(0xFFD9FFDE),
Color(0xFFD9FFDE),
Color(0xFFFFFFFF),
Color(0xFFFFFFFF),
],
stops: [0, 0.2, 0.4, 1],
),
), ),
controller: _refreshController,
onRefresh: _refresh,
onLoading: () {
_refresh();
},
child: SingleChildScrollView( child: SingleChildScrollView(
physics: BouncingScrollPhysics(), physics: BouncingScrollPhysics(),
child: Container( child: Column(
padding: EdgeInsets.only(bottom: 30.h), children: [
child: Column( Container(
children: [ padding: EdgeInsets.only(
Container( top: MediaQuery.of(context).padding.top + 12.h,
padding: EdgeInsets.only( bottom: 15.h,
top: MediaQuery.of(context).padding.top + 12.h, right: 16.w,
bottom: 15.h, left: 16.w,
right: 16.w, ),
left: 16.w), child: Row(
child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, children: [
children: [ Expanded(
Expanded( child: Text(
child: Text( S.of(context).xiaoxi,
S.of(context).xiaoxi, style: TextStyle(
style: TextStyle( color: Colors.black,
color: Colors.black, fontSize: 18.sp,
fontSize: 18.sp, fontWeight: MyFontWeight.bold,
fontWeight: MyFontWeight.bold,
),
), ),
), ),
GestureDetector( ),
behavior: HitTestBehavior.opaque, GestureDetector(
onTap: () { behavior: HitTestBehavior.opaque,
Navigator.of(context) onTap: () {
.pushNamed('/router/chat_friend_group').then((value) { Navigator.of(context).pushNamed('/router/chat_friend_group')
_refresh(); .then((value) {
}); _refresh();
}, });
child: Container( },
padding: EdgeInsets.all(12), child: Container(
decoration: BoxDecoration( padding: EdgeInsets.all(12),
color: Color(0xFFFFFFFF), decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r), color: Color(0xFFFFFFFF),
), borderRadius: BorderRadius.circular(20.r),
child: Image.asset( ),
"assets/image/friend_grouping.webp", child: Image.asset(
fit: BoxFit.fill, "assets/image/friend_grouping.webp",
height: 14.h, fit: BoxFit.fill,
width: 14.h, height: 14.h,
), width: 14.h,
), ),
), ),
], ),
), ],
), ),
imPageSearch(), ),
chatList(), imPageSearch(),
// buildMessage(),fgg chatList(),
], ],
),
), ),
), ),
), ),
@ -372,12 +361,13 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
Widget chatList() { Widget chatList() {
return Container( return Container(
child: SlidableAutoCloseBehavior( child: SlidableAutoCloseBehavior(
child: ListView.builder( child: ListView(
padding: EdgeInsets.only(top: 16), padding: EdgeInsets.only(top: 16),
itemCount: userIds.length,
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, position) { children: conversationIds.map((e) {
debugPrint("---conversationIds: ${e}");
int position = conversationIds.indexOf(e);
return ClipRRect( return ClipRRect(
// borderRadius: BorderRadius.all(Radius.circular(4)), // borderRadius: BorderRadius.all(Radius.circular(4)),
child: Slidable( child: Slidable(
@ -388,7 +378,7 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
children: [ children: [
CustomSlidableAction( CustomSlidableAction(
onPressed: (bc) { onPressed: (bc) {
showDelDialog(userIds[position]); showDelDialog(conversationIds[position]);
}, },
backgroundColor: Color(0xFFFB312B), backgroundColor: Color(0xFFFB312B),
foregroundColor: Colors.white, foregroundColor: Colors.white,
@ -408,42 +398,41 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
), ),
], ],
), ),
child:GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
if (userIds[position] == sharedPreferences.getString("userId")) { Navigator.of(context).pushNamed(
SmartDialog.showToast("不能跟自己聊天", alignment: Alignment.center); '/router/chat_details_page',
return; arguments: {
} "toUser": contactMap[conversationIds[position]],
Navigator.of(context).pushNamed( },
'/router/chat_details_page', ).then((value) {
arguments: { unreadCountMap[conversationIds[position]] = 0;
"toUser": contactMap[userIds[position]], updateLastMessage(conversationIds[position]);
}, _refresh();
).then((value) { });
unreadCountMap[userIds[position]] = 0; },
updateLastMessage(userIds[position]); child: chatItem(conversationIds[position]),
_refresh(); ),
});
},
child: chatItem(userIds[position])),
), ),
); );
}, }).toList(),
), ),
), ),
); );
} }
Widget chatItem(userId) { Widget chatItem(conversationId) {
return Container( return Container(
padding: EdgeInsets.only(left: 16.w, right: 17.w, bottom: 18.h), padding: EdgeInsets.only(
left: 16.w, right: 17.w, bottom: 18.h,
),
child: Row( child: Row(
children: [ children: [
MImage( MImage(
!contactMap.containsKey(userId) !contactMap.containsKey(conversationId)
? null ? null
: contactMap[userId]?.avatar ?? "", : contactMap[conversationId]?.avatar ?? "",
isCircle: true, isCircle: true,
height: 54.h, height: 54.h,
width: 54.h, width: 54.h,
@ -462,9 +451,9 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
!contactMap.containsKey(userId) !contactMap.containsKey(conversationId)
? "" ? ""
: contactMap[userId]?.nickname ?? "", : contactMap[conversationId]?.nickname ?? "",
// overflow: TextOverflow.fade, // overflow: TextOverflow.fade,
maxLines: 1, maxLines: 1,
style: TextStyle( style: TextStyle(
@ -475,10 +464,10 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
), ),
), ),
Text( Text(
lastMessageMap[userId]?.time != null lastMessageMap[conversationId]?.time != null
? AppUtils.timeFormatter( ? AppUtils.timeFormatter(
DateTime.fromMillisecondsSinceEpoch(num.parse( DateTime.fromMillisecondsSinceEpoch(num.parse(
lastMessageMap[userId]?.time ?? ""))) lastMessageMap[conversationId]?.time ?? "")))
: "", : "",
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
@ -495,7 +484,7 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
lastMessageMap[userId]?.content ?? "", lastMessageMap[conversationId]?.content ?? "",
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
@ -505,7 +494,7 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
), ),
), ),
), ),
if (unreadCountMap[userId] != null && unreadCountMap[userId] > 0) if (unreadCountMap[conversationId] != null && unreadCountMap[conversationId] > 0)
Container( Container(
width: 16, width: 16,
height: 16, height: 16,
@ -514,7 +503,7 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
color: Color(0xFFFF441A), color: Color(0xFFFF441A),
), ),
child: RoundButton( child: RoundButton(
text: "${unreadCountMap[userId]}", text: "${unreadCountMap[conversationId]}",
textColor: Colors.white, textColor: Colors.white,
fontWeight: MyFontWeight.regular, fontWeight: MyFontWeight.regular,
backgroup: Color(0xFFFF441A), backgroup: Color(0xFFFF441A),
@ -534,7 +523,7 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
/// ///
showDelDialog(userId) { showDelDialog(conversationId) {
showDialog( showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
@ -560,7 +549,8 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
fontWeight: MyFontWeight.bold, fontWeight: MyFontWeight.bold,
), ),
), ),
)), ),
),
// Spacer(), // Spacer(),
Container( Container(
height:1.h, height:1.h,
@ -596,7 +586,7 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () async{ onTap: () async{
await hxDatabase.deleteByUser(contactMap[userId]?.mid ?? ""); await hxDatabase.deleteByUser(conversationId);
_refresh(); _refresh();
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
@ -605,10 +595,10 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
color: Color(0xFFFF370A), color: Color(0xFFFF370A),
) ),
) ),
) ),
) ),
], ],
) )
], ],

Loading…
Cancel
Save