mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-02 00:17:41 +01:00
Gate poll, pin, and reaction UX in terminated groups.
This commit is contained in:
@@ -258,7 +258,7 @@ public final class MenuState {
|
||||
|
||||
return builder.shouldShowCopyAction(!actionMessage && !remoteDelete && hasText && !hasGift && !hasPayment && !hasPoll)
|
||||
.shouldShowDeleteAction(!hasInMemory && onlyContainsCompleteMessages(selectedParts))
|
||||
.shouldShowReactions(!conversationRecipient.isReleaseNotes())
|
||||
.shouldShowReactions(!conversationRecipient.isReleaseNotes() && !conversationRecipient.isInactiveGroup())
|
||||
.shouldShowPaymentDetails(hasPayment)
|
||||
.shouldShowPollTerminate(hasPollTerminate)
|
||||
.shouldShowPinMessage(canPinMessage)
|
||||
|
||||
@@ -3003,6 +3003,14 @@ class ConversationFragment :
|
||||
return
|
||||
}
|
||||
|
||||
if (conversationGroupViewModel.groupRecordSnapshot?.isTerminated == true) {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setMessage(R.string.conversation_activity__group_action_not_allowed_group_ended)
|
||||
.setPositiveButton(android.R.string.ok) { d, _ -> d.dismiss() }
|
||||
.show()
|
||||
return
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(getString(R.string.Poll__end_poll_title))
|
||||
.setMessage(getString(R.string.Poll__end_poll_body))
|
||||
@@ -3434,7 +3442,7 @@ class ConversationFragment :
|
||||
context ?: return
|
||||
val reactionsTag = "REACTIONS"
|
||||
if (parentFragmentManager.findFragmentByTag(reactionsTag) == null) {
|
||||
ReactionsBottomSheetDialogFragment.create(messageId, isMms).show(childFragmentManager, reactionsTag)
|
||||
ReactionsBottomSheetDialogFragment.create(messageId, isMms, conversationGroupViewModel.groupRecordSnapshot?.isTerminated == true).show(childFragmentManager, reactionsTag)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3590,6 +3598,13 @@ class ConversationFragment :
|
||||
}
|
||||
|
||||
override fun onToggleVote(poll: PollRecord, pollOption: PollOption, isChecked: Boolean) {
|
||||
if (conversationGroupViewModel.groupRecordSnapshot?.isTerminated == true) {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setMessage(R.string.conversation_activity__group_action_not_allowed_group_ended)
|
||||
.setPositiveButton(android.R.string.ok) { d, _ -> d.dismiss() }
|
||||
.show()
|
||||
return
|
||||
}
|
||||
viewModel.toggleVote(poll, pollOption, isChecked)
|
||||
}
|
||||
|
||||
|
||||
@@ -221,6 +221,13 @@ class ConversationRepository(
|
||||
if (threadRecipient.isPushV2Group && threadRecipient.groupId.getOrNull()?.isV2 != true) {
|
||||
Log.w(TAG, "Missing group id")
|
||||
emitter.tryOnError(Exception("Poll terminate failed"))
|
||||
return@create
|
||||
}
|
||||
|
||||
if (threadRecipient.isPushV2Group && !SignalDatabase.groups.isActive(threadRecipient.requireGroupId())) {
|
||||
Log.w(TAG, "Cannot end poll in terminated or inactive group")
|
||||
emitter.tryOnError(Exception("Poll terminate failed"))
|
||||
return@create
|
||||
}
|
||||
|
||||
val message = OutgoingMessage.pollTerminateMessage(
|
||||
|
||||
@@ -73,7 +73,7 @@ class ConversationGroupViewModel(
|
||||
|
||||
fun canEditGroupInfo(): Boolean {
|
||||
val memberLevel = _memberLevel.value ?: return true
|
||||
return memberLevel.groupTableMemberLevel == GroupTable.MemberLevel.ADMINISTRATOR || memberLevel.allMembersCanEditGroupInfo
|
||||
return groupRecordSnapshot?.isActive == true && (memberLevel.groupTableMemberLevel == GroupTable.MemberLevel.ADMINISTRATOR || memberLevel.allMembersCanEditGroupInfo)
|
||||
}
|
||||
|
||||
fun blockJoinRequests(recipient: Recipient): Single<GroupBlockJoinRequestResult> {
|
||||
|
||||
@@ -23,6 +23,12 @@ final class ReactionRecipientsAdapter extends RecyclerView.Adapter<ReactionRecip
|
||||
private ReactionViewPagerAdapter.EventListener listener = null;
|
||||
private List<ReactionDetails> data = Collections.emptyList();
|
||||
|
||||
private final boolean isGroupTerminated;
|
||||
|
||||
ReactionRecipientsAdapter(boolean isGroupTerminated) {
|
||||
this.isGroupTerminated = isGroupTerminated;
|
||||
}
|
||||
|
||||
void setListener(ReactionViewPagerAdapter.EventListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
@@ -42,7 +48,7 @@ final class ReactionRecipientsAdapter extends RecyclerView.Adapter<ReactionRecip
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
holder.bind(data.get(position), listener);
|
||||
holder.bind(data.get(position), listener, isGroupTerminated);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,7 +74,7 @@ final class ReactionRecipientsAdapter extends RecyclerView.Adapter<ReactionRecip
|
||||
tapToRemoveText = itemView.findViewById(R.id.reactions_bottom_view_recipient_tap_to_remove_action_text);
|
||||
}
|
||||
|
||||
void bind(@NonNull ReactionDetails reaction, ReactionViewPagerAdapter.EventListener listener) {
|
||||
void bind(@NonNull ReactionDetails reaction, ReactionViewPagerAdapter.EventListener listener, boolean isGroupTerminated) {
|
||||
this.emoji.setText(reaction.getDisplayEmoji());
|
||||
|
||||
if (reaction.getSender().isSelf()) {
|
||||
@@ -76,8 +82,13 @@ final class ReactionRecipientsAdapter extends RecyclerView.Adapter<ReactionRecip
|
||||
this.avatar.setAvatar(Glide.with(avatar), null, false);
|
||||
this.badge.setBadge(null);
|
||||
AvatarUtil.loadIconIntoImageView(reaction.getSender(), avatar);
|
||||
itemView.setOnClickListener((view) -> listener.onClick());
|
||||
tapToRemoveText.setVisibility(View.VISIBLE);
|
||||
if (isGroupTerminated) {
|
||||
itemView.setOnClickListener(null);
|
||||
tapToRemoveText.setVisibility(View.GONE);
|
||||
} else {
|
||||
itemView.setOnClickListener((view) -> listener.onClick());
|
||||
tapToRemoveText.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
this.recipient.setText(reaction.getSender().getDisplayName(itemView.getContext()));
|
||||
this.avatar.setAvatar(Glide.with(avatar), reaction.getSender(), false);
|
||||
|
||||
@@ -20,10 +20,12 @@ class ReactionViewPagerAdapter extends ListAdapter<EmojiCount, ReactionViewPager
|
||||
|
||||
private int selectedPosition = 0;
|
||||
private final EventListener listener;
|
||||
private final boolean isGroupTerminated;
|
||||
|
||||
protected ReactionViewPagerAdapter(@NonNull EventListener listener) {
|
||||
protected ReactionViewPagerAdapter(@NonNull EventListener listener, boolean isGroupTerminated) {
|
||||
super(new AlwaysChangedDiffUtil<>());
|
||||
this.listener = listener;
|
||||
this.listener = listener;
|
||||
this.isGroupTerminated = isGroupTerminated;
|
||||
}
|
||||
|
||||
@NonNull EmojiCount getEmojiCount(int position) {
|
||||
@@ -38,7 +40,7 @@ class ReactionViewPagerAdapter extends ListAdapter<EmojiCount, ReactionViewPager
|
||||
|
||||
@Override
|
||||
public @NonNull ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.reactions_bottom_sheet_dialog_fragment_recycler, parent, false));
|
||||
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.reactions_bottom_sheet_dialog_fragment_recycler, parent, false), isGroupTerminated);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,12 +70,13 @@ class ReactionViewPagerAdapter extends ListAdapter<EmojiCount, ReactionViewPager
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final RecyclerView recycler;
|
||||
private final ReactionRecipientsAdapter adapter = new ReactionRecipientsAdapter();
|
||||
private final ReactionRecipientsAdapter adapter;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
public ViewHolder(@NonNull View itemView, boolean isGroupTerminated) {
|
||||
super(itemView);
|
||||
|
||||
recycler = (RecyclerView) itemView;
|
||||
adapter = new ReactionRecipientsAdapter(isGroupTerminated);
|
||||
|
||||
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
@@ -83,8 +86,8 @@ class ReactionViewPagerAdapter extends ListAdapter<EmojiCount, ReactionViewPager
|
||||
}
|
||||
|
||||
public void onBind(@NonNull EmojiCount emojiCount, EventListener listener) {
|
||||
adapter.updateData(emojiCount.getReactions());
|
||||
adapter.setListener(listener);
|
||||
adapter.updateData(emojiCount.getReactions());
|
||||
}
|
||||
|
||||
public void setSelected(int position) {
|
||||
|
||||
@@ -33,8 +33,9 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
|
||||
public final class ReactionsBottomSheetDialogFragment extends BottomSheetDialogFragment {
|
||||
|
||||
private static final String ARGS_MESSAGE_ID = "reactions.args.message.id";
|
||||
private static final String ARGS_IS_MMS = "reactions.args.is.mms";
|
||||
private static final String ARGS_MESSAGE_ID = "reactions.args.message.id";
|
||||
private static final String ARGS_IS_MMS = "reactions.args.is.mms";
|
||||
private static final String ARGS_IS_GROUP_TERMINATED = "reactions.args.is.group.terminated";
|
||||
|
||||
private ViewPager2 recipientPagerView;
|
||||
private ReactionViewPagerAdapter recipientsAdapter;
|
||||
@@ -44,11 +45,16 @@ public final class ReactionsBottomSheetDialogFragment extends BottomSheetDialogF
|
||||
private final LifecycleDisposable disposables = new LifecycleDisposable();
|
||||
|
||||
public static DialogFragment create(long messageId, boolean isMms) {
|
||||
return create(messageId, isMms, false);
|
||||
}
|
||||
|
||||
public static DialogFragment create(long messageId, boolean isMms, boolean isGroupTerminated) {
|
||||
Bundle args = new Bundle();
|
||||
DialogFragment fragment = new ReactionsBottomSheetDialogFragment();
|
||||
|
||||
args.putLong(ARGS_MESSAGE_ID, messageId);
|
||||
args.putBoolean(ARGS_IS_MMS, isMms);
|
||||
args.putBoolean(ARGS_IS_GROUP_TERMINATED, isGroupTerminated);
|
||||
|
||||
fragment.setArguments(args);
|
||||
|
||||
@@ -144,7 +150,8 @@ public final class ReactionsBottomSheetDialogFragment extends BottomSheetDialogF
|
||||
}
|
||||
|
||||
private void setUpRecipientsRecyclerView() {
|
||||
recipientsAdapter = new ReactionViewPagerAdapter(() -> viewModel.removeReactionEmoji());
|
||||
boolean isGroupTerminated = requireArguments().getBoolean(ARGS_IS_GROUP_TERMINATED, false);
|
||||
recipientsAdapter = new ReactionViewPagerAdapter(() -> viewModel.removeReactionEmoji(), isGroupTerminated);
|
||||
|
||||
recipientPagerView.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user