mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-12-26 04:48:51 +00:00
Get conversation message
This commit is contained in:
parent
1ec197202c
commit
e2202a4794
@ -1,9 +1,11 @@
|
||||
import 'package:comunic/helpers/database/conversations_database_helper.dart';
|
||||
import 'package:comunic/helpers/users_helper.dart';
|
||||
import 'package:comunic/lists/conversation_messages_list.dart';
|
||||
import 'package:comunic/lists/conversations_list.dart';
|
||||
import 'package:comunic/lists/users_list.dart';
|
||||
import 'package:comunic/models/api_request.dart';
|
||||
import 'package:comunic/models/conversation.dart';
|
||||
import 'package:comunic/models/conversation_message.dart';
|
||||
import 'package:comunic/utils/account_utils.dart';
|
||||
|
||||
/// Conversation helper
|
||||
@ -67,7 +69,7 @@ class ConversationsHelper {
|
||||
/// cached version of the conversation will be used, else it will always get
|
||||
/// the information from the server
|
||||
Future<Conversation> getSingle(int id, {bool force = false}) async {
|
||||
if(force || ! await _conversationsDatabaseHelper.has(id))
|
||||
if (force || !await _conversationsDatabaseHelper.has(id))
|
||||
return await _downloadSingle(id);
|
||||
else
|
||||
return _conversationsDatabaseHelper.get(id);
|
||||
@ -112,7 +114,7 @@ class ConversationsHelper {
|
||||
}
|
||||
|
||||
/// Turn an API entry into a [Conversation] object
|
||||
Conversation _apiToConversation(Map<String, dynamic> map){
|
||||
Conversation _apiToConversation(Map<String, dynamic> map) {
|
||||
return Conversation(
|
||||
id: map["ID"],
|
||||
ownerID: map["ID_owner"],
|
||||
@ -123,4 +125,35 @@ class ConversationsHelper {
|
||||
members: map["members"].map<int>((f) => int.parse(f)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Refresh the list of messages of a conversation
|
||||
///
|
||||
/// Set [lastMessageID] to 0 to specify that we do not have any message of the
|
||||
/// conversation yet or another value else
|
||||
Future<ConversationMessagesList> downloadNewMessagesSingle(int conversationID,
|
||||
{int lastMessageID = 0}) async {
|
||||
// Execute the request on the server
|
||||
final response = await APIRequest(
|
||||
uri: "conversations/refresh_single",
|
||||
needLogin: true,
|
||||
args: {
|
||||
"conversationID": conversationID.toString(),
|
||||
"last_message_id": lastMessageID.toString()
|
||||
}).exec();
|
||||
|
||||
if (response.code != 200) return null;
|
||||
|
||||
// Parse the response of the server
|
||||
ConversationMessagesList list = ConversationMessagesList();
|
||||
response.getArray().forEach((f) {
|
||||
list.add(ConversationMessage(
|
||||
id: f["ID"],
|
||||
userID: f["ID_user"],
|
||||
timeInsert: f["time_insert"],
|
||||
message: f["message"],
|
||||
imageURL: f["image_path"]));
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
35
lib/lists/conversation_messages_list.dart
Normal file
35
lib/lists/conversation_messages_list.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:comunic/models/conversation_message.dart';
|
||||
|
||||
/// Conversations messages list
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class ConversationMessagesList extends ListBase<ConversationMessage> {
|
||||
final List<ConversationMessage> _list = List();
|
||||
|
||||
set length(int v) => _list.length = v;
|
||||
|
||||
int get length => _list.length;
|
||||
|
||||
@override
|
||||
ConversationMessage operator [](int index) {
|
||||
return _list[index];
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, ConversationMessage value) {
|
||||
_list[index] = value;
|
||||
}
|
||||
|
||||
/// Get the list of the users ID who own a message in this list
|
||||
List<int> getUsersID() {
|
||||
final List<int> users = List();
|
||||
|
||||
for (ConversationMessage message in this)
|
||||
if (!users.contains(message.userID)) users.add(message.userID);
|
||||
|
||||
return users;
|
||||
}
|
||||
}
|
@ -7,10 +7,10 @@ import 'package:comunic/models/user.dart';
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class UsersList extends ListBase<User> {
|
||||
|
||||
List<User> _list = List();
|
||||
|
||||
int get length => _list.length;
|
||||
|
||||
set length(l) => _list.length = l;
|
||||
|
||||
@override
|
||||
@ -24,11 +24,13 @@ class UsersList extends ListBase<User> {
|
||||
}
|
||||
|
||||
/// Find a user with a specific ID
|
||||
User getUser(int userID){
|
||||
for(int i = 0; i < this.length; i++)
|
||||
if(this[i].id == userID)
|
||||
return this[i];
|
||||
User getUser(int userID) {
|
||||
for (int i = 0; i < this.length; i++)
|
||||
if (this[i].id == userID) return this[i];
|
||||
|
||||
throw "User not found in the list!";
|
||||
throw "User not found in the list!";
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the list of users ID present in this list
|
||||
List<int> get usersID => List.generate(length, (i) => this[i].id);
|
||||
}
|
||||
|
29
lib/models/conversation_message.dart
Normal file
29
lib/models/conversation_message.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Single conversation message
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class ConversationMessage implements Comparable {
|
||||
final int id;
|
||||
final int userID;
|
||||
final int timeInsert;
|
||||
final String message;
|
||||
final String imageURL;
|
||||
|
||||
const ConversationMessage({
|
||||
@required this.id,
|
||||
@required this.userID,
|
||||
@required this.timeInsert,
|
||||
@required this.message,
|
||||
@required this.imageURL,
|
||||
}) : assert(id != null),
|
||||
assert(userID != null),
|
||||
assert(timeInsert != null),
|
||||
assert(message != null);
|
||||
|
||||
@override
|
||||
int compareTo(other) {
|
||||
return id.compareTo(other.id);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import 'package:comunic/helpers/conversations_helper.dart';
|
||||
import 'package:comunic/models/conversation.dart';
|
||||
import 'package:comunic/ui/screens/conversation_screen.dart';
|
||||
import 'package:comunic/utils/intl_utils.dart';
|
||||
import 'package:comunic/utils/ui_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -38,16 +39,14 @@ class _ConversationRouteState extends State<ConversationRoute> {
|
||||
Future<void> _loadConversation() async {
|
||||
setError(false);
|
||||
|
||||
_conversation =
|
||||
await _conversationsHelper.getSingle(widget.conversationID);
|
||||
_conversation = await _conversationsHelper.getSingle(widget.conversationID);
|
||||
|
||||
if (_conversation == null) return setError(true);
|
||||
|
||||
final conversationName =
|
||||
await ConversationsHelper.getConversationNameAsync(_conversation);
|
||||
|
||||
if(conversationName == null)
|
||||
return setError(true);
|
||||
if (conversationName == null) return setError(true);
|
||||
|
||||
setState(() {
|
||||
_conversationName = conversationName;
|
||||
@ -72,8 +71,12 @@ class _ConversationRouteState extends State<ConversationRoute> {
|
||||
],
|
||||
);
|
||||
|
||||
//if (_conversationName == null || _conversation == null)
|
||||
if (_conversationName == null || _conversation == null)
|
||||
return buildCenteredProgressBar();
|
||||
|
||||
return ConversationScreen(
|
||||
conversationID: widget.conversationID,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
94
lib/ui/screens/conversation_screen.dart
Normal file
94
lib/ui/screens/conversation_screen.dart
Normal file
@ -0,0 +1,94 @@
|
||||
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/ui/tiles/conversation_message_tile.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> {
|
||||
final ConversationsHelper _conversationsHelper = ConversationsHelper();
|
||||
final UsersHelper _usersHelper = UsersHelper();
|
||||
ConversationMessagesList _messages;
|
||||
UsersList _usersInfo = UsersList();
|
||||
ErrorLevel _error = ErrorLevel.NONE;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_loadMessages();
|
||||
}
|
||||
|
||||
void _setError(ErrorLevel err) => setState(() => _error = err);
|
||||
|
||||
/// 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);
|
||||
});
|
||||
}
|
||||
|
||||
/// Error handling
|
||||
Widget _buildError() {
|
||||
return buildErrorCard(tr("Could not load the list of messages!"));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_error == ErrorLevel.MAJOR) return _buildError();
|
||||
|
||||
if (_messages == null) return buildCenteredProgressBar();
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: _messages.length,
|
||||
itemBuilder: (c, i) {
|
||||
return ConversationMessageTile(
|
||||
message: _messages.elementAt(i),
|
||||
userInfo: _usersInfo.getUser(_messages[i].userID),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
22
lib/ui/tiles/conversation_message_tile.dart
Normal file
22
lib/ui/tiles/conversation_message_tile.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:comunic/models/conversation_message.dart';
|
||||
import 'package:comunic/models/user.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Conversation message tile
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class ConversationMessageTile extends StatelessWidget {
|
||||
final ConversationMessage message;
|
||||
final User userInfo;
|
||||
|
||||
const ConversationMessageTile({Key key, this.message, this.userInfo})
|
||||
: assert(message != null),
|
||||
assert(userInfo != null),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(message.message);
|
||||
}
|
||||
}
|
@ -11,4 +11,17 @@ List<int> listToIntList(List<dynamic> srcList){
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// Find the list of missing elements of a [testList] from a [srcList]
|
||||
List<T> findMissingFromList<T>(List<T> srcList, List<T>testList) {
|
||||
|
||||
List<T> dest = List();
|
||||
|
||||
testList.forEach((f){
|
||||
if(!srcList.contains(f) && !dest.contains(f))
|
||||
dest.add(f);
|
||||
});
|
||||
|
||||
return dest;
|
||||
}
|
Loading…
Reference in New Issue
Block a user