mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 10:20:25 +01:00
Add mentions for v2 group chats.
This commit is contained in:
committed by
Greyson Parrelli
parent
0bb9c1d650
commit
b2d4c5d14b
@@ -149,7 +149,7 @@ final class GroupManagerV1 {
|
||||
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false, false, false, null, null, null, null, null);
|
||||
}
|
||||
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0, false, null, Collections.emptyList(), Collections.emptyList());
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
||||
long threadId = MessageSender.send(context, outgoingMessage, -1, false, null);
|
||||
|
||||
return new GroupActionResult(groupRecipient, threadId, newMemberCount, Collections.emptyList());
|
||||
@@ -241,6 +241,7 @@ final class GroupManagerV1 {
|
||||
false,
|
||||
null,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,6 +519,7 @@ final class GroupManagerV2 {
|
||||
false,
|
||||
null,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
|
||||
if (plainGroupChange != null && DecryptedGroupUtil.changeIsEmptyExceptForProfileKeyChanges(plainGroupChange)) {
|
||||
|
||||
@@ -240,7 +240,7 @@ public final class GroupV1MessageProcessor {
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
RecipientId recipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(GroupId.v1orThrow(group.getGroupId()));
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, storage, null, content.getTimestamp(), 0, false, null, Collections.emptyList(), Collections.emptyList());
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, storage, null, content.getTimestamp(), 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null);
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;
|
||||
import org.thoughtcrime.securesms.recipients.ui.notifications.CustomNotificationsDialogFragment;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.LifecycleCursorWrapper;
|
||||
import org.thoughtcrime.securesms.util.views.LearnMoreTextView;
|
||||
|
||||
@@ -99,6 +100,8 @@ public class ManageGroupFragment extends LoggingFragment {
|
||||
private TextView muteNotificationsUntilLabel;
|
||||
private TextView customNotificationsButton;
|
||||
private View customNotificationsRow;
|
||||
private View mentionsRow;
|
||||
private TextView mentionsValue;
|
||||
private View toggleAllMembers;
|
||||
|
||||
private final Recipient.FallbackPhotoProvider fallbackPhotoProvider = new Recipient.FallbackPhotoProvider() {
|
||||
@@ -156,6 +159,8 @@ public class ManageGroupFragment extends LoggingFragment {
|
||||
muteNotificationsRow = view.findViewById(R.id.group_mute_notifications_row);
|
||||
customNotificationsButton = view.findViewById(R.id.group_custom_notifications_button);
|
||||
customNotificationsRow = view.findViewById(R.id.group_custom_notifications_row);
|
||||
mentionsRow = view.findViewById(R.id.group_mentions_row);
|
||||
mentionsValue = view.findViewById(R.id.group_mentions_value);
|
||||
toggleAllMembers = view.findViewById(R.id.toggle_all_members);
|
||||
|
||||
groupV1Indicator.setOnLinkClickListener(v -> GroupsLearnMoreBottomSheetDialogFragment.show(requireFragmentManager()));
|
||||
@@ -317,7 +322,6 @@ public class ManageGroupFragment extends LoggingFragment {
|
||||
|
||||
customNotificationsRow.setVisibility(View.VISIBLE);
|
||||
|
||||
//noinspection CodeBlock2Expr
|
||||
if (NotificationChannels.supported()) {
|
||||
viewModel.hasCustomNotifications().observe(getViewLifecycleOwner(), hasCustomNotifications -> {
|
||||
customNotificationsButton.setText(hasCustomNotifications ? R.string.ManageGroupActivity_on
|
||||
@@ -325,6 +329,10 @@ public class ManageGroupFragment extends LoggingFragment {
|
||||
});
|
||||
}
|
||||
|
||||
mentionsRow.setVisibility(FeatureFlags.mentions() && groupId.isV2() ? View.VISIBLE : View.GONE);
|
||||
mentionsRow.setOnClickListener(v -> viewModel.handleMentionNotificationSelection());
|
||||
viewModel.getMentionSetting().observe(getViewLifecycleOwner(), value -> mentionsValue.setText(value));
|
||||
|
||||
viewModel.getSnackbarEvents().observe(getViewLifecycleOwner(), this::handleSnackbarEvent);
|
||||
viewModel.getInvitedDialogEvents().observe(getViewLifecycleOwner(), this::handleInvitedDialogEvent);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.thoughtcrime.securesms.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.groups.GroupAccessControl;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException;
|
||||
@@ -152,6 +153,13 @@ final class ManageGroupRepository {
|
||||
});
|
||||
}
|
||||
|
||||
void setMentionSetting(RecipientDatabase.MentionSetting mentionSetting) {
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
RecipientId recipientId = Recipient.externalGroup(context, groupId).getId();
|
||||
DatabaseFactory.getRecipientDatabase(context).setMentionSetting(recipientId, mentionSetting);
|
||||
});
|
||||
}
|
||||
|
||||
static final class GroupStateResult {
|
||||
|
||||
private final long threadId;
|
||||
|
||||
@@ -22,6 +22,8 @@ import org.thoughtcrime.securesms.ExpirationDialog;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader;
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase;
|
||||
import org.thoughtcrime.securesms.database.MentionUtil;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.loaders.MediaLoader;
|
||||
import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
|
||||
import org.thoughtcrime.securesms.groups.GroupAccessControl;
|
||||
@@ -31,6 +33,7 @@ import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupErrors;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry;
|
||||
import org.thoughtcrime.securesms.groups.ui.addmembers.AddMembersActivity;
|
||||
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupMentionSettingDialog;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
@@ -75,6 +78,7 @@ public class ManageGroupViewModel extends ViewModel {
|
||||
private final LiveData<Boolean> canLeaveGroup;
|
||||
private final LiveData<Boolean> canBlockGroup;
|
||||
private final LiveData<Boolean> showLegacyIndicator;
|
||||
private final LiveData<String> mentionSetting;
|
||||
|
||||
private ManageGroupViewModel(@NonNull Context context, @NonNull ManageGroupRepository manageGroupRepository) {
|
||||
this.context = context;
|
||||
@@ -114,6 +118,8 @@ public class ManageGroupViewModel extends ViewModel {
|
||||
recipient -> recipient.getNotificationChannel() != null || !NotificationChannels.supported());
|
||||
this.canLeaveGroup = liveGroup.isActive();
|
||||
this.canBlockGroup = Transformations.map(this.groupRecipient, recipient -> !recipient.isBlocked());
|
||||
this.mentionSetting = Transformations.distinctUntilChanged(Transformations.map(this.groupRecipient,
|
||||
recipient -> MentionUtil.getMentionSettingDisplayValue(context, recipient.getMentionSetting())));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@@ -207,6 +213,10 @@ public class ManageGroupViewModel extends ViewModel {
|
||||
return canLeaveGroup;
|
||||
}
|
||||
|
||||
LiveData<String> getMentionSetting() {
|
||||
return mentionSetting;
|
||||
}
|
||||
|
||||
void handleExpirationSelection() {
|
||||
manageGroupRepository.getRecipient(groupRecipient ->
|
||||
ExpirationDialog.show(context,
|
||||
@@ -250,6 +260,10 @@ public class ManageGroupViewModel extends ViewModel {
|
||||
memberListCollapseState.setValue(CollapseState.OPEN);
|
||||
}
|
||||
|
||||
void handleMentionNotificationSelection() {
|
||||
manageGroupRepository.getRecipient(r -> GroupMentionSettingDialog.show(context, r.getMentionSetting(), mentionSetting -> manageGroupRepository.setMentionSetting(mentionSetting)));
|
||||
}
|
||||
|
||||
private void onBlockAndLeaveConfirmed() {
|
||||
SimpleProgressDialog.DismissibleDialog dismissibleDialog = SimpleProgressDialog.showDelayed(context);
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package org.thoughtcrime.securesms.groups.ui.managegroup.dialogs;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CheckedTextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.util.Consumer;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.MentionSetting;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
|
||||
public final class GroupMentionSettingDialog {
|
||||
|
||||
public static void show(@NonNull Context context, @NonNull MentionSetting mentionSetting, @Nullable Consumer<MentionSetting> callback) {
|
||||
SelectionCallback selectionCallback = new SelectionCallback(mentionSetting, callback);
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.GroupMentionSettingDialog_notify_me_for_mentions)
|
||||
.setView(getView(context, mentionSetting, selectionCallback))
|
||||
.setPositiveButton(android.R.string.ok, selectionCallback)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
private static View getView(@NonNull Context context, @NonNull MentionSetting mentionSetting, @NonNull SelectionCallback selectionCallback) {
|
||||
View root = LayoutInflater.from(context).inflate(R.layout.group_mention_setting_dialog, null, false);
|
||||
CheckedTextView defaultOption = root.findViewById(R.id.group_mention_setting_default);
|
||||
CheckedTextView alwaysNotify = root.findViewById(R.id.group_mention_setting_always_notify);
|
||||
CheckedTextView dontNotify = root.findViewById(R.id.group_mention_setting_dont_notify);
|
||||
|
||||
defaultOption.setText(SignalStore.notificationSettings().isMentionNotifiesMeEnabled() ? R.string.GroupMentionSettingDialog_default_notify_me
|
||||
: R.string.GroupMentionSettingDialog_default_dont_notify_me);
|
||||
|
||||
View.OnClickListener listener = (v) -> {
|
||||
defaultOption.setChecked(defaultOption == v);
|
||||
alwaysNotify.setChecked(alwaysNotify == v);
|
||||
dontNotify.setChecked(dontNotify == v);
|
||||
|
||||
if (defaultOption.isChecked()) selectionCallback.selection = MentionSetting.GLOBAL;
|
||||
else if (alwaysNotify.isChecked()) selectionCallback.selection = MentionSetting.ALWAYS_NOTIFY;
|
||||
else if (dontNotify.isChecked()) selectionCallback.selection = MentionSetting.DO_NOT_NOTIFY;
|
||||
};
|
||||
|
||||
defaultOption.setOnClickListener(listener);
|
||||
alwaysNotify.setOnClickListener(listener);
|
||||
dontNotify.setOnClickListener(listener);
|
||||
|
||||
switch (mentionSetting) {
|
||||
case GLOBAL:
|
||||
listener.onClick(defaultOption);
|
||||
break;
|
||||
case ALWAYS_NOTIFY:
|
||||
listener.onClick(alwaysNotify);
|
||||
break;
|
||||
case DO_NOT_NOTIFY:
|
||||
listener.onClick(dontNotify);
|
||||
break;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private static class SelectionCallback implements DialogInterface.OnClickListener {
|
||||
|
||||
@NonNull private final MentionSetting previousMentionSetting;
|
||||
@NonNull private MentionSetting selection;
|
||||
@Nullable private final Consumer<MentionSetting> callback;
|
||||
|
||||
public SelectionCallback(@NonNull MentionSetting previousMentionSetting, @Nullable Consumer<MentionSetting> callback) {
|
||||
this.previousMentionSetting = previousMentionSetting;
|
||||
this.selection = previousMentionSetting;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (callback != null && selection != previousMentionSetting) {
|
||||
callback.accept(selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -232,6 +232,7 @@ public final class GroupsV2StateProcessor {
|
||||
false,
|
||||
null,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
|
||||
try {
|
||||
@@ -397,7 +398,7 @@ public final class GroupsV2StateProcessor {
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
RecipientId recipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, null, timestamp, 0, false, null, Collections.emptyList(), Collections.emptyList());
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, null, timestamp, 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user