diff --git a/lib/helpers/groups_helper.dart b/lib/helpers/groups_helper.dart index 58ece46..26b9706 100644 --- a/lib/helpers/groups_helper.dart +++ b/lib/helpers/groups_helper.dart @@ -73,7 +73,7 @@ class GroupsHelper { // Check which groups information to download final toDownload = Set(); groups.forEach((groupID) { - if (_groupsListCache.containsKey(groupID)) + if (!force && _groupsListCache.containsKey(groupID)) list[groupID] = _groupsListCache[groupID]; else toDownload.add(groupID); @@ -101,8 +101,11 @@ class GroupsHelper { .toSet(); /// Perform a simple membership request - Future _simpleMembershipRequest(int groupID, String uri) async => - (await (APIRequest(uri: uri, needLogin: true)..addInt("id", groupID)) + Future _simpleMembershipRequest(int groupID, String uri, + {Map args}) async => + (await (APIRequest(uri: uri, needLogin: true) + ..addInt("id", groupID) + ..addArgs(args == null ? Map() : args)) .exec()) .isOK; @@ -118,6 +121,12 @@ class GroupsHelper { Future sendRequest(int groupID) async => _simpleMembershipRequest(groupID, "groups/send_request"); + /// Respond to a group membership invitation + Future respondInvitation(int groupID, bool accept) async => + _simpleMembershipRequest(groupID, "groups/respond_invitation", args: { + "accept": accept ? "true" : "false", + }); + /// Turn an API entry into a group object Group _getGroupFromAPI(Map map) { return Group( diff --git a/lib/models/api_request.dart b/lib/models/api_request.dart index 0cc9c15..f268c3d 100644 --- a/lib/models/api_request.dart +++ b/lib/models/api_request.dart @@ -31,6 +31,8 @@ class APIRequest { void addFile(String name, File file) => files[name] = file; + void addArgs(Map newArgs) => args.addAll(newArgs); + /// Execute the request Future exec() async => APIHelper().exec(this); diff --git a/lib/ui/widgets/group_membership_widget.dart b/lib/ui/widgets/group_membership_widget.dart index 4daf1da..0f69569 100644 --- a/lib/ui/widgets/group_membership_widget.dart +++ b/lib/ui/widgets/group_membership_widget.dart @@ -43,8 +43,8 @@ class _GroupMembershipWidgetState extends SafeState { return Text(tr("Member")); case GroupMembershipLevel.INVITED: - // TODO: Handle this case. - break; + return _buildInvitedState(); + case GroupMembershipLevel.PENDING: return _buildPendingState(); @@ -53,6 +53,49 @@ class _GroupMembershipWidgetState extends SafeState { } } + /// Build invited state + Widget _buildInvitedState() { + return RichText( + text: TextSpan(children: [ + WidgetSpan( + child: Icon(Icons.info_outline, size: 12), + alignment: PlaceholderAlignment.middle), + TextSpan(text: " " + tr("Invited") + " "), + TextSpan( + text: tr("Accept"), + style: TextStyle(color: Colors.green), + recognizer: TapGestureRecognizer() + ..onTap = () => _respondInvitation(true)), + TextSpan(text: " "), + TextSpan( + text: tr("Reject"), + style: TextStyle(color: Colors.red), + recognizer: TapGestureRecognizer() + ..onTap = () => _respondInvitation(false)), + ]), + ); + } + + /// Respond to an invitation + void _respondInvitation(bool accept) async { + if (!accept && + !await showConfirmDialog( + context: context, + message: tr("Do you really want to reject this invitation?"))) + return; + + if (!await GroupsHelper().respondInvitation(_id, accept)) + showSimpleSnack(context, tr("Could not respond to your invitation!")); + else { + // Refresh state + group.membershipLevel = + accept ? GroupMembershipLevel.MEMBER : GroupMembershipLevel.VISITOR; + this.setState(() {}); + + if (this.widget.onUpdated != null) this.widget.onUpdated(); + } + } + /// Build pending state Widget _buildPendingState() { return RichText(