2022-03-12 08:44:21 +00:00
import ' dart:math ' ;
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 {
2021-03-17 16:14:53 +00:00
final bool showAppBar ;
2022-03-10 18:39:57 +00:00
const FriendsListScreen ( { Key ? key , this . showAppBar = true } ) : super ( key: key ) ;
2021-03-17 16:14:53 +00:00
2019-05-01 15:52:41 +00:00
@ override
State < StatefulWidget > createState ( ) = > _FriendsListScreenState ( ) ;
}
class _FriendsListScreenState extends SafeState < FriendsListScreen > {
/// Helpers
final _friendsHelper = FriendsHelper ( ) ;
final _usersHelper = UsersHelper ( ) ;
/// Widget members
_ErrorsLevel _error = _ErrorsLevel . NONE ;
2022-03-10 18:39:57 +00:00
FriendsList ? _friendsList ;
late UsersList _usersInfo ;
2022-03-12 08:42:07 +00:00
final _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
@ 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 {
2022-03-12 08:42:07 +00:00
if ( _refreshIndicatorKey . currentState ! = null )
await _refreshIndicatorKey . currentState ! . show ( ) ;
else
await _getList ( ) ;
2019-05-04 07:37:53 +00:00
}
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
2022-03-10 18:39:57 +00:00
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: [
2021-03-13 14:28:34 +00:00
TextButton (
2019-05-04 07:37:53 +00:00
onPressed: _refreshList ,
2019-05-01 15:52:41 +00:00
child: Text (
2022-03-10 18:39:57 +00:00
tr ( " Retry " ) ! . toUpperCase ( ) ,
2019-05-01 15:52:41 +00:00
style: TextStyle ( color: Colors . white ) ,
) ,
) ,
] ,
) ;
@ override
2020-05-16 15:36:52 +00:00
Widget build ( BuildContext context ) = > Scaffold (
2021-03-17 16:14:53 +00:00
appBar: widget . showAppBar
? AppBar (
2022-03-10 18:39:57 +00:00
title: Text ( tr ( " Your friends list " ) ! ) ,
2021-03-17 16:14:53 +00:00
)
: null ,
2020-05-16 15:36:52 +00:00
body: _buildBody ( ) ,
) ;
Widget _buildBody ( ) {
2019-05-01 15:52:41 +00:00
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 ( ) ,
2022-03-12 08:44:21 +00:00
itemCount: max ( _friendsList ! . length , 1 ) ,
itemBuilder: ( c , i ) {
if ( _friendsList ! . isEmpty )
return Padding (
padding: const EdgeInsets . all ( 8.0 ) ,
child: Center (
child: Text ( tr ( " You do not have any friend yet! " ) ! ) ) ,
) ;
return _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-04 07:37:53 +00:00
) ,
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 ) )
2022-03-10 18:39:57 +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 ) )
2022-03-10 18:39:57 +00:00
showSimpleSnack ( context , tr ( " Could not update following status! " ) ! ) ;
2019-05-01 17:46:13 +00:00
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 (
2022-03-10 18:39:57 +00:00
title: Text ( tr ( " Delete friend " ) ! ) ,
2020-05-16 15:36:52 +00:00
content: Text ( tr (
2022-03-10 18:39:57 +00:00
" 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! " ) ! ) ,
2020-05-16 15:36:52 +00:00
actions: < Widget > [
2021-03-13 14:28:34 +00:00
TextButton (
2020-05-16 15:36:52 +00:00
onPressed: ( ) = > Navigator . pop ( context , false ) ,
2022-03-10 18:39:57 +00:00
child: Text ( tr ( " Cancel " ) ! . toUpperCase ( ) ) ,
2019-05-01 17:29:46 +00:00
) ,
2021-03-13 14:28:34 +00:00
TextButton (
2020-05-16 15:36:52 +00:00
onPressed: ( ) = > Navigator . pop ( context , true ) ,
child: Text (
2022-03-10 18:39:57 +00:00
tr ( " Confirm " ) ! . toUpperCase ( ) ,
2020-05-16 15:36:52 +00:00
style: TextStyle ( color: Colors . red ) ,
) ,
) ,
] ,
) ,
2019-05-01 17:29:46 +00:00
) ;
if ( choice = = null | | ! choice ) return ;
// Forward the request to the server
if ( ! await _friendsHelper . removeFriend ( f . id ) )
showSimpleSnack (
2022-03-10 18:39:57 +00:00
context , tr ( " Could not delete this person from your friends list! " ) ! ) ;
2019-05-01 17:29:46 +00:00
// 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
}