2019-05-01 15:52:41 +00:00
import ' package:comunic/helpers/friends_helper.dart ' ;
import ' package:comunic/helpers/users_helper.dart ' ;
import ' package:comunic/lists/friends_list.dart ' ;
import ' package:comunic/lists/users_list.dart ' ;
2019-05-01 16:01:20 +00:00
import ' package:comunic/models/friend.dart ' ;
2019-05-01 15:52:41 +00:00
import ' package:comunic/ui/tiles/accepted_friend_tile.dart ' ;
import ' package:comunic/ui/tiles/pending_friend_tile.dart ' ;
import ' package:comunic/ui/widgets/safe_state.dart ' ;
2019-05-02 06:09:40 +00:00
import ' package:comunic/utils/conversations_utils.dart ' ;
2019-05-01 15:52:41 +00:00
import ' package:comunic/utils/intl_utils.dart ' ;
import ' package:comunic/utils/ui_utils.dart ' ;
import ' package:flutter/material.dart ' ;
/// Friends list screen
///
/// Display the list of friends of the current user
///
/// @author Pierre HUBERT
enum _ErrorsLevel { NONE , MINOR , MAJOR }
class FriendsListScreen extends StatefulWidget {
@ override
State < StatefulWidget > createState ( ) = > _FriendsListScreenState ( ) ;
}
class _FriendsListScreenState extends SafeState < FriendsListScreen > {
/// Helpers
final _friendsHelper = FriendsHelper ( ) ;
final _usersHelper = UsersHelper ( ) ;
/// Widget members
_ErrorsLevel _error = _ErrorsLevel . NONE ;
FriendsList _friendsList ;
UsersList _usersInfo ;
2019-05-04 07:37:53 +00:00
GlobalKey < RefreshIndicatorState > _refreshIndicatorKey =
GlobalKey < RefreshIndicatorState > ( ) ;
2019-05-01 15:52:41 +00:00
/// Useful setters
set error ( _ErrorsLevel err ) = > setState ( ( ) = > _error = err ) ;
2019-05-01 17:29:46 +00:00
void _gotError ( ) {
error = _friendsList = = null ? _ErrorsLevel . MAJOR : _ErrorsLevel . MINOR ;
}
2019-05-01 15:52:41 +00:00
2019-05-04 07:37:53 +00:00
2019-05-01 15:52:41 +00:00
@ override
void didChangeDependencies ( ) {
super . didChangeDependencies ( ) ;
2019-05-04 17:35:03 +00:00
_getList ( ) ;
}
/// Initialize list retrieving
Future < void > _getList ( ) async {
await _loadList ( false ) ;
await _loadList ( true ) ;
2019-05-01 15:52:41 +00:00
}
2019-05-04 07:37:53 +00:00
/// Refresh the list of friends
Future < void > _refreshList ( ) async {
await _refreshIndicatorKey . currentState . show ( ) ;
}
2019-05-01 15:52:41 +00:00
/// Load the list of friends
2019-05-04 17:35:03 +00:00
Future < void > _loadList ( bool online ) async {
2019-05-01 15:52:41 +00:00
error = _ErrorsLevel . NONE ;
// Get the list of friends
2019-05-04 17:35:03 +00:00
final list = await _friendsHelper . getList ( online: online ) ;
// Check if there is no cache yet
if ( ! online & & list . isEmpty ) return ;
2019-05-01 15:52:41 +00:00
// Check for errors
if ( list = = null ) return _gotError ( ) ;
// Get information about related users
final users = await _usersHelper . getUsersInfo ( list . usersId ) ;
// Check for errors
if ( users = = null ) return _gotError ( ) ;
// Apply new information
setState ( ( ) {
2019-05-04 17:35:03 +00:00
_friendsList = list . . sort ( ) ;
2019-05-01 15:52:41 +00:00
_usersInfo = users ;
} ) ;
error = _ErrorsLevel . NONE ;
}
/// Build and return loading error
2019-05-01 16:01:20 +00:00
Widget _buildError ( ) = > buildErrorCard (
2019-05-01 15:52:41 +00:00
tr ( " Could not load your list of friends! " ) ,
actions: [
FlatButton (
2019-05-04 07:37:53 +00:00
onPressed: _refreshList ,
2019-05-01 15:52:41 +00:00
child: Text (
tr ( " Retry " ) . toUpperCase ( ) ,
style: TextStyle ( color: Colors . white ) ,
) ,
) ,
] ,
) ;
@ override
Widget build ( BuildContext context ) {
if ( _error = = _ErrorsLevel . MAJOR ) return _buildError ( ) ;
if ( _friendsList = = null ) return buildCenteredProgressBar ( ) ;
2019-05-04 07:37:53 +00:00
return Column (
2019-05-01 15:52:41 +00:00
children: < Widget > [
2019-05-04 07:37:53 +00:00
// Check for errors
Container ( child: _error ! = _ErrorsLevel . NONE ? _buildError ( ) : null ) ,
// List of friends
Expanded (
child: RefreshIndicator (
key: _refreshIndicatorKey ,
2019-05-04 17:35:03 +00:00
onRefresh: ( ) = > _loadList ( true ) ,
2019-05-04 07:37:53 +00:00
child: ListView . builder (
physics: AlwaysScrollableScrollPhysics ( ) ,
itemCount: _friendsList . length ,
itemBuilder: ( c , i ) = > _friendsList [ i ] . accepted
? AcceptedFriendTile (
friend: _friendsList [ i ] ,
user: _usersInfo . getUser ( _friendsList [ i ] . id ) ,
onOpenPrivateConversation: _openPrivateConversation ,
onSetFollowing: _setFollowingFriend ,
onRequestDelete: _deleteFriend ,
)
: PendingFriendTile (
friend: _friendsList [ i ] ,
user: _usersInfo . getUser ( _friendsList [ i ] . id ) ,
onRespond: _respondRequest ,
) ) ,
) ,
2019-05-01 15:52:41 +00:00
) ,
] ,
) ;
}
2019-05-01 16:01:20 +00:00
/// Respond to friendship request
Future < void > _respondRequest ( Friend f , bool accept ) async {
if ( ! await _friendsHelper . respondRequest ( f . id , accept ) )
2019-05-01 17:29:46 +00:00
showSimpleSnack ( context , tr ( " Could not respond to friendship request! " ) ) ;
2019-05-01 16:01:20 +00:00
// Load the list of friends again
2019-05-04 07:37:53 +00:00
_refreshList ( ) ;
2019-05-01 16:01:20 +00:00
}
2019-05-01 17:29:46 +00:00
2019-05-01 17:46:13 +00:00
/// Update following status of a friend
Future < void > _setFollowingFriend ( Friend friend , bool follow ) async {
2019-05-02 06:09:40 +00:00
if ( ! await _friendsHelper . setFollowing ( friend . id , follow ) )
2019-05-01 17:46:13 +00:00
showSimpleSnack ( context , tr ( " Could not update following status! " ) ) ;
2019-05-04 07:37:53 +00:00
_refreshList ( ) ;
2019-05-01 17:46:13 +00:00
}
2019-05-01 17:29:46 +00:00
/// Handles deletion request of a friend
Future < void > _deleteFriend ( Friend f ) async {
final choice = await showDialog < bool > (
context: context ,
builder: ( b ) = > AlertDialog (
title: Text ( tr ( " Delete friend " ) ) ,
content: Text ( tr (
" Are you sure do you want to remove this friend from your list of friends ? A friendship request will have to be sent to get this user back to your list! " ) ) ,
actions: < Widget > [
FlatButton (
onPressed: ( ) = > Navigator . pop ( context , false ) ,
child: Text ( tr ( " Cancel " ) . toUpperCase ( ) ) ,
) ,
FlatButton (
onPressed: ( ) = > Navigator . pop ( context , true ) ,
child: Text (
tr ( " Confirm " ) . toUpperCase ( ) ,
style: TextStyle ( color: Colors . red ) ,
) ,
) ,
] ,
) ,
) ;
if ( choice = = null | | ! choice ) return ;
// Forward the request to the server
if ( ! await _friendsHelper . removeFriend ( f . id ) )
showSimpleSnack (
context , tr ( " Could not delete this person from your friends list! " ) ) ;
// Refresh list
2019-05-04 07:37:53 +00:00
_refreshList ( ) ;
2019-05-01 17:29:46 +00:00
}
2019-05-02 06:09:40 +00:00
/// Open a private conversation for a given [friend]
Future < void > _openPrivateConversation ( Friend friend ) async {
await openPrivateConversation ( context , friend . id ) ;
}
2019-05-01 15:52:41 +00:00
}