diff --git a/lib/controller/message/chat_settings_controller.dart b/lib/controller/message/chat_settings_controller.dart new file mode 100644 index 0000000..27e026c --- /dev/null +++ b/lib/controller/message/chat_settings_controller.dart @@ -0,0 +1,151 @@ +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:get/get.dart'; +import 'package:im_flutter_sdk/im_flutter_sdk.dart'; + +import '../../im/im_manager.dart'; +import '../../pages/home/report_page.dart'; + +class ChatSettingsController extends GetxController { + final String userId; + + // 用户信息 + final Rx userInfo = Rx(null); + + // 是否拉黑 + final RxBool isBlacklisted = RxBool(false); + + // 是否关注 + final RxBool isFollowing = RxBool(false); + + // 备注名 + final RxString remark = RxString(''); + + ChatSettingsController({required this.userId}); + + @override + void onInit() { + super.onInit(); + // 初始化时获取用户信息 + fetchUserInfo(); + // 检查黑名单状态 + checkBlacklistStatus(); + // 检查关注状态 + checkFollowStatus(); + } + + /// 获取用户信息 + Future fetchUserInfo() async { + try { + final EMUserInfo? info = await IMManager.instance.getUserInfo(userId); + if (info != null) { + userInfo.value = info; + if (Get.isLogEnable) { + Get.log('获取用户信息成功: ${info.nickName}'); + } + } else { + if (Get.isLogEnable) { + Get.log('未找到用户信息: $userId'); + } + } + } catch (e) { + if (Get.isLogEnable) { + Get.log('获取用户信息失败: $e'); + } + } + } + + /// 检查黑名单状态 + Future checkBlacklistStatus() async { + try { + // 从服务器获取黑名单列表 + final blacklist = await IMManager.instance.getBlacklist(); + isBlacklisted.value = blacklist.contains(userId); + } catch (e) { + if (Get.isLogEnable) { + Get.log('检查黑名单状态失败: $e'); + } + isBlacklisted.value = false; + } + } + + /// 检查关注状态 + Future checkFollowStatus() async { + try { + // TODO: 调用实际的API检查关注状态 + // 这里暂时模拟 + isFollowing.value = false; + } catch (e) { + if (Get.isLogEnable) { + Get.log('检查关注状态失败: $e'); + } + } + } + + /// 切换黑名单状态 + Future toggleBlacklist(bool value) async { + try { + if (value) { + // 加入黑名单 + await IMManager.instance.addToBlacklist(userId); + isBlacklisted.value = true; + SmartDialog.showToast('已加入黑名单'); + } else { + // 移出黑名单 + await IMManager.instance.removeFromBlacklist(userId); + isBlacklisted.value = false; + SmartDialog.showToast('已移出黑名单'); + } + update(); + } catch (e) { + if (Get.isLogEnable) { + Get.log('操作黑名单失败: $e'); + } + SmartDialog.showToast('操作失败,请重试'); + } + } + + /// 切换关注状态 + Future toggleFollow() async { + try { + if (isFollowing.value) { + // 取消关注 + // TODO: 调用实际的取消关注API + isFollowing.value = false; + SmartDialog.showToast('已取消关注'); + } else { + // 关注 + // TODO: 调用实际的关注API + isFollowing.value = true; + SmartDialog.showToast('已关注'); + } + update(); + } catch (e) { + if (Get.isLogEnable) { + Get.log('操作关注失败: $e'); + } + SmartDialog.showToast('操作失败,请重试'); + } + } + + /// 设置备注名 + Future setRemark(String newRemark) async { + try { + // TODO: 调用实际的设置备注名API + remark.value = newRemark; + SmartDialog.showToast('备注名设置成功'); + update(); + } catch (e) { + if (Get.isLogEnable) { + Get.log('设置备注名失败: $e'); + } + SmartDialog.showToast('设置失败,请重试'); + } + } + + /// 举报用户 + void reportUser() { + // 跳转到举报页面 + Get.to(() => ReportPage()); + } +} + diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index be3ae32..cb31a71 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -25,6 +25,7 @@ class Assets { static const String imagesEdit = 'assets/images/edit.png'; static const String imagesEditAvatarsIcon = 'assets/images/edit_avatars_icon.png'; static const String imagesEmoji = 'assets/images/emoji.png'; + static const String imagesEmojiTab = 'assets/images/emoji_tab.png'; static const String imagesExampleContent = 'assets/images/example_content.png'; static const String imagesFemale = 'assets/images/female.png'; static const String imagesFireIcon = 'assets/images/fire_icon.png'; diff --git a/lib/im/im_manager.dart b/lib/im/im_manager.dart index da377cd..dd90158 100644 --- a/lib/im/im_manager.dart +++ b/lib/im/im_manager.dart @@ -402,6 +402,40 @@ class IMManager { } } + /// 添加用户到黑名单 + Future addToBlacklist(String userId) async { + try { + await EMClient.getInstance.contactManager.addUserToBlockList(userId); + print('已将用户 $userId 添加到黑名单'); + } catch (e) { + print('添加黑名单失败: $e'); + rethrow; + } + } + + /// 从黑名单移除用户 + Future removeFromBlacklist(String userId) async { + try { + await EMClient.getInstance.contactManager.removeUserFromBlockList(userId); + print('已将用户 $userId 从黑名单移除'); + } catch (e) { + print('移除黑名单失败: $e'); + rethrow; + } + } + + /// 获取黑名单列表 + Future> getBlacklist() async { + try { + final list = await EMClient.getInstance.contactManager.getBlockListFromServer(); + print('获取黑名单列表成功,共 ${list.length} 个用户'); + return list; + } catch (e) { + print('获取黑名单列表失败: $e'); + return []; + } + } + /// 清理资源 void dispose() { try { diff --git a/lib/pages/message/chat_page.dart b/lib/pages/message/chat_page.dart index a2efe33..690ce82 100644 --- a/lib/pages/message/chat_page.dart +++ b/lib/pages/message/chat_page.dart @@ -9,6 +9,7 @@ import '../../controller/message/voice_player_manager.dart'; import '../../generated/assets.dart'; import '../../../widget/message/chat_input_bar.dart'; import '../../../widget/message/message_item.dart'; +import 'chat_settings_page.dart'; class ChatPage extends StatefulWidget { final String userId; @@ -68,7 +69,10 @@ class _ChatPageState extends State { Container( padding: EdgeInsets.only(right: 16.w), child: Image.asset(Assets.imagesMore, width: 16.w), - ).onTap(() {}), + ).onTap(() { + // 跳转到聊天设置页面 + Get.to(() => ChatSettingsPage(userId: widget.userId)); + }), ], leading: IconButton( icon: Icon(Icons.arrow_back_ios), diff --git a/lib/pages/message/chat_settings_page.dart b/lib/pages/message/chat_settings_page.dart new file mode 100644 index 0000000..0c79f27 --- /dev/null +++ b/lib/pages/message/chat_settings_page.dart @@ -0,0 +1,323 @@ +import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +import '../../controller/message/chat_settings_controller.dart'; +import '../../generated/assets.dart'; + +class ChatSettingsPage extends StatelessWidget { + final String userId; + + const ChatSettingsPage({required this.userId, super.key}); + + @override + Widget build(BuildContext context) { + // 初始化控制器 + Get.put(ChatSettingsController(userId: userId)); + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + title: Text( + '聊天设置', + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + ), + centerTitle: true, + backgroundColor: Colors.white, + elevation: 0, + leading: IconButton( + icon: Icon(Icons.arrow_back_ios, color: Colors.black, size: 20.w), + onPressed: () => Get.back(), + ), + ), + body: GetBuilder( + builder: (controller) { + return Column( + children: [ + // 用户信息区域 + _buildUserInfoSection(controller), + + // 分隔线 + Container( + height: 8.h, + color: Color(0xFFF5F5F5), + ), + + // 设置选项 + _buildSettingsList(controller), + + // 间隔 + SizedBox(height: 17.h), + + // 关注按钮 + _buildFollowButton(controller), + + SizedBox(height: MediaQuery.of(context).padding.bottom + 20.h), + ], + ); + }, + ), + ); + } + + // 用户信息区域 + Widget _buildUserInfoSection(ChatSettingsController controller) { + return Container( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), + child: Row( + children: [ + // 头像 + Obx(() { + final userInfo = controller.userInfo.value; + return ClipOval( + child: userInfo?.avatarUrl != null && userInfo!.avatarUrl!.isNotEmpty + ? Image.network( + userInfo.avatarUrl!, + width: 50.w, + height: 50.w, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return Image.asset( + Assets.imagesAvatarsExample, + width: 50.w, + height: 50.w, + fit: BoxFit.cover, + ); + }, + ) + : Image.asset( + Assets.imagesAvatarsExample, + width: 50.w, + height: 50.w, + fit: BoxFit.cover, + ), + ); + }), + + SizedBox(width: 12.w), + + // 昵称 + Expanded( + child: Obx(() { + final userInfo = controller.userInfo.value; + return Text( + userInfo?.nickName ?? '加载中...', + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + ); + }), + ), + + // 右箭头 + Icon( + Icons.arrow_forward_ios, + size: 16.w, + color: Color(0xFF999999), + ), + ], + ), + ).onTap(() { + // 点击跳转到用户详情页 + // TODO: 导航到用户详情页 + }); + } + + // 设置选项列表 + Widget _buildSettingsList(ChatSettingsController controller) { + return Column( + children: [ + // 设置备注名 + _buildSettingItem( + title: '设置备注名', + showArrow: true, + onTap: () { + // TODO: 打开设置备注名弹窗 + _showSetRemarkDialog(controller); + }, + ), + + _buildDivider(), + + // 加入黑名单 + _buildSwitchItem( + title: '加入黑名单', + value: controller.isBlacklisted.value, + onChanged: (value) { + controller.toggleBlacklist(value); + }, + ), + + _buildDivider(), + + // 举报 + _buildSettingItem( + title: '举报', + showArrow: true, + onTap: () { + // TODO: 跳转到举报页面 + controller.reportUser(); + }, + ), + + _buildDivider(), + + ], + ); + } + + // 设置项(带箭头) + Widget _buildSettingItem({ + required String title, + bool showArrow = false, + VoidCallback? onTap, + }) { + return Container( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), + child: Row( + children: [ + Expanded( + child: Text( + title, + style: TextStyle( + fontSize: 16.sp, + color: Colors.black, + ), + ), + ), + if (showArrow) + Icon( + Icons.arrow_forward_ios, + size: 16.w, + color: Color(0xFF999999), + ), + ], + ), + ).onTap(onTap); + } + + // 开关项 + Widget _buildSwitchItem({ + required String title, + required bool value, + required ValueChanged onChanged, + }) { + return Container( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), + child: Row( + children: [ + Expanded( + child: Text( + title, + style: TextStyle( + fontSize: 16.sp, + color: Colors.black, + ), + ), + ), + Obx(() { + final controller = Get.find(); + return CupertinoSwitch( + value: controller.isBlacklisted.value, + onChanged: onChanged, + activeColor: Color.fromRGBO(117, 98, 249, 1), + ); + }), + ], + ), + ); + } + + // 分隔线 + Widget _buildDivider() { + return Container( + margin: EdgeInsets.only(left: 16.w), + height: 1.h, + color: Color(0xFFF5F5F5), + ); + } + + // 关注按钮 + Widget _buildFollowButton(ChatSettingsController controller) { + return Obx(() { + final isFollowing = controller.isFollowing.value; + return Container( + margin: EdgeInsets.symmetric(horizontal: 25.w), + width: double.infinity, + height: 50.h, + child: ElevatedButton( + onPressed: () { + controller.toggleFollow(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color.fromRGBO(117, 98, 249, 1), + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24.r), + ), + elevation: 0, + ), + child: Text( + isFollowing ? '已关注' : '关注', + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w500, + ), + ), + ), + ); + }); + } + + // 设置备注名对话框 + void _showSetRemarkDialog(ChatSettingsController controller) { + final TextEditingController textController = TextEditingController(); + + Get.dialog( + AlertDialog( + title: Text('设置备注名'), + content: TextField( + controller: textController, + decoration: InputDecoration( + hintText: '请输入备注名', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.r), + ), + ), + autofocus: true, + ), + actions: [ + TextButton( + onPressed: () => Get.back(), + child: Text( + '取消', + style: TextStyle(color: Color(0xFF999999)), + ), + ), + TextButton( + onPressed: () { + final remark = textController.text.trim(); + if (remark.isNotEmpty) { + controller.setRemark(remark); + Get.back(); + } + }, + child: Text( + '确定', + style: TextStyle(color: Color(0xFFA05CFF)), + ), + ), + ], + ), + ); + } +} + diff --git a/lib/widget/emoji_panel.dart b/lib/widget/emoji_panel.dart index b161fe6..9bd962a 100644 --- a/lib/widget/emoji_panel.dart +++ b/lib/widget/emoji_panel.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../config/emoji_config.dart'; +import '../generated/assets.dart'; /// 表情选择面板 class EmojiPanel extends StatefulWidget { @@ -84,7 +85,7 @@ class _EmojiPanelState extends State { ), padding: EdgeInsets.all(8.w), child: Image.asset( - 'assets/images/emoji_tab.png', + Assets.imagesEmojiTab, fit: BoxFit.contain, ), ),