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/database/conversations_database_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/users_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/conversations_list.dart';
 | 
				
			||||||
import 'package:comunic/lists/users_list.dart';
 | 
					import 'package:comunic/lists/users_list.dart';
 | 
				
			||||||
import 'package:comunic/models/api_request.dart';
 | 
					import 'package:comunic/models/api_request.dart';
 | 
				
			||||||
import 'package:comunic/models/conversation.dart';
 | 
					import 'package:comunic/models/conversation.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/conversation_message.dart';
 | 
				
			||||||
import 'package:comunic/utils/account_utils.dart';
 | 
					import 'package:comunic/utils/account_utils.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Conversation helper
 | 
					/// Conversation helper
 | 
				
			||||||
@@ -67,7 +69,7 @@ class ConversationsHelper {
 | 
				
			|||||||
  /// cached version of the conversation will be used, else it will always get
 | 
					  /// cached version of the conversation will be used, else it will always get
 | 
				
			||||||
  /// the information from the server
 | 
					  /// the information from the server
 | 
				
			||||||
  Future<Conversation> getSingle(int id, {bool force = false}) async {
 | 
					  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);
 | 
					      return await _downloadSingle(id);
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      return _conversationsDatabaseHelper.get(id);
 | 
					      return _conversationsDatabaseHelper.get(id);
 | 
				
			||||||
@@ -112,7 +114,7 @@ class ConversationsHelper {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Turn an API entry into a [Conversation] object
 | 
					  /// Turn an API entry into a [Conversation] object
 | 
				
			||||||
  Conversation _apiToConversation(Map<String, dynamic> map){
 | 
					  Conversation _apiToConversation(Map<String, dynamic> map) {
 | 
				
			||||||
    return Conversation(
 | 
					    return Conversation(
 | 
				
			||||||
      id: map["ID"],
 | 
					      id: map["ID"],
 | 
				
			||||||
      ownerID: map["ID_owner"],
 | 
					      ownerID: map["ID_owner"],
 | 
				
			||||||
@@ -123,4 +125,35 @@ class ConversationsHelper {
 | 
				
			|||||||
      members: map["members"].map<int>((f) => int.parse(f)).toList(),
 | 
					      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
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UsersList extends ListBase<User> {
 | 
					class UsersList extends ListBase<User> {
 | 
				
			||||||
 | 
					 | 
				
			||||||
  List<User> _list = List();
 | 
					  List<User> _list = List();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int get length => _list.length;
 | 
					  int get length => _list.length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  set length(l) => _list.length = l;
 | 
					  set length(l) => _list.length = l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
@@ -24,11 +24,13 @@ class UsersList extends ListBase<User> {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Find a user with a specific ID
 | 
					  /// Find a user with a specific ID
 | 
				
			||||||
  User getUser(int userID){
 | 
					  User getUser(int userID) {
 | 
				
			||||||
    for(int i = 0; i < this.length; i++)
 | 
					    for (int i = 0; i < this.length; i++)
 | 
				
			||||||
      if(this[i].id == userID)
 | 
					      if (this[i].id == userID) return this[i];
 | 
				
			||||||
        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/helpers/conversations_helper.dart';
 | 
				
			||||||
import 'package:comunic/models/conversation.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/intl_utils.dart';
 | 
				
			||||||
import 'package:comunic/utils/ui_utils.dart';
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
@@ -38,16 +39,14 @@ class _ConversationRouteState extends State<ConversationRoute> {
 | 
				
			|||||||
  Future<void> _loadConversation() async {
 | 
					  Future<void> _loadConversation() async {
 | 
				
			||||||
    setError(false);
 | 
					    setError(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _conversation =
 | 
					    _conversation = await _conversationsHelper.getSingle(widget.conversationID);
 | 
				
			||||||
        await _conversationsHelper.getSingle(widget.conversationID);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_conversation == null) return setError(true);
 | 
					    if (_conversation == null) return setError(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    final conversationName =
 | 
					    final conversationName =
 | 
				
			||||||
        await ConversationsHelper.getConversationNameAsync(_conversation);
 | 
					        await ConversationsHelper.getConversationNameAsync(_conversation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(conversationName == null)
 | 
					    if (conversationName == null) return setError(true);
 | 
				
			||||||
      return setError(true);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setState(() {
 | 
					    setState(() {
 | 
				
			||||||
      _conversationName = conversationName;
 | 
					      _conversationName = conversationName;
 | 
				
			||||||
@@ -72,8 +71,12 @@ class _ConversationRouteState extends State<ConversationRoute> {
 | 
				
			|||||||
        ],
 | 
					        ],
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //if (_conversationName == null || _conversation == null)
 | 
					    if (_conversationName == null || _conversation == null)
 | 
				
			||||||
      return buildCenteredProgressBar();
 | 
					      return buildCenteredProgressBar();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ConversationScreen(
 | 
				
			||||||
 | 
					      conversationID: widget.conversationID,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @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;
 | 
					  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