mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-26 19:56:02 +01:00
Add block request action button to collapsed join request events.
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user