import 'package:comunic/helpers/conversations_helper.dart'; import 'package:comunic/helpers/users_helper.dart'; import 'package:comunic/lists/conversation_messages_list.dart'; import 'package:comunic/lists/users_list.dart'; import 'package:comunic/models/new_conversation_message.dart'; import 'package:comunic/ui/tiles/conversation_message_tile.dart'; import 'package:comunic/utils/files_utils.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/list_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; /// Conversation screen /// /// @author Pierre HUBERT enum ErrorLevel { NONE, MINOR, MAJOR } class ConversationScreen extends StatefulWidget { final int conversationID; const ConversationScreen({Key key, this.conversationID}) : assert(conversationID != null), super(key: key); @override State createState() => _ConversationScreenState(); } class _ConversationScreenState extends State { //Helpers final ConversationsHelper _conversationsHelper = ConversationsHelper(); final UsersHelper _usersHelper = UsersHelper(); // Class members ConversationMessagesList _messages; UsersList _usersInfo = UsersList(); ErrorLevel _error = ErrorLevel.NONE; bool _isMessageValid = false; bool _isSendingMessage = false; TextEditingController _textEditingController = TextEditingController(); @override void didChangeDependencies() { super.didChangeDependencies(); _loadMessages(); } void _setError(ErrorLevel err) => setState(() => _error = err); void _setSending(bool sending) => setState(() => _isSendingMessage = sending); /// Method called when an error occurred while loading messages void _errorLoading() { _setError(_messages == null ? ErrorLevel.MAJOR : ErrorLevel.MINOR); } /// Load a list of messages Future _loadMessages() async { //First, get the messages final messages = await _conversationsHelper .downloadNewMessagesSingle(widget.conversationID); if (messages == null) return _errorLoading(); //Then get information about users final usersToGet = findMissingFromList(_usersInfo.usersID, messages.getUsersID()); final users = await _usersHelper.getUsersInfo(usersToGet); if (users == null) _errorLoading(); // Save the new list of messages setState(() { _usersInfo.addAll(users); if (_messages == null) _messages = messages; else _messages.addAll(messages); //Reverse the order of the messages _messages.sort(); final reverse =_messages.reversed; _messages = ConversationMessagesList(); _messages.addAll(reverse); }); } /// Pick and send an image Future _sendImage(BuildContext context) async { final image = await pickImage(context); if (image == null) return null; _submitMessage( context, NewConversationMessage( conversationID: widget.conversationID, message: null, image: image, ), ); // In case a message was already written in the input _updatedText(_textEditingController.text); } /// Send a new text message Future _submitTextMessage(BuildContext context, String content) async { if (await _submitMessage( context, NewConversationMessage( conversationID: widget.conversationID, message: content, )) == SendMessageResult.SUCCESS) _clearSendMessageForm(); } /// Submit a new message Future _submitMessage( BuildContext context, NewConversationMessage message) async { //Send the message _setSending(true); final result = await _conversationsHelper.sendMessage(message); _setSending(false); //Check the result of the operation if (result != SendMessageResult.SUCCESS) Scaffold.of(context).showSnackBar( SnackBar( content: Text( result == SendMessageResult.MESSAGE_REJECTED ? tr("Message rejected by the server!") : tr("Could not send message!"), ), duration: Duration(milliseconds: 500), ), ); return result; } void _updatedText(String text) { setState(() { _isMessageValid = text.length > 4; }); } /// Clear send message form void _clearSendMessageForm() { setState(() { _textEditingController = TextEditingController(); _isMessageValid = false; }); } /// Check if a message is the last message of a user or not bool _isLastMessage(int index) { return index == 0 || (index > 0 && _messages[index - 1].userID != _messages[index].userID); } /// Check if a message is the first message of a user or not bool _isFirstMessage(int index) { return index == _messages.length - 1 || (index < _messages.length - 1 && _messages[index + 1].userID != _messages[index].userID); } /// Error handling Widget _buildError() { return buildErrorCard(tr("Could not load the list of messages!")); } /// Messages list Widget _buildMessagesList() { return Expanded( child: ListView.builder( reverse: true, itemCount: _messages.length, itemBuilder: (c, i) { return ConversationMessageTile( message: _messages.elementAt(i), userInfo: _usersInfo.getUser(_messages[i].userID), isLastMessage: _isLastMessage(i), isFirstMessage: _isFirstMessage(i), ); }), ); } /// Send message from Widget _buildSendMessageForm() { return new Container( margin: const EdgeInsets.symmetric(horizontal: 8.0), child: new Row( children: [ // Image area new Container( margin: new EdgeInsets.symmetric(horizontal: 4.0), child: new IconButton( icon: new Icon( Icons.photo_camera, color: _isSendingMessage ? Theme.of(context).disabledColor : Theme.of(context).accentColor, ), onPressed: () => _sendImage(context), ), ), // Message area new Flexible( child: new TextField( enabled: !_isSendingMessage, controller: _textEditingController, onChanged: _updatedText, onSubmitted: _isMessageValid ? (s) => _submitTextMessage(context, s) : null, decoration: new InputDecoration.collapsed(hintText: tr("Send a message")), ), ), // Send button new Container( margin: const EdgeInsets.symmetric(horizontal: 4.0), child: new IconButton( icon: new Icon( Icons.send, color: !_isSendingMessage && _isMessageValid ? Theme.of(context).accentColor : Theme.of(context).disabledColor, ), onPressed: !_isSendingMessage && _isMessageValid ? () => _submitTextMessage(context, _textEditingController.text) : null, ), ), ], ), ); } @override Widget build(BuildContext context) { if (_error == ErrorLevel.MAJOR) return _buildError(); if (_messages == null) return buildCenteredProgressBar(); return Column( children: [ _buildMessagesList(), Divider(), _buildSendMessageForm() ], ); } }