Update delete for everyone functionality to match requirements.
This commit is contained in:
parent
c877aba09f
commit
1752972be9
9 changed files with 70 additions and 22 deletions
|
@ -81,6 +81,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.groups.GroupId;
|
import org.thoughtcrime.securesms.groups.GroupId;
|
||||||
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
|
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
|
||||||
import org.thoughtcrime.securesms.jobs.MultiDeviceViewOnceOpenJob;
|
import org.thoughtcrime.securesms.jobs.MultiDeviceViewOnceOpenJob;
|
||||||
|
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.longmessage.LongMessageActivity;
|
import org.thoughtcrime.securesms.longmessage.LongMessageActivity;
|
||||||
|
@ -694,19 +695,35 @@ public class ConversationFragment extends LoggingFragment {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (RemoteDeleteUtil.isValidSend(messageRecords, System.currentTimeMillis())) {
|
if (RemoteDeleteUtil.isValidSend(messageRecords, System.currentTimeMillis())) {
|
||||||
builder.setNeutralButton(R.string.ConversationFragment_delete_for_everyone, (dialog, which) -> {
|
builder.setNeutralButton(R.string.ConversationFragment_delete_for_everyone, (dialog, which) -> handleDeleteForEveryone(messageRecords));
|
||||||
SignalExecutors.BOUNDED.execute(() -> {
|
|
||||||
for (MessageRecord message : messageRecords) {
|
|
||||||
MessageSender.sendRemoteDelete(context, message.getId(), message.isMms());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
builder.setNegativeButton(android.R.string.cancel, null);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleDeleteForEveryone(Set<MessageRecord> messageRecords) {
|
||||||
|
Runnable deleteForEveryone = () -> {
|
||||||
|
SignalExecutors.BOUNDED.execute(() -> {
|
||||||
|
for (MessageRecord message : messageRecords) {
|
||||||
|
MessageSender.sendRemoteDelete(ApplicationDependencies.getApplication(), message.getId(), message.isMms());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (SignalStore.uiHints().hasConfirmedDeleteForEveryoneOnce()) {
|
||||||
|
deleteForEveryone.run();
|
||||||
|
} else {
|
||||||
|
new AlertDialog.Builder(requireActivity())
|
||||||
|
.setMessage(R.string.ConversationFragment_this_message_will_be_permanently_deleted_for_everyone)
|
||||||
|
.setPositiveButton(R.string.ConversationFragment_delete_for_everyone, (dialog, which) -> {
|
||||||
|
SignalStore.uiHints().markHasConfirmedDeleteForEveryoneOnce();
|
||||||
|
deleteForEveryone.run();
|
||||||
|
})
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleDisplayDetails(MessageRecord message) {
|
private void handleDisplayDetails(MessageRecord message) {
|
||||||
startActivity(MessageDetailsActivity.getIntentForMessageDetails(requireContext(), message, recipient.getId(), threadId));
|
startActivity(MessageDetailsActivity.getIntentForMessageDetails(requireContext(), message, recipient.getId(), threadId));
|
||||||
|
|
|
@ -36,7 +36,6 @@ import android.text.style.BackgroundColorSpan;
|
||||||
import android.text.style.CharacterStyle;
|
import android.text.style.CharacterStyle;
|
||||||
import android.text.style.ClickableSpan;
|
import android.text.style.ClickableSpan;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.text.style.RelativeSizeSpan;
|
|
||||||
import android.text.style.StyleSpan;
|
import android.text.style.StyleSpan;
|
||||||
import android.text.style.URLSpan;
|
import android.text.style.URLSpan;
|
||||||
import android.text.util.Linkify;
|
import android.text.util.Linkify;
|
||||||
|
@ -389,11 +388,11 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
||||||
/// MessageRecord Attribute Parsers
|
/// MessageRecord Attribute Parsers
|
||||||
|
|
||||||
private void setBubbleState(MessageRecord messageRecord) {
|
private void setBubbleState(MessageRecord messageRecord) {
|
||||||
if (messageRecord.isOutgoing()) {
|
if (messageRecord.isOutgoing() && !messageRecord.isRemoteDelete()) {
|
||||||
bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY);
|
bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY);
|
||||||
footer.setTextColor(ThemeUtil.getThemedColor(context, R.attr.conversation_item_sent_text_secondary_color));
|
footer.setTextColor(ThemeUtil.getThemedColor(context, R.attr.conversation_item_sent_text_secondary_color));
|
||||||
footer.setIconColor(ThemeUtil.getThemedColor(context, R.attr.conversation_item_sent_icon_color));
|
footer.setIconColor(ThemeUtil.getThemedColor(context, R.attr.conversation_item_sent_icon_color));
|
||||||
} else if (isViewOnceMessage(messageRecord) && ViewOnceUtil.isViewed((MmsMessageRecord) messageRecord)) {
|
} else if (messageRecord.isRemoteDelete() || (isViewOnceMessage(messageRecord) && ViewOnceUtil.isViewed((MmsMessageRecord) messageRecord))) {
|
||||||
bodyBubble.getBackground().setColorFilter(ThemeUtil.getThemedColor(context, R.attr.conversation_item_reveal_viewed_background_color), PorterDuff.Mode.MULTIPLY);
|
bodyBubble.getBackground().setColorFilter(ThemeUtil.getThemedColor(context, R.attr.conversation_item_reveal_viewed_background_color), PorterDuff.Mode.MULTIPLY);
|
||||||
footer.setTextColor(ThemeUtil.getThemedColor(context, R.attr.conversation_item_sent_text_secondary_color));
|
footer.setTextColor(ThemeUtil.getThemedColor(context, R.attr.conversation_item_sent_text_secondary_color));
|
||||||
footer.setIconColor(ThemeUtil.getThemedColor(context, R.attr.conversation_item_sent_icon_color));
|
footer.setIconColor(ThemeUtil.getThemedColor(context, R.attr.conversation_item_sent_icon_color));
|
||||||
|
@ -456,7 +455,8 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldDrawBodyBubbleOutline(MessageRecord messageRecord) {
|
private boolean shouldDrawBodyBubbleOutline(MessageRecord messageRecord) {
|
||||||
return !messageRecord.isOutgoing() && isViewOnceMessage(messageRecord) && ViewOnceUtil.isViewed((MmsMessageRecord) messageRecord);
|
boolean isIncomingViewedOnce = !messageRecord.isOutgoing() && isViewOnceMessage(messageRecord) && ViewOnceUtil.isViewed((MmsMessageRecord) messageRecord);
|
||||||
|
return isIncomingViewedOnce || messageRecord.isRemoteDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCaptionlessMms(MessageRecord messageRecord) {
|
private boolean isCaptionlessMms(MessageRecord messageRecord) {
|
||||||
|
@ -529,12 +529,16 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
||||||
bodyText.setMovementMethod(LongClickMovementMethod.getInstance(getContext()));
|
bodyText.setMovementMethod(LongClickMovementMethod.getInstance(getContext()));
|
||||||
|
|
||||||
if (messageRecord.isRemoteDelete()) {
|
if (messageRecord.isRemoteDelete()) {
|
||||||
String deletedMessage = context.getString(R.string.ConversationItem_this_message_was_deleted);
|
String deletedMessage = context.getString(messageRecord.isOutgoing() ? R.string.ConversationItem_you_deleted_this_message : R.string.ConversationItem_this_message_was_deleted);
|
||||||
SpannableString italics = new SpannableString(deletedMessage);
|
SpannableString italics = new SpannableString(deletedMessage);
|
||||||
italics.setSpan(new RelativeSizeSpan(0.9f), 0, deletedMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
||||||
italics.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, deletedMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
italics.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, deletedMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
italics.setSpan(new ForegroundColorSpan(ThemeUtil.getThemedColor(context, R.attr.conversation_item_delete_for_everyone_text_color)),
|
||||||
|
0,
|
||||||
|
deletedMessage.length(),
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
bodyText.setText(italics);
|
bodyText.setText(italics);
|
||||||
|
bodyText.setVisibility(View.VISIBLE);
|
||||||
} else if (isCaptionlessMms(messageRecord)) {
|
} else if (isCaptionlessMms(messageRecord)) {
|
||||||
bodyText.setVisibility(View.GONE);
|
bodyText.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -453,7 +453,7 @@ public class ConversationListItem extends RelativeLayout
|
||||||
if (extra != null && extra.isViewOnce()) {
|
if (extra != null && extra.isViewOnce()) {
|
||||||
return new SpannableString(emphasisAdded(getViewOnceDescription(context, thread.getContentType())));
|
return new SpannableString(emphasisAdded(getViewOnceDescription(context, thread.getContentType())));
|
||||||
} else if (extra != null && extra.isRemoteDelete()) {
|
} else if (extra != null && extra.isRemoteDelete()) {
|
||||||
return new SpannableString(emphasisAdded(context.getString(R.string.ThreadRecord_this_message_was_deleted)));
|
return new SpannableString(emphasisAdded(context.getString(thread.isOutgoing() ? R.string.ThreadRecord_you_deleted_this_message : R.string.ThreadRecord_this_message_was_deleted)));
|
||||||
} else {
|
} else {
|
||||||
return new SpannableString(Util.emptyIfNull(thread.getBody()));
|
return new SpannableString(Util.emptyIfNull(thread.getBody()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class UiHints extends SignalStoreValues {
|
public class UiHints extends SignalStoreValues {
|
||||||
|
|
||||||
private static final String HAS_SEEN_GROUP_SETTINGS_MENU_TOAST = "uihints.has_seen_group_settings_menu_toast";
|
private static final String HAS_SEEN_GROUP_SETTINGS_MENU_TOAST = "uihints.has_seen_group_settings_menu_toast";
|
||||||
|
private static final String HAS_CONFIRMED_DELETE_FOR_EVERYONE_ONCE = "uihints.has_confirmed_delete_for_everyone_once";
|
||||||
|
|
||||||
UiHints(@NonNull KeyValueStore store) {
|
UiHints(@NonNull KeyValueStore store) {
|
||||||
super(store);
|
super(store);
|
||||||
|
@ -22,4 +23,12 @@ public class UiHints extends SignalStoreValues {
|
||||||
public boolean hasSeenGroupSettingsMenuToast() {
|
public boolean hasSeenGroupSettingsMenuToast() {
|
||||||
return getBoolean(HAS_SEEN_GROUP_SETTINGS_MENU_TOAST, false);
|
return getBoolean(HAS_SEEN_GROUP_SETTINGS_MENU_TOAST, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void markHasConfirmedDeleteForEveryoneOnce() {
|
||||||
|
putBoolean(HAS_CONFIRMED_DELETE_FOR_EVERYONE_ONCE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasConfirmedDeleteForEveryoneOnce() {
|
||||||
|
return getBoolean(HAS_CONFIRMED_DELETE_FOR_EVERYONE_ONCE, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||||
|
@ -633,6 +635,10 @@ public class Recipient {
|
||||||
return groupId != null && groupId.isV2();
|
return groupId != null && groupId.isV2();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActiveGroup() {
|
||||||
|
return Stream.of(getParticipants()).anyMatch(Recipient::isLocalNumber);
|
||||||
|
}
|
||||||
|
|
||||||
public @NonNull List<Recipient> getParticipants() {
|
public @NonNull List<Recipient> getParticipants() {
|
||||||
return new ArrayList<>(participants);
|
return new ArrayList<>(participants);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
public final class RemoteDeleteUtil {
|
public final class RemoteDeleteUtil {
|
||||||
|
|
||||||
private static final long RECEIVE_THRESHOLD = TimeUnit.DAYS.toMillis(1);
|
private static final long RECEIVE_THRESHOLD = TimeUnit.DAYS.toMillis(1);
|
||||||
private static final long SEND_THRESHOLD = TimeUnit.MINUTES.toMillis(30);
|
private static final long SEND_THRESHOLD = TimeUnit.HOURS.toMillis(3);
|
||||||
|
|
||||||
private RemoteDeleteUtil() {}
|
private RemoteDeleteUtil() {}
|
||||||
|
|
||||||
|
@ -21,17 +21,23 @@ public final class RemoteDeleteUtil {
|
||||||
boolean isValidSender = (deleteSender.isLocalNumber() && targetMessage.isOutgoing()) ||
|
boolean isValidSender = (deleteSender.isLocalNumber() && targetMessage.isOutgoing()) ||
|
||||||
(!deleteSender.isLocalNumber() && !targetMessage.isOutgoing());
|
(!deleteSender.isLocalNumber() && !targetMessage.isOutgoing());
|
||||||
|
|
||||||
return isValidSender &&
|
return isValidSender &&
|
||||||
targetMessage.getIndividualRecipient().equals(deleteSender) &&
|
targetMessage.getIndividualRecipient().equals(deleteSender) &&
|
||||||
(deleteServerTimestamp - targetMessage.getServerTimestamp()) < RECEIVE_THRESHOLD;
|
(deleteServerTimestamp - targetMessage.getServerTimestamp()) < RECEIVE_THRESHOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isValidSend(@NonNull Collection<MessageRecord> targetMessages, long currentTime) {
|
public static boolean isValidSend(@NonNull Collection<MessageRecord> targetMessages, long currentTime) {
|
||||||
// TODO [greyson] [remote-delete] Update with server timestamp when available for outgoing messages
|
// TODO [greyson] [remote-delete] Update with server timestamp when available for outgoing messages
|
||||||
return Stream.of(targetMessages)
|
return Stream.of(targetMessages).allMatch(message -> isValidSend(message, currentTime));
|
||||||
.allMatch(message -> message.isOutgoing() &&
|
}
|
||||||
!message.isRemoteDelete() &&
|
|
||||||
!message.isPending() &&
|
private static boolean isValidSend(MessageRecord message, long currentTime) {
|
||||||
(currentTime - message.getDateSent()) < SEND_THRESHOLD);
|
return message.isOutgoing() &&
|
||||||
|
message.isPush() &&
|
||||||
|
(!message.getRecipient().isGroup() || message.getRecipient().isActiveGroup()) &&
|
||||||
|
!message.getRecipient().isLocalNumber() &&
|
||||||
|
!message.isRemoteDelete() &&
|
||||||
|
!message.isPending() &&
|
||||||
|
(currentTime - message.getDateSent()) < SEND_THRESHOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@
|
||||||
<attr name="conversation_item_sticky_date_text_color" format="color" />
|
<attr name="conversation_item_sticky_date_text_color" format="color" />
|
||||||
<attr name="conversation_item_image_outline_color" format="color" />
|
<attr name="conversation_item_image_outline_color" format="color" />
|
||||||
<attr name="conversation_item_reveal_viewed_background_color" format="color" />
|
<attr name="conversation_item_reveal_viewed_background_color" format="color" />
|
||||||
|
<attr name="conversation_item_delete_for_everyone_text_color" format="color" />
|
||||||
<attr name="conversation_scroll_to_bottom_background" format="reference" />
|
<attr name="conversation_scroll_to_bottom_background" format="reference" />
|
||||||
<attr name="conversation_scroll_to_bottom_foreground_color" format="color" />
|
<attr name="conversation_scroll_to_bottom_foreground_color" format="color" />
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,7 @@
|
||||||
<string name="ConversationItem_download_more">  Download More</string>
|
<string name="ConversationItem_download_more">  Download More</string>
|
||||||
<string name="ConversationItem_pending">  Pending</string>
|
<string name="ConversationItem_pending">  Pending</string>
|
||||||
<string name="ConversationItem_this_message_was_deleted">This message was deleted.</string>
|
<string name="ConversationItem_this_message_was_deleted">This message was deleted.</string>
|
||||||
|
<string name="ConversationItem_you_deleted_this_message">You deleted this message.</string>
|
||||||
|
|
||||||
<!-- ConversationActivity -->
|
<!-- ConversationActivity -->
|
||||||
<string name="ConversationActivity_reset_secure_session_question">Reset secure session?</string>
|
<string name="ConversationActivity_reset_secure_session_question">Reset secure session?</string>
|
||||||
|
@ -312,6 +313,7 @@
|
||||||
<string name="ConversationFragment_deleting_messages">Deleting messages…</string>
|
<string name="ConversationFragment_deleting_messages">Deleting messages…</string>
|
||||||
<string name="ConversationFragment_delete_for_me">Delete for me</string>
|
<string name="ConversationFragment_delete_for_me">Delete for me</string>
|
||||||
<string name="ConversationFragment_delete_for_everyone">Delete for everyone</string>
|
<string name="ConversationFragment_delete_for_everyone">Delete for everyone</string>
|
||||||
|
<string name="ConversationFragment_this_message_will_be_permanently_deleted_for_everyone">This message will be permanently deleted for everyone in the conversation. Members will be able to see that you deleted a message.</string>
|
||||||
<string name="ConversationFragment_quoted_message_not_found">Original message not found</string>
|
<string name="ConversationFragment_quoted_message_not_found">Original message not found</string>
|
||||||
<string name="ConversationFragment_quoted_message_no_longer_available">Original message no longer available</string>
|
<string name="ConversationFragment_quoted_message_no_longer_available">Original message no longer available</string>
|
||||||
<string name="ConversationFragment_failed_to_open_message">Failed to open message</string>
|
<string name="ConversationFragment_failed_to_open_message">Failed to open message</string>
|
||||||
|
@ -1162,6 +1164,7 @@
|
||||||
<string name="ThreadRecord_view_once_video">View-once video</string>
|
<string name="ThreadRecord_view_once_video">View-once video</string>
|
||||||
<string name="ThreadRecord_view_once_media">View-once media</string>
|
<string name="ThreadRecord_view_once_media">View-once media</string>
|
||||||
<string name="ThreadRecord_this_message_was_deleted">This message was deleted.</string>
|
<string name="ThreadRecord_this_message_was_deleted">This message was deleted.</string>
|
||||||
|
<string name="ThreadRecord_you_deleted_this_message">You deleted this message.</string>
|
||||||
<string name="ThreadRecord_s_is_on_signal">%s is on Signal!</string>
|
<string name="ThreadRecord_s_is_on_signal">%s is on Signal!</string>
|
||||||
<string name="ThreadRecord_disappearing_messages_disabled">Disappearing messages disabled</string>
|
<string name="ThreadRecord_disappearing_messages_disabled">Disappearing messages disabled</string>
|
||||||
<string name="ThreadRecord_disappearing_message_time_updated_to_s">Disappearing message time set to %s</string>
|
<string name="ThreadRecord_disappearing_message_time_updated_to_s">Disappearing message time set to %s</string>
|
||||||
|
|
|
@ -319,6 +319,7 @@
|
||||||
<item name="conversation_item_sticky_date_text_color">@color/core_grey_60</item>
|
<item name="conversation_item_sticky_date_text_color">@color/core_grey_60</item>
|
||||||
<item name="conversation_item_image_outline_color">@color/transparent_black_20</item>
|
<item name="conversation_item_image_outline_color">@color/transparent_black_20</item>
|
||||||
<item name="conversation_item_reveal_viewed_background_color">?conversation_background</item>
|
<item name="conversation_item_reveal_viewed_background_color">?conversation_background</item>
|
||||||
|
<item name="conversation_item_delete_for_everyone_text_color">@color/core_grey_90</item>
|
||||||
<item name="conversation_scroll_to_bottom_background">@drawable/scroll_to_bottom_background_light</item>
|
<item name="conversation_scroll_to_bottom_background">@drawable/scroll_to_bottom_background_light</item>
|
||||||
<item name="conversation_scroll_to_bottom_foreground_color">@color/grey_600</item>
|
<item name="conversation_scroll_to_bottom_foreground_color">@color/grey_600</item>
|
||||||
|
|
||||||
|
@ -545,6 +546,7 @@
|
||||||
<item name="conversation_item_sticky_date_text_color">@color/core_grey_25</item>
|
<item name="conversation_item_sticky_date_text_color">@color/core_grey_25</item>
|
||||||
<item name="conversation_item_image_outline_color">@color/transparent_white_20</item>
|
<item name="conversation_item_image_outline_color">@color/transparent_white_20</item>
|
||||||
<item name="conversation_item_reveal_viewed_background_color">?conversation_background</item>
|
<item name="conversation_item_reveal_viewed_background_color">?conversation_background</item>
|
||||||
|
<item name="conversation_item_delete_for_everyone_text_color">@color/core_grey_15</item>
|
||||||
|
|
||||||
<item name="safety_number_change_dialog_button_background">@color/core_grey_75</item>
|
<item name="safety_number_change_dialog_button_background">@color/core_grey_75</item>
|
||||||
<item name="safety_number_change_dialog_button_text_color">@color/core_grey_05</item>
|
<item name="safety_number_change_dialog_button_text_color">@color/core_grey_05</item>
|
||||||
|
|
Loading…
Add table
Reference in a new issue