mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 12:14:11 +00:00 
			
		
		
		
	Get and show the list of conversations
This commit is contained in:
		
							
								
								
									
										5
									
								
								lib/enums/load_error_level.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								lib/enums/load_error_level.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					/// Load error level
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum LoadErrorLevel {MINOR, MAJOR, NONE}
 | 
				
			||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
import 'dart:convert';
 | 
					import 'dart:convert';
 | 
				
			||||||
import 'dart:io';
 | 
					import 'dart:io';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:comunic/helpers/account_credentials_helper.dart';
 | 
				
			||||||
import 'package:comunic/models/api_request.dart';
 | 
					import 'package:comunic/models/api_request.dart';
 | 
				
			||||||
import 'package:comunic/models/api_response.dart';
 | 
					import 'package:comunic/models/api_response.dart';
 | 
				
			||||||
import 'package:comunic/models/config.dart';
 | 
					import 'package:comunic/models/config.dart';
 | 
				
			||||||
@@ -23,7 +24,12 @@ class APIHelper {
 | 
				
			|||||||
      request.addString("serviceToken", config().serviceToken);
 | 
					      request.addString("serviceToken", config().serviceToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      //Add user tokens (if required)
 | 
					      //Add user tokens (if required)
 | 
				
			||||||
      if (request.needLogin) throw "Can add user tokens right now !";
 | 
					      if (request.needLogin) {
 | 
				
			||||||
 | 
					        final tokens = await AccountCredentialsHelper().get();
 | 
				
			||||||
 | 
					        assert(tokens != null);
 | 
				
			||||||
 | 
					        request.addString("userToken1", tokens.tokenOne);
 | 
				
			||||||
 | 
					        request.addString("userToken2", tokens.tokenTwo);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Prepare request body
 | 
					      // Prepare request body
 | 
				
			||||||
      String requestBody = "";
 | 
					      String requestBody = "";
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								lib/helpers/conversations_helper.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								lib/helpers/conversations_helper.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/models/api_request.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/conversation.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Conversation helper
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConversationsHelper {
 | 
				
			||||||
 | 
					  /// Download the list of conversations from the server
 | 
				
			||||||
 | 
					  Future<List<Conversation>> downloadList() async {
 | 
				
			||||||
 | 
					    final response =
 | 
				
			||||||
 | 
					        await APIRequest(uri: "conversations/getList", needLogin: true).exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (response.code != 200) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      List<Conversation> list = List();
 | 
				
			||||||
 | 
					      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(),
 | 
				
			||||||
 | 
					          )));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } on Exception catch(e){
 | 
				
			||||||
 | 
					      print(e.toString());
 | 
				
			||||||
 | 
					      return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/helpers/api_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/api_response.dart';
 | 
				
			||||||
import 'package:meta/meta.dart';
 | 
					import 'package:meta/meta.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// API Request model
 | 
					/// API Request model
 | 
				
			||||||
@@ -11,12 +13,11 @@ class APIRequest {
 | 
				
			|||||||
  final bool needLogin;
 | 
					  final bool needLogin;
 | 
				
			||||||
  Map<String, String> args;
 | 
					  Map<String, String> args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  APIRequest({
 | 
					  APIRequest({@required this.uri, this.needLogin = false, this.args})
 | 
				
			||||||
    @required this.uri,
 | 
					      : assert(uri != null),
 | 
				
			||||||
    this.needLogin = false,
 | 
					        assert(needLogin != null) {
 | 
				
			||||||
  })  : assert(uri != null),
 | 
					    if (this.args == null) this.args = Map();
 | 
				
			||||||
        assert(needLogin != null),
 | 
					  }
 | 
				
			||||||
        args = Map();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void addString(String name, String value) => args[name] = value;
 | 
					  void addString(String name, String value) => args[name] = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -24,4 +25,7 @@ class APIRequest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  void addBool(String name, bool value) =>
 | 
					  void addBool(String name, bool value) =>
 | 
				
			||||||
      args[name] = value ? "true" : "false";
 | 
					      args[name] = value ? "true" : "false";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Execute the request
 | 
				
			||||||
 | 
					  Future<APIResponse> exec() async => APIHelper().exec(this);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								lib/models/conversation.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								lib/models/conversation.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					import 'package:meta/meta.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Conversation model
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Conversation {
 | 
				
			||||||
 | 
					  final int id;
 | 
				
			||||||
 | 
					  final int ownerID;
 | 
				
			||||||
 | 
					  final int lastActive;
 | 
				
			||||||
 | 
					  final String name;
 | 
				
			||||||
 | 
					  final bool following;
 | 
				
			||||||
 | 
					  final bool sawLastMessage;
 | 
				
			||||||
 | 
					  final List<int> members;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const Conversation({
 | 
				
			||||||
 | 
					    @required this.id,
 | 
				
			||||||
 | 
					    @required this.ownerID,
 | 
				
			||||||
 | 
					    @required this.lastActive,
 | 
				
			||||||
 | 
					    @required this.name,
 | 
				
			||||||
 | 
					    @required this.following,
 | 
				
			||||||
 | 
					    @required this.sawLastMessage,
 | 
				
			||||||
 | 
					    @required this.members,
 | 
				
			||||||
 | 
					  })  : assert(id != null),
 | 
				
			||||||
 | 
					        assert(ownerID != null),
 | 
				
			||||||
 | 
					        assert(lastActive != null),
 | 
				
			||||||
 | 
					        assert(following != null),
 | 
				
			||||||
 | 
					        assert(sawLastMessage != null),
 | 
				
			||||||
 | 
					        assert(members != null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/ui/screens/conversations_screen.dart';
 | 
				
			||||||
import 'package:comunic/ui/screens/menus_screen.dart';
 | 
					import 'package:comunic/ui/screens/menus_screen.dart';
 | 
				
			||||||
import 'package:comunic/ui/tiles/CustomBottomNavigationBarItem.dart';
 | 
					import 'package:comunic/ui/tiles/CustomBottomNavigationBarItem.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
@@ -48,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 Text("Conversations");
 | 
					        return ConversationsScreen();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case 1:
 | 
					      case 1:
 | 
				
			||||||
        return MenuScreen();
 | 
					        return MenuScreen();
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										87
									
								
								lib/ui/screens/conversations_screen.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								lib/ui/screens/conversations_screen.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/enums/load_error_level.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/helpers/conversations_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/conversation.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/tiles/conversation_tile.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Conversations screen
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConversationsScreen extends StatefulWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  State<StatefulWidget> createState() => _ConversationScreenState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _ConversationScreenState extends State<ConversationsScreen> {
 | 
				
			||||||
 | 
					  final ConversationsHelper _conversationsHelper = ConversationsHelper();
 | 
				
			||||||
 | 
					  List<Conversation> _list;
 | 
				
			||||||
 | 
					  LoadErrorLevel _error = LoadErrorLevel.NONE;
 | 
				
			||||||
 | 
					  bool _loading = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void didChangeDependencies() {
 | 
				
			||||||
 | 
					    super.didChangeDependencies();
 | 
				
			||||||
 | 
					    _loadConversations();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void setError(LoadErrorLevel err) => setState(() => _error = err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void setLoading(bool loading) => setState(() => _loading = loading);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void gotLoadingError() {
 | 
				
			||||||
 | 
					    setLoading(false);
 | 
				
			||||||
 | 
					    setError(_list == null ? LoadErrorLevel.MAJOR : LoadErrorLevel.MINOR);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Load the list of conversations
 | 
				
			||||||
 | 
					  Future<void> _loadConversations() async {
 | 
				
			||||||
 | 
					    setError(LoadErrorLevel.NONE);
 | 
				
			||||||
 | 
					    setLoading(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final list = await _conversationsHelper.downloadList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (list == null) return gotLoadingError();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Save list
 | 
				
			||||||
 | 
					    _list = list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setLoading(false);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Build an error card
 | 
				
			||||||
 | 
					  Widget _buildErrorCard() {
 | 
				
			||||||
 | 
					    return buildErrorCard(
 | 
				
			||||||
 | 
					      tr("Could not retrieve the list of conversations!"),
 | 
				
			||||||
 | 
					      actions: <Widget>[
 | 
				
			||||||
 | 
					        FlatButton(
 | 
				
			||||||
 | 
					          onPressed: _loadConversations,
 | 
				
			||||||
 | 
					          child: Text(
 | 
				
			||||||
 | 
					            tr("Retry").toUpperCase(),
 | 
				
			||||||
 | 
					            style: TextStyle(
 | 
				
			||||||
 | 
					              color: Colors.white,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    if (_error == LoadErrorLevel.MAJOR) return _buildErrorCard();
 | 
				
			||||||
 | 
					    if (_list == null) return buildCenteredProgressBar();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Show the list of conversations
 | 
				
			||||||
 | 
					    return ListView.builder(
 | 
				
			||||||
 | 
					      itemBuilder: (context, index) {
 | 
				
			||||||
 | 
					        return ConversationTile(
 | 
				
			||||||
 | 
					          conversation: _list.elementAt(index),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      itemCount: _list.length,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										55
									
								
								lib/ui/tiles/conversation_tile.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								lib/ui/tiles/conversation_tile.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/models/conversation.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Single conversation tile
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConversationTile extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Conversation conversation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const ConversationTile({Key key, this.conversation}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _buildSubInformation(IconData icon, String content) {
 | 
				
			||||||
 | 
					    return Row(
 | 
				
			||||||
 | 
					      children: <Widget>[
 | 
				
			||||||
 | 
					        Icon(
 | 
				
			||||||
 | 
					          icon,
 | 
				
			||||||
 | 
					          size: 15.0,
 | 
				
			||||||
 | 
					          color: Colors.grey,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        Text(" " + content),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return ListTile(
 | 
				
			||||||
 | 
					      title: Text(conversation.name == null ? "Unknown" : conversation.name),
 | 
				
			||||||
 | 
					      leading: Icon(
 | 
				
			||||||
 | 
					        conversation.sawLastMessage ? Icons.check_circle : Icons.lens,
 | 
				
			||||||
 | 
					        color: conversation.sawLastMessage ? null : Colors.blue,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      isThreeLine: true,
 | 
				
			||||||
 | 
					      subtitle: Column(
 | 
				
			||||||
 | 
					        crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
				
			||||||
 | 
					        children: <Widget>[
 | 
				
			||||||
 | 
					          _buildSubInformation(Icons.access_time, "time"), //TODO : improve the way the time is shown
 | 
				
			||||||
 | 
					          _buildSubInformation(
 | 
				
			||||||
 | 
					            Icons.group,
 | 
				
			||||||
 | 
					            conversation.members.length == 1
 | 
				
			||||||
 | 
					                ? tr("1 member")
 | 
				
			||||||
 | 
					                : tr(
 | 
				
			||||||
 | 
					                    "%num% members",
 | 
				
			||||||
 | 
					                    args: {
 | 
				
			||||||
 | 
					                      "num": conversation.members.length.toString(),
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,7 +5,15 @@
 | 
				
			|||||||
/// Translate a string
 | 
					/// Translate a string
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// Translate a given [string] into the current language, if available
 | 
					/// Translate a given [string] into the current language, if available
 | 
				
			||||||
String tr(String string) {
 | 
					///
 | 
				
			||||||
 | 
					/// Then apply the list of [args] to the string, each argument name is
 | 
				
			||||||
 | 
					/// surrounded by '%'
 | 
				
			||||||
 | 
					String tr(String string, {Map<String, String> args}) {
 | 
				
			||||||
  //TODO : create translation system
 | 
					  //TODO : create translation system
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  //Apply arguments
 | 
				
			||||||
 | 
					  if(args != null)
 | 
				
			||||||
 | 
					    args.forEach((key, value) => string = string.replaceAll("%$key%", value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return string;
 | 
					  return string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -18,7 +18,7 @@ Widget buildLoadingPage() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Build and return an error card
 | 
					/// Build and return an error card
 | 
				
			||||||
Widget buildErrorCard(String message) {
 | 
					Widget buildErrorCard(String message, {List<Widget> actions}) {
 | 
				
			||||||
  return Card(
 | 
					  return Card(
 | 
				
			||||||
    elevation: 2.0,
 | 
					    elevation: 2.0,
 | 
				
			||||||
    color: Colors.red,
 | 
					    color: Colors.red,
 | 
				
			||||||
@@ -39,6 +39,9 @@ Widget buildErrorCard(String message) {
 | 
				
			|||||||
              style: TextStyle(color: Colors.white),
 | 
					              style: TextStyle(color: Colors.white),
 | 
				
			||||||
              maxLines: null,
 | 
					              maxLines: null,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          Row(
 | 
				
			||||||
 | 
					            children: actions == null ? <Widget>[] : actions,
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user