import 'package:dart_mq/dart_mq.dart'; import 'package:flutter/material.dart'; import 'package:flutter_chat_ui/flutter_chat_ui.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'package:stadtbote/content_views/utils/content_view_widget.dart'; import 'package:stadtbote/main.dart'; import 'package:stadtbote/messages/pop_content_view_message.dart'; import 'package:stadtbote/model/chat_message.dart' as sbmessage; import 'package:stadtbote/model/session_status.dart'; import 'package:stadtbote/objectbox.g.dart'; import 'package:stadtbote/network_messages/messages_showed.dart'; import 'package:stadtbote/tools/constants.dart'; import 'package:stadtbote/tools/messages/publish_payload_message.dart'; import '../tools/app_localizations.dart'; import '../tools/util.dart'; class MessagesPage extends ContentViewWidget { const MessagesPage({super.key}); @override State createState() => _MessagesPageState(); @override Future getHeaderWidget(BuildContext context) async { await Future.delayed(const Duration(microseconds: 0)); return _HeaderWidget(); } } class _MessagesPageState extends State with ProducerMixin { bool _initCompleted = false; late String _sid; late final List _messages = []; final _user = const types.User( id: '82091008-a484-4a89-ae75-a22bf8d6f3ac', ); final _central = const types.User( id: '82091008-a484-4a89-ae75-a22bf8d6f3ad', ); @override void initState() { super.initState(); Future.delayed(const Duration(seconds: 0), () async { final box = MyApp.objectBoxStore.box(); final sessions = box.getAll(); var status = sessions.isNotEmpty ? sessions.first : null; _sid = status != null ? status.sid : 'unknown'.tr; _sendMessagesReadMessage(); await _fetchMessages(); _initCompleted = true; if (mounted) { setState(() {}); } }); } @override Widget build(BuildContext context) { if (!_initCompleted) { return Util.getWaitWidget(context); } return Stack( children: [ Chat( messages: _messages, textMessageOptions: const TextMessageOptions(isTextSelectable: false), onSendPressed: _handleSendPressed, showUserAvatars: false, showUserNames: false, user: _user, onMessageTap: (context, message) => {_showDeleteMessageDialog(context, message)}, ), ], ); } void _handleSendPressed(types.PartialText text) async { var now = DateTime.now(); var message = sbmessage.ChatMessage(); message.text = text.text; message.from = _sid; message.subj = ''; message.time = Util.nowUnixSecondsUtc(); message.read = true; message.id = await sbmessage.ChatMessage.getNextId(); final box = MyApp.objectBoxStore.box(); box.put(message); sendMessage( routingKey: Constants.messageTopicPublishPayload, payload: PublishPayloadMessage( topic: "message", message: message.toJson(), acknowledgeRequired: true), ); _messages.insert( 0, types.TextMessage( author: _user, createdAt: now.millisecondsSinceEpoch, id: message.id.toString(), text: text.text, )); setState(() {}); } Future _fetchMessages() async { _messages.clear(); final box = MyApp.objectBoxStore.box(); var messages = box.getAll(); for (var message in messages) { _messages.add(types.TextMessage( author: message.from == _sid ? _user : _central, createdAt: message.time * 1000, id: message.id.toString(), text: "${message.subj}\n${message.text}", )); _messages.sort((a, b) => b.createdAt! > a.createdAt! ? 1 : 0); message.read = true; box.put(message); } setState(() {}); } _showDeleteMessageDialog(BuildContext context, types.Message message) async { await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( contentPadding: EdgeInsets.zero, shadowColor: Colors.transparent, backgroundColor: Colors.white, content: StatefulBuilder( builder: (BuildContext context, StateSetter setState) { return SizedBox( key: GlobalKey(), height: 120, width: MediaQuery.of(context).size.width * 1.2, child: Padding( padding: const EdgeInsets.all(8.0), child: Container( height: 100, padding: const EdgeInsets.all(5), child: Column( children: [ Text('delete_message_confirm'.tr), const SizedBox(height: 20), Row(children: [ Expanded( child: getDefaultButton('no'.tr, () => {Navigator.of(context).pop()}), ), const SizedBox(width: 20), Expanded( child: getDefaultButton( 'yes'.tr, () async => { MyApp.objectBoxStore.box() .remove(int.parse(message.id)), _fetchMessages(), setState(() {}), Navigator.of(MyApp.appNavigatorKey .currentContext!) .pop() }), ) ]) ], ), ), )); })); }); } void _sendMessagesReadMessage() async { final box = MyApp.objectBoxStore.box(); final query = box.query(ChatMessage_.read.equals(false)).build(); var unreadChatMessages = query.find(); query.close(); if (unreadChatMessages.isNotEmpty) { List chatMessageIds = []; for (var message in unreadChatMessages) { chatMessageIds.add(message.id.toString()); } var chatMessagesShowed = ChatMessagesReceived(); chatMessagesShowed.ids = chatMessageIds; chatMessagesShowed.time = Util.nowUnixSecondsUtc(); sendMessage( routingKey: Constants.messageTopicPublishPayload, payload: PublishPayloadMessage( topic: "mssg_received", message: chatMessagesShowed.toJson(), acknowledgeRequired: false), ); } } } class _HeaderWidget extends StatefulWidget { @override State<_HeaderWidget> createState() => _HeaderWidgetState(); } class _HeaderWidgetState extends State<_HeaderWidget> with ProducerMixin { @override void initState() { super.initState(); } @override Widget build(BuildContext context) { var cellWidth = (MediaQuery.of(context).size.width - 60 - 60 - 25) / 2; return Padding( padding: const EdgeInsets.all(8), child: Stack( alignment: Alignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: true, child: Container( width: 60, height: 60, decoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.white, ), child: FittedBox( child: GestureDetector( onTap: () async { sendMessage( routingKey: Constants.messageTopicPopContentView, payload: PopContentViewMessage(count: 1), ); }, child: const CircleAvatar( radius: 10, backgroundColor: Constants.colorPrimary, child: Padding( padding: EdgeInsets.all(1.0), child: Icon(Icons.arrow_back, size: 20.0, color: Colors.white)), ), ), ), ), ), Visibility( visible: false, child: Container( width: 60, height: 60, decoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.red, ), child: FittedBox( child: GestureDetector( onTap: () async { sendMessage( routingKey: Constants.messageTopicPopContentView, payload: PopContentViewMessage(count: 1), ); }, child: const CircleAvatar( backgroundColor: Constants.colorPrimary, radius: 10, child: Padding( padding: EdgeInsets.all(1.0), child: Icon(Icons.info_outline, size: 20.0, color: Colors.white))), ), ), ), ), ], ), SizedBox( height: 100, width: cellWidth * 2, child: const Center( child: Text( textAlign: TextAlign.center, "Nachrichten", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, color: Colors.white), ), ), ), ], ), ); } }