mirror of
https://github.com/Linloir/Simple-TCP-Client.git
synced 2025-12-18 17:28:11 +08:00
Improvement:
- Change logic of unread messages
This commit is contained in:
parent
832982a415
commit
5834bcaa58
@ -12,7 +12,7 @@ import 'package:tcp_client/home/cubit/home_cubit.dart';
|
|||||||
import 'package:tcp_client/home/cubit/home_state.dart';
|
import 'package:tcp_client/home/cubit/home_state.dart';
|
||||||
import 'package:tcp_client/home/view/contact_page/contact_page.dart';
|
import 'package:tcp_client/home/view/contact_page/contact_page.dart';
|
||||||
import 'package:tcp_client/home/view/contact_page/cubit/contact_cubit.dart';
|
import 'package:tcp_client/home/view/contact_page/cubit/contact_cubit.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/cubit/msg_list/msg_list_cubit.dart';
|
import 'package:tcp_client/home/view/message_page/cubit/msg_list_cubit.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/mesage_page.dart';
|
import 'package:tcp_client/home/view/message_page/mesage_page.dart';
|
||||||
import 'package:tcp_client/home/view/profile_page/profile_page.dart';
|
import 'package:tcp_client/home/view/profile_page/profile_page.dart';
|
||||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import 'package:tcp_client/home/cubit/home_cubit.dart';
|
|||||||
import 'package:tcp_client/home/cubit/home_state.dart';
|
import 'package:tcp_client/home/cubit/home_state.dart';
|
||||||
import 'package:tcp_client/home/view/contact_page/cubit/contact_cubit.dart';
|
import 'package:tcp_client/home/view/contact_page/cubit/contact_cubit.dart';
|
||||||
import 'package:tcp_client/home/view/contact_page/models/contact_model.dart';
|
import 'package:tcp_client/home/view/contact_page/models/contact_model.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/cubit/msg_list/msg_list_cubit.dart';
|
import 'package:tcp_client/home/view/message_page/cubit/msg_list_cubit.dart';
|
||||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
|
import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
|
||||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||||
|
|||||||
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author : Linloir
|
|
||||||
* @Date : 2022-10-12 23:37:49
|
|
||||||
* @LastEditTime : 2022-10-17 13:10:49
|
|
||||||
* @Description :
|
|
||||||
*/
|
|
||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
import 'package:tcp_client/home/view/message_page/models/message_info.dart';
|
|
||||||
|
|
||||||
class MessageListState extends Equatable {
|
|
||||||
final List<MessageInfo> messageList;
|
|
||||||
|
|
||||||
const MessageListState({
|
|
||||||
required this.messageList
|
|
||||||
});
|
|
||||||
|
|
||||||
static MessageListState empty() => const MessageListState(messageList: []);
|
|
||||||
|
|
||||||
MessageListState updateWithSingle({
|
|
||||||
required MessageInfo messageInfo
|
|
||||||
}) {
|
|
||||||
var newList = <MessageInfo>[messageInfo];
|
|
||||||
for(var msgInfo in messageList) {
|
|
||||||
if(msgInfo.targetUser == messageInfo.targetUser) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
newList.add(msgInfo);
|
|
||||||
}
|
|
||||||
return MessageListState(messageList: newList);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageListState updateWithList({
|
|
||||||
required List<MessageInfo> orderedNewMessages
|
|
||||||
}) {
|
|
||||||
var newList = <MessageInfo>[];
|
|
||||||
Set<int> addedUsers = {};
|
|
||||||
var insertListIndex = 0;
|
|
||||||
var origListIndex = 0;
|
|
||||||
while(
|
|
||||||
insertListIndex < orderedNewMessages.length &&
|
|
||||||
origListIndex < messageList.length
|
|
||||||
) {
|
|
||||||
if(addedUsers.contains(orderedNewMessages[insertListIndex].targetUser)) {
|
|
||||||
insertListIndex += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(addedUsers.contains(messageList[origListIndex].targetUser)) {
|
|
||||||
origListIndex += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(
|
|
||||||
(messageList[origListIndex].message?.timeStamp ?? 0) >
|
|
||||||
(orderedNewMessages[insertListIndex].message?.timeStamp ?? 0)
|
|
||||||
) {
|
|
||||||
newList.add(messageList[origListIndex]);
|
|
||||||
addedUsers.add(messageList[origListIndex].targetUser);
|
|
||||||
origListIndex += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newList.add(orderedNewMessages[insertListIndex]);
|
|
||||||
addedUsers.add(orderedNewMessages[insertListIndex].targetUser);
|
|
||||||
insertListIndex += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Add the messages left
|
|
||||||
while(origListIndex < messageList.length) {
|
|
||||||
if(addedUsers.contains(messageList[origListIndex].targetUser)) {
|
|
||||||
origListIndex += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
newList.add(messageList[origListIndex]);
|
|
||||||
addedUsers.add(messageList[origListIndex].targetUser);
|
|
||||||
origListIndex += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
while(insertListIndex < orderedNewMessages.length) {
|
|
||||||
if(addedUsers.contains(orderedNewMessages[insertListIndex].targetUser)) {
|
|
||||||
insertListIndex += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
newList.add(orderedNewMessages[insertListIndex]);
|
|
||||||
addedUsers.add(orderedNewMessages[insertListIndex].targetUser);
|
|
||||||
insertListIndex += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MessageListState(messageList: newList);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageListState deleteOf({
|
|
||||||
required MessageInfo messageInfo
|
|
||||||
}) {
|
|
||||||
var newList = <MessageInfo>[];
|
|
||||||
for(var msgInfo in messageList) {
|
|
||||||
if(msgInfo == messageInfo) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
newList.add(msgInfo);
|
|
||||||
}
|
|
||||||
return MessageListState(messageList: newList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [...messageList];
|
|
||||||
}
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-12 23:38:31
|
* @Date : 2022-10-12 23:38:31
|
||||||
* @LastEditTime : 2022-10-23 16:30:24
|
* @LastEditTime : 2022-10-23 20:43:56
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/cubit/msg_list/msg_list_state.dart';
|
import 'package:tcp_client/home/view/message_page/cubit/msg_list_state.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/models/message_info.dart';
|
import 'package:tcp_client/home/view/message_page/models/message_info.dart';
|
||||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
|
import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
|
||||||
@ -40,7 +40,24 @@ class MessageListCubit extends Cubit<MessageListState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return msgList;
|
return msgList;
|
||||||
}).then((msgList) => emit(state.updateWithList(orderedNewMessages: msgList)));
|
}).then((msgList) async {
|
||||||
|
//get new message list
|
||||||
|
var newList = updateWithList(orderedNewMessages: msgList);
|
||||||
|
//get unread message count
|
||||||
|
var curUser = (await SharedPreferences.getInstance()).getInt('userid');
|
||||||
|
Map<int, int> unreadCnt = {};
|
||||||
|
for(var msg in newList) {
|
||||||
|
var cnt = await localServiceRepository.getUnreadCount(
|
||||||
|
userid: curUser!,
|
||||||
|
targetid: msg.targetUser
|
||||||
|
);
|
||||||
|
unreadCnt.update(msg.targetUser, (value) => cnt, ifAbsent: () => cnt,);
|
||||||
|
}
|
||||||
|
//Emit new state
|
||||||
|
if(!isClosed) {
|
||||||
|
emit(state.copyWith(messageList: newList, unreadCnt: unreadCnt));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final LocalServiceRepository localServiceRepository;
|
final LocalServiceRepository localServiceRepository;
|
||||||
@ -52,7 +69,7 @@ class MessageListCubit extends Cubit<MessageListState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var newList = [MessageInfo(targetUser: targetUser), ...state.messageList];
|
var newList = [MessageInfo(targetUser: targetUser), ...state.messageList];
|
||||||
emit(MessageListState(messageList: newList));
|
emit(state.copyWith(messageList: newList));
|
||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
var currentUserID = pref.getInt('userid');
|
var currentUserID = pref.getInt('userid');
|
||||||
var msgUserList = pref.getStringList('${currentUserID}msg') ?? [];
|
var msgUserList = pref.getStringList('${currentUserID}msg') ?? [];
|
||||||
@ -65,6 +82,12 @@ class MessageListCubit extends Cubit<MessageListState> {
|
|||||||
tcpRepository.pushRequest(FetchMessageRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
tcpRepository.pushRequest(FetchMessageRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearUnread({required int targetID}) {
|
||||||
|
var unreadCnt = state.unreadCnt;
|
||||||
|
unreadCnt.update(targetID, (value) => 0, ifAbsent: () => 0,);
|
||||||
|
emit(state.copyWith(unreadCnt: unreadCnt));
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _onResponse(TCPResponse response) async {
|
Future<void> _onResponse(TCPResponse response) async {
|
||||||
switch(response.type) {
|
switch(response.type) {
|
||||||
case TCPResponseType.sendMessage: {
|
case TCPResponseType.sendMessage: {
|
||||||
@ -75,10 +98,11 @@ class MessageListCubit extends Cubit<MessageListState> {
|
|||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
var currentUserID = pref.getInt('userid');
|
var currentUserID = pref.getInt('userid');
|
||||||
var targetUser = message.senderID == currentUserID ? message.recieverID : message.senderID;
|
var targetUser = message.senderID == currentUserID ? message.recieverID : message.senderID;
|
||||||
emit(state.updateWithSingle(messageInfo: MessageInfo(
|
var newList = updateWithSingle(messageInfo: MessageInfo(
|
||||||
message: message,
|
message: message,
|
||||||
targetUser: targetUser
|
targetUser: targetUser
|
||||||
)));
|
));
|
||||||
|
emit(state.copyWith(messageList: newList));
|
||||||
var msgUserList = state.messageList.map((e) => e.targetUser.toString()).toList();
|
var msgUserList = state.messageList.map((e) => e.targetUser.toString()).toList();
|
||||||
pref.setStringList('${currentUserID}msg', msgUserList);
|
pref.setStringList('${currentUserID}msg', msgUserList);
|
||||||
}
|
}
|
||||||
@ -92,6 +116,8 @@ class MessageListCubit extends Cubit<MessageListState> {
|
|||||||
|
|
||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
var curUser = pref.getInt('userid');
|
var curUser = pref.getInt('userid');
|
||||||
|
|
||||||
|
Map<int, int> unreadCnt = state.unreadCnt;
|
||||||
for(var message in response.messages) {
|
for(var message in response.messages) {
|
||||||
//Since the message can be send to or from the current user
|
//Since the message can be send to or from the current user
|
||||||
//it's neccessary to identify the other user's id of the message
|
//it's neccessary to identify the other user's id of the message
|
||||||
@ -106,10 +132,22 @@ class MessageListCubit extends Cubit<MessageListState> {
|
|||||||
message: message
|
message: message
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
//Add to unreadCnt
|
||||||
|
var lastReadTime = await localServiceRepository.fetchReadHistory(
|
||||||
|
userid: curUser!,
|
||||||
|
targetid: targetUser
|
||||||
|
);
|
||||||
|
if(lastReadTime < message.timeStamp) {
|
||||||
|
unreadCnt.update(targetUser, (value) => value + 1, ifAbsent: () => 1,);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Use the meessage list to create new state
|
//Use the meessage list to create new state
|
||||||
emit(state.updateWithList(orderedNewMessages: latestMessages));
|
var newMessageList = updateWithList(orderedNewMessages: latestMessages);
|
||||||
|
//Emit new state
|
||||||
|
if(!isClosed) {
|
||||||
|
emit(state.copyWith(messageList: newMessageList, unreadCnt: unreadCnt));
|
||||||
|
}
|
||||||
|
|
||||||
var msgUserList = state.messageList.map((e) => e.targetUser.toString()).toList();
|
var msgUserList = state.messageList.map((e) => e.targetUser.toString()).toList();
|
||||||
pref.setStringList('${curUser}msg', msgUserList);
|
pref.setStringList('${curUser}msg', msgUserList);
|
||||||
@ -124,12 +162,26 @@ class MessageListCubit extends Cubit<MessageListState> {
|
|||||||
var targetUser = response.message.senderID == curUser ?
|
var targetUser = response.message.senderID == curUser ?
|
||||||
response.message.recieverID :
|
response.message.recieverID :
|
||||||
response.message.senderID;
|
response.message.senderID;
|
||||||
emit(state.updateWithSingle(
|
var newList = updateWithSingle(
|
||||||
messageInfo: MessageInfo(
|
messageInfo: MessageInfo(
|
||||||
targetUser: targetUser,
|
targetUser: targetUser,
|
||||||
message: response.message
|
message: response.message
|
||||||
)
|
)
|
||||||
));
|
);
|
||||||
|
var unreadCnt = state.unreadCnt;
|
||||||
|
var lastReadTime = await localServiceRepository.fetchReadHistory(
|
||||||
|
userid: curUser!,
|
||||||
|
targetid: targetUser
|
||||||
|
);
|
||||||
|
if(lastReadTime < response.message.timeStamp) {
|
||||||
|
unreadCnt.update(targetUser, (value) => value + 1, ifAbsent: () => 1,);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unreadCnt.update(targetUser, (value) => 0, ifAbsent: () => 0,);
|
||||||
|
}
|
||||||
|
if(!isClosed) {
|
||||||
|
emit(state.copyWith(messageList: newList, unreadCnt: unreadCnt));
|
||||||
|
}
|
||||||
var msgUserList = pref.getStringList('${curUser}msg') ?? [];
|
var msgUserList = pref.getStringList('${curUser}msg') ?? [];
|
||||||
msgUserList.remove('$targetUser');
|
msgUserList.remove('$targetUser');
|
||||||
msgUserList.insert(0, '$targetUser');
|
msgUserList.insert(0, '$targetUser');
|
||||||
@ -140,6 +192,92 @@ class MessageListCubit extends Cubit<MessageListState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<MessageInfo> updateWithSingle({
|
||||||
|
required MessageInfo messageInfo
|
||||||
|
}) {
|
||||||
|
var newList = <MessageInfo>[messageInfo];
|
||||||
|
for(var msgInfo in state.messageList) {
|
||||||
|
if(msgInfo.targetUser == messageInfo.targetUser) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
newList.add(msgInfo);
|
||||||
|
}
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MessageInfo> updateWithList({
|
||||||
|
required List<MessageInfo> orderedNewMessages
|
||||||
|
}) {
|
||||||
|
var newList = <MessageInfo>[];
|
||||||
|
Set<int> addedUsers = {};
|
||||||
|
var insertListIndex = 0;
|
||||||
|
var origListIndex = 0;
|
||||||
|
while(
|
||||||
|
insertListIndex < orderedNewMessages.length &&
|
||||||
|
origListIndex < state.messageList.length
|
||||||
|
) {
|
||||||
|
if(addedUsers.contains(orderedNewMessages[insertListIndex].targetUser)) {
|
||||||
|
insertListIndex += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(addedUsers.contains(state.messageList[origListIndex].targetUser)) {
|
||||||
|
origListIndex += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(
|
||||||
|
(state.messageList[origListIndex].message?.timeStamp ?? 0) >
|
||||||
|
(orderedNewMessages[insertListIndex].message?.timeStamp ?? 0)
|
||||||
|
) {
|
||||||
|
newList.add(state.messageList[origListIndex]);
|
||||||
|
addedUsers.add(state.messageList[origListIndex].targetUser);
|
||||||
|
origListIndex += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newList.add(orderedNewMessages[insertListIndex]);
|
||||||
|
addedUsers.add(orderedNewMessages[insertListIndex].targetUser);
|
||||||
|
insertListIndex += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Add the messages left
|
||||||
|
while(origListIndex < state.messageList.length) {
|
||||||
|
if(addedUsers.contains(state.messageList[origListIndex].targetUser)) {
|
||||||
|
origListIndex += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
newList.add(state.messageList[origListIndex]);
|
||||||
|
addedUsers.add(state.messageList[origListIndex].targetUser);
|
||||||
|
origListIndex += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
while(insertListIndex < orderedNewMessages.length) {
|
||||||
|
if(addedUsers.contains(orderedNewMessages[insertListIndex].targetUser)) {
|
||||||
|
insertListIndex += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
newList.add(orderedNewMessages[insertListIndex]);
|
||||||
|
addedUsers.add(orderedNewMessages[insertListIndex].targetUser);
|
||||||
|
insertListIndex += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MessageInfo> deleteOf({
|
||||||
|
required MessageInfo messageInfo
|
||||||
|
}) {
|
||||||
|
var newList = <MessageInfo>[];
|
||||||
|
for(var msgInfo in state.messageList) {
|
||||||
|
if(msgInfo == messageInfo) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
newList.add(msgInfo);
|
||||||
|
}
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
subscription.cancel();
|
subscription.cancel();
|
||||||
120
lib/home/view/message_page/cubit/msg_list_state.dart
Normal file
120
lib/home/view/message_page/cubit/msg_list_state.dart
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* @Author : Linloir
|
||||||
|
* @Date : 2022-10-12 23:37:49
|
||||||
|
* @LastEditTime : 2022-10-23 20:50:19
|
||||||
|
* @Description :
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:tcp_client/home/view/message_page/models/message_info.dart';
|
||||||
|
|
||||||
|
class MessageListState extends Equatable {
|
||||||
|
final List<MessageInfo> messageList;
|
||||||
|
final Map<int, int> unreadCnt;
|
||||||
|
|
||||||
|
const MessageListState({
|
||||||
|
required this.messageList,
|
||||||
|
required this.unreadCnt
|
||||||
|
});
|
||||||
|
|
||||||
|
static MessageListState empty() => const MessageListState(messageList: [], unreadCnt: {});
|
||||||
|
|
||||||
|
MessageListState copyWith({
|
||||||
|
List<MessageInfo>? messageList,
|
||||||
|
Map<int, int>? unreadCnt
|
||||||
|
}) {
|
||||||
|
return MessageListState(
|
||||||
|
messageList: messageList ?? this.messageList,
|
||||||
|
unreadCnt: unreadCnt ?? this.unreadCnt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageListState updateWithSingle({
|
||||||
|
// required MessageInfo messageInfo
|
||||||
|
// }) {
|
||||||
|
// var newList = <MessageInfo>[messageInfo];
|
||||||
|
// for(var msgInfo in messageList) {
|
||||||
|
// if(msgInfo.targetUser == messageInfo.targetUser) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// newList.add(msgInfo);
|
||||||
|
// }
|
||||||
|
// return MessageListState(messageList: newList);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// MessageListState updateWithList({
|
||||||
|
// required List<MessageInfo> orderedNewMessages
|
||||||
|
// }) {
|
||||||
|
// var newList = <MessageInfo>[];
|
||||||
|
// Set<int> addedUsers = {};
|
||||||
|
// var insertListIndex = 0;
|
||||||
|
// var origListIndex = 0;
|
||||||
|
// while(
|
||||||
|
// insertListIndex < orderedNewMessages.length &&
|
||||||
|
// origListIndex < messageList.length
|
||||||
|
// ) {
|
||||||
|
// if(addedUsers.contains(orderedNewMessages[insertListIndex].targetUser)) {
|
||||||
|
// insertListIndex += 1;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if(addedUsers.contains(messageList[origListIndex].targetUser)) {
|
||||||
|
// origListIndex += 1;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if(
|
||||||
|
// (messageList[origListIndex].message?.timeStamp ?? 0) >
|
||||||
|
// (orderedNewMessages[insertListIndex].message?.timeStamp ?? 0)
|
||||||
|
// ) {
|
||||||
|
// newList.add(messageList[origListIndex]);
|
||||||
|
// addedUsers.add(messageList[origListIndex].targetUser);
|
||||||
|
// origListIndex += 1;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// newList.add(orderedNewMessages[insertListIndex]);
|
||||||
|
// addedUsers.add(orderedNewMessages[insertListIndex].targetUser);
|
||||||
|
// insertListIndex += 1;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //Add the messages left
|
||||||
|
// while(origListIndex < messageList.length) {
|
||||||
|
// if(addedUsers.contains(messageList[origListIndex].targetUser)) {
|
||||||
|
// origListIndex += 1;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// newList.add(messageList[origListIndex]);
|
||||||
|
// addedUsers.add(messageList[origListIndex].targetUser);
|
||||||
|
// origListIndex += 1;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// while(insertListIndex < orderedNewMessages.length) {
|
||||||
|
// if(addedUsers.contains(orderedNewMessages[insertListIndex].targetUser)) {
|
||||||
|
// insertListIndex += 1;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// newList.add(orderedNewMessages[insertListIndex]);
|
||||||
|
// addedUsers.add(orderedNewMessages[insertListIndex].targetUser);
|
||||||
|
// insertListIndex += 1;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return MessageListState(messageList: newList);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// MessageListState deleteOf({
|
||||||
|
// required MessageInfo messageInfo
|
||||||
|
// }) {
|
||||||
|
// var newList = <MessageInfo>[];
|
||||||
|
// for(var msgInfo in messageList) {
|
||||||
|
// if(msgInfo == messageInfo) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// newList.add(msgInfo);
|
||||||
|
// }
|
||||||
|
// return MessageListState(messageList: newList);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [...unreadCnt.entries, ...messageList];
|
||||||
|
}
|
||||||
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author : Linloir
|
|
||||||
* @Date : 2022-10-23 16:30:45
|
|
||||||
* @LastEditTime : 2022-10-23 17:46:28
|
|
||||||
* @Description :
|
|
||||||
*/
|
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:tcp_client/home/view/message_page/cubit/msg_tile/msg_tile_state.dart';
|
|
||||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
|
||||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_response.dart';
|
|
||||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
|
||||||
|
|
||||||
class MessageTileCubit extends Cubit<MessageTileState> {
|
|
||||||
MessageTileCubit({
|
|
||||||
required this.tcpRepository,
|
|
||||||
required this.localServiceRepository,
|
|
||||||
required this.targetID
|
|
||||||
}): super(const MessageTileState(unreadCount: 0)) {
|
|
||||||
Future<int>(() async {
|
|
||||||
return await localServiceRepository.getUnreadCount(
|
|
||||||
userid: (await SharedPreferences.getInstance()).getInt('userid')!,
|
|
||||||
targetid: targetID
|
|
||||||
);
|
|
||||||
}).then((value) => emit(state + value));
|
|
||||||
subscription = tcpRepository.responseStreamBroadcast.listen(_onResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
final TCPRepository tcpRepository;
|
|
||||||
final LocalServiceRepository localServiceRepository;
|
|
||||||
final int targetID;
|
|
||||||
late final StreamSubscription subscription;
|
|
||||||
|
|
||||||
Future<void> _onResponse(TCPResponse response) async {
|
|
||||||
var pref = await SharedPreferences.getInstance();
|
|
||||||
var userID = pref.getInt('userid');
|
|
||||||
if(userID == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var readHistoryTimestamp = await localServiceRepository.fetchReadHistory(
|
|
||||||
userid: userID,
|
|
||||||
targetid: targetID
|
|
||||||
);
|
|
||||||
if(response.type == TCPResponseType.fetchMessage) {
|
|
||||||
//Count unread incoming message count
|
|
||||||
response as FetchMessageResponse;
|
|
||||||
var addCnt = 0;
|
|
||||||
for(var message in response.messages) {
|
|
||||||
if(message.senderID == targetID && message.recieverID == userID) {
|
|
||||||
if(readHistoryTimestamp < message.timeStamp) {
|
|
||||||
addCnt += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!isClosed) {
|
|
||||||
emit(state + addCnt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(response.type == TCPResponseType.forwardMessage) {
|
|
||||||
//Count unread incoming message count
|
|
||||||
response as ForwardMessageResponse;
|
|
||||||
if(response.message.senderID == targetID && response.message.recieverID == userID) {
|
|
||||||
if(readHistoryTimestamp < response.message.timeStamp) {
|
|
||||||
if(!isClosed) {
|
|
||||||
emit(state + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(!isClosed) {
|
|
||||||
emit(const MessageTileState(unreadCount: 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearUnread() {
|
|
||||||
emit(const MessageTileState(unreadCount: 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> close() {
|
|
||||||
subscription.cancel();
|
|
||||||
return super.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author : Linloir
|
|
||||||
* @Date : 2022-10-23 16:30:52
|
|
||||||
* @LastEditTime : 2022-10-23 16:40:47
|
|
||||||
* @Description :
|
|
||||||
*/
|
|
||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
|
|
||||||
class MessageTileState extends Equatable {
|
|
||||||
final int unreadCount;
|
|
||||||
|
|
||||||
const MessageTileState({required this.unreadCount});
|
|
||||||
|
|
||||||
MessageTileState operator +(int other) {
|
|
||||||
return MessageTileState(unreadCount: unreadCount + other);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [unreadCount];
|
|
||||||
}
|
|
||||||
@ -1,15 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-11 11:05:18
|
* @Date : 2022-10-11 11:05:18
|
||||||
* @LastEditTime : 2022-10-23 17:38:30
|
* @LastEditTime : 2022-10-23 20:47:33
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
|
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/cubit/msg_list/msg_list_cubit.dart';
|
import 'package:tcp_client/home/view/message_page/cubit/msg_list_cubit.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/cubit/msg_list/msg_list_state.dart';
|
import 'package:tcp_client/home/view/message_page/cubit/msg_list_state.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/view/message_tile.dart';
|
import 'package:tcp_client/home/view/message_page/view/message_tile.dart';
|
||||||
|
|
||||||
class MessagePage extends StatelessWidget {
|
class MessagePage extends StatelessWidget {
|
||||||
@ -31,9 +31,9 @@ class MessagePage extends StatelessWidget {
|
|||||||
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
|
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return MessageTile(
|
return MessageTile(
|
||||||
key: ValueKey(state.messageList[index].targetUser),
|
|
||||||
userID: state.messageList[index].targetUser,
|
userID: state.messageList[index].targetUser,
|
||||||
message: state.messageList[index].message,
|
message: state.messageList[index].message,
|
||||||
|
unreadCnt: state.unreadCnt[state.messageList[index].targetUser],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) {
|
separatorBuilder: (context, index) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 13:17:52
|
* @Date : 2022-10-13 13:17:52
|
||||||
* @LastEditTime : 2022-10-23 17:55:44
|
* @LastEditTime : 2022-10-23 20:49:21
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -10,8 +10,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:tcp_client/chat/chat_page.dart';
|
import 'package:tcp_client/chat/chat_page.dart';
|
||||||
import 'package:tcp_client/common/avatar/avatar.dart';
|
import 'package:tcp_client/common/avatar/avatar.dart';
|
||||||
import 'package:tcp_client/common/username/username.dart';
|
import 'package:tcp_client/common/username/username.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/cubit/msg_tile/msg_tile_cubit.dart';
|
import 'package:tcp_client/home/view/message_page/cubit/msg_list_cubit.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/cubit/msg_tile/msg_tile_state.dart';
|
|
||||||
import 'package:tcp_client/repositories/common_models/message.dart';
|
import 'package:tcp_client/repositories/common_models/message.dart';
|
||||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||||
@ -21,176 +20,162 @@ class MessageTile extends StatelessWidget {
|
|||||||
const MessageTile({
|
const MessageTile({
|
||||||
required this.userID,
|
required this.userID,
|
||||||
this.message,
|
this.message,
|
||||||
|
required int? unreadCnt,
|
||||||
super.key
|
super.key
|
||||||
});
|
}): unreadCnt = unreadCnt ?? 0;
|
||||||
|
|
||||||
final int userID;
|
final int userID;
|
||||||
final Message? message;
|
final Message? message;
|
||||||
|
final int unreadCnt;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider<MessageTileCubit>(
|
return IntrinsicHeight(
|
||||||
key: ValueKey(userID),
|
child: Stack(
|
||||||
create: (context) {
|
fit: StackFit.expand,
|
||||||
return MessageTileCubit(
|
children: [
|
||||||
tcpRepository: context.read<TCPRepository>(),
|
InkWell(
|
||||||
localServiceRepository: context.read<LocalServiceRepository>(),
|
onTap: () {
|
||||||
targetID: userID
|
if(message != null) {
|
||||||
);
|
context.read<LocalServiceRepository>().setReadHistory(
|
||||||
},
|
userid: message!.recieverID == userID ? message!.senderID : message!.recieverID,
|
||||||
child: Builder(
|
targetid: userID,
|
||||||
key: ValueKey(userID),
|
timestamp: message!.timeStamp
|
||||||
builder: (context) => IntrinsicHeight(
|
);
|
||||||
child: Stack(
|
}
|
||||||
fit: StackFit.expand,
|
context.read<MessageListCubit>().clearUnread(targetID: userID);
|
||||||
children: [
|
Navigator.of(context).push(ChatPage.route(
|
||||||
InkWell(
|
userRepository: context.read<UserRepository>(),
|
||||||
onTap: () {
|
localServiceRepository: context.read<LocalServiceRepository>(),
|
||||||
if(message != null) {
|
tcpRepository: context.read<TCPRepository>(),
|
||||||
context.read<LocalServiceRepository>().setReadHistory(
|
userID: userID
|
||||||
userid: message!.recieverID == userID ? message!.senderID : message!.recieverID,
|
));
|
||||||
targetid: userID,
|
},
|
||||||
timestamp: message!.timeStamp
|
),
|
||||||
);
|
Padding(
|
||||||
}
|
padding: const EdgeInsets.symmetric(
|
||||||
context.read<MessageTileCubit>().clearUnread();
|
vertical: 8.0,
|
||||||
Navigator.of(context).push(ChatPage.route(
|
horizontal: 24.0
|
||||||
userRepository: context.read<UserRepository>(),
|
),
|
||||||
localServiceRepository: context.read<LocalServiceRepository>(),
|
child: Row(
|
||||||
tcpRepository: context.read<TCPRepository>(),
|
mainAxisSize: MainAxisSize.max,
|
||||||
userID: userID
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
));
|
children: [
|
||||||
},
|
IgnorePointer(
|
||||||
),
|
child: UserAvatar(userid: userID),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 8.0,
|
|
||||||
horizontal: 24.0
|
|
||||||
),
|
),
|
||||||
child: Row(
|
// if(userInfo.avatarEncoded != null && userInfo.avatarEncoded!.isEmpty)
|
||||||
mainAxisSize: MainAxisSize.max,
|
// Container(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
// decoration: BoxDecoration(
|
||||||
children: [
|
// borderRadius: BorderRadius.circular(5.0),
|
||||||
IgnorePointer(
|
// border: Border.all(
|
||||||
child: UserAvatar(userid: userID),
|
// color: Colors.grey[700]!,
|
||||||
),
|
// width: 1.0
|
||||||
// if(userInfo.avatarEncoded != null && userInfo.avatarEncoded!.isEmpty)
|
// )
|
||||||
// Container(
|
// ),
|
||||||
// decoration: BoxDecoration(
|
// child: ClipRRect(
|
||||||
// borderRadius: BorderRadius.circular(5.0),
|
// borderRadius: BorderRadius.circular(5.0),
|
||||||
// border: Border.all(
|
// child: OverflowBox(
|
||||||
// color: Colors.grey[700]!,
|
// alignment: Alignment.center,
|
||||||
// width: 1.0
|
// child: FittedBox(
|
||||||
// )
|
// fit: BoxFit.fitWidth,
|
||||||
// ),
|
// child: Image.memory(base64Decode(userInfo.avatarEncoded!)),
|
||||||
// child: ClipRRect(
|
// ),
|
||||||
// borderRadius: BorderRadius.circular(5.0),
|
// )
|
||||||
// child: OverflowBox(
|
// ),
|
||||||
// alignment: Alignment.center,
|
// ),
|
||||||
// child: FittedBox(
|
// if(userInfo.avatarEncoded == null || userInfo.avatarEncoded!.isEmpty)
|
||||||
// fit: BoxFit.fitWidth,
|
// Container(
|
||||||
// child: Image.memory(base64Decode(userInfo.avatarEncoded!)),
|
// color: Colors.grey,
|
||||||
// ),
|
// decoration: BoxDecoration(
|
||||||
// )
|
// borderRadius: BorderRadius.circular(5.0),
|
||||||
// ),
|
// border: Border.all(
|
||||||
// ),
|
// color: Colors.grey[700]!,
|
||||||
// if(userInfo.avatarEncoded == null || userInfo.avatarEncoded!.isEmpty)
|
// width: 1.0
|
||||||
// Container(
|
// )
|
||||||
// color: Colors.grey,
|
// ),
|
||||||
// decoration: BoxDecoration(
|
// ),
|
||||||
// borderRadius: BorderRadius.circular(5.0),
|
const SizedBox(width: 16,),
|
||||||
// border: Border.all(
|
Expanded(
|
||||||
// color: Colors.grey[700]!,
|
child: Column(
|
||||||
// width: 1.0
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
// )
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
// ),
|
children: [
|
||||||
// ),
|
const SizedBox(height: 6,),
|
||||||
const SizedBox(width: 16,),
|
Padding(
|
||||||
Expanded(
|
padding: const EdgeInsets.symmetric(
|
||||||
child: Column(
|
vertical: 2.0,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
horizontal: 0
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 6,),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 2.0,
|
|
||||||
horizontal: 0
|
|
||||||
),
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: UserNameText(userid: userID, fontWeight: FontWeight.bold,),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 2.0
|
|
||||||
),
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: Text(
|
|
||||||
message?.type == MessageType.image ? '[Image]' : message?.contentDecoded ?? '',
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6,),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
if(message != null)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 8.0,
|
|
||||||
bottom: 8.0
|
|
||||||
),
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: Text(
|
|
||||||
getTimeStamp(message!.timeStamp)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
BlocBuilder<MessageTileCubit, MessageTileState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return state.unreadCount == 0 ? Container() : Container(
|
|
||||||
margin: const EdgeInsets.only(
|
|
||||||
bottom: 8.0
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 10.0,
|
|
||||||
vertical: 4.0
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(50),
|
|
||||||
color: Colors.blue.withOpacity(0.9)
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'${state.unreadCount > 99 ? '99+' : state.unreadCount}',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
],
|
child: IgnorePointer(
|
||||||
),
|
child: UserNameText(userid: userID, fontWeight: FontWeight.bold,),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 2.0
|
||||||
|
),
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: Text(
|
||||||
|
message?.type == MessageType.image ? '[Image]' : message?.contentDecoded ?? '',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6,),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
if(message != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 8.0,
|
||||||
|
bottom: 8.0
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: Text(
|
||||||
|
getTimeStamp(message!.timeStamp)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if(unreadCnt != 0)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
bottom: 8.0
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10.0,
|
||||||
|
vertical: 4.0
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
color: Colors.blue.withOpacity(0.9)
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'${unreadCnt > 99 ? '99+' : unreadCnt}',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user