Add block request action button to collapsed join request events.

This commit is contained in:
Cody Henthorne
2022-03-15 20:41:48 -04:00
parent 130d5a8945
commit d3049a3433
11 changed files with 188 additions and 5 deletions

View File

@@ -115,10 +115,12 @@ import org.thoughtcrime.securesms.giph.mp4.GiphyMp4ProjectionPlayerHolder;
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4ProjectionRecycler;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange;
import org.thoughtcrime.securesms.groups.ui.GroupErrors;
import org.thoughtcrime.securesms.groups.ui.invitesandrequests.invite.GroupLinkInviteFriendsBottomSheetDialogFragment;
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupDescriptionDialog;
import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationInfoBottomSheetDialogFragment;
import org.thoughtcrime.securesms.groups.v2.GroupDescriptionUtil;
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository;
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
import org.thoughtcrime.securesms.jobs.MultiDeviceViewOnceOpenJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
@@ -151,6 +153,7 @@ import org.thoughtcrime.securesms.stickers.StickerPackPreviewActivity;
import org.thoughtcrime.securesms.util.CachedInflater;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.HtmlUtil;
import org.thoughtcrime.securesms.util.LifecycleDisposable;
import org.thoughtcrime.securesms.util.MessageRecordUtil;
import org.thoughtcrime.securesms.util.RemoteDeleteUtil;
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
@@ -236,6 +239,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
private Colorizer colorizer;
private ConversationUpdateTick conversationUpdateTick;
private MultiselectItemDecoration multiselectItemDecoration;
private LifecycleDisposable lifecycleDisposable;
public static void prepare(@NonNull Context context) {
FrameLayout parent = new FrameLayout(context);
@@ -322,6 +326,9 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
giphyMp4ProjectionRecycler = initializeGiphyMp4();
lifecycleDisposable = new LifecycleDisposable();
lifecycleDisposable.bindTo(getViewLifecycleOwner());
this.groupViewModel = new ViewModelProvider(getParentFragment(), new ConversationGroupViewModel.Factory()).get(ConversationGroupViewModel.class);
this.messageCountsViewModel = new ViewModelProvider(getParentFragment()).get(MessageCountsViewModel.class);
this.conversationViewModel = new ViewModelProvider(getParentFragment(), new ConversationViewModel.Factory()).get(ConversationViewModel.class);
@@ -1862,6 +1869,15 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
startActivity(AppSettingsActivity.subscriptions(requireContext()));
}
}
@Override
public void onBlockJoinRequest(@NonNull Recipient recipient) {
new MaterialAlertDialogBuilder(requireContext()).setTitle(R.string.ConversationFragment__block_request)
.setMessage(getString(R.string.ConversationFragment__s_will_not_be_able_to_join_or_request_to_join_this_group_via_the_group_link, recipient.getDisplayName(requireContext())))
.setNegativeButton(R.string.ConversationFragment__cancel, null)
.setPositiveButton(R.string.ConversationFragment__block_request_button, (d, w) -> handleBlockJoinRequest(recipient))
.show();
}
}
public void refreshList() {
@@ -1892,6 +1908,18 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
actionMode = ((AppCompatActivity)getActivity()).startSupportActionMode(actionModeCallback);
}
private void handleBlockJoinRequest(@NonNull Recipient recipient) {
lifecycleDisposable.add(
groupViewModel.blockJoinRequests(ConversationFragment.this.recipient.get(), recipient)
.subscribe(result -> {
if (result instanceof GroupManagementRepository.GroupManagementResult.Failure) {
int failureReason = GroupErrors.getUserDisplayMessage(((GroupManagementRepository.GroupManagementResult.Failure) result).getReason());
Toast.makeText(requireContext(), failureReason, Toast.LENGTH_SHORT).show();
}
})
);
}
private final class CheckExpirationDataObserver extends RecyclerView.AdapterDataObserver {
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {

View File

@@ -26,6 +26,8 @@ import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil;
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.groups.ui.invitesandrequests.invite.GroupLinkInviteFriendsBottomSheetDialogFragment;
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository;
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository.GroupManagementResult;
import org.thoughtcrime.securesms.profiles.spoofing.ReviewRecipient;
import org.thoughtcrime.securesms.profiles.spoofing.ReviewUtil;
import org.thoughtcrime.securesms.recipients.Recipient;
@@ -38,6 +40,9 @@ import java.io.IOException;
import java.util.Collections;
import java.util.List;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Single;
final class ConversationGroupViewModel extends ViewModel {
private final MutableLiveData<Recipient> liveRecipient;
@@ -46,11 +51,13 @@ final class ConversationGroupViewModel extends ViewModel {
private final LiveData<Integer> actionableRequestingMembers;
private final LiveData<ReviewState> reviewState;
private final LiveData<List<RecipientId>> gv1MigrationSuggestions;
private final GroupManagementRepository groupManagementRepository;
private boolean firstTimeInviteFriendsTriggered;
private ConversationGroupViewModel() {
this.liveRecipient = new MutableLiveData<>();
this.liveRecipient = new MutableLiveData<>();
this.groupManagementRepository = new GroupManagementRepository();
LiveData<GroupRecord> groupRecord = LiveDataUtil.mapAsync(liveRecipient, ConversationGroupViewModel::getGroupRecordForRecipient);
LiveData<List<Recipient>> duplicates = LiveDataUtil.mapAsync(groupRecord, record -> {
@@ -213,6 +220,11 @@ final class ConversationGroupViewModel extends ViewModel {
GroupLinkInviteFriendsBottomSheetDialogFragment.show(supportFragmentManager, groupId);
}
public Single<GroupManagementResult> blockJoinRequests(@NonNull Recipient groupRecipient, @NonNull Recipient recipient) {
return groupManagementRepository.blockJoinRequests(groupRecipient.requireGroupId().requireV2(), recipient)
.observeOn(AndroidSchedulers.mainThread());
}
static final class ReviewState {
private static final ReviewState EMPTY = new ReviewState(null, Recipient.UNKNOWN, 0);

View File

@@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.database.model.InMemoryMessageRecord;
import org.thoughtcrime.securesms.database.model.LiveUpdateMessage;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.UpdateDescription;
import org.thoughtcrime.securesms.groups.LiveGroup;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
@@ -85,6 +86,7 @@ public final class ConversationUpdateItem extends FrameLayout
private final PresentOnChange presentOnChange = new PresentOnChange();
private final RecipientObserverManager senderObserver = new RecipientObserverManager(presentOnChange);
private final RecipientObserverManager groupObserver = new RecipientObserverManager(presentOnChange);
private final GroupDataManager groupData = new GroupDataManager(presentOnChange);
public ConversationUpdateItem(Context context) {
super(context);
@@ -153,8 +155,9 @@ public final class ConversationUpdateItem extends FrameLayout
senderObserver.observe(lifecycleOwner, messageRecord.getIndividualRecipient());
if (conversationRecipient.isActiveGroup() && conversationMessage.getMessageRecord().isGroupCall()) {
if (conversationRecipient.isActiveGroup() && (conversationMessage.getMessageRecord().isGroupCall() || conversationMessage.getMessageRecord().isCollapsedGroupV2JoinUpdate())) {
groupObserver.observe(lifecycleOwner, conversationRecipient);
groupData.observe(lifecycleOwner, conversationRecipient);
} else {
groupObserver.observe(lifecycleOwner, null);
}
@@ -269,6 +272,47 @@ public final class ConversationUpdateItem extends FrameLayout
}
}
static final class GroupDataManager {
private final Observer<Recipient> recipientObserver;
private final Observer<Boolean> isSelfAdminSetter;
private LiveGroup liveGroup;
private LiveData<Boolean> liveIsSelfAdmin;
private boolean isSelfAdmin;
private Recipient conversationRecipient;
GroupDataManager(@NonNull Observer<Recipient> observer) {
this.recipientObserver = observer;
this.isSelfAdminSetter = isSelfAdmin -> {
this.isSelfAdmin = isSelfAdmin;
recipientObserver.onChanged(conversationRecipient);
};
}
public void observe(@NonNull LifecycleOwner lifecycleOwner, @Nullable Recipient recipient) {
if (liveGroup != null) {
liveIsSelfAdmin.removeObserver(isSelfAdminSetter);
liveIsSelfAdmin = null;
}
if (recipient != null) {
conversationRecipient = recipient;
liveGroup = new LiveGroup(recipient.requireGroupId());
liveIsSelfAdmin = liveGroup.isSelfAdmin();
liveIsSelfAdmin.observe(lifecycleOwner, isSelfAdminSetter);
} else {
conversationRecipient = null;
liveGroup = null;
}
}
public boolean isSelfAdmin() {
return isSelfAdmin;
}
}
@Override
public @NonNull MultiselectPart getMultiselectPartForLatestTouch() {
return conversationMessage.getMultiselectCollection().asSingle().getSinglePart();
@@ -427,6 +471,14 @@ public final class ConversationUpdateItem extends FrameLayout
eventListener.onChangeNumberUpdateContact(conversationMessage.getMessageRecord().getIndividualRecipient());
}
});
} else if (conversationMessage.getMessageRecord().isCollapsedGroupV2JoinUpdate() && groupData.isSelfAdmin()) {
actionButton.setText(R.string.ConversationUpdateItem_block_request);
actionButton.setVisibility(VISIBLE);
actionButton.setOnClickListener(v -> {
if (batchSelected.isEmpty() && eventListener != null) {
eventListener.onBlockJoinRequest(conversationMessage.getMessageRecord().getIndividualRecipient());
}
});
} else {
actionButton.setVisibility(GONE);
actionButton.setOnClickListener(null);