mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-22 21:09:21 +00:00
233 lines
7.2 KiB
Dart
233 lines
7.2 KiB
Dart
import 'dart:math';
|
|
|
|
import 'package:comunic/enums/report_target_type.dart';
|
|
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';
|
|
import 'package:comunic/models/friend.dart';
|
|
import 'package:comunic/models/report_target.dart';
|
|
import 'package:comunic/ui/dialogs/report_dialog.dart';
|
|
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';
|
|
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';
|
|
|
|
/// Friends list screen
|
|
///
|
|
/// Display the list of friends of the current user
|
|
///
|
|
/// @author Pierre HUBERT
|
|
|
|
enum _ErrorsLevel { NONE, MINOR, MAJOR }
|
|
|
|
class FriendsListScreen extends StatefulWidget {
|
|
final bool showAppBar;
|
|
|
|
const FriendsListScreen({Key? key, this.showAppBar = true}) : super(key: key);
|
|
|
|
@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;
|
|
late UsersList _usersInfo;
|
|
final _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();
|
|
|
|
/// Useful setters
|
|
set error(_ErrorsLevel err) => setState(() => _error = err);
|
|
|
|
void _gotError() {
|
|
error = _friendsList == null ? _ErrorsLevel.MAJOR : _ErrorsLevel.MINOR;
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
_getList();
|
|
}
|
|
|
|
/// Initialize list retrieving
|
|
Future<void> _getList() async {
|
|
await _loadList(false);
|
|
await _loadList(true);
|
|
}
|
|
|
|
/// Refresh the list of friends
|
|
Future<void> _refreshList() async {
|
|
if (_refreshIndicatorKey.currentState != null)
|
|
await _refreshIndicatorKey.currentState!.show();
|
|
else
|
|
await _getList();
|
|
}
|
|
|
|
/// Load the list of friends
|
|
Future<void> _loadList(bool online) async {
|
|
error = _ErrorsLevel.NONE;
|
|
|
|
// Get the list of friends
|
|
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();
|
|
|
|
// Get information about related users
|
|
final users = await _usersHelper.getUsersInfo(list.usersId);
|
|
|
|
// Check for errors
|
|
if (users == null) return _gotError();
|
|
|
|
// Apply new information
|
|
setState(() {
|
|
_friendsList = list..sort();
|
|
_usersInfo = users;
|
|
});
|
|
error = _ErrorsLevel.NONE;
|
|
}
|
|
|
|
/// Build and return loading error
|
|
Widget _buildError() => buildErrorCard(
|
|
tr("Could not load your list of friends!"),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: _refreshList,
|
|
child: Text(
|
|
tr("Retry")!.toUpperCase(),
|
|
style: TextStyle(color: Colors.white),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
|
|
@override
|
|
Widget build(BuildContext context) => Scaffold(
|
|
appBar: widget.showAppBar
|
|
? AppBar(
|
|
title: Text(tr("Your friends list")!),
|
|
)
|
|
: null,
|
|
body: _buildBody(),
|
|
);
|
|
|
|
Widget _buildBody() {
|
|
if (_error == _ErrorsLevel.MAJOR) return _buildError();
|
|
if (_friendsList == null) return buildCenteredProgressBar();
|
|
|
|
return Column(
|
|
children: <Widget>[
|
|
// Check for errors
|
|
Container(child: _error != _ErrorsLevel.NONE ? _buildError() : null),
|
|
|
|
// List of friends
|
|
Expanded(
|
|
child: RefreshIndicator(
|
|
key: _refreshIndicatorKey,
|
|
onRefresh: () => _loadList(true),
|
|
child: ListView.builder(
|
|
physics: AlwaysScrollableScrollPhysics(),
|
|
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,
|
|
onReportFriend: _reportFriend,
|
|
)
|
|
: PendingFriendTile(
|
|
friend: _friendsList![i],
|
|
user: _usersInfo.getUser(_friendsList![i].id),
|
|
onRespond: _respondRequest,
|
|
onReport: _reportFriend,
|
|
);
|
|
}),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
/// Respond to friendship request
|
|
Future<void> _respondRequest(Friend f, bool accept) async {
|
|
if (!await _friendsHelper.respondRequest(f.id, accept))
|
|
showSimpleSnack(context, tr("Could not respond to friendship request!")!);
|
|
|
|
// Load the list of friends again
|
|
_refreshList();
|
|
}
|
|
|
|
/// Update following status of a friend
|
|
Future<void> _setFollowingFriend(Friend friend, bool follow) async {
|
|
if (!await _friendsHelper.setFollowing(friend.id, follow))
|
|
showSimpleSnack(context, tr("Could not update following status!")!);
|
|
|
|
_refreshList();
|
|
}
|
|
|
|
/// 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>[
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context, false),
|
|
child: Text(tr("Cancel")!.toUpperCase()),
|
|
),
|
|
TextButton(
|
|
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
|
|
_refreshList();
|
|
}
|
|
|
|
/// Report a friend
|
|
Future<void> _reportFriend(Friend friend) async => await showReportDialog(
|
|
ctx: context, target: ReportTarget(ReportTargetType.User, friend.id));
|
|
|
|
/// Open a private conversation for a given [friend]
|
|
Future<void> _openPrivateConversation(Friend friend) async {
|
|
await openPrivateConversation(context, friend.id);
|
|
}
|
|
}
|