import 'dart:async'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hive_flutter/hive_flutter.dart'; import '/database/box_type.dart'; import '/models/contact_model.dart'; import '/models/init_get_it.dart'; import '/models/route_state_model.dart'; import '/utils/format_datetime.dart'; import 'components/friend_message_bubble.dart'; import 'components/message_input_box.dart'; class FriendMessageScreen extends StatefulWidget { const FriendMessageScreen({ super.key, required this.friendId, }); final String friendId; @override State createState() => _FriendMessageScreenState(); } class _FriendMessageScreenState extends State { final ScrollController _controller = ScrollController(); final Box _chatSettingBox = Hive.box('chat_setting'); @override void dispose() { super.dispose(); _controller.dispose(); } @override Widget build(BuildContext context) { Timer( const Duration(milliseconds: 300), () => getIt.get().changeRoute( 'Message', newQuery: {'friendId': widget.friendId}, ), ); return Scaffold( appBar: AppBar( leading: IconButton( onPressed: () { context.go('/chat'); }, icon: const Icon(Icons.arrow_back), ), // friend remark or nickname title: getIt.get().friends[widget.friendId]!.friendRemark.isEmpty ? Text( getIt .get() .friends[widget.friendId]! .nickname, ) : Text( getIt.get().friends[widget.friendId]!.friendRemark, ), centerTitle: true, actions: [ IconButton( onPressed: () {}, icon: const Icon(Icons.menu), splashRadius: 18, ), ], ), body: Column( children: [ Expanded( child: Align( alignment: Alignment.topCenter, child: ValueListenableBuilder( valueListenable: Hive.box('message_${widget.friendId}') .listenable(), builder: (context, value, _) { // Set unreadCount to 0 when at message screen ChatSetting? chatSetting = _chatSettingBox.get(widget.friendId); // whether it is a brand new chat if (chatSetting != null) { chatSetting.unreadCount = 0; _chatSettingBox.put(widget.friendId, chatSetting); } Future.delayed( const Duration( milliseconds: 100, ), () => _controller.animateTo( 0, duration: const Duration(milliseconds: 500), curve: Curves.linear, ), ); return ListView.builder( physics: const BouncingScrollPhysics( parent: AlwaysScrollableScrollPhysics(), ), // addAutomaticKeepAlives: false, controller: _controller, shrinkWrap: true, reverse: true, itemCount: Hive.box('message_${widget.friendId}').length, itemBuilder: (context, index) { Box messageTBox = Hive.box('message_${widget.friendId}'); int length = messageTBox.length; int i = length - index - 1; MessageT messageT = messageTBox.getAt(i)!; List allAttachments = []; // Do not reverse the list, cause what i want is // rigth slide to next image, left to last otherwise for (var element in messageTBox.values) { if (element.attachments.isNotEmpty) { allAttachments.addAll(element.attachments); } } return FriendMessageBubble( key: ValueKey(messageT.msgId), index: i, length: length, contactId: widget.friendId, senderId: messageT.senderId, dateTime: formatMessageDateTime(messageT.dateTime), isShowTime: messageT.isShowTime, type: messageT.type, text: messageT.text, attachments: messageT.attachments, allAttachments: allAttachments, ); }, ); }, ), ), ), MessageInputBox( chatType: 0, contactId: widget.friendId, scrollController: _controller, ), ], ), bottomNavigationBar: null, ); } }