implement hiding msg
parent
5c2022d107
commit
fa81ae090d
|
@ -1,227 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:together_mobile/database/hive_database.dart';
|
||||
import 'package:together_mobile/request/message.dart';
|
||||
|
||||
import 'package:together_mobile/screens/chat/components/group_chat_chat_tile.dart';
|
||||
import 'components/friend_chat_tile.dart';
|
||||
import 'components/add_menu.dart';
|
||||
import 'package:together_mobile/database/box_type.dart';
|
||||
import 'package:together_mobile/models/websocket_model.dart';
|
||||
import 'package:together_mobile/utils/format_datetime.dart';
|
||||
import 'package:together_mobile/models/contact_model.dart';
|
||||
import 'package:together_mobile/models/apply_list_model.dart';
|
||||
import 'package:together_mobile/request/apply.dart';
|
||||
import 'package:together_mobile/request/server.dart';
|
||||
import 'package:together_mobile/request/contact.dart';
|
||||
import 'package:together_mobile/models/user_model.dart';
|
||||
import 'package:together_mobile/models/init_get_it.dart';
|
||||
import 'package:together_mobile/request/user_profile.dart';
|
||||
|
||||
class ChatScreen extends StatefulWidget {
|
||||
const ChatScreen({super.key});
|
||||
|
||||
@override
|
||||
State<ChatScreen> createState() => _ChatScreenState();
|
||||
}
|
||||
|
||||
class _ChatScreenState extends State<ChatScreen> {
|
||||
Future<bool> _initData() async {
|
||||
if (!getIt.get<UserProfile>().isInitialised) {
|
||||
await HiveDatabase.init();
|
||||
|
||||
getIt.get<WebSocketManager>().connect(getIt.get<UserAccount>().id, false);
|
||||
|
||||
String userId = getIt.get<UserAccount>().id;
|
||||
|
||||
List<Map<String, dynamic>> res = await Future.wait([
|
||||
getMyProfile(userId),
|
||||
getApplyList(userId),
|
||||
getContact(userId),
|
||||
]);
|
||||
|
||||
await getIt.get<UserProfile>().init(res[0]['data']);
|
||||
|
||||
if (res[1]['code'] == 10600) {
|
||||
getIt.get<ApplyList>().init(res[1]['data']);
|
||||
}
|
||||
|
||||
if (res[2]['code'] == 10700) {
|
||||
getIt.get<Contact>().init(res[2]['data']);
|
||||
}
|
||||
|
||||
Map<String, dynamic> contactAcctProfRes = await getContactAccountProfiles(
|
||||
getIt.get<Contact>().friends.keys.toList(),
|
||||
getIt.get<Contact>().groupChats.keys.toList(),
|
||||
);
|
||||
|
||||
if (contactAcctProfRes['code'] == 10700) {
|
||||
getIt.get<ContactAccountProfile>().init(contactAcctProfRes['data']);
|
||||
}
|
||||
|
||||
await _getUnreceivedMsg(userId);
|
||||
}
|
||||
|
||||
return Future(() => true);
|
||||
}
|
||||
|
||||
Future<void> _getUnreceivedMsg(String userId) async {
|
||||
print('触发了获取信息事件..................');
|
||||
final res = await getUnreceivedMsg(userId);
|
||||
|
||||
if (res['code'] == 10900) {
|
||||
for (var msg in res['data'] as List<Map<String, dynamic>>) {
|
||||
if (msg['event'] == 'friend-chat-msg') {
|
||||
receiveFriendMsg(msg, false);
|
||||
} else if (msg['event'] == 'group-chat-msg') {
|
||||
receiveGroupChatMsg(msg, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: _initData(),
|
||||
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: getIt.get<UserProfile>().avatar.isEmpty
|
||||
? const CircleAvatar(
|
||||
backgroundImage: AssetImage('assets/images/user_2.png'),
|
||||
)
|
||||
: CircleAvatar(
|
||||
backgroundImage: CachedNetworkImageProvider(
|
||||
'$userAvatarsUrl/${getIt.get<UserProfile>().avatar}',
|
||||
),
|
||||
),
|
||||
title: Text(getIt.get<UserProfile>().nickname),
|
||||
centerTitle: true,
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
splashRadius: 20,
|
||||
icon: const Icon(Icons.search),
|
||||
),
|
||||
const AddMenu(),
|
||||
],
|
||||
),
|
||||
// Use ListView.builder because it renders list element on demand
|
||||
body: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
String userId = getIt.get<UserAccount>().id;
|
||||
if (getIt.get<WebSocketManager>().socketStatus ==
|
||||
SocketStatus.closed) {
|
||||
getIt.get<WebSocketManager>().connect(userId, false);
|
||||
}
|
||||
await _getUnreceivedMsg(userId);
|
||||
},
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable:
|
||||
Hive.box<ChatSetting>('chat_setting').listenable(),
|
||||
builder: (context, Box<ChatSetting> box, _) {
|
||||
final List<ChatSetting> openedChat =
|
||||
box.values.where((element) => element.isOpen).toList();
|
||||
|
||||
// latestMsg on the top
|
||||
openedChat.sort(
|
||||
(a, b) => b.latestDateTime.compareTo(a.latestDateTime),
|
||||
);
|
||||
|
||||
if (openedChat.isEmpty) {
|
||||
return const Center(
|
||||
child: Text(
|
||||
'没有最新消息',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
letterSpacing: 5.0,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return ListView.builder(
|
||||
physics: const BouncingScrollPhysics(
|
||||
parent: AlwaysScrollableScrollPhysics(),
|
||||
),
|
||||
itemCount: openedChat.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
String contactId = openedChat[index].contactId;
|
||||
String showedTime = formatTileDateTime(
|
||||
openedChat[index].latestDateTime,
|
||||
);
|
||||
int unreadCount = openedChat[index].unreadCount;
|
||||
|
||||
return ValueListenableBuilder(
|
||||
valueListenable:
|
||||
Hive.box<MessageT>('message_$contactId')
|
||||
.listenable(),
|
||||
builder: (context, messageTBox, _) {
|
||||
int length = messageTBox.length;
|
||||
if (length > 0) {
|
||||
MessageT messageT =
|
||||
messageTBox.getAt(length - 1)!;
|
||||
if (openedChat[index].type == 0) {
|
||||
return FriendChatTile(
|
||||
key: ValueKey(contactId),
|
||||
index: index,
|
||||
contactId: contactId,
|
||||
senderId: messageT.senderId,
|
||||
messageType: messageT.type,
|
||||
text: messageT.text,
|
||||
attachments: messageT.attachments,
|
||||
dateTime: showedTime,
|
||||
isShowTime: messageT.isShowTime,
|
||||
unreadCount: unreadCount,
|
||||
);
|
||||
} else {
|
||||
return GroupChatChatTile(
|
||||
key: ValueKey(contactId),
|
||||
index: index,
|
||||
contactId: contactId,
|
||||
senderId: messageT.senderId,
|
||||
messageType: messageT.type,
|
||||
text: messageT.text,
|
||||
attachments: messageT.attachments,
|
||||
dateTime: showedTime,
|
||||
isShowTime: messageT.isShowTime,
|
||||
unreadCount: unreadCount,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 60,
|
||||
height: 60,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Text('Loading data....'),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -205,7 +205,6 @@ class _ChatScreenState extends State<ChatScreen> with GetItStateMixin {
|
|||
if (openedChat[index].type == 0) {
|
||||
return FriendChatTile(
|
||||
key: ValueKey(contactId),
|
||||
index: index,
|
||||
contactId: contactId,
|
||||
senderId: messageT.senderId,
|
||||
messageType: messageT.type,
|
||||
|
|
|
@ -15,7 +15,6 @@ import 'badge_avatar.dart';
|
|||
class FriendChatTile extends StatefulWidget {
|
||||
const FriendChatTile({
|
||||
super.key,
|
||||
required this.index,
|
||||
required this.contactId,
|
||||
required this.senderId,
|
||||
required this.messageType,
|
||||
|
@ -26,7 +25,7 @@ class FriendChatTile extends StatefulWidget {
|
|||
required this.unreadCount,
|
||||
});
|
||||
|
||||
final int index, unreadCount;
|
||||
final int unreadCount;
|
||||
final String contactId, senderId, messageType, text, dateTime;
|
||||
final List<String> attachments;
|
||||
final bool isShowTime;
|
||||
|
@ -38,14 +37,14 @@ class FriendChatTile extends StatefulWidget {
|
|||
class _FriendChatTileState extends State<FriendChatTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Box<ChatSetting> chatSettingBox = Hive.box<ChatSetting>('chat_setting');
|
||||
ChatSetting chatSetting = chatSettingBox.get(widget.contactId)!;
|
||||
return Slidable(
|
||||
key: const ValueKey(0),
|
||||
endActionPane: ActionPane(
|
||||
motion: const BehindMotion(),
|
||||
dismissible: DismissiblePane(
|
||||
onDismissed: () {
|
||||
Box<ChatSetting> chatSettingBox = Hive.box('chat_setting');
|
||||
ChatSetting chatSetting = chatSettingBox.getAt(widget.index)!;
|
||||
chatSetting.isOpen = false;
|
||||
chatSettingBox.put(widget.contactId, chatSetting);
|
||||
},
|
||||
|
@ -59,11 +58,14 @@ class _FriendChatTileState extends State<FriendChatTile> {
|
|||
label: '置顶',
|
||||
),
|
||||
SlidableAction(
|
||||
onPressed: (BuildContext context) {},
|
||||
onPressed: (BuildContext context) {
|
||||
chatSetting.isHideMsg = !chatSetting.isHideMsg;
|
||||
chatSettingBox.put(widget.contactId, chatSetting);
|
||||
},
|
||||
foregroundColor: kContentColorDark,
|
||||
backgroundColor: kPrimaryColor,
|
||||
icon: Icons.remove_red_eye,
|
||||
label: '隐藏消息',
|
||||
label: chatSetting.isHideMsg ? '显示消息' : '隐藏消息',
|
||||
flex: 1,
|
||||
),
|
||||
],
|
||||
|
|
|
@ -9,7 +9,6 @@ import 'package:together_mobile/common/constants.dart';
|
|||
import 'package:together_mobile/database/box_type.dart';
|
||||
import 'package:together_mobile/models/contact_model.dart';
|
||||
import 'package:together_mobile/models/init_get_it.dart';
|
||||
import 'package:together_mobile/models/route_state_model.dart';
|
||||
import 'package:together_mobile/request/server.dart';
|
||||
import 'badge_avatar.dart';
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class RowFloatingButtons extends StatelessWidget {
|
|||
}
|
||||
|
||||
// ignore: use_build_context_synchronously
|
||||
context.goNamed(
|
||||
context.pushReplacementNamed(
|
||||
'Message',
|
||||
queryParameters: {'friendId': friendId, 'type': '0'},
|
||||
);
|
||||
|
|
|
@ -40,7 +40,6 @@ class FriendProfileScreen extends StatelessWidget {
|
|||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
getIt.get<RouteState>().changeRoute('FriendSetting');
|
||||
context.pushNamed(
|
||||
'FriendSetting',
|
||||
queryParameters: {'friendId': friendId},
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:go_router/go_router.dart';
|
|||
import 'package:together_mobile/common/constants.dart';
|
||||
import 'package:together_mobile/models/init_get_it.dart';
|
||||
import 'package:together_mobile/models/contact_model.dart';
|
||||
import 'package:together_mobile/models/route_state_model.dart';
|
||||
import 'package:together_mobile/models/user_model.dart';
|
||||
import 'package:together_mobile/models/websocket_model.dart';
|
||||
import 'package:together_mobile/request/contact.dart';
|
||||
|
@ -49,6 +50,11 @@ class _FriendSettingScreenState extends State<FriendSettingScreen> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Timer(
|
||||
const Duration(milliseconds: 300),
|
||||
() => getIt.get<RouteState>().changeRoute('FriendProfile'),
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
|
|
|
@ -3,8 +3,10 @@ import 'dart:io';
|
|||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
|
||||
import 'package:together_mobile/common/constants.dart';
|
||||
import 'package:together_mobile/database/box_type.dart';
|
||||
import 'package:together_mobile/models/contact_model.dart';
|
||||
import 'package:together_mobile/models/init_get_it.dart';
|
||||
import 'package:together_mobile/models/user_model.dart';
|
||||
|
@ -13,6 +15,8 @@ import 'package:together_mobile/request/server.dart';
|
|||
class FriendMessageBubble extends StatefulWidget {
|
||||
const FriendMessageBubble({
|
||||
super.key,
|
||||
required this.index,
|
||||
required this.length,
|
||||
required this.contactId,
|
||||
required this.senderId,
|
||||
required this.type,
|
||||
|
@ -22,6 +26,7 @@ class FriendMessageBubble extends StatefulWidget {
|
|||
required this.attachments,
|
||||
});
|
||||
|
||||
final int index, length;
|
||||
final String contactId, senderId, type, dateTime, text;
|
||||
final bool isShowTime;
|
||||
final List<String> attachments;
|
||||
|
@ -34,11 +39,13 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
|
|||
// add late here so you can access widget instance
|
||||
List<bool> _isImagesLoaded = [];
|
||||
final List<Timer> _timerList = [];
|
||||
late bool _isHideMsg;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_isImagesLoaded = List.filled(widget.attachments.length, false);
|
||||
|
||||
for (var i = 0; i < widget.attachments.length; i++) {
|
||||
String imagePath =
|
||||
'${getIt.get<UserProfile>().baseImageDir}/${widget.attachments[i]}';
|
||||
|
@ -47,7 +54,8 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
|
|||
_isImagesLoaded[i] = true;
|
||||
} else {
|
||||
_isImagesLoaded[i] = false;
|
||||
_timerList.add(Timer.periodic(
|
||||
_timerList.add(
|
||||
Timer.periodic(
|
||||
const Duration(milliseconds: 200),
|
||||
(timer) {
|
||||
if ((file.existsSync())) {
|
||||
|
@ -57,17 +65,37 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
|
|||
timer.cancel();
|
||||
}
|
||||
},
|
||||
));
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final chatSettingBox = Hive.box<ChatSetting>('chat_setting');
|
||||
late final chatSetting = chatSettingBox.get(widget.contactId);
|
||||
_isHideMsg = chatSetting!.isHideMsg;
|
||||
|
||||
if (_isHideMsg) {
|
||||
if (widget.index + 1 == widget.length) {
|
||||
_isHideMsg = false;
|
||||
Timer(
|
||||
const Duration(milliseconds: 3500),
|
||||
() {
|
||||
setState(() {
|
||||
_isHideMsg = true;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
for (var element in _timerList) {
|
||||
element.cancel();
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -137,8 +165,10 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (_isHideMsg) const Text('消息已隐藏'),
|
||||
|
||||
// text message content
|
||||
if (widget.text.isNotEmpty)
|
||||
if (widget.text.isNotEmpty && !_isHideMsg)
|
||||
Text(
|
||||
widget.text,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
|
@ -147,7 +177,7 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
|
|||
height: 10,
|
||||
),
|
||||
// image content if have
|
||||
if (widget.attachments.isNotEmpty)
|
||||
if (widget.attachments.isNotEmpty && !_isHideMsg)
|
||||
...List.generate(
|
||||
widget.attachments.length,
|
||||
(int index) {
|
||||
|
@ -187,13 +217,18 @@ class _FriendMessageBubbleState extends State<FriendMessageBubble> {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (_isHideMsg)
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isHideMsg = false;
|
||||
});
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
child: const Text('显示信息'),
|
||||
child: const Text('显示消息'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -3,8 +3,10 @@ import 'dart:io';
|
|||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
||||
import 'package:together_mobile/common/constants.dart';
|
||||
import 'package:together_mobile/database/box_type.dart';
|
||||
import 'package:together_mobile/models/contact_model.dart';
|
||||
import 'package:together_mobile/models/init_get_it.dart';
|
||||
import 'package:together_mobile/models/user_model.dart';
|
||||
|
@ -14,6 +16,8 @@ import 'package:together_mobile/request/server.dart';
|
|||
class GroupChatMessageBubble extends StatefulWidget {
|
||||
const GroupChatMessageBubble({
|
||||
super.key,
|
||||
required this.index,
|
||||
required this.length,
|
||||
required this.contactId,
|
||||
required this.senderId,
|
||||
required this.type,
|
||||
|
@ -23,6 +27,7 @@ class GroupChatMessageBubble extends StatefulWidget {
|
|||
required this.attachments,
|
||||
});
|
||||
|
||||
final int index, length;
|
||||
final String contactId, senderId, type, dateTime, text;
|
||||
final bool isShowTime;
|
||||
final List<String> attachments;
|
||||
|
@ -35,6 +40,7 @@ class _GroupChatMessageBubbleState extends State<GroupChatMessageBubble> {
|
|||
// add late here so you can access widget instance
|
||||
List<bool> _isImagesLoaded = [];
|
||||
final List<Timer> _timerList = [];
|
||||
late bool _isHideMsg;
|
||||
|
||||
Future<bool> _getMemberGroupChatProfile() async {
|
||||
if (widget.senderId == getIt.get<UserAccount>().id) {
|
||||
|
@ -100,6 +106,24 @@ class _GroupChatMessageBubbleState extends State<GroupChatMessageBubble> {
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
final chatSettingBox = Hive.box<ChatSetting>('chat_setting');
|
||||
late final chatSetting = chatSettingBox.get(widget.contactId);
|
||||
_isHideMsg = chatSetting!.isHideMsg;
|
||||
|
||||
if (_isHideMsg) {
|
||||
if (widget.index + 1 == widget.length) {
|
||||
_isHideMsg = false;
|
||||
Timer(
|
||||
const Duration(milliseconds: 3500),
|
||||
() {
|
||||
setState(() {
|
||||
_isHideMsg = true;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -123,6 +123,8 @@ class _FriendMessageScreenState extends State<FriendMessageScreen> {
|
|||
|
||||
return FriendMessageBubble(
|
||||
key: ValueKey(i),
|
||||
index: i,
|
||||
length: length,
|
||||
contactId: widget.friendId,
|
||||
senderId: messageT.senderId,
|
||||
dateTime: formatMessageDateTime(messageT.dateTime),
|
||||
|
|
|
@ -134,6 +134,8 @@ class _GroupChatMessageScreenState extends State<GroupChatMessageScreen> {
|
|||
|
||||
return GroupChatMessageBubble(
|
||||
key: ValueKey(i),
|
||||
index: i,
|
||||
length: length,
|
||||
contactId: widget.groupChatId,
|
||||
senderId: messageT.senderId,
|
||||
dateTime: formatMessageDateTime(messageT.dateTime),
|
||||
|
|
Loading…
Reference in New Issue