Files
chat-flutter/lib/views/msg/msg_chat_view.dart
2025-09-12 20:35:12 +08:00

265 lines
8.0 KiB
Dart

import 'package:date_format/date_format.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:demo/config/app_config.dart';
import 'package:demo/event/event_setting.dart';
import 'package:demo/views/chat/chat_bottom_check.dart';
import 'package:demo/views/chat/chat_message.dart';
import 'package:demo/views/chat/chat_message_bubble.dart';
import 'package:demo/views/friend/friend_details_view.dart';
import 'package:demo/views/chat/chat_bottom.dart';
import 'package:demo/views/group/group_details_view.dart';
import 'package:demo/views/msg/msg_chat_controller.dart';
import 'package:demo/component/component_checkbox.dart';
import 'package:demo/tools/tools_enum.dart';
import 'package:demo/tools/tools_sqlite.dart';
import 'package:demo/tools/tools_storage.dart';
import 'package:demo/component/component_action.dart';
import 'package:demo/component/component_common.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
// 聊天页面
class MsgChatView extends GetView<MsgChatController> {
// 路由地址
static const String routeName = '/msg_chat';
const MsgChatView({super.key});
@override
Widget build(BuildContext context) {
Get.lazyPut(() => MsgChatController());
return GestureDetector(
onTap: () {
// 关闭小桌板
EventSetting().handle(SettingModel(SettingType.close));
},
child: Scaffold(
backgroundColor: const Color.fromARGB(255, 245, 241, 241),
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Obx(
() => Text(
controller.chatTitle.value,
style: const TextStyle(
color: Colors.black,
fontSize: 16,
),
),
),
actions: [
ComponentAction(
icon: const Icon(Icons.more_horiz),
onTap: () {
LocalChat localChat = ToolsStorage().chat();
// 好友
if (ChatTalk.friend == localChat.chatTalk) {
Get.toNamed(
FriendDetailsView.routeName,
arguments: localChat.chatId,
);
}
// 群组
else if (ChatTalk.group == localChat.chatTalk) {
Get.toNamed(
GroupDetailsView.routeName,
arguments: localChat.chatId,
);
}
},
),
],
),
body: PagedListView<int, ChatHis>(
pagingController: controller.pagingController,
scrollController: controller.scrollController,
shrinkWrap: true,
reverse: true,
builderDelegate: PagedChildBuilderDelegate<ChatHis>(
itemBuilder: (context, chatHis, index) {
return AutoScrollTag(
key: ValueKey(index),
controller: controller.scrollController,
index: index,
child: Obx(
() => _buildChatItem(chatHis),
),
);
},
noItemsFoundIndicatorBuilder: (context) {
return Container();
},
),
),
bottomNavigationBar: Obx(() {
// 多选菜单
if (controller.configCheckBox.isTrue) {
return ChatBottomCheck(
configCheckBox: controller.configCheckBox,
checkboxList: controller.checkboxList,
);
}
// 输入框
return ChatBottom(
controller.scrollController,
controller.textController,
);
}),
),
);
}
// 渲染聊天
_buildChatItem(ChatHis chatHis) {
return GestureDetector(
onTap: () {
// 关闭小桌板
EventSetting().handle(SettingModel(SettingType.close));
// 验证复选框
if (controller.configCheckBox.isFalse) {
return;
}
if (controller.checkboxList.containsKey(chatHis.msgId)) {
controller.checkboxList.remove(chatHis.msgId);
} else if (controller.checkboxList.length > 9) {
// 提醒
EasyLoading.showToast('多选不能超过10条哦');
} else {
controller.checkboxList[chatHis.msgId] = chatHis;
}
},
child: Container(
color: Colors.transparent,
padding: const EdgeInsets.all(8.0),
child: IgnorePointer(
ignoring: controller.configCheckBox.isTrue,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildCheckbox(chatHis),
const SizedBox(width: 60),
Expanded(
child: GestureDetector(
onLongPressStart: (LongPressStartDetails details) {
_buildDialog(details, chatHis);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
_buildContent(chatHis),
const SizedBox(
height: 10,
),
_buildTime(chatHis),
],
),
),
),
_buildPortrait(chatHis),
],
),
),
),
);
}
_buildPortrait(ChatHis chatHis) {
switch (chatHis.msgType) {
case MsgType.tips:
return Container();
default:
break;
}
// 默认
String portrait = controller.localUser.portrait;
String userId = controller.localUser.userId;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Column(
children: [
InkWell(
onTap: () {
// 好友
if (ChatTalk.friend == chatHis.chatTalk) {
Get.toNamed(
FriendDetailsView.routeName,
arguments: userId,
);
}
// 群组
else if (ChatTalk.group == chatHis.chatTalk) {
Get.toNamed(
FriendDetailsView.routeName,
arguments: userId,
);
}
},
child: ComponentCommon.showAvatar(portrait, size: 45),
),
],
),
);
}
_buildCheckbox(ChatHis chatHis) {
if (controller.configCheckBox.isFalse) {
return Container();
}
return ComponentCheckbox(
value: controller.checkboxList.containsKey(chatHis.msgId),
onChanged: (bool value) {},
);
}
_buildContent(ChatHis chatHis) {
return ChatMessage(
chatHis,
controller.audioPlayer,
);
}
_buildDialog(LongPressStartDetails details, ChatHis chatHis) {
if (controller.keyboard.isVisible) {
// 关闭小桌板
EventSetting().handle(SettingModel(SettingType.close));
} else {
showGeneralDialog(
context: AppConfig.navigatorKey.currentState!.context,
barrierColor: Colors.black.withOpacity(0.0),
barrierDismissible: true,
barrierLabel: '',
pageBuilder: (
BuildContext buildContext,
Animation animation,
Animation secondaryAnimation,
) {
return ChatMessageBubble(
chatHis: chatHis,
height: details.globalPosition.dy,
configCheckBox: controller.configCheckBox,
);
},
);
}
}
_buildTime(ChatHis chatHis) {
TextAlign textAlign = TextAlign.right;
switch (chatHis.msgType) {
case MsgType.tips:
textAlign = TextAlign.center;
break;
default:
break;
}
String label = formatDate(
chatHis.createTime,
[yyyy, '-', mm, '-', dd, ' ', HH, ':', nn, ':', ss],
);
return ComponentCommon.tips(
label,
textAlign: textAlign,
);
}
}