1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-29 08:16:28 +00:00
comunicmobile/lib/ui/screens/conversation_screen.dart
2019-04-25 11:13:02 +02:00

211 lines
6.1 KiB
Dart

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<StatefulWidget> createState() => _ConversationScreenState();
}
class _ConversationScreenState extends State<ConversationScreen> {
//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<void> _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);
_messages.sort();
});
}
/// Pick and send an image
Future<void> _sendImage(BuildContext context) async {
final image = await pickImage(context);
}
/// Send a new message
Future<void> _submitMessage(BuildContext context, String content) async {
//Send the message
_setSending(true);
final result = await _conversationsHelper.sendMessage(
NewConversationMessage(
conversationID: widget.conversationID, message: content));
_setSending(false);
//Check the result of the operation
if (result == SendMessageResult.SUCCESS)
_clearSendMessageForm();
else
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),
),
);
}
/// Clear send message form
void _clearSendMessageForm() {
setState(() {
_textEditingController = TextEditingController();
_isMessageValid = false;
});
}
/// Error handling
Widget _buildError() {
return buildErrorCard(tr("Could not load the list of messages!"));
}
/// Messages list
Widget _buildMessagesList() {
return Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (c, i) {
return ConversationMessageTile(
message: _messages.elementAt(i),
userInfo: _usersInfo.getUser(_messages[i].userID),
);
}),
);
}
/// Send message from
Widget _buildSendMessageForm() {
return new Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: new Row(
children: <Widget>[
// Image area
new Container(
margin: new EdgeInsets.symmetric(horizontal: 4.0),
child: new IconButton(
icon: new Icon(
Icons.photo_camera,
color: Theme.of(context).accentColor,
),
onPressed: () => _sendImage(context)),
),
// Message area
new Flexible(
child: new TextField(
controller: _textEditingController,
onChanged: (String messageText) {
setState(() {
_isMessageValid = messageText.length > 4;
});
},
onSubmitted:
_isMessageValid ? (s) => _submitMessage(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
? () => _submitMessage(context, _textEditingController.text)
: null,
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
if (_error == ErrorLevel.MAJOR) return _buildError();
if (_messages == null) return buildCenteredProgressBar();
return Column(
children: <Widget>[
_buildMessagesList(),
Divider(),
_buildSendMessageForm()
],
);
}
}