1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-25 22:39:22 +00:00

Create user access denied route

This commit is contained in:
Pierre HUBERT 2019-06-15 16:01:58 +02:00
parent 972cee0a18
commit 4fb34e6f90
7 changed files with 330 additions and 4 deletions

View File

@ -2,6 +2,7 @@ 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:comunic/models/friend_status.dart';
import 'package:meta/meta.dart';
/// Friends helper
@ -65,7 +66,7 @@ class FriendsHelper {
"accept": accept.toString()
}).exec();
return response.code == 200;
return response.isOK;
}
/// Update following status for a friend
@ -91,6 +92,28 @@ class FriendsHelper {
return response.code == 200;
}
/// Get friendship status. Throw an exception in case of failure
Future<FriendStatus> getFriendshipStatus(int userID) async {
final response = await APIRequest(
uri: "friends/getStatus",
needLogin: true,
args: {"friendID": userID.toString()},
).exec();
if (response.code != 200)
throw Exception("Could not get friendship status!");
final obj = response.getObject();
return FriendStatus(
userID: userID,
areFriend: obj["are_friend"],
sentRequest: obj["sent_request"],
receivedRequest: obj["received_request"],
following: obj["following"],
);
}
/// Get and return the list of friends of an other user
///
/// Throws an Exception if could not get the list of friends
@ -106,4 +129,24 @@ class FriendsHelper {
return Set<int>.from(response.getArray());
}
/// Send a friendship request to a specified user
Future<bool> sendRequest(int userID) async {
return (await APIRequest(
uri: "friends/sendRequest",
needLogin: true,
args: {"friendID": userID.toString()},
).exec())
.isOK;
}
/// Cancel a friendship request
Future<bool> cancelRequest(int userID) async {
return (await APIRequest(
uri: "friends/removeRequest",
needLogin: true,
args: {"friendID": userID.toString()},
).exec())
.isOK;
}
}

View File

@ -12,7 +12,11 @@ import 'package:comunic/models/user.dart';
/// @author Pierre HUBERT
/// Handle advanced information error
enum GetUserAdvancedInformationErrorCause { NOT_FOUND, NETWORK_ERROR }
enum GetUserAdvancedInformationErrorCause {
NOT_FOUND,
NETWORK_ERROR,
NOT_AUTHORIZED
}
class GetUserAdvancedUserError extends Error {
final GetUserAdvancedInformationErrorCause cause;
@ -76,6 +80,11 @@ class UsersHelper {
return list;
}
/// Get information about a single user. Throws in case of failure
Future<User> getSingleWithThrow(int user) async {
return (await getListWithThrow(Set<int>()..add(user)))[0];
}
/// Get users information from a given [Set]
Future<UsersList> getList(Set<int> users,
{bool forceDownload = false}) async {
@ -125,6 +134,9 @@ class UsersHelper {
if (response.code == 404)
cause = GetUserAdvancedInformationErrorCause.NOT_FOUND;
if (response.code == 401)
cause = GetUserAdvancedInformationErrorCause.NOT_AUTHORIZED;
throw new GetUserAdvancedUserError(cause);
}

View File

@ -0,0 +1,27 @@
import 'package:meta/meta.dart';
/// Simple friendship status
///
/// @author Pierre HUBERT
class FriendStatus {
final int userID;
final bool areFriend;
final bool sentRequest;
final bool receivedRequest;
final bool following;
const FriendStatus({
@required this.userID,
@required this.areFriend,
@required this.sentRequest,
@required this.receivedRequest,
@required this.following,
}) : assert(userID != null),
assert(areFriend != null),
assert(sentRequest != null),
assert(receivedRequest != null),
assert(following != null);
bool get noRequestExchanged => !areFriend && !sentRequest && !receivedRequest;
}

View File

@ -0,0 +1,120 @@
import 'package:comunic/helpers/friends_helper.dart';
import 'package:comunic/helpers/users_helper.dart';
import 'package:comunic/models/friend_status.dart';
import 'package:comunic/models/user.dart';
import 'package:comunic/ui/routes/user_page_route.dart';
import 'package:comunic/ui/widgets/FrienshipStatusWidget.dart';
import 'package:comunic/ui/widgets/account_image_widget.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';
/// User access denied route
///
/// @author Pierre HUBERT
class UserAccessDeniedRoute extends StatefulWidget {
final int userID;
const UserAccessDeniedRoute({Key key, @required this.userID})
: assert(userID != null),
super(key: key);
@override
_UserAccessDeniedRouteState createState() => _UserAccessDeniedRouteState();
}
class _UserAccessDeniedRouteState extends State<UserAccessDeniedRoute> {
final UsersHelper usersHelper = UsersHelper();
final FriendsHelper friendsHelper = FriendsHelper();
GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
GlobalKey<RefreshIndicatorState>();
FriendStatus _status;
User _user;
bool _error = false;
void setError(bool e) => setState(() => _error = e);
@override
void didChangeDependencies() {
super.didChangeDependencies();
refresh();
}
Future<void> refresh() async {
try {
final status = await friendsHelper.getFriendshipStatus(widget.userID);
final user = await usersHelper.getSingleWithThrow(widget.userID);
// Check if the two users are friend now
if (status.areFriend)
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (c) => UserPageRoute(
userID: widget.userID,
),
),
);
setState(() {
_status = status;
_user = user;
});
} catch (e) {
setError(true);
}
}
@override
Widget build(BuildContext context) {
if (!_error && _status == null) return buildLoadingPage(showAppBar: true);
return Scaffold(
appBar: AppBar(
title: Text(_error ? "Error" : _user.displayName),
),
body: RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: refresh,
child: ListView.builder(
itemBuilder: (c, i) => _scrollBuild(),
itemCount: 1,
),
),
);
}
Widget _scrollBuild() {
if (_error) return _buildError();
return _buildPage();
}
Widget _buildError() {
return buildErrorCard("Could get information about your friendship!");
}
Widget _buildPage() {
return Center(
child: Column(
children: <Widget>[
AccountImageWidget(
user: _user,
width: 75,
),
Text(
_user.displayName,
style: TextStyle(fontSize: 25.0),
),
Text(tr("This account is private.")),
FriendshipStatusWidget(
status: _status,
onFriendshipUpdated: () => _refreshIndicatorKey.currentState.show(),
)
],
),
);
}
}

