kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add new bottom actionbar to chat list.
rodzic
2167522f7d
commit
f533a898f5
|
@ -0,0 +1,13 @@
|
|||
package org.thoughtcrime.securesms.components.menu
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
/**
|
||||
* Represents an action to be rendered via [SignalContextMenu] or [SignalBottomActionBar]
|
||||
*/
|
||||
data class ActionItem(
|
||||
@DrawableRes val iconRes: Int,
|
||||
@StringRes val titleRes: Int,
|
||||
val action: Runnable
|
||||
)
|
|
@ -0,0 +1,92 @@
|
|||
package org.thoughtcrime.securesms.components.menu
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
|
||||
/**
|
||||
* A bar that displays a set of action buttons. Intended as a replacement for ActionModes, this gives you a simple interface to add a bunch of actions, and
|
||||
* the bar itself will handle putting things in the overflow and whatnot.
|
||||
*
|
||||
* Overflow items are rendered in a [SignalContextMenu].
|
||||
*/
|
||||
class SignalBottomActionBar(context: Context, attributeSet: AttributeSet) : LinearLayout(context, attributeSet) {
|
||||
|
||||
val items: MutableList<ActionItem> = mutableListOf()
|
||||
|
||||
init {
|
||||
orientation = HORIZONTAL
|
||||
setBackgroundResource(R.drawable.signal_bottom_action_bar_background)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
elevation = 20f
|
||||
}
|
||||
}
|
||||
|
||||
fun setItems(items: List<ActionItem>) {
|
||||
this.items.clear()
|
||||
this.items.addAll(items)
|
||||
present(this.items)
|
||||
}
|
||||
|
||||
private fun present(items: List<ActionItem>) {
|
||||
if (width == 0) {
|
||||
post { present(items) }
|
||||
return
|
||||
}
|
||||
|
||||
val widthDp: Float = ViewUtil.pxToDp(width.toFloat())
|
||||
val minButtonWidthDp = 70
|
||||
val maxButtons: Int = (widthDp / minButtonWidthDp).toInt()
|
||||
val usableButtonCount = when {
|
||||
items.size <= maxButtons -> items.size
|
||||
else -> maxButtons - 1
|
||||
}
|
||||
|
||||
val renderableItems: List<ActionItem> = items.subList(0, usableButtonCount)
|
||||
val overflowItems: List<ActionItem> = if (renderableItems.size < items.size) items.subList(usableButtonCount, items.size) else emptyList()
|
||||
|
||||
removeAllViews()
|
||||
|
||||
renderableItems.forEach { item ->
|
||||
val view: View = LayoutInflater.from(context).inflate(R.layout.signal_bottom_action_bar_item, this, false)
|
||||
addView(view)
|
||||
bindItem(view, item)
|
||||
}
|
||||
|
||||
if (overflowItems.isNotEmpty()) {
|
||||
val view: View = LayoutInflater.from(context).inflate(R.layout.signal_bottom_action_bar_item, this, false)
|
||||
addView(view)
|
||||
bindItem(
|
||||
view,
|
||||
ActionItem(
|
||||
iconRes = R.drawable.ic_more_horiz_24,
|
||||
titleRes = R.string.SignalBottomActionBar_more,
|
||||
action = {
|
||||
SignalContextMenu.Builder(view, parent as ViewGroup)
|
||||
.preferredHorizontalPosition(SignalContextMenu.HorizontalPosition.END)
|
||||
.offsetY(ViewUtil.dpToPx(8))
|
||||
.show(overflowItems)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindItem(view: View, item: ActionItem) {
|
||||
val icon: ImageView = view.findViewById(R.id.signal_bottom_action_bar_item_icon)
|
||||
val title: TextView = view.findViewById(R.id.signal_bottom_action_bar_item_title)
|
||||
|
||||
icon.setImageResource(item.iconRes)
|
||||
title.setText(item.titleRes)
|
||||
view.setOnClickListener { item.action.run() }
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package org.thoughtcrime.securesms.components
|
||||
package org.thoughtcrime.securesms.components.menu
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.os.Build
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -8,8 +9,6 @@ import android.view.ViewGroup
|
|||
import android.widget.ImageView
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -17,6 +16,7 @@ import org.thoughtcrime.securesms.R
|
|||
import org.thoughtcrime.securesms.util.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.MappingModel
|
||||
import org.thoughtcrime.securesms.util.MappingViewHolder
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
|
||||
/**
|
||||
* A custom context menu that will show next to an anchor view and display several options. Basically a PopupMenu with custom UI and positioning rules.
|
||||
|
@ -27,10 +27,11 @@ import org.thoughtcrime.securesms.util.MappingViewHolder
|
|||
*/
|
||||
class SignalContextMenu private constructor(
|
||||
val anchor: View,
|
||||
val container: View,
|
||||
val items: List<Item>,
|
||||
val container: ViewGroup,
|
||||
val items: List<ActionItem>,
|
||||
val baseOffsetX: Int = 0,
|
||||
val baseOffsetY: Int = 0,
|
||||
val horizontalPosition: HorizontalPosition = HorizontalPosition.START,
|
||||
val onDismiss: Runnable? = null
|
||||
) : PopupWindow(
|
||||
LayoutInflater.from(anchor.context).inflate(R.layout.signal_context_menu, null),
|
||||
|
@ -77,8 +78,14 @@ class SignalContextMenu private constructor(
|
|||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
)
|
||||
|
||||
val menuBottomBound = anchor.y + anchor.height + contentView.measuredHeight + baseOffsetY
|
||||
val menuTopBound = anchor.y - contentView.measuredHeight - baseOffsetY
|
||||
val anchorRect = Rect(anchor.left, anchor.top, anchor.right, anchor.bottom).also {
|
||||
if (anchor.parent != container) {
|
||||
container.offsetDescendantRectToMyCoords(anchor, it)
|
||||
}
|
||||
}
|
||||
|
||||
val menuBottomBound = anchorRect.bottom + contentView.measuredHeight + baseOffsetY
|
||||
val menuTopBound = anchorRect.top - contentView.measuredHeight - baseOffsetY
|
||||
|
||||
val screenBottomBound = container.height
|
||||
val screenTopBound = container.y
|
||||
|
@ -88,16 +95,33 @@ class SignalContextMenu private constructor(
|
|||
if (menuBottomBound < screenBottomBound) {
|
||||
offsetY = baseOffsetY
|
||||
} else if (menuTopBound > screenTopBound) {
|
||||
offsetY = -(anchor.height + contentView.measuredHeight + baseOffsetY)
|
||||
offsetY = -(anchorRect.height() + contentView.measuredHeight + baseOffsetY)
|
||||
mappingAdapter.submitList(items.reversed().toAdapterItems())
|
||||
} else {
|
||||
offsetY = -((anchor.height / 2) + (contentView.measuredHeight / 2) + baseOffsetY)
|
||||
offsetY = -((anchorRect.height() / 2) + (contentView.measuredHeight / 2) + baseOffsetY)
|
||||
}
|
||||
|
||||
showAsDropDown(anchor, baseOffsetX, offsetY)
|
||||
val offsetX: Int = when (horizontalPosition) {
|
||||
HorizontalPosition.START -> {
|
||||
if (ViewUtil.isLtr(context)) {
|
||||
baseOffsetX
|
||||
} else {
|
||||
-(baseOffsetX + contentView.measuredWidth)
|
||||
}
|
||||
}
|
||||
HorizontalPosition.END -> {
|
||||
if (ViewUtil.isLtr(context)) {
|
||||
-(baseOffsetX + contentView.measuredWidth - anchorRect.width())
|
||||
} else {
|
||||
baseOffsetX - anchorRect.width()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showAsDropDown(anchor, offsetX, offsetY)
|
||||
}
|
||||
|
||||
private fun List<Item>.toAdapterItems(): List<DisplayItem> {
|
||||
private fun List<ActionItem>.toAdapterItems(): List<DisplayItem> {
|
||||
return this.mapIndexed { index, item ->
|
||||
val displayType: DisplayType = when {
|
||||
this.size == 1 -> DisplayType.ONLY
|
||||
|
@ -110,14 +134,8 @@ class SignalContextMenu private constructor(
|
|||
}
|
||||
}
|
||||
|
||||
data class Item(
|
||||
@DrawableRes val iconRes: Int,
|
||||
@StringRes val titleRes: Int,
|
||||
val action: Runnable
|
||||
)
|
||||
|
||||
private data class DisplayItem(
|
||||
val item: Item,
|
||||
val item: ActionItem,
|
||||
val displayType: DisplayType
|
||||
) : MappingModel<DisplayItem> {
|
||||
override fun areItemsTheSame(newItem: DisplayItem): Boolean {
|
||||
|
@ -129,7 +147,7 @@ class SignalContextMenu private constructor(
|
|||
}
|
||||
}
|
||||
|
||||
enum class DisplayType {
|
||||
private enum class DisplayType {
|
||||
TOP, BOTTOM, MIDDLE, ONLY
|
||||
}
|
||||
|
||||
|
@ -162,18 +180,23 @@ class SignalContextMenu private constructor(
|
|||
}
|
||||
}
|
||||
|
||||
enum class HorizontalPosition {
|
||||
START, END
|
||||
}
|
||||
|
||||
/**
|
||||
* @param anchor The view to put the pop-up on
|
||||
* @param container A parent of [anchor] that represents the acceptable boundaries of the popup
|
||||
*/
|
||||
class Builder(
|
||||
val anchor: View,
|
||||
val container: View
|
||||
val container: ViewGroup
|
||||
) {
|
||||
|
||||
var onDismiss: Runnable? = null
|
||||
var offsetX: Int = 0
|
||||
var offsetY: Int = 0
|
||||
var offsetX = 0
|
||||
var offsetY = 0
|
||||
var horizontalPosition = HorizontalPosition.START
|
||||
|
||||
fun onDismiss(onDismiss: Runnable): Builder {
|
||||
this.onDismiss = onDismiss
|
||||
|
@ -190,13 +213,19 @@ class SignalContextMenu private constructor(
|
|||
return this
|
||||
}
|
||||
|
||||
fun show(items: List<Item>) {
|
||||
fun preferredHorizontalPosition(horizontalPosition: HorizontalPosition): Builder {
|
||||
this.horizontalPosition = horizontalPosition
|
||||
return this
|
||||
}
|
||||
|
||||
fun show(items: List<ActionItem>) {
|
||||
SignalContextMenu(
|
||||
anchor = anchor,
|
||||
container = container,
|
||||
items = items,
|
||||
baseOffsetX = offsetX,
|
||||
baseOffsetY = offsetY,
|
||||
horizontalPosition = horizontalPosition,
|
||||
onDismiss = onDismiss
|
||||
).show()
|
||||
}
|
|
@ -1855,8 +1855,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
|||
|
||||
private class ActionModeCallback implements ActionMode.Callback {
|
||||
|
||||
private int statusBarColor;
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
MenuInflater inflater = mode.getMenuInflater();
|
||||
|
@ -1864,16 +1862,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
|||
|
||||
mode.setTitle(calculateSelectedItemCount());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
Window window = getActivity().getWindow();
|
||||
statusBarColor = window.getStatusBarColor();
|
||||
WindowUtil.setStatusBarColor(window, getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
|
||||
if (!ThemeUtil.isDarkTheme(getContext())) {
|
||||
WindowUtil.setLightStatusBar(getActivity().getWindow());
|
||||
}
|
||||
|
||||
setCorrectActionModeMenuVisibility(menu);
|
||||
listener.onMessageActionToolbarOpened();
|
||||
return true;
|
||||
|
@ -1888,12 +1876,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
|||
public void onDestroyActionMode(ActionMode mode) {
|
||||
((ConversationAdapter)list.getAdapter()).clearSelection();
|
||||
list.invalidateItemDecorations();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
WindowUtil.setStatusBarColor(requireActivity().getWindow(), statusBarColor);
|
||||
}
|
||||
|
||||
WindowUtil.setLightStatusBarFromTheme(requireActivity());
|
||||
actionMode = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,11 +104,6 @@ public class ConversationListArchiveFragment extends ConversationListFragment im
|
|||
return R.plurals.ConversationListFragment_moved_conversations_to_inbox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @MenuRes int getActionModeMenuRes() {
|
||||
return R.menu.conversation_list_batch_unarchive;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @DrawableRes int getArchiveIconRes() {
|
||||
return R.drawable.ic_unarchive_white_36dp;
|
||||
|
|
|
@ -45,12 +45,10 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.MenuRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.PluralsRes;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.view.ActionMode;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
@ -80,7 +78,9 @@ import org.thoughtcrime.securesms.NewConversationActivity;
|
|||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.RatingManager;
|
||||
import org.thoughtcrime.securesms.components.SearchToolbar;
|
||||
import org.thoughtcrime.securesms.components.SignalContextMenu;
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem;
|
||||
import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar;
|
||||
import org.thoughtcrime.securesms.components.menu.SignalContextMenu;
|
||||
import org.thoughtcrime.securesms.components.UnreadPaymentsView;
|
||||
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
|
||||
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
|
||||
|
@ -148,6 +148,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
|||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
@ -200,6 +201,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
private VoiceNoteMediaControllerOwner mediaControllerOwner;
|
||||
private Stub<FrameLayout> voiceNotePlayerViewStub;
|
||||
private VoiceNotePlayerView voiceNotePlayerView;
|
||||
private SignalBottomActionBar bottomActionBar;
|
||||
|
||||
|
||||
private Stopwatch startupStopwatch;
|
||||
|
@ -242,6 +244,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
toolbarShadow = view.findViewById(R.id.conversation_list_toolbar_shadow);
|
||||
proxyStatus = view.findViewById(R.id.conversation_list_proxy_status);
|
||||
unreadPaymentsDot = view.findViewById(R.id.unread_payments_indicator);
|
||||
bottomActionBar = view.findViewById(R.id.conversation_list_bottom_action_bar);
|
||||
reminderView = new Stub<>(view.findViewById(R.id.reminder));
|
||||
emptyState = new Stub<>(view.findViewById(R.id.empty_state));
|
||||
searchToolbar = new Stub<>(view.findViewById(R.id.search_toolbar));
|
||||
|
@ -777,10 +780,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
|
||||
return null;
|
||||
}, none -> {
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
actionMode = null;
|
||||
}
|
||||
endActionModeIfActive();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -792,10 +792,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
StorageSyncHelper.scheduleSyncForDataChange();
|
||||
return null;
|
||||
}, none -> {
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
actionMode = null;
|
||||
}
|
||||
endActionModeIfActive();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -825,11 +822,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
super.onPostExecute(result);
|
||||
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
actionMode = null;
|
||||
}
|
||||
endActionModeIfActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -881,10 +874,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
dialog.dismiss();
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
actionMode = null;
|
||||
}
|
||||
endActionModeIfActive();
|
||||
}
|
||||
}.executeOnExecutor(SignalExecutors.BOUNDED);
|
||||
}
|
||||
|
@ -906,9 +896,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
Snackbar.LENGTH_LONG)
|
||||
.setTextColor(Color.WHITE)
|
||||
.show();
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
}
|
||||
endActionModeIfActive();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -919,9 +907,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
|
||||
return null;
|
||||
}, unused -> {
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
}
|
||||
endActionModeIfActive();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -933,21 +919,40 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
|
||||
return null;
|
||||
}, unused -> {
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
}
|
||||
endActionModeIfActive();
|
||||
});
|
||||
}
|
||||
|
||||
private void handleSelectAllThreads() {
|
||||
defaultAdapter.selectAllThreads();
|
||||
actionMode.setTitle(String.valueOf(defaultAdapter.getBatchSelectionIds().size()));
|
||||
updateMultiSelectState();
|
||||
}
|
||||
|
||||
private void handleCreateConversation(long threadId, Recipient recipient, int distributionType) {
|
||||
getNavigator().goToConversation(recipient.getId(), threadId, distributionType, -1);
|
||||
}
|
||||
|
||||
private void startActionMode() {
|
||||
actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(ConversationListFragment.this);
|
||||
ViewUtil.fadeIn(bottomActionBar, 250);
|
||||
ViewUtil.fadeOut(fab, 250);
|
||||
ViewUtil.fadeOut(cameraFab, 250);
|
||||
}
|
||||
|
||||
private void endActionModeIfActive() {
|
||||
if (actionMode != null) {
|
||||
endActionMode();
|
||||
}
|
||||
}
|
||||
|
||||
private void endActionMode() {
|
||||
actionMode.finish();
|
||||
actionMode = null;
|
||||
ViewUtil.fadeOut(bottomActionBar, 250);
|
||||
ViewUtil.fadeIn(fab, 250);
|
||||
ViewUtil.fadeIn(cameraFab, 250);
|
||||
}
|
||||
|
||||
private void onSubmitList(@NonNull List<Conversation> conversationList) {
|
||||
defaultAdapter.submitList(conversationList);
|
||||
onPostSubmitList(conversationList.size());
|
||||
|
@ -1016,10 +1021,9 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
defaultAdapter.toggleConversationInBatchSet(conversation);
|
||||
|
||||
if (defaultAdapter.getBatchSelectionIds().size() == 0) {
|
||||
actionMode.finish();
|
||||
endActionModeIfActive();
|
||||
} else {
|
||||
actionMode.setTitle(String.valueOf(defaultAdapter.getBatchSelectionIds().size()));
|
||||
setCorrectMenuVisibility(actionMode.getMenu());
|
||||
updateMultiSelectState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1035,35 +1039,35 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
|
||||
Collection<Long> id = Collections.singleton(conversation.getThreadRecord().getThreadId());
|
||||
|
||||
List<SignalContextMenu.Item> items = new ArrayList<>();
|
||||
List<ActionItem> items = new ArrayList<>();
|
||||
|
||||
if (!conversation.getThreadRecord().isArchived()) {
|
||||
if (conversation.getThreadRecord().isRead()) {
|
||||
items.add(new SignalContextMenu.Item(R.drawable.ic_unread_24, R.string.ConversationListFragment_unread, () -> handleMarkAsUnread(id)));
|
||||
items.add(new ActionItem(R.drawable.ic_unread_24, R.string.ConversationListFragment_unread, () -> handleMarkAsUnread(id)));
|
||||
} else {
|
||||
items.add(new SignalContextMenu.Item(R.drawable.ic_read_24, R.string.ConversationListFragment_read, () -> handleMarkAsRead(id)));
|
||||
items.add(new ActionItem(R.drawable.ic_read_24, R.string.ConversationListFragment_read, () -> handleMarkAsRead(id)));
|
||||
}
|
||||
|
||||
if (conversation.getThreadRecord().isPinned()) {
|
||||
items.add(new SignalContextMenu.Item(R.drawable.ic_unpin_24, R.string.ConversationListFragment_unpin, () -> handleUnpin(id)));
|
||||
items.add(new ActionItem(R.drawable.ic_unpin_24, R.string.ConversationListFragment_unpin, () -> handleUnpin(id)));
|
||||
} else {
|
||||
items.add(new SignalContextMenu.Item(R.drawable.ic_pin_24, R.string.ConversationListFragment_pin, () -> handlePin(Collections.singleton(conversation))));
|
||||
items.add(new ActionItem(R.drawable.ic_pin_24, R.string.ConversationListFragment_pin, () -> handlePin(Collections.singleton(conversation))));
|
||||
}
|
||||
}
|
||||
|
||||
items.add(new SignalContextMenu.Item(R.drawable.ic_select_24, R.string.ConversationListFragment_select, () -> {
|
||||
items.add(new ActionItem(R.drawable.ic_select_24, R.string.ConversationListFragment_select, () -> {
|
||||
defaultAdapter.initializeBatchMode(true);
|
||||
defaultAdapter.toggleConversationInBatchSet(conversation);
|
||||
actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(ConversationListFragment.this);
|
||||
startActionMode();
|
||||
}));
|
||||
|
||||
if (conversation.getThreadRecord().isArchived()) {
|
||||
items.add(new SignalContextMenu.Item(R.drawable.ic_unarchive_24, R.string.ConversationListFragment_unarchive, () -> handleArchive(id, false)));
|
||||
items.add(new ActionItem(R.drawable.ic_unarchive_24, R.string.ConversationListFragment_unarchive, () -> handleArchive(id, false)));
|
||||
} else {
|
||||
items.add(new SignalContextMenu.Item(R.drawable.ic_archive_24, R.string.ConversationListFragment_archive, () -> handleArchive(id, false)));
|
||||
items.add(new ActionItem(R.drawable.ic_archive_24, R.string.ConversationListFragment_archive, () -> handleArchive(id, false)));
|
||||
}
|
||||
|
||||
items.add(new SignalContextMenu.Item(R.drawable.ic_delete_24, R.string.ConversationListFragment_delete, () -> handleDelete(id)));
|
||||
items.add(new ActionItem(R.drawable.ic_delete_24, R.string.ConversationListFragment_delete, () -> handleDelete(id)));
|
||||
|
||||
new SignalContextMenu.Builder(view, list)
|
||||
.offsetX(ViewUtil.dpToPx(12))
|
||||
|
@ -1076,45 +1080,26 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
MenuInflater inflater = getActivity().getMenuInflater();
|
||||
|
||||
inflater.inflate(R.menu.conversation_list_batch_pin, menu);
|
||||
inflater.inflate(getActionModeMenuRes(), menu);
|
||||
inflater.inflate(R.menu.conversation_list_batch, menu);
|
||||
|
||||
mode.setTitle("1");
|
||||
|
||||
WindowUtil.setStatusBarColor(requireActivity().getWindow(), getResources().getColor(R.color.action_mode_status_bar));
|
||||
|
||||
mode.setTitle(requireContext().getResources().getQuantityString(R.plurals.ConversationListFragment_s_selected, 1, 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
setCorrectMenuVisibility(menu);
|
||||
updateMultiSelectState();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_select_all: handleSelectAllThreads(); return true;
|
||||
case R.id.menu_delete_selected: handleDelete(defaultAdapter.getBatchSelectionIds()); return true;
|
||||
case R.id.menu_pin_selected: handlePin(defaultAdapter.getBatchSelection()); return true;
|
||||
case R.id.menu_unpin_selected: handleUnpin(defaultAdapter.getBatchSelectionIds()); return true;
|
||||
case R.id.menu_archive_selected: handleArchive(defaultAdapter.getBatchSelectionIds(), true); return true;
|
||||
case R.id.menu_mark_as_read: handleMarkAsRead(defaultAdapter.getBatchSelectionIds()); return true;
|
||||
case R.id.menu_mark_as_unread: handleMarkAsUnread(defaultAdapter.getBatchSelectionIds()); return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
defaultAdapter.initializeBatchMode(false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.statusBarColor});
|
||||
WindowUtil.setStatusBarColor(getActivity().getWindow(), color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
|
@ -1131,7 +1116,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
lightStatusBarAttr.recycle();
|
||||
}
|
||||
|
||||
actionMode = null;
|
||||
endActionModeIfActive();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
|
@ -1145,29 +1130,41 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
closeSearchIfOpen();
|
||||
}
|
||||
|
||||
private void setCorrectMenuVisibility(@NonNull Menu menu) {
|
||||
private void updateMultiSelectState() {
|
||||
int count = defaultAdapter.getBatchSelectionIds().size();
|
||||
boolean hasUnread = Stream.of(defaultAdapter.getBatchSelection()).anyMatch(conversation -> !conversation.getThreadRecord().isRead());
|
||||
boolean hasUnpinned = Stream.of(defaultAdapter.getBatchSelection()).anyMatch(conversation -> !conversation.getThreadRecord().isPinned());
|
||||
boolean canPin = viewModel.getPinnedCount() < MAXIMUM_PINNED_CONVERSATIONS;
|
||||
|
||||
if (actionMode != null) {
|
||||
actionMode.setTitle(requireContext().getResources().getQuantityString(R.plurals.ConversationListFragment_s_selected, count, count));
|
||||
}
|
||||
|
||||
List<ActionItem> items = new ArrayList<>();
|
||||
|
||||
if (hasUnread) {
|
||||
menu.findItem(R.id.menu_mark_as_unread).setVisible(false);
|
||||
menu.findItem(R.id.menu_mark_as_read).setVisible(true);
|
||||
items.add(new ActionItem(R.drawable.ic_read_24, R.string.ConversationListFragment_read, () -> handleMarkAsRead(defaultAdapter.getBatchSelectionIds())));
|
||||
} else {
|
||||
menu.findItem(R.id.menu_mark_as_unread).setVisible(true);
|
||||
menu.findItem(R.id.menu_mark_as_read).setVisible(false);
|
||||
items.add(new ActionItem(R.drawable.ic_unread_24, R.string.ConversationListFragment_unread, () -> handleMarkAsUnread(defaultAdapter.getBatchSelectionIds())));
|
||||
}
|
||||
|
||||
if (!isArchived() && hasUnpinned && canPin) {
|
||||
menu.findItem(R.id.menu_pin_selected).setVisible(true);
|
||||
menu.findItem(R.id.menu_unpin_selected).setVisible(false);
|
||||
items.add(new ActionItem(R.drawable.ic_pin_24, R.string.ConversationListFragment_pin, () -> handlePin(defaultAdapter.getBatchSelection())));
|
||||
} else if (!isArchived() && !hasUnpinned) {
|
||||
menu.findItem(R.id.menu_pin_selected).setVisible(false);
|
||||
menu.findItem(R.id.menu_unpin_selected).setVisible(true);
|
||||
} else {
|
||||
menu.findItem(R.id.menu_pin_selected).setVisible(false);
|
||||
menu.findItem(R.id.menu_unpin_selected).setVisible(false);
|
||||
items.add(new ActionItem(R.drawable.ic_unpin_24, R.string.ConversationListFragment_unpin, () -> handleUnpin(defaultAdapter.getBatchSelectionIds())));
|
||||
}
|
||||
|
||||
if (isArchived()) {
|
||||
items.add(new ActionItem(R.drawable.ic_unarchive_24, R.string.ConversationListFragment_unarchive, () -> handleArchive(defaultAdapter.getBatchSelectionIds(), true)));
|
||||
} else {
|
||||
items.add(new ActionItem(R.drawable.ic_archive_24, R.string.ConversationListFragment_archive, () -> handleArchive(defaultAdapter.getBatchSelectionIds(), true)));
|
||||
}
|
||||
|
||||
items.add(new ActionItem(R.drawable.ic_delete_24, R.string.ConversationListFragment_delete, () -> handleDelete(defaultAdapter.getBatchSelectionIds())));
|
||||
|
||||
items.add(new ActionItem(R.drawable.ic_select_24, R.string.ConversationListFragment_select_all, this::handleSelectAllThreads));
|
||||
|
||||
bottomActionBar.setItems(items);
|
||||
}
|
||||
|
||||
protected Toolbar getToolbar(@NonNull View rootView) {
|
||||
|
@ -1178,10 +1175,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
return R.plurals.ConversationListFragment_conversations_archived;
|
||||
}
|
||||
|
||||
protected @MenuRes int getActionModeMenuRes() {
|
||||
return R.menu.conversation_list_batch_archive;
|
||||
}
|
||||
|
||||
protected @DrawableRes int getArchiveIconRes() {
|
||||
return R.drawable.ic_archive_white_36dp;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M20,12C20,12.2967 19.912,12.5867 19.7472,12.8334C19.5824,13.08 19.3481,13.2723 19.074,13.3858C18.7999,13.4994 18.4983,13.5291 18.2074,13.4712C17.9164,13.4133 17.6491,13.2704 17.4393,13.0607C17.2296,12.8509 17.0867,12.5836 17.0288,12.2926C16.9709,12.0017 17.0007,11.7001 17.1142,11.426C17.2277,11.1519 17.42,10.9176 17.6666,10.7528C17.9133,10.588 18.2033,10.5 18.5,10.5C18.8978,10.5 19.2794,10.658 19.5607,10.9393C19.842,11.2206 20,11.6022 20,12ZM12,10.5C11.7033,10.5 11.4133,10.588 11.1666,10.7528C10.92,10.9176 10.7277,11.1519 10.6142,11.426C10.5007,11.7001 10.4709,12.0017 10.5288,12.2926C10.5867,12.5836 10.7296,12.8509 10.9393,13.0607C11.1491,13.2704 11.4164,13.4133 11.7074,13.4712C11.9983,13.5291 12.2999,13.4994 12.574,13.3858C12.8481,13.2723 13.0824,13.08 13.2472,12.8334C13.412,12.5867 13.5,12.2967 13.5,12C13.5,11.6022 13.342,11.2206 13.0607,10.9393C12.7794,10.658 12.3978,10.5 12,10.5ZM5.5,10.5C5.2033,10.5 4.9133,10.588 4.6666,10.7528C4.42,10.9176 4.2277,11.1519 4.1142,11.426C4.0006,11.7001 3.9709,12.0017 4.0288,12.2926C4.0867,12.5836 4.2296,12.8509 4.4393,13.0607C4.6491,13.2704 4.9164,13.4133 5.2074,13.4712C5.4983,13.5291 5.7999,13.4994 6.074,13.3858C6.3481,13.2723 6.5824,13.08 6.7472,12.8334C6.912,12.5867 7,12.2967 7,12C7,11.6022 6.842,11.2206 6.5607,10.9393C6.2794,10.658 5.8978,10.5 5.5,10.5V10.5Z"
|
||||
android:fillColor="@color/signal_icon_tint_action"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@color/signal_icon_tint_action"
|
||||
android:pathData="M19.53,5.53l-1.06,-1.06l-6.47,6.469l-6.47,-6.469l-1.06,1.06l6.469,6.47l-6.469,6.47l1.06,1.06l6.47,-6.469l6.47,6.469l1.06,-1.06l-6.469,-6.47l6.469,-6.47z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="@dimen/signal_context_menu_corner_radius" />
|
||||
<solid android:color="@color/signal_background_dialog" />
|
||||
|
||||
</shape>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/action_mode_close_button"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
app:srcCompat="@drawable/ic_x_24" >
|
||||
</ImageView>
|
|
@ -253,4 +253,17 @@
|
|||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.components.menu.SignalBottomActionBar
|
||||
android:id="@+id/conversation_list_bottom_action_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="36dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
android:layout_width="@dimen/conversation_list_avatar_size"
|
||||
android:layout_height="@dimen/conversation_list_avatar_size"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:contentDescription="@string/conversation_list_item_view__contact_photo_image"
|
||||
android:foreground="@drawable/contact_photo_background"
|
||||
app:layout_constraintStart_toEndOf="@id/conversation_list_item_check_container"
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/signal_bottom_action_bar_item_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
tools:src="@drawable/ic_archive_24"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/signal_bottom_action_bar_item_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.Signal.Body2"
|
||||
tools:text="Archive"/>
|
||||
|
||||
|
||||
</LinearLayout>
|
|
@ -1,28 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_delete_selected"
|
||||
android:icon="@drawable/ic_trash_24"
|
||||
android:title="@string/conversation_list_batch__menu_delete_selected"
|
||||
app:iconTint="@color/signal_icon_tint_primary"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_mark_as_read"
|
||||
android:title="@string/conversation_list_batch__menu_mark_as_read"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_mark_as_unread"
|
||||
android:title="@string/conversation_list_batch__menu_mark_as_unread"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_select_all"
|
||||
android:title="@string/conversation_list_batch__menu_select_all"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:title="@string/conversation_list_batch_archive__menu_archive_selected"
|
||||
android:id="@+id/menu_archive_selected"
|
||||
android:icon="@drawable/ic_archive_white_24dp"
|
||||
app:iconTint="@color/signal_icon_tint_primary"
|
||||
app:showAsAction="always"/>
|
||||
|
||||
</menu>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/menu_pin_selected"
|
||||
android:icon="@drawable/ic_pin_24"
|
||||
android:title="@string/conversation_list_batch__menu_pin_selected"
|
||||
app:iconTint="@color/signal_icon_tint_primary"
|
||||
app:showAsAction="always" />
|
||||
<item
|
||||
android:id="@+id/menu_unpin_selected"
|
||||
android:icon="@drawable/ic_unpin_24"
|
||||
android:title="@string/conversation_list_batch__menu_unpin_selected"
|
||||
app:iconTint="@color/signal_icon_tint_primary"
|
||||
app:showAsAction="always" />
|
||||
</menu>
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:title="@string/conversation_list_batch_unarchive__menu_unarchive_selected"
|
||||
android:id="@+id/menu_archive_selected"
|
||||
android:icon="@drawable/ic_unarchive_white_24dp"
|
||||
app:iconTint="@color/signal_icon_tint_primary"
|
||||
app:showAsAction="always"/>
|
||||
|
||||
</menu>
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
<color name="signal_icon_tint_primary">@color/core_grey_15</color>
|
||||
<color name="signal_icon_tint_secondary">@color/core_grey_25</color>
|
||||
<color name="signal_icon_tint_action">@color/signal_icon_tint_primary</color>
|
||||
|
||||
<color name="signal_icon_tint_tab_selected">@color/core_white</color>
|
||||
<color name="signal_icon_tint_tab_unselected">@color/core_grey_25</color>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
<color name="signal_icon_tint_primary">@color/core_grey_75</color>
|
||||
<color name="signal_icon_tint_secondary">@color/core_grey_60</color>
|
||||
<color name="signal_icon_tint_action">@color/core_black</color>
|
||||
|
||||
<color name="signal_icon_tint_tab_selected">@color/core_grey_75</color>
|
||||
<color name="signal_icon_tint_tab_unselected">@color/core_grey_45</color>
|
||||
|
|
|
@ -374,6 +374,11 @@
|
|||
<string name="ConversationListFragment_archive">Archive</string>
|
||||
<string name="ConversationListFragment_unarchive">Unarchive</string>
|
||||
<string name="ConversationListFragment_delete">Delete</string>
|
||||
<string name="ConversationListFragment_select_all">Select all</string>
|
||||
<plurals name="ConversationListFragment_s_selected">
|
||||
<item quantity="one">%d selected</item>
|
||||
<item quantity="other">%d selected</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ConversationListItem -->
|
||||
<string name="ConversationListItem_key_exchange_message">Key exchange message</string>
|
||||
|
@ -1580,6 +1585,9 @@
|
|||
<string name="SharedContactView_invite_to_signal">Invite to Signal</string>
|
||||
<string name="SharedContactView_message">Signal Message</string>
|
||||
|
||||
<!-- SignalBottomActionBar -->
|
||||
<string name="SignalBottomActionBar_more">More</string>
|
||||
|
||||
<!-- SignalPinReminders -->
|
||||
<string name="SignalPinReminders_well_remind_you_again_later">We\'ll remind you again later.</string>
|
||||
<string name="SignalPinReminders_well_remind_you_again_tomorrow">We\'ll remind you again tomorrow.</string>
|
||||
|
|
|
@ -384,8 +384,10 @@
|
|||
</style>
|
||||
|
||||
<style name="TextSecure.ActionModeStyle" parent="@style/Widget.AppCompat.ActionMode">
|
||||
<item name="titleTextStyle">@style/Signal.DayNight.TitleTextStyle</item>
|
||||
<item name="titleTextStyle">@style/TextAppearance.Signal.Title.ActionMode</item>
|
||||
<item name="closeItemLayout">@layout/action_mode_close_layout</item>
|
||||
<item name="theme">@style/Signal.ActionModeTheme</item>
|
||||
<item name="android:paddingStart">10dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Signal.ActionModeTheme" parent="ThemeOverlay.AppCompat">
|
||||
|
|
|
@ -166,6 +166,12 @@
|
|||
<style name="TextAppearance.Signal.Subtitle2" parent="@style/TextAppearance.MaterialComponents.Subtitle2">
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Signal.Title.ActionMode" parent="">
|
||||
<item name="android:textSize">20sp</item>
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:letterSpacing" tools:ignore="NewApi">0.01</item>
|
||||
</style>
|
||||
|
||||
<style name="Signal.Text.MessageRequest.Title" parent="Base.TextAppearance.AppCompat.Title">
|
||||
<item name="android:textSize">20sp</item>
|
||||
<item name="android:textColor">@color/signal_text_primary</item>
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
|
||||
<item name="actionBarStyle">@style/TextSecure.LightActionBar</item>
|
||||
<item name="actionBarTabBarStyle">@style/TextSecure.LightActionBar.TabBar</item>
|
||||
<item name="actionModeBackground">@color/signal_background_secondary</item>
|
||||
<item name="actionModeBackground">@color/signal_background_primary</item>
|
||||
<item name="actionModeCloseDrawable">@drawable/ic_x_tinted</item>
|
||||
<item name="actionModeStyle">@style/TextSecure.ActionModeStyle</item>
|
||||
<item name="android:textColor">@color/text_color_light_theme</item>
|
||||
|
@ -204,7 +204,7 @@
|
|||
<item name="actionBarStyle">@style/TextSecure.DarkActionBar</item>
|
||||
<item name="actionBarTabBarStyle">@style/TextSecure.DarkActionBar.TabBar</item>
|
||||
<item name="actionBarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
|
||||
<item name="actionModeBackground">@color/signal_background_secondary</item>
|
||||
<item name="actionModeBackground">@color/signal_background_primary</item>
|
||||
<item name="actionModeCloseDrawable">@drawable/ic_x_tinted</item>
|
||||
<item name="actionModeStyle">@style/TextSecure.ActionModeStyle</item>
|
||||
<item name="android:textColor">@color/text_color_dark_theme</item>
|
||||
|
|
Ładowanie…
Reference in New Issue