import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:surface/controllers/chat_message_controller.dart'; import 'package:surface/providers/channel.dart'; import 'package:surface/types/chat.dart'; import 'package:surface/widgets/chat/chat_message.dart'; import 'package:surface/widgets/chat/chat_message_input.dart'; import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/loading_indicator.dart'; import 'package:very_good_infinite_list/very_good_infinite_list.dart'; class ChatRoomScreen extends StatefulWidget { final String scope; final String alias; const ChatRoomScreen({super.key, required this.scope, required this.alias}); @override State createState() => _ChatRoomScreenState(); } class _ChatRoomScreenState extends State { bool _isBusy = false; SnChannel? _channel; late final ChatMessageController _messageController; Future _fetchChannel() async { setState(() => _isBusy = true); try { final chan = context.read(); _channel = await chan.getChannel('${widget.scope}:${widget.alias}'); } catch (err) { if (!mounted) return; context.showErrorDialog(err); } finally { setState(() => _isBusy = false); } } @override void initState() { super.initState(); _messageController = ChatMessageController(context); _fetchChannel().then((_) async { await _messageController.initialize(_channel!); await _messageController.checkUpdate(); }); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_channel?.name ?? 'loading'.tr()), ), body: ListenableBuilder( listenable: _messageController, builder: (context, _) { return Column( children: [ LoadingIndicator(isActive: _isBusy), if (_messageController.isPending) Expanded( child: const CircularProgressIndicator().center(), ), if (!_messageController.isPending) Expanded( child: InfiniteList( reverse: true, padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 12, ), hasReachedMax: _messageController.isAllLoaded, itemCount: _messageController.messages.length, isLoading: _messageController.isLoading, onFetchData: () { _messageController.loadMessages(); }, itemBuilder: (context, idx) { final message = _messageController.messages[idx]; return ChatMessage( data: message, isPending: _messageController.unconfirmedMessages .contains(message.uuid), ); }, ), ), if (!_messageController.isPending) Material( elevation: 2, child: ChatMessageInput(controller: _messageController) .padding(bottom: MediaQuery.of(context).padding.bottom), ), ], ); }, ), ); } }