View File

@ -2,6 +2,7 @@ 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/routes/user_access_denied_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';
@ -57,8 +58,17 @@ class _UserPageRouteState extends State<UserPageRoute> {
});
_setStatus(_PageStatus.READY);
} on GetUserAdvancedUserError {
} on GetUserAdvancedUserError catch (e) {
_setStatus(_PageStatus.ERROR);
if (e.cause == GetUserAdvancedInformationErrorCause.NOT_AUTHORIZED)
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (c) => UserAccessDeniedRoute(
userID: widget.userID,
),
),
);
}
}

View File

@ -0,0 +1,114 @@
import 'package:comunic/helpers/friends_helper.dart';
import 'package:comunic/models/friend_status.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';
/// Friendship status widget
///
/// @author Pierre HUBERT
const WhiteTextColorStyle = TextStyle(color: Colors.white);
class FriendshipStatusWidget extends StatefulWidget {
final FriendStatus status;
final void Function() onFriendshipUpdated;
const FriendshipStatusWidget({
Key key,
@required this.status,
@required this.onFriendshipUpdated,
}) : assert(status != null),
assert(onFriendshipUpdated != null),
super(key: key);
@override
_FriendshipStatusWidgetState createState() => _FriendshipStatusWidgetState();
}
class _FriendshipStatusWidgetState extends State<FriendshipStatusWidget> {
final FriendsHelper _friendsHelper = FriendsHelper();
bool _sentRequest = false;
int get friendID => widget.status.userID;
void setSentRequest(bool sent) => setState(() => _sentRequest = sent);
@override
void didUpdateWidget(FriendshipStatusWidget oldWidget) {
super.didUpdateWidget(oldWidget);
setSentRequest(false);
}
@override
Widget build(BuildContext context) {
if (_sentRequest) return Container();
// No request sent yet
if (widget.status.noRequestExchanged) {
return RaisedButton(
child: Text(tr("Send request").toUpperCase()),
onPressed: () =>
executeRequest(() => _friendsHelper.sendRequest(friendID)),
);
}
// Already sent a friendship request
if (widget.status.sentRequest) {
return RaisedButton(
child: Text(
tr("Cancel request").toUpperCase(),
style: WhiteTextColorStyle,
),
color: Colors.red,
onPressed: () =>
executeRequest(() => _friendsHelper.cancelRequest(friendID)),
);
}
// Received a friendship request
if (widget.status.receivedRequest) {
return Column(
children: <Widget>[
RaisedButton(
child: Text(
tr("Accept request").toUpperCase(),
style: WhiteTextColorStyle,
),
color: Colors.green,
onPressed: () => executeRequest(
() => _friendsHelper.respondRequest(friendID, true)),
),
RaisedButton(
child: Text(
tr("Reject request").toUpperCase(),
style: WhiteTextColorStyle,
),
color: Colors.red,
onPressed: () => executeRequest(
() => _friendsHelper.respondRequest(friendID, false)),
)
],
);
}
// The two users are friends, offers to follow him
return RaisedButton(
child: Text((widget.status.following ? tr("Following") : tr("Follow"))
.toUpperCase()),
onPressed: () => executeRequest(() =>
_friendsHelper.setFollowing(friendID, !widget.status.following)),
);
}
/// Send friendship request
Future<void> executeRequest(Future<bool> Function() func) async {
setSentRequest(true);
if (!await func())
showSimpleSnack(context, tr("Could not update your membership!"));
widget.onFriendshipUpdated();
}
}

View File

@ -21,7 +21,7 @@ Widget buildLoadingPage({
return Scaffold(
appBar: showAppBar
? AppBar(
title: Text(routeTitle),
title: routeTitle == null ? null : Text(routeTitle),
)
: null,
body: buildCenteredProgressBar(),