Browse Source

聊天修改

dart3_last
fff 1 week ago
parent
commit
a467c719cb
  1. 537
      lib/im/chat_details_page.dart

537
lib/im/chat_details_page.dart

@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:huixiang/constant.dart';
import 'package:huixiang/data/base_data.dart';
@ -20,12 +21,9 @@ import 'package:huixiang/im/out/message.pb.dart';
import 'package:huixiang/main.dart';
import 'package:huixiang/retrofit/retrofit_api.dart';
import 'package:huixiang/utils/shared_preference.dart';
import 'package:huixiang/view_widget/classic_header.dart';
import 'package:huixiang/view_widget/my_appbar.dart';
import 'package:image_pickers/image_pickers.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import '../../community/release_dynamic.dart';
import '../../generated/l10n.dart';
import '../../utils/font_weight.dart';
@ -62,7 +60,9 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
UserInfo? userInfo;
// final OnChatMessage? _tempOnChatMessage = OnChatMsgInstance.instance.onChatMessage;
final ScrollController scrollController = ScrollController();
GlobalKey<AnimatedListState> animatedListKey = GlobalKey<AnimatedListState>();
GlobalKey<SliverAnimatedListState> newanimatedListKey = GlobalKey<SliverAnimatedListState>();
GlobalKey<SliverAnimatedListState> loadanimatedListKey = GlobalKey<SliverAnimatedListState>();
GlobalKey centerKey = GlobalKey();
String tex = "";
String selfUserId = "";
ImUser? _toUser;
@ -72,8 +72,11 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
double inputWidgetHeight = 95;
double dynamicInputHeight = 0;
RefreshController refreshController = RefreshController();
List<Message> messages = [];
late StreamSubscription<bool> keyboardSubscription;
bool loading = false;
List<Message> newmessages = [];
List<Message> loadmessages = [];
int page = 0;
loadMessageList() async {
@ -91,8 +94,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
await refresh();
socketClient.addCallback(_toUser?.mid ?? '', (Message message) {
messages.add(message);
animatedListKey.currentState?.insertItem(messages.length - 1);
newmessages.add(message);
newanimatedListKey.currentState?.insertItem(newmessages.length - 1);
if ((message.msgType == MsgType.VIDEO.value || message.msgType == MsgType.IMAGE.value) && (message.attach?.isNotEmpty ?? false)) {
imageUrl.add(message.attach!);
}
@ -102,7 +105,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
});
});
messageImageUrl();
messageImageUrl(newmessages);
// refreshState();
// jumpToBottom();
@ -112,40 +115,45 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
List<Message>? messagePage = await hxDatabase.queryUList(conversation, page: page + 1, pageSize: 10);
debugPrint("refresh-message-list: ${messagePage?.length ?? ''} page: $page");
if (messagePage?.isEmpty ?? true) {
refreshController.refreshCompleted();
// refreshController.refreshCompleted();
return 0;
} else {
refreshController.refreshCompleted();
// refreshController.refreshCompleted();
page += 1;
}
double height = 0;
await Future.forEach(messagePage!, (element) async {
height += await chatDetailsItemHeight(element);
});
if (scrollController.hasClients) {
debugPrint("refresh-message-height: ${height} page: $page");
scrollController.position.restoreOffset(height, initialRestore: true);
}
if (page == 1) {
messages.addAll(messagePage.reversed.toList());
animatedListKey.currentState?.insertAllItems(0, messagePage.length);
await Future.forEach(messagePage!, (element) async {
height += await chatDetailsItemHeight(element);
});
if (scrollController.hasClients) {
debugPrint("refresh-message-height: ${height} page: $page");
scrollController.position.restoreOffset(height, initialRestore: true);
}
newmessages.addAll(messagePage!.reversed.toList());
newanimatedListKey.currentState?.insertAllItems(0, messagePage.length);
} else {
messages.insertAll(0, messagePage.reversed.toList());
animatedListKey.currentState?.insertAllItems(0, messagePage.length, duration: 300.milliseconds);
loadmessages.addAll(messagePage!.toList());
loadanimatedListKey.currentState?.insertAllItems(0, messagePage.length, duration: 300.milliseconds);
}
await messageShowTime();
return height;
}
///
messageImageUrl() {
imageUrl = messages.where((e) => (e.msgType == MsgType.VIDEO.value || e.msgType == MsgType.IMAGE.value) && (e.attach?.isNotEmpty ?? false)).map((e) => "${e.attach}").toList();
messageImageUrl(List<Message> messages) {
List<String> images = messages.where((e) => (e.msgType == MsgType.VIDEO.value || e.msgType == MsgType.IMAGE.value) && (e.attach?.isNotEmpty ?? false)).map((e) => "${e.attach}").toList();
if (images.isNotEmpty) {
imageUrl.addAll(images);
}
}
Future messageShowTime() async {
List<Message>? messagePages = await hxDatabase.queryTList(conversation);
for (var value in messages) {
Message? message = messagePages?.firstWhere((element) => value.id == element.id, orElse: () => messages.first);
List<Message> tempMessages = newmessages + loadmessages;
for (var value in tempMessages) {
Message? message = messagePages?.firstWhere((element) => value.id == element.id, orElse: () => tempMessages.first);
value.showTime = message != null;
}
}
@ -174,8 +182,6 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
if (mounted) setState(() {});
}
late StreamSubscription<bool> keyboardSubscription;
@override
void initState() {
super.initState();
@ -188,15 +194,18 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
queryUser();
loadMessageList();
scrollController.addListener(() {
debugPrint("scrollController-onChange: ${scrollController.position.pixels}");
if (messages.length >= 10 && scrollController.position.pixels < -80) {
if (!loading) {
loading = true;
refresh().then((value) => loading = false);
}
}
});
// scrollController.addListener(() {
// debugPrint("scrollController-onChange: ${scrollController.position.pixels}");
// if (scrollController.position.pixels < -80) {
// if (!loading) {
// loading = true;
// refresh().then((value) {
// loading = false;
// messageImageUrl(loadmessages);
// });
// }
// }
// });
var keyboardVisibilityController = KeyboardVisibilityController();
keyboardSubscription = keyboardVisibilityController.onChange.listen((bool visible) {
@ -237,8 +246,6 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
});
}
bool loading = false;
void jumpToBottom() {
Future.delayed(const Duration(milliseconds: 400), () {
if (scrollController.hasClients && scrollController.position.pixels != scrollController.position.maxScrollExtent) {
@ -295,8 +302,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
moreShow = false;
}
if (emojiShowing) {
if (inputWidgetHeight == 95) {
inputWidgetHeight += (keyboard == -1 ? 270 : keyboard);
if (inputWidgetHeight < 270) {
inputWidgetHeight = 95 + (keyboard == -1 ? 270 : keyboard);
jumpToBottom();
}
} else {
@ -360,8 +367,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
String fileUrl = await qiniu.uploadFile(apiService!, path);
socketClient.sendMessage(_toUser?.mid ?? '', fileUrl, attach: path, msgType: galleryMode == GalleryMode.image ? 2 : 4).then((value) {
Message message = value;
messages.add(message);
animatedListKey.currentState?.insertItem(messages.length - 1);
newmessages.add(message);
newanimatedListKey.currentState?.insertItem(newmessages.length - 1);
chatController.clear();
messageShowTime().then((value) {
refreshState();
@ -391,7 +398,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
},
heightRatioWithWidth: 0.82,
);
});
},
);
} else if (await Permission.camera.isGranted) {
if (await Permission.storage.isPermanentlyDenied) {
showCupertinoDialog(
@ -409,7 +417,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
},
heightRatioWithWidth: 0.82,
);
});
},
);
} else if (await Permission.storage.isGranted) {
Media? medias = await ImagePickers.openCamera(
cameraMimeType: CameraMimeType.photo,
@ -425,8 +434,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
String fileUrl = await qiniu.uploadFile(apiService!, path);
socketClient.sendMessage(_toUser?.mid ?? '', fileUrl, attach: path, msgType: 2).then((value) {
Message message = value;
messages.add(message);
animatedListKey.currentState?.insertItem(messages.length - 1);
newmessages.add(message);
newanimatedListKey.currentState?.insertItem(newmessages.length - 1);
chatController.clear();
messageShowTime().then((value) {
refreshState();
@ -564,33 +573,67 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
),
),
),
body: Container(
height: MediaQuery.of(context).size.height - kToolbarHeight - MediaQuery.of(context).padding.top - MediaQuery.of(context).viewInsets.bottom,
child: Column(
children: [
Expanded(
child: chatDetailsList(),
flex: 1,
),
input(),
],
),
body:
// Container(
// height: MediaQuery.of(context).size.height - kToolbarHeight - MediaQuery.of(context).padding.top - MediaQuery.of(context).viewInsets.bottom,
// child:
Column(
children: [
Expanded(
child: chatDetailsList(),
flex: 1,
),
input(),
],
),
// ),
),
);
}
///
Widget chatDetailsList() {
return AnimatedList(
key: animatedListKey,
initialItemCount: messages.length,
return RefreshIndicator(
child: CustomScrollView(
center: centerKey,
controller: scrollController,
physics: BouncingScrollPhysics()..frictionFactor(0.8),
itemBuilder: (context, position, animation) {
return chatDetailsItem(position);
physics: ClampingScrollPhysics(),
slivers: [
SliverAnimatedList(
itemBuilder: (context, index, animation) {
Message message = loadmessages[index];
return chatDetailsItem(message, index, loadanimatedListKey);
},
key: loadanimatedListKey,
initialItemCount: loadmessages.length,
),
SliverPadding(
padding: EdgeInsets.zero,
key: centerKey,
),
SliverAnimatedList(
itemBuilder: (context, index, animation) {
Message message = newmessages[index];
return chatDetailsItem(message, index, loadanimatedListKey);
},
key: newanimatedListKey,
initialItemCount: newmessages.length,
),
],
),
onRefresh: () async {
refresh();
},
);
// return AnimatedList(
// key: animatedListKey,
// initialItemCount: messages.length,
// controller: scrollController,
// physics: BouncingScrollPhysics()..frictionFactor(0.8),
// itemBuilder: (context, position, animation) {
// return chatDetailsItem(position);
// },
// );
}
Future<double> chatDetailsItemHeight(Message message) async {
@ -644,10 +687,10 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
return textPainter.height;
}
Widget chatDetailsItem(position) {
bool isSelf = messages[position].fromId == selfUserId;
bool isText = messages[position].msgType == 1;
bool isImage = messages[position].msgType == 2;
Widget chatDetailsItem(Message message, index, animationKey) {
bool isSelf = message.fromId == selfUserId;
bool isText = message.msgType == 1;
bool isImage = message.msgType == 2;
GlobalKey _buttonKey = GlobalKey();
return Container(
padding: EdgeInsets.only(
@ -656,12 +699,12 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
),
child: Column(
children: [
if (messages[position].showTime)
if (message.showTime)
Text(
// position == messages.length-1
// ?
AppUtils.milliTimeFormatter(DateTime.fromMillisecondsSinceEpoch(
int.parse(messages[position].time)))
int.parse(message.time)))
// : AppUtils.getTimeDisplay(
// DateTime.fromMillisecondsSinceEpoch(
// int.parse(messages[position].time)),
@ -739,7 +782,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
alignment: Alignment.centerLeft,
child: GestureDetector(
onLongPress: () {
showMessageMenu(context, _buttonKey, messages[position]);
showMessageMenu(context, _buttonKey, message, index, loadanimatedListKey);
},
child: Container(
decoration: BoxDecoration(
@ -760,7 +803,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
horizontal: 12.w,
),
child: Text(
tex = messages[position].content,
tex = message.content,
textAlign: TextAlign.left,
style: TextStyle(
height: 1.2.h,
@ -789,7 +832,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (messages[position].state == 3)
if (message.state == 3)
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
@ -808,7 +851,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
),
),
),
if (messages[position].state == 3)
if (message.state == 3)
SizedBox(
width: 12.w,
),
@ -817,7 +860,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
alignment: Alignment.centerRight,
child: InkWell(
onLongPress: () {
showMessageMenu(context, _buttonKey, messages[position]);
showMessageMenu(context, _buttonKey, message, index, loadanimatedListKey);
},
child: Container(
decoration: BoxDecoration(
@ -838,7 +881,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
horizontal: 12.w,
),
child: Text(
tex = messages[position].content,
tex = message.content,
textAlign: TextAlign.left,
style: TextStyle(
height: 1.2,
@ -901,18 +944,18 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
),
GestureDetector(
onLongPress: () {
showMessageMenu(context, _buttonKey, messages[position]);
showMessageMenu(context, _buttonKey, message, index, loadanimatedListKey);
},
onTap: () {
if (imageUrl.contains(messages[position].attach) && (messages[position].attach?.isNotEmpty ?? false)) {
ImagePickers.previewImages(imageUrl, imageUrl.indexOf(messages[position].attach!));
if (imageUrl.contains(message.attach) && (message.attach?.isNotEmpty ?? false)) {
ImagePickers.previewImages(imageUrl, imageUrl.indexOf(message.attach!));
}
},
child: FutureBuilder(
future: fetchImageSize(messages[position]),
future: fetchImageSize(message),
key: _buttonKey,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (messages[position].attach?.isEmpty ?? true) {
if (message.attach?.isEmpty ?? true) {
return SizedBox(
width: 180.w,
height: 200.h,
@ -920,7 +963,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
}
if (snapshot.connectionState == ConnectionState.waiting || snapshot.hasError) {
return Image.file(
File(messages[position].attach!),
File(message.attach!),
width: 180.w,
height: 200.h,
alignment: Alignment.centerLeft,
@ -928,7 +971,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
);
} else {
return Image.file(
File(messages[position].attach!),
File(message.attach!),
width: snapshot.data.width,
height: snapshot.data.height,
alignment: Alignment.centerLeft,
@ -956,18 +999,18 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
Spacer(),
GestureDetector(
onLongPress: () {
showMessageMenu(context, _buttonKey, messages[position]);
showMessageMenu(context, _buttonKey, message, index, loadanimatedListKey);
},
onTap: () {
if (imageUrl.contains(messages[position].attach) && (messages[position].attach?.isNotEmpty ?? false)) {
ImagePickers.previewImages(imageUrl, imageUrl.indexOf(messages[position].attach!));
if (imageUrl.contains(message.attach) && (message.attach?.isNotEmpty ?? false)) {
ImagePickers.previewImages(imageUrl, imageUrl.indexOf(message.attach!));
}
},
child: FutureBuilder (
future: fetchImageSize(messages[position]),
future: fetchImageSize(message),
key: _buttonKey,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (messages[position].attach?.isEmpty ?? true) {
if (message.attach?.isEmpty ?? true) {
return SizedBox(
width: 180.w,
height: 200.h,
@ -975,7 +1018,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
}
if (snapshot.connectionState == ConnectionState.waiting || snapshot.hasError) {
return Image.file(
File(messages[position].attach!),
File(message.attach!),
width: 180.w,
height: 200.h,
alignment: Alignment.centerRight,
@ -983,7 +1026,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
);
} else {
return Image.file(
File(messages[position].attach!),
File(message.attach!),
width: snapshot.data.width,
height: snapshot.data.height,
alignment: Alignment.centerRight,
@ -1029,119 +1072,225 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
}
///
showMessageMenu(context, _buttonKey, message) {
showMessageMenu(context, _buttonKey, message, index, animatedListKey) {
RenderBox renderBox = _buttonKey.currentContext.findRenderObject() as RenderBox;
Offset buttonPosition = renderBox.localToGlobal(Offset.zero);
Size buttonSize = renderBox.size;
showMenu(
context: context, ///
elevation: 0,
color: Colors.transparent,
position: RelativeRect.fromLTRB(
buttonPosition.dx + (buttonSize.width - 180.w) / 2, //
buttonPosition.dy - 68,
buttonPosition.dx + buttonSize.width,
buttonPosition.dy,
),
///
items: [
PopupMenuItem(
value: 1,
padding: EdgeInsets.zero,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
Container(
padding: EdgeInsets.only(bottom: 13.h),
child: Container(
width: 180.w,
decoration: BoxDecoration(
color: Color(0xFF2A2A2A),
borderRadius: BorderRadius.circular(6),
),
padding: EdgeInsets.symmetric(
horizontal: 32.w,
vertical: 7.5.h,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
setState(() {
this.copy(message.content);
Navigator.pop(context);
});
},
child: Column(
children: [
Image.asset(
"assets/image/icon_chat_copy.webp",
height: 16,
width: 16,
),
SizedBox(
height: 2.h,
),
Text(
"复制",
textAlign:
TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
fontWeight: MyFontWeight
.regular,
),
// showMenu(
// context: context, ///
// elevation: 0,
// color: Colors.transparent,
// position: RelativeRect.fromLTRB(
// buttonPosition.dx + (buttonSize.width - 180.w) / 2, //
// buttonPosition.dy - 68,
// buttonPosition.dx + buttonSize.width,
// buttonPosition.dy,
// ),
// ///
// items: [
// PopupMenuItem(
// value: 1,
// padding: EdgeInsets.zero,
// child: Stack(
// alignment: Alignment.bottomCenter,
// children: [
// Container(
// padding: EdgeInsets.only(bottom: 13.h),
// child: Container(
// width: 180.w,
// decoration: BoxDecoration(
// color: Color(0xFF2A2A2A),
// borderRadius: BorderRadius.circular(6),
// ),
// padding: EdgeInsets.symmetric(
// horizontal: 32.w,
// vertical: 7.5.h,
// ),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// GestureDetector(
// onTap: () {
// setState(() {
// this.copy(message.content);
// Navigator.pop(context);
// });
// },
// child: Column(
// children: [
// Image.asset(
// "assets/image/icon_chat_copy.webp",
// height: 16,
// width: 16,
// ),
// SizedBox(
// height: 2.h,
// ),
// Text(
// "复制",
// textAlign:
// TextAlign.center,
// style: TextStyle(
// color: Colors.white,
// fontSize: 12.sp,
// fontWeight: MyFontWeight
// .regular,
// ),
// ),
// ],
// ),
// ),
// GestureDetector(
// onTap: () async {
// await hxDatabase.deleteByMsgId("${message.id}");
// if (animatedListKey == loadanimatedListKey) {
// loadmessages.remove(message);
// animatedListKey.currentState?.removeItem(index, (context, animation) {return Container();});
// } else {
// newmessages.remove(message);
// animatedListKey.currentState?.removeItem(index, (context, animation) {return Container();});
// }
// Navigator.pop(context);
// },
// child: Column(
// children: [
// Image.asset(
// "assets/image/icon_chat_delete.webp",
// height: 16,
// width: 16,
// ),
// SizedBox(
// height: 2.h,
// ),
// Text(
// S.of(context).shanchu,
// textAlign: TextAlign.center,
// style: TextStyle(
// color: Colors.white,
// fontSize: 12.sp,
// fontWeight: MyFontWeight.regular,
// ),
// ),
// ],
// ),
// ),
// ],
// ),
// ),
// ),
// Image.asset(
// "assets/image/icon_copy_j.webp",
// height: 17,
// width: 17,
// ),
// ],
// ),
// ),
// ],
// );
SmartDialog.showAttach(
targetContext: _buttonKey.currentContext,
builder: (ctx) {
return Stack(
alignment: Alignment.bottomCenter,
children: [
Container(
padding: EdgeInsets.only(bottom: 13.h),
child: Container(
width: 180.w,
decoration: BoxDecoration(
color: Color(0xFF2A2A2A),
borderRadius: BorderRadius.circular(6),
),
padding: EdgeInsets.symmetric(
horizontal: 32.w,
vertical: 7.5.h,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
setState(() {
this.copy(message.content);
Navigator.pop(context);
});
},
child: Column(
children: [
Image.asset(
"assets/image/icon_chat_copy.webp",
height: 16,
width: 16,
),
SizedBox(
height: 2.h,
),
Text(
"复制",
textAlign:
TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
fontWeight: MyFontWeight
.regular,
),
],
),
),
],
),
GestureDetector(
onTap: () async {
await hxDatabase.deleteByMsgId("${message.id}");
int index = messages.indexOf(message);
messages.remove(message);
),
GestureDetector(
onTap: () async {
await hxDatabase.deleteByMsgId("${message.id}");
if (animatedListKey == loadanimatedListKey) {
loadmessages.remove(message);
animatedListKey.currentState?.removeItem(index, (context, animation) {return Container();});
Navigator.pop(context);
},
child: Column(
children: [
Image.asset(
"assets/image/icon_chat_delete.webp",
height: 16,
width: 16,
),
SizedBox(
height: 2.h,
),
Text(
S.of(context).shanchu,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
fontWeight: MyFontWeight.regular,
),
} else {
newmessages.remove(message);
animatedListKey.currentState?.removeItem(index, (context, animation) {return Container();});
}
Navigator.pop(context);
},
child: Column(
children: [
Image.asset(
"assets/image/icon_chat_delete.webp",
height: 16,
width: 16,
),
SizedBox(
height: 2.h,
),
Text(
S.of(context).shanchu,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
fontWeight: MyFontWeight.regular,
),
],
),
),
],
),
],
),
),
],
),
),
Image.asset(
"assets/image/icon_copy_j.webp",
height: 17,
width: 17,
),
],
),
),
],
),
Image.asset(
"assets/image/icon_copy_j.webp",
height: 17,
width: 17,
),
],
);
},
);
}
Future<Size> fetchImageSize(Message message) async {
@ -1240,8 +1389,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
socketClient.sendMessage(_toUser?.mid ?? '', commentText)
.then((value) {
Message message = value;
messages.add(message);
animatedListKey.currentState?.insertItem(messages.length - 1);
newmessages.add(message);
newanimatedListKey.currentState?.insertItem(newmessages.length - 1);
chatController.clear();
messageShowTime().then((value) {
refreshState();

Loading…
Cancel
Save