yumi-flutter/lib/modules/chat/message/sc_message_page.dart
2026-07-08 10:25:04 +08:00

478 lines
17 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:yumi/app_localizations.dart';
import 'package:yumi/ui_kit/components/sc_debounce_widget.dart';
import 'package:yumi/ui_kit/components/text/sc_text.dart';
import 'package:yumi/services/audio/rtm_manager.dart';
import 'package:provider/provider.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:yumi/app/constants/sc_global_config.dart';
import 'package:yumi/app/config/business_logic_strategy.dart';
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
import 'package:yumi/ui_kit/theme/socialchat_theme.dart';
import 'package:yumi/ui_kit/widgets/msg/message_conversation_list_page.dart';
import '../chat_route.dart';
///消息
class SCMessagePage extends StatefulWidget {
final bool isFromRoom;
const SCMessagePage({super.key, this.isFromRoom = false});
@override
State<SCMessagePage> createState() => _MessagePageState();
}
class _MessagePageState extends State<SCMessagePage> {
BusinessLogicStrategy get _strategy => SCGlobalConfig.businessLogicStrategy;
bool showSystemAnnouncementTips = true;
final TextEditingController _messageSearchController =
TextEditingController();
final FocusNode _messageSearchFocusNode = FocusNode();
bool _isSearchingMessages = false;
String _messageSearchText = "";
@override
void initState() {
super.initState();
showSystemAnnouncementTips = DataPersistence.getBool(
"${AccountStorage().getCurrentUser()?.userProfile?.account}-ShowSystemAnnouncementTips",
defaultValue: true,
);
_checkLogin();
}
void _checkLogin() async {
V2TimValueCallback<int> getLoginStatusRes =
await TencentImSDKPlugin.v2TIMManager.getLoginStatus();
if (getLoginStatusRes.code == 0) {
var status = getLoginStatusRes.data; // getLoginStatusRes.data为用户登录状态值
if (status == 1) {
// 已登录
///处理有时候拉不到最后一条消息
Provider.of<RtmProvider>(
context,
listen: false,
).initConversation().then((value) {
Future.delayed(Duration(milliseconds: 550), () {
Provider.of<RtmProvider>(
context,
listen: false,
).initConversation().then((value) {
setState(() {});
});
});
});
} else if (status == 2) {
// 登录中
} else if (status == 3) {
// 未登录
Provider.of<RtmProvider>(
context,
listen: false,
).loginTencetRtm(context).then((value) {
_checkLogin();
});
}
setState(() {});
}
}
@override
void dispose() {
_messageSearchController.dispose();
_messageSearchFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
widget.isFromRoom
? Image.asset(
_strategy.getMessagePageIndexMaskIcon(),
width: ScreenUtil().screenWidth,
fit: BoxFit.cover,
)
: Container(),
DefaultTabController(
length: 1,
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: null,
title:
_isSearchingMessages
? _messageSearchField()
: TabBar(
tabs:
[SCAppLocalizations.of(context)!.message]
.map(
(e) => Padding(
padding: EdgeInsets.only(
bottom: 3.w,
top: 4.w,
),
child: Text(e),
),
)
.toList(),
dividerColor: Colors.transparent,
labelStyle: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
),
unselectedLabelStyle: TextStyle(
fontSize: 15.sp,
color: Colors.white,
fontWeight: FontWeight.normal,
),
indicator: BoxDecoration(),
//TabBarIndicator(),
indicatorSize: TabBarIndicatorSize.label,
isScrollable: true,
tabAlignment: TabAlignment.start,
labelColor: SocialChatTheme.primaryLight,
),
actions: [
SCDebounceWidget(
child: Container(
padding: EdgeInsetsDirectional.only(start: 10.w, end: 10.w),
child:
_isSearchingMessages
? Icon(Icons.close, size: 22.w, color: Colors.white)
: Image.asset(
"sc_images/index/sc_icon_serach.png",
width: 20.w,
height: 20.w,
),
),
onTap: () {
if (_isSearchingMessages) {
_stopMessageSearch();
} else {
_startMessageSearch();
}
},
),
],
),
body: TabBarView(
children: [
Consumer<RtmProvider>(
builder: (_, provider, __) {
return Container(
margin: EdgeInsetsDirectional.symmetric(horizontal: 10.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"sc_images/index/sc_index_msg_content_bg.png",
),
fit: BoxFit.fill,
),
),
child: Column(
children: [
if (!_isSearchingMessages) _headMenu(provider),
Expanded(
child: Container(
margin: EdgeInsets.only(
top: 0.w,
left: 8.w,
right: 8.w,
),
child: MessageConversationListPage(
false,
searchQuery: _messageSearchText,
),
),
),
],
),
);
},
),
],
),
),
),
],
);
}
Widget _messageSearchField() {
return Container(
height: 36.w,
alignment: AlignmentDirectional.center,
decoration: BoxDecoration(
color: const Color(0xff18F2B1).withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(20.w),
),
child: Row(
children: [
SizedBox(width: 10.w),
Image.asset(
"sc_images/index/sc_icon_serach2.png",
width: 18.w,
height: 18.w,
color: const Color(0xff18F2B1),
),
SizedBox(width: 6.w),
Expanded(
child: TextField(
controller: _messageSearchController,
focusNode: _messageSearchFocusNode,
autofocus: true,
cursorColor: SocialChatTheme.primaryLight,
style: TextStyle(color: Colors.white, fontSize: 14.sp),
decoration: InputDecoration(
hintText:
"${SCAppLocalizations.of(context)!.search} ID/${SCAppLocalizations.of(context)!.userName}",
hintStyle: TextStyle(color: Colors.white54, fontSize: 13.sp),
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.zero,
),
onChanged: (value) {
setState(() {
_messageSearchText = value;
});
},
),
),
],
),
);
}
void _startMessageSearch() {
setState(() {
_isSearchingMessages = true;
});
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
_messageSearchFocusNode.requestFocus();
}
});
}
void _stopMessageSearch() {
_messageSearchController.clear();
_messageSearchFocusNode.unfocus();
setState(() {
_isSearchingMessages = false;
_messageSearchText = "";
});
}
Widget _headMenu(RtmProvider provider) {
return Container(
margin: EdgeInsetsDirectional.symmetric(
horizontal: 20.w,
).copyWith(top: 10.w),
child: Column(
spacing: 15.w,
children: [
SCDebounceWidget(
child: Stack(
children: [
Row(
children: [
SizedBox(height: 3.w),
Image.asset(
_strategy.getMessagePageActivityMessageIcon(),
width: 45.w,
height: 45.w,
),
SizedBox(width: 5.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
text(
SCAppLocalizations.of(context)!.activity,
textColor: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.bold,
),
SizedBox(height: 3.w),
text(
"[${SCAppLocalizations.of(context)!.newMessage}]",
fontSize: 12.sp,
textColor: Colors.white54,
),
],
),
],
),
PositionedDirectional(
bottom: 0,
end: 10.w,
child: Visibility(
visible: provider.activityUnReadCount > 0,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 6.w),
alignment: Alignment.center,
height: 16.w,
decoration: BoxDecoration(
//gradient: LinearGradient(colors: [Color(0xffA447FF), Color(0xff623CE9)]),
color: Colors.red,
shape: BoxShape.circle,
//borderRadius: BorderRadius.all(Radius.circular(7.w)),
),
child: Text(
"${provider.activityUnReadCount > 99 ? '99+' : provider.activityUnReadCount}",
style: TextStyle(
fontSize: 10.sp,
color: Color(0xffffffff),
fontWeight: FontWeight.w400,
decoration: TextDecoration.none,
),
),
),
),
),
],
),
onTap: () {
provider.updateActivityCount(0);
SCNavigatorUtils.push(
context,
SCChatRouter.activity,
replace: false,
);
},
),
SCDebounceWidget(
child: Row(
children: [
SizedBox(height: 3.w),
Image.asset(
_strategy.getMessagePageSystemMessageIcon(),
width: 45.w,
height: 45.w,
),
SizedBox(width: 6.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
text(
SCAppLocalizations.of(context)!.system,
textColor: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.bold,
),
SizedBox(height: 3.w),
Row(
children: [
Expanded(
child: text(
"[${SCAppLocalizations.of(context)!.newMessage}]",
fontSize: 12.sp,
textColor: Colors.white54,
),
),
SizedBox(width: 5.w),
_unreadBadge(provider.systemUnReadCount),
],
),
],
),
),
],
),
onTap: () async {
var conversation = provider.getPreferredSystemConversation();
provider.updateSystemCount(0);
var bool = await provider.startConversation(conversation);
if (!bool) return;
var json = jsonEncode(conversation.toJson());
SCNavigatorUtils.push(
context,
"${SCChatRouter.systemChat}?conversation=${Uri.encodeComponent(json)}",
);
},
),
SCDebounceWidget(
child: Row(
children: [
SizedBox(height: 3.w),
Image.asset(
_strategy.getMessagePageNotificationMessageIcon(),
width: 45.w,
height: 45.w,
),
SizedBox(width: 6.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
text(
SCAppLocalizations.of(context)!.notifcation,
textColor: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.bold,
),
SizedBox(height: 3.w),
Row(
children: [
Expanded(
child: text(
"[${SCAppLocalizations.of(context)!.newMessage}]",
fontSize: 12.sp,
textColor: Colors.white54,
),
),
SizedBox(width: 5.w),
_unreadBadge(provider.notifcationUnReadCount),
],
),
],
),
),
],
),
onTap: () {
provider.updateNotificationCount(0);
SCNavigatorUtils.push(
context,
SCChatRouter.notifcation,
replace: false,
);
},
),
],
),
);
}
Widget _unreadBadge(int unreadCount) {
return Visibility(
visible: unreadCount > 0,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 6.w),
alignment: Alignment.center,
height: 16.w,
decoration: BoxDecoration(color: Colors.red, shape: BoxShape.circle),
child: Text(
"${unreadCount > 99 ? '99+' : unreadCount}",
style: TextStyle(
fontSize: 10.sp,
color: Color(0xffffffff),
fontWeight: FontWeight.w400,
decoration: TextDecoration.none,
),
),
),
);
}
}