diff --git a/lib/helpers/friends_helper.dart b/lib/helpers/friends_helper.dart index effa397..4acac67 100644 --- a/lib/helpers/friends_helper.dart +++ b/lib/helpers/friends_helper.dart @@ -9,7 +9,6 @@ import 'package:meta/meta.dart'; /// @author Pierre HUBERT class FriendsHelper { - final FriendsDatabaseHelper _friendsDatabaseHelper = FriendsDatabaseHelper(); /// Get the list of friends of the user from the server @@ -50,10 +49,8 @@ class FriendsHelper { /// Get the list, either from an online or an offline source Future getList({@required bool online}) async { - - if(online) + if (online) return await _downloadList(); - else return FriendsList()..addAll(await _friendsDatabaseHelper.getAll()); } @@ -74,13 +71,12 @@ class FriendsHelper { /// Update following status for a friend Future setFollowing(int friendID, bool follow) async { final response = await APIRequest( - uri: "friends/setFollowing", - needLogin: true, - args: { - "friendID" : friendID.toString(), - "follow": follow.toString() - } - ).exec(); + uri: "friends/setFollowing", + needLogin: true, + args: { + "friendID": friendID.toString(), + "follow": follow.toString() + }).exec(); return response.code == 200; } @@ -88,11 +84,26 @@ class FriendsHelper { /// Remove a friend from the list Future removeFriend(int friendID) async { final response = await APIRequest( - uri: "friends/remove", - needLogin: true, - args: {"friendID" : friendID.toString()} - ).exec(); + uri: "friends/remove", + needLogin: true, + args: {"friendID": friendID.toString()}).exec(); return response.code == 200; } + + /// Get and return the list of friends of an other user + /// + /// Throws an Exception if could not get the list of friends + Future> getOtherUserList(int userID) async { + final response = await APIRequest( + uri: "friends/get_user_list", + needLogin: true, + args: {"userID": userID.toString()}, + ).exec(); + + if (response.code != 200) + throw new Exception("Could not get the list of friends of this user!"); + + return Set.from(response.getArray()); + } } diff --git a/lib/ui/routes/other_friends_lists_route.dart b/lib/ui/routes/other_friends_lists_route.dart new file mode 100644 index 0000000..41d0d24 --- /dev/null +++ b/lib/ui/routes/other_friends_lists_route.dart @@ -0,0 +1,114 @@ +import 'package:comunic/helpers/friends_helper.dart'; +import 'package:comunic/helpers/users_helper.dart'; +import 'package:comunic/lists/users_list.dart'; +import 'package:comunic/models/user.dart'; +import 'package:comunic/ui/tiles/simple_user_tile.dart'; +import 'package:comunic/utils/intl_utils.dart'; +import 'package:comunic/utils/navigation_utils.dart'; +import 'package:comunic/utils/ui_utils.dart'; +import 'package:flutter/material.dart'; + +/// Other friends list route (not intended to display current user friends list) +/// +/// @author Pierre HUBERT + +class OtherUserFriendsListRoute extends StatefulWidget { + final User user; + + const OtherUserFriendsListRoute({ + Key key, + @required this.user, + }) : assert(user != null), + super(key: key); + + @override + _OtherUserFriendsListRouteState createState() => + _OtherUserFriendsListRouteState(); +} + +class _OtherUserFriendsListRouteState extends State { + final FriendsHelper friendsHelper = FriendsHelper(); + final UsersHelper usersHelper = UsersHelper(); + + UsersList _list; + bool _error = false; + + String get _routeName => + tr("Friends of %name%", args: {"name": widget.user.displayName}); + + void setError(bool e) => setState(() => _error = e); + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + load(); + } + + /// Load the list of friends of the user + Future load() async { + setError(false); + + try { + final list = await usersHelper.getListWithThrow( + await friendsHelper.getOtherUserList(widget.user.id)); + + setState(() { + _list = list; + }); + } catch (e, st) { + print(e); + print(st); + setError(true); + } + } + + @override + Widget build(BuildContext context) { + if (_error) return _buildError(); + + if (_list == null) + return buildLoadingPage( + showAppBar: true, + routeTitle: _routeName, + ); + + return Scaffold( + appBar: AppBar( + title: Text(_routeName), + ), + body: ListView.builder( + itemCount: _list.length, + itemBuilder: (c, i) => SimpleUserTile( + user: _list[i], + onTap: (u) => openUserPage( + context: context, + userID: u.id, + ), + ), + ), + ); + } + + Widget _buildError() { + return Scaffold( + appBar: AppBar( + title: Text(_routeName), + ), + body: buildErrorCard( + tr( + "Could not get the list of friends of %name% !", + args: {"name": widget.user.displayName}, + ), + actions: [ + FlatButton( + child: Text( + tr("Try again").toUpperCase(), + style: TextStyle(color: Colors.white), + ), + onPressed: load, + ) + ], + ), + ); + } +} diff --git a/lib/ui/routes/user_page_route.dart b/lib/ui/routes/user_page_route.dart index fc864c2..ac80f74 100644 --- a/lib/ui/routes/user_page_route.dart +++ b/lib/ui/routes/user_page_route.dart @@ -1,8 +1,10 @@ import 'package:comunic/helpers/posts_helper.dart'; import 'package:comunic/helpers/users_helper.dart'; import 'package:comunic/models/advanced_user_info.dart'; +import 'package:comunic/ui/routes/other_friends_lists_route.dart'; import 'package:comunic/ui/widgets/network_image_widget.dart'; import 'package:comunic/ui/widgets/posts_list_widget.dart'; +import 'package:comunic/utils/conversations_utils.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; @@ -13,6 +15,8 @@ import 'package:flutter/material.dart'; enum _PageStatus { LOADING, ERROR, READY } +enum _MenuOptions { FRIENDS_LIST } + class UserPageRoute extends StatefulWidget { final int userID; @@ -105,6 +109,7 @@ class _UserPageRouteState extends State { NetworkImageWidget( url: _userInfo.accountImageURL, height: _appBarHeight, + roundedEdges: false, ), // This gradient ensures that the toolbar icons are distinct // against the background image. @@ -130,6 +135,26 @@ class _UserPageRouteState extends State { ], ), ), + actions: [ + IconButton( + icon: Icon( + Icons.chat, + ), + onPressed: () { + openPrivateConversation(context, widget.userID); + }, + ), + PopupMenuButton<_MenuOptions>( + itemBuilder: (c) => [ + PopupMenuItem( + child: Text(tr("Friends")), + enabled: _userInfo != null, + value: _MenuOptions.FRIENDS_LIST, + ) + ], + onSelected: _selectedMenuOption, + ), + ], ); } @@ -146,4 +171,19 @@ class _UserPageRouteState extends State { ), ); } + + /// Method called each time a menu option is selected + void _selectedMenuOption(_MenuOptions value) { + switch (value) { + case _MenuOptions.FRIENDS_LIST: + Navigator.of(context).push( + MaterialPageRoute( + builder: (c) => OtherUserFriendsListRoute( + user: _userInfo, + ), + ), + ); + break; + } + } } diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart index b30e3fa..31e3095 100644 --- a/lib/utils/ui_utils.dart +++ b/lib/utils/ui_utils.dart @@ -14,8 +14,16 @@ Widget buildCenteredProgressBar() { } /// Build and return a full loading page -Widget buildLoadingPage() { +Widget buildLoadingPage({ + bool showAppBar = false, + String routeTitle, +}) { return Scaffold( + appBar: showAppBar + ? AppBar( + title: Text(routeTitle), + ) + : null, body: buildCenteredProgressBar(), ); }