Update Mention UI/UX to match latest designs.

master
Cody Henthorne 2020-08-13 09:54:33 -04:00 committed by Greyson Parrelli
parent d63e5165eb
commit 724f3e872b
30 changed files with 353 additions and 201 deletions

View File

@ -4,12 +4,6 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.widget.TextViewCompat;
import androidx.appcompat.widget.AppCompatTextView;
import android.text.Annotation;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@ -17,12 +11,18 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.content.ContextCompat;
import androidx.core.widget.TextViewCompat;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable;
import org.thoughtcrime.securesms.components.emoji.parsing.EmojiParser;
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
import org.thoughtcrime.securesms.components.mention.MentionRendererDelegate;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
@ -242,4 +242,10 @@ public class EmojiTextView extends AppCompatTextView {
this.originalFontSize = TypedValue.applyDimension(unit, size, getResources().getDisplayMetrics());
super.setTextSize(unit, size);
}
public void setMentionBackgroundTint(@ColorInt int mentionBackgroundTint) {
if (renderMentions) {
mentionRendererDelegate.setTint(mentionBackgroundTint);
}
}
}

View File

@ -9,10 +9,10 @@ import android.text.Spanned;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Px;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ContextUtil;
import org.thoughtcrime.securesms.util.DrawableUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
@ -27,25 +27,28 @@ public class MentionRendererDelegate {
private final MentionRenderer single;
private final MentionRenderer multi;
private final int horizontalPadding;
private final Drawable drawable;
private final Drawable drawableLeft;
private final Drawable drawableMid;
private final Drawable drawableEnd;
public MentionRendererDelegate(@NonNull Context context, @ColorInt int tint) {
this.horizontalPadding = ViewUtil.dpToPx(2);
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.mention_text_bg);
Drawable drawableLeft = ContextCompat.getDrawable(context, R.drawable.mention_text_bg_left);
Drawable drawableMid = ContextCompat.getDrawable(context, R.drawable.mention_text_bg_mid);
Drawable drawableEnd = ContextCompat.getDrawable(context, R.drawable.mention_text_bg_right);
drawable = DrawableUtil.tint(ContextUtil.requireDrawable(context, R.drawable.mention_text_bg), tint);
drawableLeft = DrawableUtil.tint(ContextUtil.requireDrawable(context, R.drawable.mention_text_bg_left), tint);
drawableMid = DrawableUtil.tint(ContextUtil.requireDrawable(context, R.drawable.mention_text_bg_mid), tint);
drawableEnd = DrawableUtil.tint(ContextUtil.requireDrawable(context, R.drawable.mention_text_bg_right), tint);
//noinspection ConstantConditions
single = new MentionRenderer.SingleLineMentionRenderer(horizontalPadding,
0,
DrawableUtil.tint(drawable, tint));
//noinspection ConstantConditions
drawable);
multi = new MentionRenderer.MultiLineMentionRenderer(horizontalPadding,
0,
DrawableUtil.tint(drawableLeft, tint),
DrawableUtil.tint(drawableMid, tint),
DrawableUtil.tint(drawableEnd, tint));
drawableLeft,
drawableMid,
drawableEnd);
}
public void draw(@NonNull Canvas canvas, @NonNull Spanned text, @NonNull Layout layout) {
@ -65,4 +68,11 @@ public class MentionRendererDelegate {
}
}
}
public void setTint(@ColorInt int tint) {
DrawableCompat.setTint(drawable, tint);
DrawableCompat.setTint(drawableLeft, tint);
DrawableCompat.setTint(drawableMid, tint);
DrawableCompat.setTint(drawableEnd, tint);
}
}

View File

