From 67a6befc02fa9c76de43aa882f0a6913c42634c4 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Sat, 4 May 2019 19:35:03 +0200 Subject: [PATCH] Cache the list of friends --- lib/helpers/database/database_contract.dart | 10 ++++++ lib/helpers/database/database_helper.dart | 13 ++++++++ .../database/friends_database_helper.dart | 15 +++++++++ lib/helpers/friends_helper.dart | 23 +++++++++++-- lib/models/friend.dart | 32 ++++++++++++++++--- lib/ui/screens/friends_list_screen.dart | 19 ++++++++--- 6 files changed, 100 insertions(+), 12 deletions(-) create mode 100644 lib/helpers/database/friends_database_helper.dart diff --git a/lib/helpers/database/database_contract.dart b/lib/helpers/database/database_contract.dart index ac116e5..e233c67 100644 --- a/lib/helpers/database/database_contract.dart +++ b/lib/helpers/database/database_contract.dart @@ -45,4 +45,14 @@ abstract class ConversationsMessagesTableContract { static const C_TIME_INSERT = "time_insert"; static const C_MESSAGE = "message"; static const C_IMAGE_URL = "image_url"; +} + +/// Friends table contract +abstract class FriendsListTableContract { + static const TABLE_NAME = "friends"; + static const C_ID = BaseTableContract.C_ID; + static const C_ACCEPTED = "accepted"; + static const C_LAST_ACTIVE = "last_active"; + static const C_FOLLOWING = "following"; + static const C_CAN_POST_TEXTS = "can_post_texts"; } \ No newline at end of file diff --git a/lib/helpers/database/database_helper.dart b/lib/helpers/database/database_helper.dart index 0e60a32..79eca72 100644 --- a/lib/helpers/database/database_helper.dart +++ b/lib/helpers/database/database_helper.dart @@ -45,6 +45,10 @@ abstract class DatabaseHelper { await db.execute( "DROP TABLE IF EXISTS ${ConversationsMessagesTableContract.TABLE_NAME}"); + // Drop friends list table + await db.execute( + "DROP TABLE IF EXISTS ${FriendsListTableContract.TABLE_NAME}"); + // Initialize database again await _initializeDatabase(db, newVersion); } @@ -82,5 +86,14 @@ abstract class DatabaseHelper { "${ConversationsMessagesTableContract.C_MESSAGE} TEXT, " "${ConversationsMessagesTableContract.C_IMAGE_URL} TEXT" ")"); + + // Friends list table + await db.execute("CREATE TABLE ${FriendsListTableContract.TABLE_NAME} (" + "${FriendsListTableContract.C_ID} INTEGER PRIMARY KEY, " + "${FriendsListTableContract.C_ACCEPTED} INTEGER, " + "${FriendsListTableContract.C_LAST_ACTIVE} INTEGER, " + "${FriendsListTableContract.C_FOLLOWING} INTEGER, " + "${FriendsListTableContract.C_CAN_POST_TEXTS} INTEGER" + ")"); } } diff --git a/lib/helpers/database/friends_database_helper.dart b/lib/helpers/database/friends_database_helper.dart new file mode 100644 index 0000000..0276a97 --- /dev/null +++ b/lib/helpers/database/friends_database_helper.dart @@ -0,0 +1,15 @@ +import 'package:comunic/helpers/database/database_contract.dart'; +import 'package:comunic/helpers/database/model_database_helper.dart'; +import 'package:comunic/models/friend.dart'; + +/// Friends database helper +/// +/// @author Pierre HUBERT + +class FriendsDatabaseHelper extends ModelDatabaseHelper { + @override + Friend initializeFromMap(Map map) => Friend.fromMap(map); + + @override + String tableName() => FriendsListTableContract.TABLE_NAME; +} \ No newline at end of file diff --git a/lib/helpers/friends_helper.dart b/lib/helpers/friends_helper.dart index c56fcb8..effa397 100644 --- a/lib/helpers/friends_helper.dart +++ b/lib/helpers/friends_helper.dart @@ -1,17 +1,22 @@ +import 'package:comunic/helpers/database/friends_database_helper.dart'; import 'package:comunic/lists/friends_list.dart'; import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/friend.dart'; +import 'package:meta/meta.dart'; /// Friends helper /// /// @author Pierre HUBERT class FriendsHelper { - /// Get the list of friends of the user + + final FriendsDatabaseHelper _friendsDatabaseHelper = FriendsDatabaseHelper(); + + /// Get the list of friends of the user from the server /// /// Returns the list of friends in case of success, or null if an error /// occurred - Future downloadList() async { + Future _downloadList() async { final response = await APIRequest( uri: "friends/getList", needLogin: true, @@ -36,9 +41,23 @@ class FriendsHelper { ), ); + // Save the list of friends + _friendsDatabaseHelper.clearTable(); + _friendsDatabaseHelper.insertAll(list); + return list; } + /// Get the list, either from an online or an offline source + Future getList({@required bool online}) async { + + if(online) + return await _downloadList(); + + else + return FriendsList()..addAll(await _friendsDatabaseHelper.getAll()); + } + /// Respond to friendship request Future respondRequest(int friendID, bool accept) async { final response = await APIRequest( diff --git a/lib/models/friend.dart b/lib/models/friend.dart index 7519215..efdf990 100644 --- a/lib/models/friend.dart +++ b/lib/models/friend.dart @@ -1,3 +1,5 @@ +import 'package:comunic/helpers/database/database_contract.dart'; +import 'package:comunic/models/cache_model.dart'; import 'package:comunic/utils/date_utils.dart'; import 'package:meta/meta.dart'; @@ -5,15 +7,14 @@ import 'package:meta/meta.dart'; /// /// @author Pierre HUBERT -class Friend { - final int id; +class Friend extends CacheModel implements Comparable { final bool accepted; final int lastActive; final bool following; final bool canPostTexts; - Friend({ - @required this.id, + const Friend({ + @required int id, @required this.accepted, @required this.lastActive, @required this.following, @@ -22,8 +23,29 @@ class Friend { assert(accepted != null), assert(lastActive != null), assert(following != null), - assert(canPostTexts != null); + assert(canPostTexts != null), + super(id: id); /// Check out whether friend is connected or not bool get isConnected => time() - 30 < lastActive; + + @override + int compareTo(Friend other) => other.lastActive.compareTo(lastActive); + + @override + Map toMap() => { + FriendsListTableContract.C_ID: id.toString(), + FriendsListTableContract.C_ACCEPTED: accepted ? 1 : 0, + FriendsListTableContract.C_LAST_ACTIVE: lastActive, + FriendsListTableContract.C_FOLLOWING: following ? 1 : 0, + FriendsListTableContract.C_CAN_POST_TEXTS: canPostTexts ? 1 : 0 + }; + + Friend.fromMap(Map map) + : assert(map != null), + accepted = map[FriendsListTableContract.C_ACCEPTED] == 1, + lastActive = map[FriendsListTableContract.C_LAST_ACTIVE], + following = map[FriendsListTableContract.C_FOLLOWING] == 1, + canPostTexts = map[FriendsListTableContract.C_CAN_POST_TEXTS] == 1, + super.fromMap(map); } diff --git a/lib/ui/screens/friends_list_screen.dart b/lib/ui/screens/friends_list_screen.dart index 24e3563..4365671 100644 --- a/lib/ui/screens/friends_list_screen.dart +++ b/lib/ui/screens/friends_list_screen.dart @@ -47,7 +47,13 @@ class _FriendsListScreenState extends SafeState { @override void didChangeDependencies() { super.didChangeDependencies(); - _loadList(); + _getList(); + } + + /// Initialize list retrieving + Future _getList() async { + await _loadList(false); + await _loadList(true); } /// Refresh the list of friends @@ -56,11 +62,14 @@ class _FriendsListScreenState extends SafeState { } /// Load the list of friends - Future _loadList() async { + Future _loadList(bool online) async { error = _ErrorsLevel.NONE; // Get the list of friends - final list = await _friendsHelper.downloadList(); + final list = await _friendsHelper.getList(online: online); + + // Check if there is no cache yet + if(!online && list.isEmpty) return; // Check for errors if (list == null) return _gotError(); @@ -73,7 +82,7 @@ class _FriendsListScreenState extends SafeState { // Apply new information setState(() { - _friendsList = list; + _friendsList = list..sort(); _usersInfo = users; }); error = _ErrorsLevel.NONE; @@ -107,7 +116,7 @@ class _FriendsListScreenState extends SafeState { Expanded( child: RefreshIndicator( key: _refreshIndicatorKey, - onRefresh: _loadList, + onRefresh: () => _loadList(true), child: ListView.builder( physics: AlwaysScrollableScrollPhysics(), itemCount: _friendsList.length,