Show reminder banner to administrators for pending group join requests.

This commit is contained in:
Alan Evans 2020-10-15 13:32:50 -03:00 committed by Greyson Parrelli
parent b46589cd14
commit 837ed76f85
6 changed files with 96 additions and 4 deletions

View File

@ -0,0 +1,44 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.PlayStoreUtil;
import java.util.List;
/**
* Shown to admins when there are pending group join requests.
*/
public final class PendingGroupJoinRequestsReminder extends Reminder {
private PendingGroupJoinRequestsReminder(@Nullable CharSequence title,
@NonNull CharSequence text)
{
super(title, text);
}
public static Reminder create(@NonNull Context context, int count) {
String message = context.getResources().getQuantityString(R.plurals.PendingGroupJoinRequestsReminder_d_pending_member_requests, count, count);
Reminder reminder = new PendingGroupJoinRequestsReminder(null, message);
reminder.addAction(new Action(context.getString(R.string.PendingGroupJoinRequestsReminder_view), R.id.reminder_action_review_join_requests));
return reminder;
}
@Override
public boolean isDismissable() {
return true;
}
@Override
public @NonNull Importance getImportance() {
return Importance.NORMAL;
}
}

View File

@ -74,7 +74,7 @@ public abstract class Reminder {
NORMAL, ERROR, TERMINAL
}
public final class Action {
public static final class Action {
private final CharSequence title;
private final int actionId;

View File

@ -115,6 +115,7 @@ import org.thoughtcrime.securesms.components.identity.UnverifiedBannerView;
import org.thoughtcrime.securesms.components.location.SignalPlace;
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
import org.thoughtcrime.securesms.components.reminder.PendingGroupJoinRequestsReminder;
import org.thoughtcrime.securesms.components.reminder.Reminder;
import org.thoughtcrime.securesms.components.reminder.ReminderView;
import org.thoughtcrime.securesms.components.reminder.ServiceOutageReminder;
@ -162,6 +163,7 @@ import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.groups.ui.GroupChangeResult;
import org.thoughtcrime.securesms.groups.ui.GroupErrors;
import org.thoughtcrime.securesms.groups.ui.LeaveGroupDialog;
import org.thoughtcrime.securesms.groups.ui.invitesandrequests.ManagePendingAndRequestingMembersActivity;
import org.thoughtcrime.securesms.groups.ui.managegroup.ManageGroupActivity;
import org.thoughtcrime.securesms.insights.InsightsLauncher;
import org.thoughtcrime.securesms.invites.InviteReminderModel;
@ -444,6 +446,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
initializeGroupViewModel();
initializeMentionsViewModel();
initializeEnabledCheck();
initializePendingRequestsBanner();
initializeSecurity(recipient.get().isRegistered(), isDefaultSms).addListener(new AssertedSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
@ -1525,6 +1528,11 @@ public class ConversationActivity extends PassphraseRequiredActivity
});
}
private void initializePendingRequestsBanner() {
groupViewModel.getActionableRequestingMembers()
.observe(this, actionablePendingGroupRequests -> updateReminders());
}
private ListenableFuture<Boolean> initializeDraftFromDatabase() {
SettableFuture<Boolean> future = new SettableFuture<>();
@ -1678,7 +1686,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
}
protected void updateReminders() {
Optional<Reminder> inviteReminder = inviteReminderModel.getReminder();
Optional<Reminder> inviteReminder = inviteReminderModel.getReminder();
Integer actionableRequestingMembers = groupViewModel.getActionableRequestingMembers().getValue();
if (UnauthorizedReminder.isEligible(this)) {
reminderView.get().showReminder(new UnauthorizedReminder(this));
@ -1696,6 +1705,13 @@ public class ConversationActivity extends PassphraseRequiredActivity
reminderView.get().setOnActionClickListener(this::handleReminderAction);
reminderView.get().setOnDismissListener(() -> inviteReminderModel.dismissReminder());
reminderView.get().showReminder(inviteReminder.get());
} else if (actionableRequestingMembers != null && actionableRequestingMembers > 0 && FeatureFlags.groupsV2manageGroupLinks()) {
reminderView.get().showReminder(PendingGroupJoinRequestsReminder.create(this, actionableRequestingMembers));
reminderView.get().setOnActionClickListener(id -> {
if (id == R.id.reminder_action_review_join_requests) {
startActivity(ManagePendingAndRequestingMembersActivity.newIntent(this, getRecipient().getGroupId().get().requireV2()));
}
});
} else if (reminderView.resolved()) {
reminderView.get().hide();
}

View File

@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.AsynchronousCallback;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
@ -30,20 +31,29 @@ final class ConversationGroupViewModel extends ViewModel {
private final MutableLiveData<Recipient> liveRecipient;
private final LiveData<GroupActiveState> groupActiveState;
private final LiveData<GroupDatabase.MemberLevel> selfMembershipLevel;
private final LiveData<Integer> actionableRequestingMembers;
private ConversationGroupViewModel() {
this.liveRecipient = new MutableLiveData<>();
LiveData<GroupRecord> groupRecord = LiveDataUtil.mapAsync(liveRecipient, ConversationGroupViewModel::getGroupRecordForRecipient);
this.groupActiveState = Transformations.distinctUntilChanged(Transformations.map(groupRecord, ConversationGroupViewModel::mapToGroupActiveState));
this.selfMembershipLevel = Transformations.distinctUntilChanged(Transformations.map(groupRecord, ConversationGroupViewModel::mapToSelfMembershipLevel));
this.groupActiveState = Transformations.distinctUntilChanged(Transformations.map(groupRecord, ConversationGroupViewModel::mapToGroupActiveState));
this.selfMembershipLevel = Transformations.distinctUntilChanged(Transformations.map(groupRecord, ConversationGroupViewModel::mapToSelfMembershipLevel));
this.actionableRequestingMembers = Transformations.distinctUntilChanged(Transformations.map(groupRecord, ConversationGroupViewModel::mapToActionableRequestingMemberCount));
}
void onRecipientChange(Recipient recipient) {
liveRecipient.setValue(recipient);
}
/**
* The number of pending group join requests that can be actioned by this client.
*/
LiveData<Integer> getActionableRequestingMembers() {
return actionableRequestingMembers;
}
LiveData<GroupActiveState> getGroupActiveState() {
return groupActiveState;
}
@ -62,6 +72,20 @@ final class ConversationGroupViewModel extends ViewModel {
}
}
private static int mapToActionableRequestingMemberCount(@Nullable GroupRecord record) {
if (record != null &&
FeatureFlags.groupsV2manageGroupLinks() &&
record.isV2Group() &&
record.memberLevel(Recipient.self()) == GroupDatabase.MemberLevel.ADMINISTRATOR)
{
return record.requireV2GroupProperties()
.getDecryptedGroup()
.getRequestingMembersCount();
} else {
return 0;
}
}
private static GroupActiveState mapToGroupActiveState(@Nullable GroupRecord record) {
if (record == null) {
return null;

View File

@ -7,4 +7,5 @@
<item name="reminder_action_view_insights" type="id" />
<item name="reminder_action_invite" type="id" />
<item name="reminder_action_update_now" type="id" />
<item name="reminder_action_review_join_requests" type="id" />
</resources>

View File

@ -435,6 +435,13 @@
<string name="ExpiredBuildReminder_this_version_of_signal_has_expired">This version of Signal has expired. Update now to send and receive messages.</string>
<string name="ExpiredBuildReminder_update_now">Update now</string>
<!-- PendingGroupJoinRequestsReminder -->
<plurals name="PendingGroupJoinRequestsReminder_d_pending_member_requests">
<item quantity="one">%d pending member request.</item>
<item quantity="many">%d pending member requests.</item>
</plurals>
<string name="PendingGroupJoinRequestsReminder_view">View</string>
<!-- ShareActivity -->
<string name="ShareActivity_share_with">Share with</string>
<string name="ShareActivity_multiple_attachments_are_only_supported">Multiple attachments are only supported for images and videos</string>