mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 04:04:18 +00:00 
			
		
		
		
	Created conversation route
This commit is contained in:
		@@ -1,4 +1,5 @@
 | 
				
			|||||||
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/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';
 | 
				
			||||||
@@ -22,15 +23,7 @@ class ConversationsHelper {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      ConversationsList list = ConversationsList();
 | 
					      ConversationsList list = ConversationsList();
 | 
				
			||||||
      response.getArray().forEach((f) => list.add(Conversation(
 | 
					      response.getArray().forEach((f) => list.add(_apiToConversation(f)));
 | 
				
			||||||
            id: f["ID"],
 | 
					 | 
				
			||||||
            ownerID: f["ID_owner"],
 | 
					 | 
				
			||||||
            lastActive: f["last_active"],
 | 
					 | 
				
			||||||
            name: f["name"] == false ? null : f["name"],
 | 
					 | 
				
			||||||
            following: f["following"] == 1,
 | 
					 | 
				
			||||||
            sawLastMessage: f["saw_last_message"] == 1,
 | 
					 | 
				
			||||||
            members: f["members"].map<int>((f) => int.parse(f)).toList(),
 | 
					 | 
				
			||||||
          )));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Update the database
 | 
					      // Update the database
 | 
				
			||||||
      await _conversationsDatabaseHelper.clearTable();
 | 
					      await _conversationsDatabaseHelper.clearTable();
 | 
				
			||||||
@@ -50,8 +43,38 @@ class ConversationsHelper {
 | 
				
			|||||||
    return list;
 | 
					    return list;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Get the name of a [conversation]. This requires information about the
 | 
					  /// Get information about a single conversation specified by its [id]
 | 
				
			||||||
  /// users of this conversation
 | 
					  Future<Conversation> _downloadSingle(int id) async {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      final response = await APIRequest(
 | 
				
			||||||
 | 
					          uri: "conversations/getInfoOne",
 | 
				
			||||||
 | 
					          needLogin: true,
 | 
				
			||||||
 | 
					          args: {"conversationID": id.toString()}).exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (response.code != 200) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final conversation = _apiToConversation(response.getObject());
 | 
				
			||||||
 | 
					      _conversationsDatabaseHelper.insertOrUpdate(conversation);
 | 
				
			||||||
 | 
					      return conversation;
 | 
				
			||||||
 | 
					    } on Exception catch (e) {
 | 
				
			||||||
 | 
					      print(e.toString());
 | 
				
			||||||
 | 
					      print("Could not get information about a single conversation !");
 | 
				
			||||||
 | 
					      return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Get information about a single conversation. If [force] is set to false,
 | 
				
			||||||
 | 
					  /// 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))
 | 
				
			||||||
 | 
					      return await _downloadSingle(id);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      return _conversationsDatabaseHelper.get(id);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Get the name of a [conversation]. This requires information
 | 
				
			||||||
 | 
					  /// about the users of this conversation
 | 
				
			||||||
  static String getConversationName(
 | 
					  static String getConversationName(
 | 
				
			||||||
      Conversation conversation, UsersList users) {
 | 
					      Conversation conversation, UsersList users) {
 | 
				
			||||||
    if (conversation.has_name) return conversation.name;
 | 
					    if (conversation.has_name) return conversation.name;
 | 
				
			||||||
@@ -69,4 +92,35 @@ class ConversationsHelper {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return name;
 | 
					    return name;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Asynchronously get the name fo the conversation
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Unlike the synchronous method, this method does not need information
 | 
				
			||||||
 | 
					  /// about the members of the conversation
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Returns null in case of failure
 | 
				
			||||||
 | 
					  static Future<String> getConversationNameAsync(
 | 
				
			||||||
 | 
					      Conversation conversation) async {
 | 
				
			||||||
 | 
					    if (conversation.has_name) return conversation.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Get information about the members of the conversation
 | 
				
			||||||
 | 
					    final members = await UsersHelper().getUsersInfo(conversation.members);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (members == null) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ConversationsHelper.getConversationName(conversation, members);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Turn an API entry into a [Conversation] object
 | 
				
			||||||
 | 
					  Conversation _apiToConversation(Map<String, dynamic> map){
 | 
				
			||||||
 | 
					    return Conversation(
 | 
				
			||||||
 | 
					      id: map["ID"],
 | 
				
			||||||
 | 
					      ownerID: map["ID_owner"],
 | 
				
			||||||
 | 
					      lastActive: map["last_active"],
 | 
				
			||||||
 | 
					      name: map["name"] == false ? null : map["name"],
 | 
				
			||||||
 | 
					      following: map["following"] == 1,
 | 
				
			||||||
 | 
					      sawLastMessage: map["saw_last_message"] == 1,
 | 
				
			||||||
 | 
					      members: map["members"].map<int>((f) => int.parse(f)).toList(),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,7 @@ class Conversation extends CacheModel implements Comparable {
 | 
				
			|||||||
        name = map[ConversationTableContract.C_NAME],
 | 
					        name = map[ConversationTableContract.C_NAME],
 | 
				
			||||||
        following = map[ConversationTableContract.C_FOLLOWING] == 1,
 | 
					        following = map[ConversationTableContract.C_FOLLOWING] == 1,
 | 
				
			||||||
        sawLastMessage = map[ConversationTableContract.C_SAW_LAST_MESSAGE] == 1,
 | 
					        sawLastMessage = map[ConversationTableContract.C_SAW_LAST_MESSAGE] == 1,
 | 
				
			||||||
        members = stringListToIntList(
 | 
					        members = listToIntList(
 | 
				
			||||||
            map[ConversationTableContract.C_MEMBERS].split(",")),
 | 
					            map[ConversationTableContract.C_MEMBERS].split(",")),
 | 
				
			||||||
        super.fromMap(map);
 | 
					        super.fromMap(map);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										90
									
								
								lib/ui/routes/conversation_route.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								lib/ui/routes/conversation_route.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/helpers/conversations_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/conversation.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Single conversation route
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConversationRoute extends StatefulWidget {
 | 
				
			||||||
 | 
					  final int conversationID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const ConversationRoute({
 | 
				
			||||||
 | 
					    Key key,
 | 
				
			||||||
 | 
					    @required this.conversationID,
 | 
				
			||||||
 | 
					  })  : assert(conversationID != null),
 | 
				
			||||||
 | 
					        super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  State<StatefulWidget> createState() => _ConversationRouteState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _ConversationRouteState extends State<ConversationRoute> {
 | 
				
			||||||
 | 
					  final ConversationsHelper _conversationsHelper = ConversationsHelper();
 | 
				
			||||||
 | 
					  Conversation _conversation;
 | 
				
			||||||
 | 
					  String _conversationName;
 | 
				
			||||||
 | 
					  bool _error = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setError(bool err) => setState(() => _error = err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void didChangeDependencies() {
 | 
				
			||||||
 | 
					    super.didChangeDependencies();
 | 
				
			||||||
 | 
					    _loadConversation();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<void> _loadConversation() async {
 | 
				
			||||||
 | 
					    setError(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _conversation =
 | 
				
			||||||
 | 
					        await _conversationsHelper.getSingle(widget.conversationID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (_conversation == null) return setError(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final conversationName =
 | 
				
			||||||
 | 
					        await ConversationsHelper.getConversationNameAsync(_conversation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(conversationName == null)
 | 
				
			||||||
 | 
					      return setError(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setState(() {
 | 
				
			||||||
 | 
					      _conversationName = conversationName;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget _buildRouteBody() {
 | 
				
			||||||
 | 
					    //Handle errors
 | 
				
			||||||
 | 
					    if (_error != null && _error)
 | 
				
			||||||
 | 
					      return buildErrorCard(
 | 
				
			||||||
 | 
					        tr("Could not get conversation information!"),
 | 
				
			||||||
 | 
					        actions: <Widget>[
 | 
				
			||||||
 | 
					          FlatButton(
 | 
				
			||||||
 | 
					            onPressed: _loadConversation,
 | 
				
			||||||
 | 
					            child: Text(
 | 
				
			||||||
 | 
					              tr("Try again").toUpperCase(),
 | 
				
			||||||
 | 
					              style: TextStyle(
 | 
				
			||||||
 | 
					                color: Colors.white,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //if (_conversationName == null || _conversation == null)
 | 
				
			||||||
 | 
					      return buildCenteredProgressBar();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Scaffold(
 | 
				
			||||||
 | 
					      appBar: AppBar(
 | 
				
			||||||
 | 
					        title: Text(
 | 
				
			||||||
 | 
					          _conversationName == null ? tr("Loading") : _conversationName,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      body: _buildRouteBody(),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import 'package:comunic/ui/screens/conversations_screen.dart';
 | 
					import 'package:comunic/ui/screens/conversations_list_screen.dart';
 | 
				
			||||||
import 'package:comunic/ui/screens/menus_screen.dart';
 | 
					import 'package:comunic/ui/screens/menus_screen.dart';
 | 
				
			||||||
import 'package:comunic/ui/tiles/custom_bottom_navigation_bar_item.dart';
 | 
					import 'package:comunic/ui/tiles/custom_bottom_navigation_bar_item.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
@@ -49,7 +49,7 @@ class _HomeRouteState extends State<HomeRoute> {
 | 
				
			|||||||
  Widget _buildBody(BuildContext context) {
 | 
					  Widget _buildBody(BuildContext context) {
 | 
				
			||||||
    switch (_currTab) {
 | 
					    switch (_currTab) {
 | 
				
			||||||
      case 0:
 | 
					      case 0:
 | 
				
			||||||
        return ConversationsScreen();
 | 
					        return ConversationsListScreen();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case 1:
 | 
					      case 1:
 | 
				
			||||||
        return MenuScreen();
 | 
					        return MenuScreen();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ import 'package:comunic/enums/load_error_level.dart';
 | 
				
			|||||||
import 'package:comunic/helpers/conversations_helper.dart';
 | 
					import 'package:comunic/helpers/conversations_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/users_helper.dart';
 | 
					import 'package:comunic/helpers/users_helper.dart';
 | 
				
			||||||
import 'package:comunic/lists/conversations_list.dart';
 | 
					import 'package:comunic/lists/conversations_list.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/routes/conversation_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/tiles/conversation_tile.dart';
 | 
					import 'package:comunic/ui/tiles/conversation_tile.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';
 | 
				
			||||||
@@ -11,12 +12,12 @@ import 'package:flutter/material.dart';
 | 
				
			|||||||
///
 | 
					///
 | 
				
			||||||
/// @author Pierre HUBERT
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ConversationsScreen extends StatefulWidget {
 | 
					class ConversationsListScreen extends StatefulWidget {
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<StatefulWidget> createState() => _ConversationScreenState();
 | 
					  State<StatefulWidget> createState() => _ConversationScreenState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _ConversationScreenState extends State<ConversationsScreen> {
 | 
					class _ConversationScreenState extends State<ConversationsListScreen> {
 | 
				
			||||||
  final ConversationsHelper _conversationsHelper = ConversationsHelper();
 | 
					  final ConversationsHelper _conversationsHelper = ConversationsHelper();
 | 
				
			||||||
  final UsersHelper _usersHelper = UsersHelper();
 | 
					  final UsersHelper _usersHelper = UsersHelper();
 | 
				
			||||||
  ConversationsList _list;
 | 
					  ConversationsList _list;
 | 
				
			||||||
@@ -88,6 +89,13 @@ class _ConversationScreenState extends State<ConversationsScreen> {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Open a conversation
 | 
				
			||||||
 | 
					  void _openConversation(BuildContext context, int conversationId){
 | 
				
			||||||
 | 
					    Navigator.of(context).push(MaterialPageRoute(builder: (c){
 | 
				
			||||||
 | 
					      return ConversationRoute(conversationID: conversationId,);
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    if (_error == LoadErrorLevel.MAJOR) return _buildErrorCard();
 | 
					    if (_error == LoadErrorLevel.MAJOR) return _buildErrorCard();
 | 
				
			||||||
@@ -103,10 +111,12 @@ class _ConversationScreenState extends State<ConversationsScreen> {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
            Expanded(
 | 
					            Expanded(
 | 
				
			||||||
              child: ListView.builder(
 | 
					              child: ListView.builder(
 | 
				
			||||||
 | 
					                controller: ScrollController(),
 | 
				
			||||||
                itemBuilder: (context, index) {
 | 
					                itemBuilder: (context, index) {
 | 
				
			||||||
                  return ConversationTile(
 | 
					                  return ConversationTile(
 | 
				
			||||||
                    conversation: _list.elementAt(index),
 | 
					                    conversation: _list.elementAt(index),
 | 
				
			||||||
                    usersList: _list.users,
 | 
					                    usersList: _list.users,
 | 
				
			||||||
 | 
					                    onOpen: (c){_openConversation(context, c.id);},
 | 
				
			||||||
                  );
 | 
					                  );
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                itemCount: _list.length,
 | 
					                itemCount: _list.length,
 | 
				
			||||||
@@ -9,14 +9,21 @@ import 'package:flutter/material.dart';
 | 
				
			|||||||
///
 | 
					///
 | 
				
			||||||
/// @author Pierre HUBERT
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef OpenConversationCallback = void Function(Conversation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ConversationTile extends StatelessWidget {
 | 
					class ConversationTile extends StatelessWidget {
 | 
				
			||||||
  final Conversation conversation;
 | 
					  final Conversation conversation;
 | 
				
			||||||
  final UsersList usersList;
 | 
					  final UsersList usersList;
 | 
				
			||||||
 | 
					  final OpenConversationCallback onOpen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const ConversationTile(
 | 
					  const ConversationTile(
 | 
				
			||||||
      {Key key, @required this.conversation, @required this.usersList})
 | 
					      {Key key,
 | 
				
			||||||
 | 
					      @required this.conversation,
 | 
				
			||||||
 | 
					      @required this.usersList,
 | 
				
			||||||
 | 
					      @required this.onOpen})
 | 
				
			||||||
      : assert(conversation != null),
 | 
					      : assert(conversation != null),
 | 
				
			||||||
        assert(usersList != null),
 | 
					        assert(usersList != null),
 | 
				
			||||||
 | 
					        assert(onOpen != null),
 | 
				
			||||||
        super(key: key);
 | 
					        super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _buildSubInformation(IconData icon, String content) {
 | 
					  _buildSubInformation(IconData icon, String content) {
 | 
				
			||||||
@@ -35,6 +42,7 @@ class ConversationTile extends StatelessWidget {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return ListTile(
 | 
					    return ListTile(
 | 
				
			||||||
 | 
					      onTap: () => onOpen(conversation),
 | 
				
			||||||
      // Conversation name
 | 
					      // Conversation name
 | 
				
			||||||
      title: Text(
 | 
					      title: Text(
 | 
				
			||||||
        ConversationsHelper.getConversationName(
 | 
					        ConversationsHelper.getConversationName(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,8 @@
 | 
				
			|||||||
///
 | 
					///
 | 
				
			||||||
/// @author Pierre HUBERT
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Transform a list of string into something else
 | 
					/// Transform a list of dynamic thins into something a list of ints
 | 
				
			||||||
List<int> stringListToIntList(List<String> srcList){
 | 
					List<int> listToIntList(List<dynamic> srcList){
 | 
				
			||||||
  List<int> list = List();
 | 
					  List<int> list = List();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  srcList.forEach((e){
 | 
					  srcList.forEach((e){
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user