yumi-flutter/lib/modules/chat/message/sc_message_page.dart

381 lines
12 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/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 'package:yumi/ui_kit/widgets/sc_home_shell_background.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: [
const Positioned.fill(child: SCHomeShellBackground()),
if (widget.isFromRoom)
Image.asset(
_strategy.getMessagePageIndexMaskIcon(),
width: ScreenUtil().screenWidth,
fit: BoxFit.cover,
),
Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
bottom: false,
child: Column(
children: [
_buildTopBar(),
Expanded(
child: Consumer<RtmProvider>(
builder: (_, provider, __) {
return Column(
children: [
if (!_isSearchingMessages) _headMenu(provider),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: MessageConversationListPage(
false,
searchQuery: _messageSearchText,
),
),
),
],
);
},
),
),
],
),
),
),
],
);
}
Widget _buildTopBar() {
return SizedBox(
height: 44.w,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: Row(
children: [
Expanded(
child:
_isSearchingMessages
? _messageSearchField()
: SCHomeShellGradientText(
SCAppLocalizations.of(context)!.message,
style: scHomeShellTitleStyle(),
),
),
SCDebounceWidget(
child: SizedBox(
width: 38.w,
height: 38.w,
child: Center(
child:
_isSearchingMessages
? Icon(Icons.close, size: 22.w, color: Colors.white)
: Image.asset(
"sc_images/index/sc_icon_serach.png",
width: 24.w,
height: 24.w,
),
),
),
onTap: () {
if (_isSearchingMessages) {
_stopMessageSearch();
} else {
_startMessageSearch();
}
},
),
],
),
),
);
}
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.black, 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: EdgeInsets.fromLTRB(10.w, 25.w, 10.w, 10.w),
height: 114.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14.w),
border: Border.all(
color: scHomeShellAccentColor.withValues(alpha: 0.2),
width: 1.w,
),
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
const Color(0xFF111A1B).withValues(alpha: 0.86),
const Color(0xFF2C4D42).withValues(alpha: 0.68),
],
),
),
child: Row(
children: [
_buildMessageShortcut(
label: SCAppLocalizations.of(context)!.notifcation,
icon: _strategy.getMessagePageNotificationMessageIcon(),
unreadCount: provider.notifcationUnReadCount,
onTap: () {
provider.updateNotificationCount(0);
SCNavigatorUtils.push(
context,
SCChatRouter.notifcation,
replace: false,
);
},
),
_buildMessageShortcut(
label: SCAppLocalizations.of(context)!.activity,
icon: _strategy.getMessagePageActivityMessageIcon(),
unreadCount: provider.activityUnReadCount,
onTap: () {
provider.updateActivityCount(0);
SCNavigatorUtils.push(
context,
SCChatRouter.activity,
replace: false,
);
},
),
_buildMessageShortcut(
label: SCAppLocalizations.of(context)!.system,
icon: _strategy.getMessagePageSystemMessageIcon(),
unreadCount: 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)}",
);
},
),
],
),
);
}
Widget _buildMessageShortcut({
required String label,
required String icon,
required int unreadCount,
required VoidCallback onTap,
}) {
return Expanded(
child: SCDebounceWidget(
onTap: onTap,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Stack(
clipBehavior: Clip.none,
children: [
Image.asset(icon, width: 52.w, height: 52.w),
if (unreadCount > 0)
PositionedDirectional(
top: -2.w,
end: -6.w,
child: _unreadBadge(unreadCount),
),
],
),
SizedBox(height: 10.w),
Text(
label,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.w700,
height: 1.2,
),
),
],
),
),
);
}
Widget _unreadBadge(int unreadCount) {
return Visibility(
visible: unreadCount > 0,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 6.w),
alignment: Alignment.center,
height: 18.w,
constraints: BoxConstraints(minWidth: 18.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,
),
),
),
);
}
}