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/users_helper.dart';
 | 
			
		||||
import 'package:comunic/lists/conversations_list.dart';
 | 
			
		||||
import 'package:comunic/lists/users_list.dart';
 | 
			
		||||
import 'package:comunic/models/api_request.dart';
 | 
			
		||||
@@ -22,15 +23,7 @@ class ConversationsHelper {
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      ConversationsList list = ConversationsList();
 | 
			
		||||
      response.getArray().forEach((f) => list.add(Conversation(
 | 
			
		||||
            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(),
 | 
			
		||||
          )));
 | 
			
		||||
      response.getArray().forEach((f) => list.add(_apiToConversation(f)));
 | 
			
		||||
 | 
			
		||||
      // Update the database
 | 
			
		||||
      await _conversationsDatabaseHelper.clearTable();
 | 
			
		||||
@@ -50,8 +43,38 @@ class ConversationsHelper {
 | 
			
		||||
    return list;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Get the name of a [conversation]. This requires information about the
 | 
			
		||||
  /// users of this conversation
 | 
			
		||||
  /// Get information about a single conversation specified by its [id]
 | 
			
		||||
  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(
 | 
			
		||||
      Conversation conversation, UsersList users) {
 | 
			
		||||
    if (conversation.has_name) return conversation.name;
 | 
			
		||||
@@ -69,4 +92,35 @@ class ConversationsHelper {
 | 
			
		||||
 | 
			
		||||
    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],
 | 
			
		||||
        following = map[ConversationTableContract.C_FOLLOWING] == 1,
 | 
			
		||||
        sawLastMessage = map[ConversationTableContract.C_SAW_LAST_MESSAGE] == 1,
 | 
			
		||||
        members = stringListToIntList(
 | 
			
		||||
        members = listToIntList(
 | 
			
		||||
            map[ConversationTableContract.C_MEMBERS].split(",")),
 | 
			
		||||
        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/tiles/custom_bottom_navigation_bar_item.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
@@ -49,7 +49,7 @@ class _HomeRouteState extends State<HomeRoute> {
 | 
			
		||||
  Widget _buildBody(BuildContext context) {
 | 
			
		||||
    switch (_currTab) {
 | 
			
		||||
      case 0:
 | 
			
		||||
        return ConversationsScreen();
 | 
			
		||||
        return ConversationsListScreen();
 | 
			
		||||
 | 
			
		||||
      case 1:
 | 
			
		||||
        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/users_helper.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/utils/intl_utils.dart';
 | 
			
		||||
import 'package:comunic/utils/ui_utils.dart';
 | 
			
		||||
@@ -11,12 +12,12 @@ import 'package:flutter/material.dart';
 | 
			
		||||
///
 | 
			
		||||
/// @author Pierre HUBERT
 | 
			
		||||
 | 
			
		||||
class ConversationsScreen extends StatefulWidget {
 | 
			
		||||
class ConversationsListScreen extends StatefulWidget {
 | 
			
		||||
  @override
 | 
			
		||||
  State<StatefulWidget> createState() => _ConversationScreenState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _ConversationScreenState extends State<ConversationsScreen> {
 | 
			
		||||
class _ConversationScreenState extends State<ConversationsListScreen> {
 | 
			
		||||
  final ConversationsHelper _conversationsHelper = ConversationsHelper();
 | 
			
		||||
  final UsersHelper _usersHelper = UsersHelper();
 | 
			
		||||
  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
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    if (_error == LoadErrorLevel.MAJOR) return _buildErrorCard();
 | 
			
		||||
@@ -103,10 +111,12 @@ class _ConversationScreenState extends State<ConversationsScreen> {
 | 
			
		||||
            ),
 | 
			
		||||
            Expanded(
 | 
			
		||||
              child: ListView.builder(
 | 
			
		||||
                controller: ScrollController(),
 | 
			
		||||
                itemBuilder: (context, index) {
 | 
			
		||||
                  return ConversationTile(
 | 
			
		||||
                    conversation: _list.elementAt(index),
 | 
			
		||||
                    usersList: _list.users,
 | 
			
		||||
                    onOpen: (c){_openConversation(context, c.id);},
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                itemCount: _list.length,
 | 
			
		||||
@@ -9,14 +9,21 @@ import 'package:flutter/material.dart';
 | 
			
		||||
///
 | 
			
		||||
/// @author Pierre HUBERT
 | 
			
		||||
 | 
			
		||||
typedef OpenConversationCallback = void Function(Conversation);
 | 
			
		||||
 | 
			
		||||
class ConversationTile extends StatelessWidget {
 | 
			
		||||
  final Conversation conversation;
 | 
			
		||||
  final UsersList usersList;
 | 
			
		||||
  final OpenConversationCallback onOpen;
 | 
			
		||||
 | 
			
		||||
  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(usersList != null),
 | 
			
		||||
        assert(onOpen != null),
 | 
			
		||||
        super(key: key);
 | 
			
		||||
 | 
			
		||||
  _buildSubInformation(IconData icon, String content) {
 | 
			
		||||
@@ -35,6 +42,7 @@ class ConversationTile extends StatelessWidget {
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return ListTile(
 | 
			
		||||
      onTap: () => onOpen(conversation),
 | 
			
		||||
      // Conversation name
 | 
			
		||||
      title: Text(
 | 
			
		||||
        ConversationsHelper.getConversationName(
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,8 @@
 | 
			
		||||
///
 | 
			
		||||
/// @author Pierre HUBERT
 | 
			
		||||
 | 
			
		||||
/// Transform a list of string into something else
 | 
			
		||||
List<int> stringListToIntList(List<String> srcList){
 | 
			
		||||
/// Transform a list of dynamic thins into something a list of ints
 | 
			
		||||
List<int> listToIntList(List<dynamic> srcList){
 | 
			
		||||
  List<int> list = List();
 | 
			
		||||
 | 
			
		||||
  srcList.forEach((e){
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user