From eaeb07db698d6b307c882b0566ef55483e3d8dda Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Wed, 15 Apr 2020 13:56:59 +0200 Subject: [PATCH] Can cancel membership request --- lib/helpers/groups_helper.dart | 15 +++- lib/models/group.dart | 2 +- lib/ui/screens/groups_list_screen.dart | 2 + lib/ui/widgets/group_membership_widget.dart | 82 +++++++++++++++++++++ 4 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 lib/ui/widgets/group_membership_widget.dart diff --git a/lib/helpers/groups_helper.dart b/lib/helpers/groups_helper.dart index 9b226a6..c050f6e 100644 --- a/lib/helpers/groups_helper.dart +++ b/lib/helpers/groups_helper.dart @@ -100,13 +100,20 @@ class GroupsHelper { .map((f) => cast(f)) .toSet(); - /// Remove group membership - Future removeMembership(int groupID) async => - (await (APIRequest(uri: "groups/remove_membership", needLogin: true) - ..addInt("id", groupID)) + /// Perform a simple membership request + Future _simpleMembershipRequest(int groupID, String uri) async => + (await (APIRequest(uri: uri, needLogin: true)..addInt("id", groupID)) .exec()) .isOK; + /// Remove group membership + Future removeMembership(int groupID) async => + _simpleMembershipRequest(groupID, "groups/remove_membership"); + + /// Cancel membership request + Future cancelRequest(int groupID) async => + _simpleMembershipRequest(groupID, "groups/cancel_request"); + /// Turn an API entry into a group object Group _getGroupFromAPI(Map map) { return Group( diff --git a/lib/models/group.dart b/lib/models/group.dart index 5d43967..a74a301 100644 --- a/lib/models/group.dart +++ b/lib/models/group.dart @@ -24,7 +24,7 @@ class Group { final String name; final String iconURL; final int numberMembers; - final GroupMembershipLevel membershipLevel; + GroupMembershipLevel membershipLevel; final GroupVisibilityLevel visibilityLevel; final GroupRegistrationLevel registrationLevel; final GroupPostCreationLevel postCreationLevel; diff --git a/lib/ui/screens/groups_list_screen.dart b/lib/ui/screens/groups_list_screen.dart index 3980000..289b56a 100644 --- a/lib/ui/screens/groups_list_screen.dart +++ b/lib/ui/screens/groups_list_screen.dart @@ -2,6 +2,7 @@ import 'package:comunic/helpers/groups_helper.dart'; import 'package:comunic/lists/groups_list.dart'; import 'package:comunic/models/group.dart'; import 'package:comunic/ui/widgets/group_icon_widget.dart'; +import 'package:comunic/ui/widgets/group_membership_widget.dart'; import 'package:comunic/ui/widgets/safe_state.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; @@ -57,6 +58,7 @@ class _GroupsListScreenState extends SafeState { .map((g) => ListTile( leading: GroupIcon(group: g), title: Text(g.displayName), + subtitle: GroupMembershipWidget(group: g), trailing: IconButton( icon: Icon(Icons.delete), onPressed: () => _deleteGroup(g)), diff --git a/lib/ui/widgets/group_membership_widget.dart b/lib/ui/widgets/group_membership_widget.dart new file mode 100644 index 0000000..e8cb516 --- /dev/null +++ b/lib/ui/widgets/group_membership_widget.dart @@ -0,0 +1,82 @@ +import 'package:comunic/helpers/groups_helper.dart'; +import 'package:comunic/models/group.dart'; +import 'package:comunic/ui/widgets/safe_state.dart'; +import 'package:comunic/utils/intl_utils.dart'; +import 'package:comunic/utils/ui_utils.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +/// Group membership information widget +/// +/// @author Pierre Hubert + +class GroupMembershipWidget extends StatefulWidget { + final Group group; + final Function() onUpdated; + + const GroupMembershipWidget({ + @required this.group, + this.onUpdated, + }) : assert(group != null); + + @override + _GroupMembershipWidgetState createState() => _GroupMembershipWidgetState(); +} + +class _GroupMembershipWidgetState extends SafeState { + Group get group => widget.group; + + int get _id => group.id; + + GroupMembershipLevel get _level => group.membershipLevel; + + @override + Widget build(BuildContext context) { + switch (_level) { + case GroupMembershipLevel.ADMINISTRATOR: + return Text(tr("Administrator")); + + case GroupMembershipLevel.MODERATOR: + return Text(tr("Moderator")); + + case GroupMembershipLevel.MEMBER: + return Text(tr("Member")); + + case GroupMembershipLevel.INVITED: + // TODO: Handle this case. + break; + case GroupMembershipLevel.PENDING: + return _buildPendingState(); + + case GroupMembershipLevel.VISITOR: + // TODO: Handle this case. + break; + } + } + + /// Build pending state + Widget _buildPendingState() { + return RichText( + text: TextSpan(children: [ + TextSpan(text: tr("Requested") + " "), + TextSpan( + text: tr("Cancel"), + style: TextStyle(color: Colors.blue), + recognizer: TapGestureRecognizer()..onTap = () => _cancelRequest()), + ]), + ); + } + + /// Cancel group membership request + void _cancelRequest() async { + if (!await GroupsHelper().cancelRequest(_id)) + showSimpleSnack(context, tr("Could not cancel your membership request!")); + else { + // Refresh state + group.membershipLevel = GroupMembershipLevel.VISITOR; + this.setState(() {}); + + if (this.widget.onUpdated != null) this.widget.onUpdated(); + } + } +}