@ -52,6 +52,7 @@ import androidx.annotation.DimenRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import com.annimon.stream.Stream;
@ -63,6 +64,7 @@ import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AudioView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.BorderlessImageView;
import org.thoughtcrime.securesms.components.ConversationItemFooter;
import org.thoughtcrime.securesms.components.ConversationItemThumbnail;
import org.thoughtcrime.securesms.components.DocumentView;
@ -70,7 +72,6 @@ import org.thoughtcrime.securesms.components.LinkPreviewView;
import org.thoughtcrime.securesms.components.Outliner;
import org.thoughtcrime.securesms.components.QuoteView;
import org.thoughtcrime.securesms.components.SharedContactView;
import org.thoughtcrime.securesms.components.BorderlessImageView;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
import org.thoughtcrime.securesms.contactshare.Contact;
@ -113,6 +114,7 @@ import org.thoughtcrime.securesms.util.LongClickMovementMethod;
import org.thoughtcrime.securesms.util.SearchUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.VibrateUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.util.guava.Optional;
@ -123,6 +125,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import static org.thoughtcrime.securesms.util.ThemeUtil.isDarkTheme;
/**
* A view that displays an individual conversation item within a conversation
* thread. Used by ComposeMessageActivity's ListActivity via a ConversationAdapter.
@ -564,6 +568,12 @@ public class ConversationItem extends LinearLayout implements BindableConversati
bodyText.setOverflowText(null);
}
if (messageRecord.isOutgoing()) {
bodyText.setMentionBackgroundTint(ContextCompat.getColor(context, isDarkTheme(context) ? R.color.core_grey_60 : R.color.core_grey_20));
} else {
bodyText.setMentionBackgroundTint(ContextCompat.getColor(context, R.color.transparent_black_40));
}
bodyText.setText(styledText);
bodyText.setVisibility(View.VISIBLE);
}
@ -1423,6 +1433,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati
@Override
public void onClick(@NonNull View widget) {
if (eventListener != null && !Recipient.resolved(mentionedRecipientId).isLocalNumber()) {
VibrateUtil.vibrateTick(context);
eventListener.onGroupMemberClicked(mentionedRecipientId, conversationRecipient.get().requireGroupId());
}
}

View File

@ -46,6 +46,6 @@ public class MentionViewHolder extends MappingViewHolder<MentionViewState> {
}
public static MappingAdapter.Factory<MentionViewState> createFactory(@Nullable MentionEventsListener mentionEventsListener) {
return new MappingAdapter.LayoutFactory<>(view -> new MentionViewHolder(view, mentionEventsListener), R.layout.mentions_recipient_list_item);
return new MappingAdapter.LayoutFactory<>(view -> new MentionViewHolder(view, mentionEventsListener), R.layout.mentions_picker_recipient_list_item);
}
}

View File

@ -1,12 +1,25 @@
package org.thoughtcrime.securesms.conversation.ui.mentions;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.conversation.ui.mentions.MentionViewHolder.MentionEventsListener;
import org.thoughtcrime.securesms.util.MappingAdapter;
import org.thoughtcrime.securesms.util.MappingModel;
import java.util.List;
public class MentionsPickerAdapter extends MappingAdapter {
public MentionsPickerAdapter(@Nullable MentionEventsListener mentionEventsListener) {
private final Runnable currentListChangedListener;
public MentionsPickerAdapter(@Nullable MentionEventsListener mentionEventsListener, @NonNull Runnable currentListChangedListener) {
this.currentListChangedListener = currentListChangedListener;
registerFactory(MentionViewState.class, MentionViewHolder.createFactory(mentionEventsListener));
}
@Override
public void onCurrentListChanged(@NonNull List<MappingModel<?>> previousList, @NonNull List<MappingModel<?>> currentList) {
super.onCurrentListChanged(previousList, currentList);
currentListChangedListener.run();
}
}

View File

@ -17,25 +17,30 @@ import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.MappingModel;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.VibrateUtil;
import java.util.Collections;
import java.util.List;
public class MentionsPickerFragment extends LoggingFragment {
private MentionsPickerAdapter adapter;
private RecyclerView list;
private View topDivider;
private View bottomDivider;
private BottomSheetBehavior<View> behavior;
private MentionsPickerViewModel viewModel;
private int defaultPeekHeight;
@Override
public @Nullable View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.mentions_picker_fragment, container, false);
list = view.findViewById(R.id.mentions_picker_list);
behavior = BottomSheetBehavior.from(view.findViewById(R.id.mentions_picker_bottom_sheet));
defaultPeekHeight = view.getContext().getResources().getDimensionPixelSize(R.dimen.mentions_picker_peek_height);
list = view.findViewById(R.id.mentions_picker_list);
topDivider = view.findViewById(R.id.mentions_picker_top_divider);
bottomDivider = view.findViewById(R.id.mentions_picker_bottom_divider);
behavior = BottomSheetBehavior.from(view.findViewById(R.id.mentions_picker_bottom_sheet));
initializeBehavior();
return view;
}
@ -43,24 +48,43 @@ public class MentionsPickerFragment extends LoggingFragment {
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
viewModel = ViewModelProviders.of(requireActivity()).get(MentionsPickerViewModel.class);
initializeList();
viewModel = ViewModelProviders.of(requireActivity()).get(MentionsPickerViewModel.class);
viewModel.getMentionList().observe(getViewLifecycleOwner(), this::updateList);
viewModel.isShowing().observe(getViewLifecycleOwner(), isShowing -> {
if (isShowing) {
VibrateUtil.vibrateTick(requireContext());
}
});
}
private void initializeBehavior() {
behavior.setState(BottomSheetBehavior.STATE_HIDDEN);
behavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
adapter.submitList(Collections.emptyList());
} else {
showDividers(true);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
showDividers(Float.isNaN(slideOffset) || slideOffset > -0.8f);
}
});
}
private void initializeList() {
adapter = new MentionsPickerAdapter(this::handleMentionClicked);
adapter = new MentionsPickerAdapter(this::handleMentionClicked, () -> updateBottomSheetBehavior(adapter.getItemCount()));
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(requireContext()) {
@Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
updateBottomSheetBehavior(adapter.getItemCount());
}
};
list.setLayoutManager(layoutManager);
list.setLayoutManager(new LinearLayoutManager(requireContext()));
list.setAdapter(adapter);
list.setItemAnimator(null);
}
@ -70,24 +94,31 @@ public class MentionsPickerFragment extends LoggingFragment {
}
private void updateList(@NonNull List<MappingModel<?>> mappingModels) {
adapter.submitList(mappingModels);
if (mappingModels.isEmpty()) {
if (adapter.getItemCount() > 0 && mappingModels.isEmpty()) {
updateBottomSheetBehavior(0);
} else {
adapter.submitList(mappingModels);
}
list.scrollToPosition(0);
}
private void updateBottomSheetBehavior(int count) {
if (count > 0) {
if (behavior.getPeekHeight() == 0) {
behavior.setPeekHeight(defaultPeekHeight, true);
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else {
list.scrollToPosition(0);
}
} else {
boolean isShowing = count > 0;
viewModel.setIsShowing(isShowing);
if (isShowing) {
list.scrollToPosition(0);
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
behavior.setPeekHeight(0);
list.post(() -> behavior.setHideable(false));
showDividers(true);
} else {
behavior.setHideable(true);
behavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
}
private void showDividers(boolean showDividers) {
topDivider.setVisibility(showDividers ? View.VISIBLE : View.GONE);
bottomDivider.setVisibility(showDividers ? View.VISIBLE : View.GONE);
}
}

View File

@ -29,11 +29,13 @@ public class MentionsPickerViewModel extends ViewModel {
private final LiveData<List<MappingModel<?>>> mentionList;
private final MutableLiveData<LiveGroup> group;
private final MutableLiveData<Query> liveQuery;
private final MutableLiveData<Boolean> isShowing;
MentionsPickerViewModel(@NonNull MentionsPickerRepository mentionsPickerRepository) {
group = new MutableLiveData<>();
liveQuery = new MutableLiveData<>(Query.NONE);
selectedRecipient = new SingleLiveEvent<>();
isShowing = new MutableLiveData<>(false);
LiveData<List<FullMember>> fullMembers = Transformations.distinctUntilChanged(Transformations.switchMap(group, LiveGroup::getFullMembers));
LiveData<Query> query = Transformations.distinctUntilChanged(liveQuery);
@ -50,10 +52,21 @@ public class MentionsPickerViewModel extends ViewModel {
selectedRecipient.setValue(recipient);
}
void setIsShowing(boolean isShowing) {
if (Objects.equals(this.isShowing.getValue(), isShowing)) {
return;
}
this.isShowing.setValue(isShowing);
}
public @NonNull LiveData<Recipient> getSelectedRecipient() {
return selectedRecipient;
}
public @NonNull LiveData<Boolean> isShowing() {
return isShowing;
}
public void onQueryChange(@Nullable String query) {
liveQuery.setValue(query == null ? Query.NONE : new Query(query));
}

View File

@ -56,7 +56,7 @@ public final class MentionUtil {
@WorkerThread
public static @NonNull UpdatedBodyAndMentions updateBodyAndMentionsWithDisplayNames(@NonNull Context context, @NonNull CharSequence body, @NonNull List<Mention> mentions) {
return update(body, mentions, m -> MENTION_STARTER + Recipient.resolved(m.getRecipientId()).getDisplayName(context));
return update(body, mentions, m -> MENTION_STARTER + Recipient.resolved(m.getRecipientId()).getMentionDisplayName(context));
}
public static @NonNull UpdatedBodyAndMentions updateBodyAndMentionsWithPlaceholders(@Nullable CharSequence body, @NonNull List<Mention> mentions) {
@ -131,9 +131,6 @@ public final class MentionUtil {
public static @NonNull String getMentionSettingDisplayValue(@NonNull Context context, @NonNull MentionSetting mentionSetting) {
switch (mentionSetting) {
case GLOBAL:
return context.getString(SignalStore.notificationSettings().isMentionNotifiesMeEnabled() ? R.string.GroupMentionSettingDialog_default_notify_me
: R.string.GroupMentionSettingDialog_default_dont_notify_me);
case ALWAYS_NOTIFY:
return context.getString(R.string.GroupMentionSettingDialog_always_notify_me);
case DO_NOT_NOTIFY:

View File

@ -279,7 +279,7 @@ public class RecipientDatabase extends Database {
}
public enum MentionSetting {
GLOBAL(0), ALWAYS_NOTIFY(1), DO_NOT_NOTIFY(2);
ALWAYS_NOTIFY(0), DO_NOT_NOTIFY(1);
private final int id;
@ -336,7 +336,7 @@ public class RecipientDatabase extends Database {
GROUPS_V2_CAPABILITY + " INTEGER DEFAULT " + Recipient.Capability.UNKNOWN.serialize() + ", " +
STORAGE_SERVICE_ID + " TEXT UNIQUE DEFAULT NULL, " +
DIRTY + " INTEGER DEFAULT " + DirtyState.CLEAN.getId() + ", " +
MENTION_SETTING + " INTEGER DEFAULT " + MentionSetting.GLOBAL.getId() + ");";
MENTION_SETTING + " INTEGER DEFAULT " + MentionSetting.ALWAYS_NOTIFY.getId() + ");";
private static final String INSIGHTS_INVITEE_LIST = "SELECT " + TABLE_NAME + "." + ID +
" FROM " + TABLE_NAME +
@ -1160,7 +1160,7 @@ public class RecipientDatabase extends Database {
}
byte[] storageKey = storageKeyRaw != null ? Base64.decodeOrThrow(storageKeyRaw) : null;
byte[] identityKey = identityKeyRaw.transform(Base64::decodeOrThrow).orNull();;
byte[] identityKey = identityKeyRaw.transform(Base64::decodeOrThrow).orNull();
IdentityDatabase.VerifiedStatus identityStatus = identityStatusRaw.transform(IdentityDatabase.VerifiedStatus::forState).or(IdentityDatabase.VerifiedStatus.DEFAULT);
@ -2288,7 +2288,7 @@ public class RecipientDatabase extends Database {
uuidValues.put(SYSTEM_CONTACT_URI, e164Settings.getSystemContactUri());
uuidValues.put(PROFILE_SHARING, uuidSettings.isProfileSharing() || e164Settings.isProfileSharing());
uuidValues.put(GROUPS_V2_CAPABILITY, uuidSettings.getGroupsV2Capability() != Recipient.Capability.UNKNOWN ? uuidSettings.getGroupsV2Capability().serialize() : e164Settings.getGroupsV2Capability().serialize());
uuidValues.put(MENTION_SETTING, uuidSettings.getMentionSetting() != MentionSetting.GLOBAL ? uuidSettings.getMentionSetting().getId() : e164Settings.getMentionSetting().getId());
uuidValues.put(MENTION_SETTING, uuidSettings.getMentionSetting() != MentionSetting.ALWAYS_NOTIFY ? uuidSettings.getMentionSetting().getId() : e164Settings.getMentionSetting().getId());
if (uuidSettings.getProfileKey() != null) {
updateProfileValuesForMerge(uuidValues, uuidSettings);
} else if (e164Settings.getProfileKey() != null) {

View File

@ -142,8 +142,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int REMAPPED_RECORDS = 67;
private static final int MENTIONS = 68;
private static final int PINNED_CONVERSATIONS = 69;
private static final int MENTION_GLOBAL_SETTING_MIGRATION = 70;
private static final int DATABASE_VERSION = 69;
private static final int DATABASE_VERSION = 70;
private static final String DATABASE_NAME = "signal.db";
private final Context context;
@ -997,6 +998,16 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL("CREATE INDEX IF NOT EXISTS thread_pinned_index ON thread (pinned)");
}
if (oldVersion < MENTION_GLOBAL_SETTING_MIGRATION) {
ContentValues updateAlways = new ContentValues();
updateAlways.put("mention_setting", 0);
db.update("recipient", updateAlways, "mention_setting = 1", null);
ContentValues updateNever = new ContentValues();
updateNever.put("mention_setting", 1);
db.update("recipient", updateNever, "mention_setting = 2", null);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();

View File

@ -23,7 +23,6 @@ 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;
@ -261,7 +260,7 @@ public class ManageGroupViewModel extends ViewModel {
}
void handleMentionNotificationSelection() {
manageGroupRepository.getRecipient(r -> GroupMentionSettingDialog.show(context, r.getMentionSetting(), mentionSetting -> manageGroupRepository.setMentionSetting(mentionSetting)));
manageGroupRepository.getRecipient(r -> GroupMentionSettingDialog.show(context, r.getMentionSetting(), manageGroupRepository::setMentionSetting));
}
private void onBlockAndLeaveConfirmed() {

View File

@ -14,7 +14,6 @@ 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 {
@ -32,31 +31,24 @@ public final class GroupMentionSettingDialog {
@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;
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;

View File

@ -1,20 +0,0 @@
package org.thoughtcrime.securesms.keyvalue;
import androidx.annotation.NonNull;
public class NotificationSettings extends SignalStoreValues {
public static final String MENTIONS_NOTIFY_ME = "notifications.mentions.notify_me";
NotificationSettings(@NonNull KeyValueStore store) {
super(store);
}
@Override
void onFirstEverAppLaunch() {
}
public boolean isMentionNotifiesMeEnabled() {
return getBoolean(MENTIONS_NOTIFY_ME, true);
}
}

View File

@ -24,7 +24,6 @@ public final class SignalStore {
private final MiscellaneousValues misc;
private final InternalValues internalValues;
private final EmojiValues emojiValues;
private final NotificationSettings notificationSettings;
private SignalStore() {
this.store = ApplicationDependencies.getKeyValueStore();
@ -38,7 +37,6 @@ public final class SignalStore {
this.misc = new MiscellaneousValues(store);
this.internalValues = new InternalValues(store);
this.emojiValues = new EmojiValues(store);
this.notificationSettings = new NotificationSettings(store);
}
public static void onFirstEverAppLaunch() {
@ -51,7 +49,6 @@ public final class SignalStore {
tooltips().onFirstEverAppLaunch();
misc().onFirstEverAppLaunch();
internalValues().onFirstEverAppLaunch();
notificationSettings().onFirstEverAppLaunch();
}
public static @NonNull KbsValues kbsValues() {
@ -94,10 +91,6 @@ public final class SignalStore {
return INSTANCE.emojiValues;
}
public static @NonNull NotificationSettings notificationSettings() {
return INSTANCE.notificationSettings;
}
public static @NonNull GroupsV2AuthorizationSignalStoreCache groupsV2AuthorizationCache() {
return new GroupsV2AuthorizationSignalStoreCache(getStore());
}

View File

@ -1,13 +1,11 @@
package org.thoughtcrime.securesms.longmessage;
import androidx.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.Intent;
import android.graphics.PorterDuff;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.NonNull;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan;
@ -16,15 +14,19 @@ import android.util.TypedValue;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProviders;
import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.color.MaterialColor;
import org.thoughtcrime.securesms.components.ConversationItemFooter;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient;
@ -36,6 +38,8 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.views.Stub;
import static org.thoughtcrime.securesms.util.ThemeUtil.isDarkTheme;
public class LongMessageActivity extends PassphraseRequiredActivity {
private static final String KEY_CONVERSATION_RECIPIENT = "recipient_id";
@ -144,7 +148,7 @@ public class LongMessageActivity extends PassphraseRequiredActivity {
bubble.getBackground().setColorFilter(message.get().getMessageRecord().getRecipient().getColor().toConversationColor(this), PorterDuff.Mode.MULTIPLY);
}
TextView text = bubble.findViewById(R.id.longmessage_text);
EmojiTextView text = bubble.findViewById(R.id.longmessage_text);
ConversationItemFooter footer = bubble.findViewById(R.id.longmessage_footer);
CharSequence trimmedBody = getTrimmedBody(message.get().getFullBody(this));
@ -154,6 +158,11 @@ public class LongMessageActivity extends PassphraseRequiredActivity {
text.setText(styledBody);
text.setMovementMethod(LinkMovementMethod.getInstance());
text.setTextSize(TypedValue.COMPLEX_UNIT_SP, TextSecurePreferences.getMessageBodyTextSize(this));
if (message.get().getMessageRecord().isOutgoing()) {
text.setMentionBackgroundTint(ContextCompat.getColor(this, isDarkTheme(this) ? R.color.core_grey_60 : R.color.core_grey_20));
} else {
text.setMentionBackgroundTint(ContextCompat.getColor(this, R.color.transparent_black_40));
}
footer.setMessageRecord(message.get().getMessageRecord(), dynamicLanguage.getCurrentLocale());
});
}

View File

@ -23,9 +23,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.core.util.Pair;
import androidx.core.util.Supplier;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -51,6 +54,7 @@ import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerViewMod
import org.thoughtcrime.securesms.imageeditor.model.EditorModel;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter;
import org.thoughtcrime.securesms.mediasend.MediaSendViewModel.HudState;
import org.thoughtcrime.securesms.mediasend.MediaSendViewModel.ViewOnceState;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.permissions.Permissions;
@ -66,8 +70,11 @@ import org.thoughtcrime.securesms.util.IOFunction;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import org.thoughtcrime.securesms.util.views.Stub;
import org.thoughtcrime.securesms.video.VideoUtil;
@ -82,6 +89,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
@ -120,8 +128,9 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
private @Nullable LiveRecipient recipient;
private TransportOption transport;
private MediaSendViewModel viewModel;
private TransportOption transport;
private MediaSendViewModel viewModel;
private MentionsPickerViewModel mentionsViewModel;
private InputAwareLayout hud;
private View captionAndRail;
@ -317,8 +326,8 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
emojiToggle.setOnClickListener(this::onEmojiToggleClicked);
}
initViewModel();
if (FeatureFlags.mentions()) initializeMentionsViewModel();
initViewModel();
revealButton.setOnClickListener(v -> viewModel.onRevealButtonToggled());
continueButton.setOnClickListener(v -> navigateToContactSelect());
@ -610,6 +619,27 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
}
private void initViewModel() {
LiveData<Pair<HudState, Boolean>> hudStateAndMentionShowing = LiveDataUtil.combineLatest(viewModel.getHudState(),
mentionsViewModel != null ? mentionsViewModel.isShowing()
: new MutableLiveData<>(false),
Pair::new);
hudStateAndMentionShowing.observe(this, p -> {
HudState state = Objects.requireNonNull(p.first);
boolean isMentionPickerShowing = Objects.requireNonNull(p.second);
int captionBackground = R.color.transparent_black_40;
if (state.getRailState() == MediaSendViewModel.RailState.VIEWABLE) {
captionBackground = R.color.core_grey_90;
} else if (state.getViewOnceState() == ViewOnceState.ENABLED) {
captionBackground = 0;
} else if (isMentionPickerShowing){
captionBackground = ThemeUtil.getThemedResourceId(this, R.attr.mention_picker_background_color);
}
captionAndRail.setBackgroundResource(captionBackground);
});
viewModel.getHudState().observe(this, state -> {
if (state == null) return;
@ -617,18 +647,6 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
composeContainer.setVisibility(state.isComposeVisible() ? View.VISIBLE : (state.getViewOnceState() == ViewOnceState.GONE ? View.GONE : View.INVISIBLE));
captionText.setVisibility(state.isCaptionVisible() ? View.VISIBLE : View.GONE);
int captionBackground;
if (state.getRailState() == MediaSendViewModel.RailState.VIEWABLE) {
captionBackground = R.color.core_grey_90;
} else if (state.getViewOnceState() == ViewOnceState.ENABLED) {
captionBackground = 0;
} else {
captionBackground = R.color.transparent_black_40;
}
captionAndRail.setBackgroundResource(captionBackground);
switch (state.getButtonState()) {
case SEND:
sendButtonContainer.setVisibility(View.VISIBLE);
@ -766,7 +784,7 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
return;
}
MentionsPickerViewModel mentionsViewModel = ViewModelProviders.of(this, new MentionsPickerViewModel.Factory()).get(MentionsPickerViewModel.class);
mentionsViewModel = ViewModelProviders.of(this, new MentionsPickerViewModel.Factory()).get(MentionsPickerViewModel.class);
recipient.observe(this, mentionsViewModel::onRecipientChange);
composeText.setMentionQueryChangedListener(query -> {
@ -799,6 +817,17 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
}
composeText.replaceTextWithMention(replacementDisplayName, recipient.getId());
});
MentionPickerPlacer mentionPickerPlacer = new MentionPickerPlacer();
mentionsViewModel.isShowing().observe(this, isShowing -> {
if (isShowing) {
composeRow.getViewTreeObserver().addOnGlobalLayoutListener(mentionPickerPlacer);
} else {
composeRow.getViewTreeObserver().removeOnGlobalLayoutListener(mentionPickerPlacer);
}
mentionPickerPlacer.onGlobalLayout();
});
}
private void presentRecipient(@Nullable Recipient recipient) {
@ -979,4 +1008,34 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
@Override
public void onFocusChange(View v, boolean hasFocus) {}
}
private class MentionPickerPlacer implements ViewTreeObserver.OnGlobalLayoutListener {
private final int composeMargin;
private final ViewGroup parent;
private final Rect composeCoordinates;
private int previousBottomMargin;
public MentionPickerPlacer() {
parent = findViewById(android.R.id.content);
composeMargin = ViewUtil.dpToPx(12);
composeCoordinates = new Rect();
}
@Override
public void onGlobalLayout() {
composeRow.getDrawingRect(composeCoordinates);
parent.offsetDescendantRectToMyCoords(composeRow, composeCoordinates);
int marginBottom = parent.getHeight() - composeCoordinates.top + composeMargin;
if (marginBottom != previousBottomMargin) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mentionSuggestions.get().getLayoutParams();
params.setMargins(0, 0, 0, marginBottom);
mentionSuggestions.get().setLayoutParams(params);
previousBottomMargin = marginBottom;
}
}
}
}

View File

@ -536,12 +536,9 @@ public class DefaultMessageNotifier implements MessageNotifier {
boolean includeMessage = true;
if (threadRecipients != null && threadRecipients.isMuted()) {
RecipientDatabase.MentionSetting mentionSetting = threadRecipients.getMentionSetting();
boolean mentionsOverrideMute = threadRecipients.getMentionSetting() == RecipientDatabase.MentionSetting.ALWAYS_NOTIFY;
boolean overrideMuted = (mentionSetting == RecipientDatabase.MentionSetting.GLOBAL && SignalStore.notificationSettings().isMentionNotifiesMeEnabled()) ||
mentionSetting == RecipientDatabase.MentionSetting.ALWAYS_NOTIFY;
includeMessage = FeatureFlags.mentions() && overrideMuted && record.hasSelfMention();
includeMessage = FeatureFlags.mentions() && mentionsOverrideMute && record.hasSelfMention();
}
if (threadRecipients == null || includeMessage) {

View File

@ -9,21 +9,17 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceDataStore;
import android.text.TextUtils;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.NotificationSettings;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import static android.app.Activity.RESULT_OK;
@ -120,18 +116,11 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
initializeCallRingtoneSummary(findPreference(TextSecurePreferences.CALL_RINGTONE_PREF));
initializeMessageVibrateSummary((SwitchPreferenceCompat)findPreference(TextSecurePreferences.VIBRATE_PREF));
initializeCallVibrateSummary((SwitchPreferenceCompat)findPreference(TextSecurePreferences.CALL_VIBRATE_PREF));
if (FeatureFlags.mentions()) {
initializeMentionsNotifyMeSummary((SwitchPreferenceCompat)findPreference(NotificationSettings.MENTIONS_NOTIFY_ME));
}
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences_notifications);
if (FeatureFlags.mentions()) {
addPreferencesFromResource(R.xml.preferences_notifications_mentions);
}
}
@Override
@ -209,11 +198,6 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
pref.setChecked(TextSecurePreferences.isCallNotificationVibrateEnabled(getContext()));
}
private void initializeMentionsNotifyMeSummary(SwitchPreferenceCompat pref) {
pref.setPreferenceDataStore(SignalStore.getPreferenceDataStore());
pref.setChecked(SignalStore.notificationSettings().isMentionNotifiesMeEnabled());
}
public static CharSequence getSummary(Context context) {
final int onCapsResId = R.string.ApplicationPreferencesActivity_On;
final int offCapsResId = R.string.ApplicationPreferencesActivity_Off;

View File

@ -318,7 +318,7 @@ public class Recipient {
this.storageId = null;
this.identityKey = null;
this.identityStatus = VerifiedStatus.DEFAULT;
this.mentionSetting = MentionSetting.GLOBAL;
this.mentionSetting = MentionSetting.ALWAYS_NOTIFY;
}
public Recipient(@NonNull RecipientId id, @NonNull RecipientDetails details, boolean resolved) {
@ -413,6 +413,17 @@ public class Recipient {
return StringUtil.isolateBidi(name);
}
public @NonNull String getMentionDisplayName(@NonNull Context context) {
String name = Util.getFirstNonEmpty(localNumber ? getProfileName().toString() : getName(context),
localNumber ? getName(context) : getProfileName().toString(),
getDisplayUsername(),
e164,
email,
context.getString(R.string.Recipient_unknown));
return StringUtil.isolateBidi(name);
}
public @NonNull String getShortDisplayName(@NonNull Context context) {
String name = Util.getFirstNonEmpty(getName(context),
getProfileName().getGivenName(),

View File

@ -164,7 +164,7 @@ public class RecipientDetails {
this.storageId = null;
this.identityKey = null;
this.identityStatus = VerifiedStatus.DEFAULT;
this.mentionSetting = MentionSetting.GLOBAL;
this.mentionSetting = MentionSetting.ALWAYS_NOTIFY;
}
public static @NonNull RecipientDetails forIndividual(@NonNull Context context, @NonNull RecipientSettings settings) {

View File

@ -0,0 +1,18 @@
package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.graphics.drawable.Drawable;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import java.util.Objects;
public final class ContextUtil {
private ContextUtil() {}
public static @NonNull Drawable requireDrawable(@NonNull Context context, @DrawableRes int drawable) {
return Objects.requireNonNull(ContextCompat.getDrawable(context, drawable));
}
}

View File

@ -0,0 +1,26 @@
package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.os.Build;
import android.os.VibrationEffect;
import android.os.Vibrator;
import androidx.annotation.NonNull;
public final class VibrateUtil {
private static final int TICK_LENGTH = 30;
private VibrateUtil() { }
public static void vibrateTick(@NonNull Context context) {
Vibrator vibrator = ServiceUtil.getVibrator(context);
if (Build.VERSION.SDK_INT >= 26) {
VibrationEffect effect = VibrationEffect.createOneShot(TICK_LENGTH, 64);
vibrator.vibrate(effect);
} else {
vibrator.vibrate(TICK_LENGTH);
}
}
}

View File

@ -15,21 +15,6 @@
android:paddingRight="?attr/dialogPreferredPadding"
android:text="@string/GroupMentionSettingDialog_receive_notifications_when_youre_mentioned_in_muted_chats" />
<CheckedTextView
android:id="@+id/group_mention_setting_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:drawableStart="?android:attr/listChoiceIndicatorSingle"
android:drawablePadding="20dp"
android:gravity="center_vertical"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:paddingStart="20dp"
android:paddingEnd="?attr/dialogPreferredPadding"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?attr/textColorAlertDialogListItem"
tools:text="@string/GroupMentionSettingDialog_default_notify_me" />
<CheckedTextView
android:id="@+id/group_mention_setting_always_notify"
android:layout_width="match_parent"

View File

@ -27,13 +27,6 @@
android:clickable="true"
android:background="@color/transparent_black_40">
<ViewStub
android:id="@+id/mediasend_mention_suggestions_stub"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout="@layout/conversation_mention_suggestions_stub"/>
<org.thoughtcrime.securesms.components.emoji.EmojiEditText
android:id="@+id/mediasend_caption"
android:layout_width="match_parent"
@ -192,4 +185,17 @@
</org.thoughtcrime.securesms.components.InputAwareLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ViewStub
android:id="@+id/mediasend_mention_suggestions_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout="@layout/conversation_mention_suggestions_stub"/>
</FrameLayout>
</FrameLayout>

View File

@ -2,28 +2,40 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:clipChildren="false">
<LinearLayout
<FrameLayout
android:id="@+id/mentions_picker_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="false"
app:behavior_peekHeight="0dp"
app:behavior_peekHeight="236dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<View
android:id="@+id/mentions_picker_top_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?conversation_mention_divider_color"/>
android:layout_height="2dp"
android:layout_gravity="top"
android:layout_marginTop="-2dp"
android:background="@drawable/compose_divider_background"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mentions_picker_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground" />
android:background="?mention_picker_background_color" />
</LinearLayout>
</FrameLayout>
<View
android:id="@+id/mentions_picker_bottom_divider"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_gravity="bottom"
android:background="@drawable/compose_divider_background"
android:visibility="gone" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,19 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:gravity="center_vertical"
android:paddingStart="12dp"
android:paddingTop="10dp"
android:paddingTop="8dp"
android:paddingEnd="8dp"
android:paddingBottom="10dp">
android:paddingBottom="8dp">
<org.thoughtcrime.securesms.components.AvatarImageView
android:id="@+id/mention_recipient_avatar"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_width="36dp"
android:layout_height="36dp"
app:fallbackImageSize="small"
tools:src="@tools:sample/avatars" />
<TextView

View File

@ -90,7 +90,8 @@
<attr name="conversation_title_color" format="reference" />
<attr name="conversation_subtitle_color" format="reference" />
<attr name="conversation_mention_background_color" format="reference" />
<attr name="conversation_mention_divider_color" format="reference" />
<attr name="mention_picker_background_color" format="reference" />
<attr name="emoji_tab_strip_background" format="color" />
<attr name="emoji_tab_indicator" format="color" />

View File

@ -159,6 +159,4 @@
<dimen name="group_manage_fragment_row_horizontal_padding">16dp</dimen>
<dimen name="wave_form_bar_width">2dp</dimen>
<dimen name="mentions_picker_peek_height">216dp</dimen>
</resources>

View File

@ -263,7 +263,8 @@
<item name="conversation_title_color">@color/white</item>
<item name="conversation_subtitle_color">@color/transparent_white_90</item>
<item name="conversation_mention_background_color">@color/core_grey_20</item>
<item name="conversation_mention_divider_color">@color/core_grey_05</item>
<item name="mention_picker_background_color">@color/core_white</item>
<item name="safety_number_change_dialog_button_background">@color/core_grey_05</item>
<item name="safety_number_change_dialog_button_text_color">@color/core_ultramarine</item>
@ -624,11 +625,12 @@
<item name="conversation_popup_theme">@style/ThemeOverlay.AppCompat.Dark</item>
<item name="conversation_title_color">@color/transparent_white_90</item>
<item name="conversation_subtitle_color">@color/transparent_white_80</item>
<item name="conversation_mention_background_color">@color/core_grey_75</item>
<item name="conversation_mention_divider_color">@color/core_grey_25</item>
<item name="conversation_mention_background_color">@color/core_grey_60</item>
<item name="conversation_scroll_to_bottom_background">@drawable/scroll_to_bottom_background_dark</item>
<item name="conversation_scroll_to_bottom_foreground_color">@color/core_white</item>
<item name="mention_picker_background_color">@color/core_grey_90</item>
<item name="reactions_overlay_toolbar_icon_tint">@color/core_white</item>
<item name="reactions_overlay_toolbar_overflow_style">@style/Signal.Toolbar.Overflow</item>
<item name="reactions_overlay_toolbar_background_color">@color/action_mode_status_bar</item>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:layout="@layout/preference_divider"/>
<PreferenceCategory android:title="@string/preferences_notifications__mentions">
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:key="notifications.mentions.notify_me"
android:title="@string/preferences_notifications__notify_me"
android:summary="@string/preferences_notifications__receive_notifications_when_youre_mentioned_in_muted_chats"
android:defaultValue="true" />
</PreferenceCategory>
</PreferenceScreen>