mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-03 19:54:12 +00:00 
			
		
		
		
	Get conversation message
This commit is contained in:
		@@ -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!";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// 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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -12,3 +12,16 @@ 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;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user