import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../api/marianumcloud/talk/chat/get_chat_response.dart'; import '../../../api/marianumcloud/talk/room/get_room_response.dart'; import '../../../extensions/date_time.dart'; import '../../../state/app/infrastructure/loadable_state/view/loadable_state_consumer.dart'; import '../../../state/app/modules/chat/bloc/chat_bloc.dart'; import '../../../state/app/modules/chat/bloc/chat_state.dart'; import '../../../theming/app_theme.dart'; import '../../../widget/clickable_app_bar.dart'; import '../../../widget/user_avatar.dart'; import 'details/chat_info.dart'; import 'talk_navigator.dart'; import 'widgets/chat_bubble.dart'; import 'widgets/chat_textfield.dart'; class ChatView extends StatefulWidget { final GetRoomResponseObject room; final String selfId; final UserAvatar avatar; const ChatView({ super.key, required this.room, required this.selfId, required this.avatar, }); @override State createState() => _ChatViewState(); } class _ChatViewState extends State { final ScrollController _listController = ScrollController(); void _refresh() { context.read().setToken(widget.room.token); } List _buildMessages(GetChatResponse response) { final messages = []; var lastDate = DateTime.now(); for (final element in response.sortByTimestamp()) { final elementDate = DateTime.fromMillisecondsSinceEpoch( element.timestamp * 1000, ); if (element.systemMessage.contains('reaction')) continue; if (element.systemMessage.contains('poll_voted')) continue; final commonRead = int.parse( response.headers?['x-chat-last-common-read'] ?? '0', ); if (!elementDate.isSameDay(lastDate)) { lastDate = elementDate; messages.add( ChatBubble( context: context, isSender: false, bubbleData: GetChatResponseObject.getDateDummy(element.timestamp), chatData: widget.room, refetch: ({bool renew = false}) => _refresh(), ), ); } messages.add( ChatBubble( context: context, isSender: element.actorId == widget.selfId && element.messageType == GetRoomResponseObjectMessageType.comment, bubbleData: element, chatData: widget.room, refetch: ({bool renew = false}) => _refresh(), isRead: element.id <= commonRead, selfId: widget.selfId, ), ); } if (response.data.length >= 200) { messages.insert( 0, ChatBubble( context: context, isSender: false, bubbleData: GetChatResponseObject.getTextDummy( 'Zurzeit können in dieser App nur die letzten 200 vergangenen Nachrichten angezeigt werden. ' 'Um ältere Nachrichten abzurufen verwende die Webversion unter https://cloud.marianum-fulda.de', ), chatData: widget.room, refetch: ({bool renew = false}) => _refresh(), ), ); } return messages; } @override Widget build(BuildContext context) => Scaffold( backgroundColor: const Color(0xffefeae2), appBar: ClickableAppBar( onTap: () => TalkNavigator.pushSplitView(context, ChatInfo(widget.room)), appBar: AppBar( title: Row( children: [ widget.avatar, const SizedBox(width: 10), Expanded( child: Text( widget.room.displayName, overflow: TextOverflow.ellipsis, maxLines: 1, ), ), ], ), ), ), body: DecoratedBox( decoration: BoxDecoration( image: DecorationImage( image: const AssetImage('assets/background/chat.png'), scale: 1.5, opacity: 1, repeat: ImageRepeat.repeat, invertColors: AppTheme.isDarkMode(context), ), ), child: Column( children: [ Expanded( child: LoadableStateConsumer( isReady: (state) => state.chatResponse != null && state.currentToken == widget.room.token, child: (state, _) => ListView( reverse: true, controller: _listController, children: _buildMessages(state.chatResponse!).reversed.toList(), ), ), ), ColoredBox( color: Theme.of(context).colorScheme.surface, child: TalkNavigator.isSecondaryVisible(context) ? ChatTextfield(widget.room.token, selfId: widget.selfId) : SafeArea( child: ChatTextfield( widget.room.token, selfId: widget.selfId, ), ), ), ], ), ), ); }