1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-25 06:19:22 +00:00

Created conversation route

This commit is contained in:
Pierre HUBERT 2019-04-24 17:46:25 +02:00
parent 4be5a1b5a8
commit 1ec197202c
7 changed files with 181 additions and 19 deletions

View File

@ -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(),
);
}
} }

View File

@ -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);

View 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(),
);
}
}

View File

@ -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();

View File

@ -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,

View File

@ -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(

View File

@ -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){