mirror of
https://github.com/lakaola/chat-flutter.git
synced 2026-07-02 04:34:29 +08:00
265 lines
8.0 KiB
Dart
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,
|
|
);
|
|
}
|
|
}
|