kopia lustrzana https://github.com/ryukoposting/Signal-Android
Show a popup menu when long-pressing on the conversation list.
rodzic
c0a68202a7
commit
3e5be2cfe2
|
@ -4,7 +4,6 @@ import android.content.Context
|
|||
import android.util.AttributeSet
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.core.content.res.use
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
|
@ -13,7 +12,6 @@ import org.thoughtcrime.securesms.badges.models.Badge
|
|||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
import java.lang.IllegalArgumentException
|
||||
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
package org.thoughtcrime.securesms.components
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
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
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.util.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.MappingModel
|
||||
import org.thoughtcrime.securesms.util.MappingViewHolder
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* This will prefer showing the menu underneath the anchor, but if there's not enough space in the container, it will show it above the anchor and reverse the
|
||||
* order of the menu items. If there's not enough room for either, it'll show it centered above the anchor. If there's not enough room then, it'll center it,
|
||||
* chop off the part that doesn't fit, and make the menu scrollable.
|
||||
*/
|
||||
class SignalContextMenu private constructor(
|
||||
val anchor: View,
|
||||
val container: View,
|
||||
val items: List<Item>,
|
||||
val baseOffsetX: Int = 0,
|
||||
val baseOffsetY: Int = 0,
|
||||
val onDismiss: Runnable? = null
|
||||
) : PopupWindow(
|
||||
LayoutInflater.from(anchor.context).inflate(R.layout.signal_context_menu, null),
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
) {
|
||||
|
||||
val context: Context = anchor.context
|
||||
|
||||
val mappingAdapter = MappingAdapter().apply {
|
||||
registerFactory(DisplayItem::class.java, ItemViewHolderFactory())
|
||||
}
|
||||
|
||||
init {
|
||||
setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.signal_context_menu_background))
|
||||
|
||||
isFocusable = true
|
||||
|
||||
if (onDismiss != null) {
|
||||
setOnDismissListener { onDismiss.run() }
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
elevation = 20f
|
||||
}
|
||||
|
||||
contentView.findViewById<RecyclerView>(R.id.signal_context_menu_list).apply {
|
||||
adapter = mappingAdapter
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
itemAnimator = null
|
||||
}
|
||||
|
||||
mappingAdapter.submitList(items.toAdapterItems())
|
||||
}
|
||||
|
||||
private fun show() {
|
||||
if (anchor.width == 0 || anchor.height == 0) {
|
||||
anchor.post(this::show)
|
||||
return
|
||||
}
|
||||
|
||||
contentView.measure(
|
||||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
|
||||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
)
|
||||
|
||||
val menuBottomBound = anchor.y + anchor.height + contentView.measuredHeight + baseOffsetY
|
||||
val menuTopBound = anchor.y - contentView.measuredHeight - baseOffsetY
|
||||
|
||||
val screenBottomBound = container.height
|
||||
val screenTopBound = container.y
|
||||
|
||||
val offsetY: Int
|
||||
|
||||
if (menuBottomBound < screenBottomBound) {
|
||||
offsetY = baseOffsetY
|
||||
} else if (menuTopBound > screenTopBound) {
|
||||
offsetY = -(anchor.height + contentView.measuredHeight + baseOffsetY)
|
||||
mappingAdapter.submitList(items.reversed().toAdapterItems())
|
||||
} else {
|
||||
offsetY = -((anchor.height / 2) + (contentView.measuredHeight / 2) + baseOffsetY)
|
||||
}
|
||||
|
||||
showAsDropDown(anchor, baseOffsetX, offsetY)
|
||||
}
|
||||
|
||||
private fun List<Item>.toAdapterItems(): List<DisplayItem> {
|
||||
return this.mapIndexed { index, item ->
|
||||
val displayType: DisplayType = when {
|
||||
this.size == 1 -> DisplayType.ONLY
|
||||
index == 0 -> DisplayType.TOP
|
||||
index == this.size - 1 -> DisplayType.BOTTOM
|
||||
else -> DisplayType.MIDDLE
|
||||
}
|
||||
|
||||
DisplayItem(item, displayType)
|
||||
}
|
||||
}
|
||||
|
||||
data class Item(
|
||||
@DrawableRes val iconRes: Int,
|
||||
@StringRes val titleRes: Int,
|
||||
val action: Runnable
|
||||
)
|
||||
|
||||
private data class DisplayItem(
|
||||
val item: Item,
|
||||
val displayType: DisplayType
|
||||
) : MappingModel<DisplayItem> {
|
||||
override fun areItemsTheSame(newItem: DisplayItem): Boolean {
|
||||
return this == newItem
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(newItem: DisplayItem): Boolean {
|
||||
return this == newItem
|
||||
}
|
||||
}
|
||||
|
||||
enum class DisplayType {
|
||||
TOP, BOTTOM, MIDDLE, ONLY
|
||||
}
|
||||
|
||||
private inner class ItemViewHolder(itemView: View) : MappingViewHolder<DisplayItem>(itemView) {
|
||||
val icon: ImageView = itemView.findViewById(R.id.signal_context_menu_item_icon)
|
||||
val title: TextView = itemView.findViewById(R.id.signal_context_menu_item_title)
|
||||
|
||||
override fun bind(model: DisplayItem) {
|
||||
icon.setImageResource(model.item.iconRes)
|
||||
title.setText(model.item.titleRes)
|
||||
itemView.setOnClickListener {
|
||||
model.item.action.run()
|
||||
dismiss()
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
when (model.displayType) {
|
||||
DisplayType.TOP -> itemView.setBackgroundResource(R.drawable.signal_context_menu_item_background_top)
|
||||
DisplayType.BOTTOM -> itemView.setBackgroundResource(R.drawable.signal_context_menu_item_background_bottom)
|
||||
DisplayType.MIDDLE -> itemView.setBackgroundResource(R.drawable.signal_context_menu_item_background_middle)
|
||||
DisplayType.ONLY -> itemView.setBackgroundResource(R.drawable.signal_context_menu_item_background_only)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ItemViewHolderFactory : MappingAdapter.Factory<DisplayItem> {
|
||||
override fun createViewHolder(parent: ViewGroup): MappingViewHolder<DisplayItem> {
|
||||
return ItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.signal_context_menu_item, parent, false))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
) {
|
||||
|
||||
var onDismiss: Runnable? = null
|
||||
var offsetX: Int = 0
|
||||
var offsetY: Int = 0
|
||||
|
||||
fun onDismiss(onDismiss: Runnable): Builder {
|
||||
this.onDismiss = onDismiss
|
||||
return this
|
||||
}
|
||||
|
||||
fun offsetX(offsetPx: Int): Builder {
|
||||
this.offsetX = offsetPx
|
||||
return this
|
||||
}
|
||||
|
||||
fun offsetY(offsetPx: Int): Builder {
|
||||
this.offsetY = offsetPx
|
||||
return this
|
||||
}
|
||||
|
||||
fun show(items: List<Item>) {
|
||||
SignalContextMenu(
|
||||
anchor = anchor,
|
||||
container = container,
|
||||
items = items,
|
||||
baseOffsetX = offsetX,
|
||||
baseOffsetY = offsetY,
|
||||
onDismiss = onDismiss
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -90,7 +90,7 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
|
|||
int position = holder.getAdapterPosition();
|
||||
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
return onConversationClickListener.onConversationLongClick(getItem(position));
|
||||
return onConversationClickListener.onConversationLongClick(getItem(position), v);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -302,8 +302,8 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
|
|||
}
|
||||
|
||||
interface OnConversationClickListener {
|
||||
void onConversationClick(Conversation conversation);
|
||||
boolean onConversationLongClick(Conversation conversation);
|
||||
void onConversationClick(@NonNull Conversation conversation);
|
||||
boolean onConversationLongClick(@NonNull Conversation conversation, @NonNull View view);
|
||||
void onShowArchiveClick();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import androidx.transition.TransitionManager;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
@ -79,6 +80,7 @@ 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.UnreadPaymentsView;
|
||||
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
|
||||
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
|
||||
|
@ -145,6 +147,8 @@ import org.thoughtcrime.securesms.util.views.Stub;
|
|||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
|
@ -762,12 +766,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
});
|
||||
}
|
||||
|
||||
private void handleMarkSelectedAsRead() {
|
||||
Context context = requireContext();
|
||||
Set<Long> selectedConversations = new HashSet<>(defaultAdapter.getBatchSelectionIds());
|
||||
private void handleMarkAsRead(@NonNull Collection<Long> ids) {
|
||||
Context context = requireContext();
|
||||
|
||||
SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> {
|
||||
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(selectedConversations, false);
|
||||
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(ids, false);
|
||||
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||
MarkReadReceiver.process(context, messageIds);
|
||||
|
@ -781,12 +784,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
});
|
||||
}
|
||||
|
||||
private void handleMarkSelectedAsUnread() {
|
||||
Context context = requireContext();
|
||||
Set<Long> selectedConversations = new HashSet<>(defaultAdapter.getBatchSelectionIds());
|
||||
private void handleMarkAsUnread(@NonNull Collection<Long> ids) {
|
||||
Context context = requireContext();
|
||||
|
||||
SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> {
|
||||
DatabaseFactory.getThreadDatabase(context).setForcedUnread(selectedConversations);
|
||||
DatabaseFactory.getThreadDatabase(context).setForcedUnread(ids);
|
||||
StorageSyncHelper.scheduleSyncForDataChange();
|
||||
return null;
|
||||
}, none -> {
|
||||
|
@ -806,8 +808,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private void handleArchiveAllSelected() {
|
||||
Set<Long> selectedConversations = new HashSet<>(defaultAdapter.getBatchSelectionIds());
|
||||
private void handleArchive(@NonNull Collection<Long> ids, boolean showProgress) {
|
||||
Set<Long> selectedConversations = new HashSet<>(ids);
|
||||
int count = selectedConversations.size();
|
||||
String snackBarTitle = getResources().getQuantityString(getArchivedSnackbarTitleRes(), count, count);
|
||||
|
||||
|
@ -816,7 +818,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
snackBarTitle,
|
||||
getString(R.string.ConversationListFragment_undo),
|
||||
getResources().getColor(R.color.amber_500),
|
||||
Snackbar.LENGTH_LONG, true)
|
||||
Snackbar.LENGTH_LONG,
|
||||
showProgress)
|
||||
{
|
||||
|
||||
@Override
|
||||
|
@ -838,22 +841,23 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
protected void reverseAction(@Nullable Void parameter) {
|
||||
reverseArchiveThreads(selectedConversations);
|
||||
}
|
||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}.executeOnExecutor(SignalExecutors.BOUNDED);
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private void handleDeleteAllSelected() {
|
||||
int conversationsCount = defaultAdapter.getBatchSelectionIds().size();
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
|
||||
alert.setIcon(R.drawable.ic_warning);
|
||||
alert.setTitle(getActivity().getResources().getQuantityString(R.plurals.ConversationListFragment_delete_selected_conversations,
|
||||
conversationsCount, conversationsCount));
|
||||
alert.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationListFragment_this_will_permanently_delete_all_n_selected_conversations,
|
||||
conversationsCount, conversationsCount));
|
||||
private void handleDelete(@NonNull Collection<Long> ids) {
|
||||
int conversationsCount = ids.size();
|
||||
MaterialAlertDialogBuilder alert = new MaterialAlertDialogBuilder(requireActivity());
|
||||
Context context = requireContext();
|
||||
|
||||
alert.setTitle(context.getResources().getQuantityString(R.plurals.ConversationListFragment_delete_selected_conversations,
|
||||
conversationsCount, conversationsCount));
|
||||
alert.setMessage(context.getResources().getQuantityString(R.plurals.ConversationListFragment_this_will_permanently_delete_all_n_selected_conversations,
|
||||
conversationsCount, conversationsCount));
|
||||
alert.setCancelable(true);
|
||||
|
||||
alert.setPositiveButton(R.string.delete, (dialog, which) -> {
|
||||
final Set<Long> selectedConversations = new HashSet<>(defaultAdapter.getBatchSelectionIds());
|
||||
final Set<Long> selectedConversations = new HashSet<>(ids);
|
||||
|
||||
if (!selectedConversations.isEmpty()) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
|
@ -861,16 +865,16 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
dialog = ProgressDialog.show(getActivity(),
|
||||
getActivity().getString(R.string.ConversationListFragment_deleting),
|
||||
getActivity().getString(R.string.ConversationListFragment_deleting_selected_conversations),
|
||||
dialog = ProgressDialog.show(requireActivity(),
|
||||
context.getString(R.string.ConversationListFragment_deleting),
|
||||
context.getString(R.string.ConversationListFragment_deleting_selected_conversations),
|
||||
true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getThreadDatabase(getActivity()).deleteConversations(selectedConversations);
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(getActivity());
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(requireActivity());
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -882,7 +886,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
actionMode = null;
|
||||
}
|
||||
}
|
||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}.executeOnExecutor(SignalExecutors.BOUNDED);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -890,8 +894,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
alert.show();
|
||||
}
|
||||
|
||||
private void handlePinAllSelected() {
|
||||
final Set<Long> toPin = new LinkedHashSet<>(Stream.of(defaultAdapter.getBatchSelection())
|
||||
private void handlePin(@NonNull Collection<Conversation> conversations) {
|
||||
final Set<Long> toPin = new LinkedHashSet<>(Stream.of(conversations)
|
||||
.filterNot(conversation -> conversation.getThreadRecord().isPinned())
|
||||
.map(conversation -> conversation.getThreadRecord().getThreadId())
|
||||
.toList());
|
||||
|
@ -902,7 +906,9 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
Snackbar.LENGTH_LONG)
|
||||
.setTextColor(Color.WHITE)
|
||||
.show();
|
||||
actionMode.finish();
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -919,13 +925,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
});
|
||||
}
|
||||
|
||||
private void handleUnpinAllSelected() {
|
||||
final Set<Long> toPin = new HashSet<>(defaultAdapter.getBatchSelectionIds());
|
||||
|
||||
private void handleUnpin(@NonNull Collection<Long> ids) {
|
||||
SimpleTask.run(SignalExecutors.BOUNDED, () -> {
|
||||
ThreadDatabase db = DatabaseFactory.getThreadDatabase(ApplicationDependencies.getApplication());
|
||||
|
||||
db.unpinConversations(toPin);
|
||||
db.unpinConversations(ids);
|
||||
|
||||
return null;
|
||||
}, unused -> {
|
||||
|
@ -1005,7 +1009,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onConversationClick(Conversation conversation) {
|
||||
public void onConversationClick(@NonNull Conversation conversation) {
|
||||
if (actionMode == null) {
|
||||
handleCreateConversation(conversation.getThreadRecord().getThreadId(), conversation.getThreadRecord().getRecipient(), conversation.getThreadRecord().getDistributionType());
|
||||
} else {
|
||||
|
@ -1021,16 +1025,51 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onConversationLongClick(Conversation conversation) {
|
||||
public boolean onConversationLongClick(@NonNull Conversation conversation, @NonNull View view) {
|
||||
if (actionMode != null) {
|
||||
onConversationClick(conversation);
|
||||
return true;
|
||||
}
|
||||
|
||||
defaultAdapter.initializeBatchMode(true);
|
||||
defaultAdapter.toggleConversationInBatchSet(conversation);
|
||||
view.setSelected(true);
|
||||
|
||||
actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(ConversationListFragment.this);
|
||||
Collection<Long> id = Collections.singleton(conversation.getThreadRecord().getThreadId());
|
||||
|
||||
List<SignalContextMenu.Item> 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)));
|
||||
} else {
|
||||
items.add(new SignalContextMenu.Item(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)));
|
||||
} else {
|
||||
items.add(new SignalContextMenu.Item(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, () -> {
|
||||
defaultAdapter.initializeBatchMode(true);
|
||||
defaultAdapter.toggleConversationInBatchSet(conversation);
|
||||
actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(ConversationListFragment.this);
|
||||
}));
|
||||
|
||||
if (conversation.getThreadRecord().isArchived()) {
|
||||
items.add(new SignalContextMenu.Item(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 SignalContextMenu.Item(R.drawable.ic_delete_24, R.string.ConversationListFragment_delete, () -> handleDelete(id)));
|
||||
|
||||
new SignalContextMenu.Builder(view, list)
|
||||
.offsetX(ViewUtil.dpToPx(12))
|
||||
.offsetY(ViewUtil.dpToPx(12))
|
||||
.onDismiss(() -> view.setSelected(false))
|
||||
.show(items);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1059,13 +1098,13 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||
@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: handleDeleteAllSelected(); return true;
|
||||
case R.id.menu_pin_selected: handlePinAllSelected(); return true;
|
||||
case R.id.menu_unpin_selected: handleUnpinAllSelected(); return true;
|
||||
case R.id.menu_archive_selected: handleArchiveAllSelected(); return true;
|
||||
case R.id.menu_mark_as_read: handleMarkSelectedAsRead(); return true;
|
||||
case R.id.menu_mark_as_unread: handleMarkSelectedAsUnread(); return true;
|
||||
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;
|
||||
|
|
|
@ -867,7 +867,7 @@ public class ThreadDatabase extends Database {
|
|||
StorageSyncHelper.scheduleSyncForDataChange();
|
||||
}
|
||||
|
||||
public void unpinConversations(@NonNull Set<Long> threadIds) {
|
||||
public void unpinConversations(@NonNull Collection<Long> threadIds) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
String placeholders = StringUtil.join(Stream.of(threadIds).map(unused -> "?").toList(), ",");
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<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="M16.5646,3.5C16.7046,3.5 16.8396,3.56 16.9346,3.665L18.5837,5.5H5.1295L6.9446,3.65C7.0346,3.555 7.1646,3.5 7.2996,3.5H16.5646ZM16.5646,2H7.2996C6.7646,2 6.2496,2.215 5.8696,2.6L3.5296,4.985C3.1646,5.36 2.9596,5.86 2.9596,6.385V19C2.9596,20.105 3.8546,21 4.9596,21H18.9596C20.0646,21 20.9596,20.105 20.9596,19V6.665C20.9596,6.17 20.7796,5.695 20.4496,5.33L18.0546,2.665C17.6746,2.24 17.1346,2 16.5646,2ZM9.5203,12L8.4596,13.0607L11.9951,16.5962L12.0077,16.5836L12.0203,16.5962L15.5558,13.0607L14.4951,12L12.7096,13.7855V9H11.2096V13.6893L9.5203,12Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"
|
||||
android:fillType="evenOdd"/>
|
||||
</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:pathData="M16.38,4.5C16.1558,3.5058 15.6,2.6174 14.804,1.981C14.008,1.3445 13.0192,0.9978 12,0.9978C10.9808,0.9978 9.992,1.3445 9.196,1.981C8.4,2.6174 7.8442,3.5058 7.62,4.5H2V6H3.5L4.86,20C4.9216,20.5507 5.1842,21.0593 5.5975,21.4284C6.0109,21.7974 6.5459,22.001 7.1,22H16.9C17.4541,22.001 17.9891,21.7974 18.4025,21.4284C18.8158,21.0593 19.0784,20.5507 19.14,20L20.5,6H22V4.5H16.38ZM12,2.5C12.6189,2.5017 13.2222,2.6949 13.7271,3.0529C14.2319,3.411 14.6137,3.9165 14.82,4.5H9.18C9.3863,3.9165 9.7681,3.411 10.2729,3.0529C10.7778,2.6949 11.3811,2.5017 12,2.5V2.5ZM8,18L7.5,8H9L9.5,18H8ZM12.75,18H11.25V8H12.75V18ZM16,18H14.5L15,8H16.5L16,18Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"/>
|
||||
</vector>
|
|
@ -3,16 +3,8 @@
|
|||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h24v24h-24z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M-0.95,10.94l12.9966,-12.9966l12.9966,12.9966l-12.9966,12.9966z"/>
|
||||
<path
|
||||
android:pathData="M18.9402,13.6639C18.9402,12.1584 17.3915,10.8804 15.1116,10.236L15.1116,7.615C15.7458,7.3572 16.2955,6.9277 16.6992,6.3748C17.1028,5.822 17.3444,5.1676 17.3969,4.485C17.3969,3.6402 14.9979,2.9525 12.0358,2.9579C9.0736,2.9633 6.6855,3.6294 6.6747,4.485C6.7271,5.1676 6.9688,5.822 7.3724,6.3748C7.7761,6.9277 8.3258,7.3572 8.9599,7.615L8.9816,10.236C6.7126,10.8588 5.153,12.1584 5.153,13.6639C5.153,15.1693 7.9364,16.2199 11.4726,16.3336L11.4726,21.7489L12.0466,22.8536L12.6206,21.7055L12.6206,16.2903C16.1568,16.2199 18.9402,15.0718 18.9402,13.6639Z"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M6.779,1.6996H16.7227C17.3729,1.6996 17.8373,2.36 17.6,2.9736C17.2233,3.946 16.4131,4.7624 15.3604,5.3188V9.0472C17.342,9.8168 18.8694,11.278 19.4422,13.0824C19.695,13.878 19.0861,14.6996 18.2502,14.6996H12.5V21.0816L11.75,22.5L11,21.0816V14.6996H5.2464C4.4156,14.6996 3.8016,13.878 4.0596,13.0772C4.6324,11.2728 6.1598,9.8116 8.1413,9.042V5.3136C7.0835,4.7624 6.2785,3.9408 5.9018,2.9684C5.6644,2.36 6.1288,1.6996 6.779,1.6996Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"
|
||||
android:fillType="evenOdd"/>
|
||||
</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:pathData="M12,2.5C6.2,2.5 1.5,6.529 1.5,11.5C1.5197,13.5188 2.2868,15.4586 3.653,16.945L3.014,20.781C2.924,21.323 3.277,21.625 3.798,21.451L8.356,19.932C9.5342,20.3077 10.7633,20.4993 12,20.5C17.8,20.5 22.5,16.471 22.5,11.5C22.5,6.529 17.727,2.5 12,2.5Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"/>
|
||||
</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:pathData="M12,1C9.8244,1 7.6977,1.6451 5.8887,2.8538C4.0798,4.0625 2.6699,5.7805 1.8373,7.7905C1.0048,9.8005 0.7869,12.0122 1.2114,14.146C1.6358,16.2798 2.6834,18.2398 4.2218,19.7782C5.7602,21.3166 7.7202,22.3642 9.854,22.7886C11.9878,23.2131 14.1995,22.9952 16.2095,22.1627C18.2195,21.3301 19.9375,19.9202 21.1462,18.1113C22.3549,16.3023 23,14.1756 23,12C23,9.0826 21.8411,6.2847 19.7782,4.2218C17.7153,2.1589 14.9174,1 12,1V1ZM10.232,17L6.166,12.934L7.227,11.874L10.227,14.874L16.768,8.333L17.834,9.4L10.232,17Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"/>
|
||||
</vector>
|
|
@ -0,0 +1,10 @@
|
|||
<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="M16.605,3.5C16.745,3.5 16.88,3.56 16.975,3.665L18.6241,5.5H5.1699L6.985,3.65C7.075,3.555 7.205,3.5 7.34,3.5H16.605ZM16.605,2H7.34C6.805,2 6.29,2.215 5.91,2.6L3.57,4.985C3.205,5.36 3,5.86 3,6.385V19C3,20.105 3.895,21 5,21H19C20.105,21 21,20.105 21,19V6.665C21,6.17 20.82,5.695 20.49,5.33L18.095,2.665C17.715,2.24 17.175,2 16.605,2ZM11.3462,16.5962H12.8462V11.9069L14.5355,13.5962L15.5962,12.5355L12.0607,9L12.0481,9.0126L12.0355,9L8.5,12.5355L9.5606,13.5962L11.3462,11.8107V16.5962Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -3,15 +3,8 @@
|
|||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h24v24h-24z"/>
|
||||
<path
|
||||
android:pathData="M17.7347,11.5045C18.4966,12.1176 18.9402,12.8582 18.9402,13.6639C18.9402,15.0719 16.1568,16.2199 12.6206,16.2903V21.7055L12.0466,22.8536L11.4726,21.7489L11.4726,16.759L17.7347,11.5045ZM16.3722,10.6896L9.8005,16.2039C7.0974,15.8626 5.153,14.9221 5.153,13.6639C5.153,12.1584 6.7126,10.8588 8.9816,10.236L8.9599,7.615C8.3258,7.3572 7.7761,6.9277 7.3724,6.3748C6.9688,5.822 6.7271,5.1676 6.6747,4.485C6.6855,3.6294 9.0736,2.9633 12.0358,2.9579C14.9979,2.9525 17.3969,3.6402 17.3969,4.485C17.3444,5.1676 17.1028,5.822 16.6992,6.3748C16.2955,6.9277 15.7458,7.3572 15.1116,7.615V10.236C15.5626,10.3635 15.9849,10.5157 16.3722,10.6896Z"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M3.91,21.1491l-0.9642,-1.1491l19.1511,-16.0697l0.9642,1.1491z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M6.779,1.6996H16.7227C17.3729,1.6996 17.8373,2.36 17.6,2.9736C17.2233,3.946 16.4131,4.7624 15.3604,5.3188V7.6702L20.4209,3.424L21.3851,4.5731L3,20L2.0358,18.8509L6.9832,14.6996H5.2464C4.4156,14.6996 3.8016,13.878 4.0596,13.0772C4.6323,11.2728 6.1598,9.8116 8.1413,9.042V5.3136C7.0834,4.7624 6.2785,3.9408 5.9018,2.9684C5.6644,2.36 6.1288,1.6996 6.779,1.6996ZM11,15.2068L17.1678,10.0313C18.2521,10.8263 19.0598,11.8779 19.4422,13.0824C19.695,13.878 19.0861,14.6996 18.2502,14.6996H12.5V21.0816L11.75,22.5L11,21.0816V15.2068Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<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="M12,2.5C13.067,2.5 14.1009,2.6399 15.077,2.8996C14.4026,3.7518 14,4.8289 14,6C14,8.7614 16.2386,11 19,11C20.2647,11 21.4198,10.5304 22.3003,9.7561C22.4312,10.3203 22.5,10.9034 22.5,11.5C22.5,16.471 17.8,20.5 12,20.5C10.7633,20.4993 9.5342,20.3077 8.356,19.932L3.798,21.451C3.277,21.625 2.924,21.323 3.014,20.781L3.653,16.945C2.2868,15.4586 1.5197,13.5188 1.5,11.5C1.5,6.529 6.2,2.5 12,2.5Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"/>
|
||||
<path
|
||||
android:pathData="M19,9.5C20.933,9.5 22.5,7.933 22.5,6C22.5,4.067 20.933,2.5 19,2.5C17.067,2.5 15.5,4.067 15.5,6C15.5,7.933 17.067,9.5 19,9.5Z"
|
||||
android:fillColor="@color/signal_icon_tint_primary"/>
|
||||
</vector>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/signal_button_primary_ripple">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/black" />
|
||||
<corners
|
||||
android:topLeftRadius="0dp"
|
||||
android:topRightRadius="0dp"
|
||||
android:bottomLeftRadius="@dimen/signal_context_menu_corner_radius"
|
||||
android:bottomRightRadius="@dimen/signal_context_menu_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/signal_button_primary_ripple">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/black" />
|
||||
<corners
|
||||
android:topLeftRadius="0dp"
|
||||
android:topRightRadius="0dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/signal_button_primary_ripple">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/black" />
|
||||
<corners
|
||||
android:topLeftRadius="@dimen/signal_context_menu_corner_radius"
|
||||
android:topRightRadius="@dimen/signal_context_menu_corner_radius"
|
||||
android:bottomLeftRadius="@dimen/signal_context_menu_corner_radius"
|
||||
android:bottomRightRadius="@dimen/signal_context_menu_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/signal_button_primary_ripple">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/black" />
|
||||
<corners
|
||||
android:topLeftRadius="@dimen/signal_context_menu_corner_radius"
|
||||
android:topRightRadius="@dimen/signal_context_menu_corner_radius"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -0,0 +1,10 @@
|
|||
<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="M16.605,3.5C16.745,3.5 16.88,3.56 16.975,3.665L18.6241,5.5H5.1699L6.985,3.65C7.075,3.555 7.205,3.5 7.34,3.5H16.605ZM4.5,7H19.5V19C19.5,19.275 19.275,19.5 19,19.5H5C4.725,19.5 4.5,19.275 4.5,19V7ZM16.605,2H7.34C6.805,2 6.29,2.215 5.91,2.6L3.57,4.985C3.205,5.36 3,5.86 3,6.385V19C3,20.105 3.895,21 5,21H19C20.105,21 21,20.105 21,19V6.665C21,6.17 20.82,5.695 20.49,5.33L18.095,2.665C17.715,2.24 17.175,2 16.605,2ZM11.25,9H12.75V13.7856L14.5355,12L15.5962,13.0607L12.0607,16.5962L12.0481,16.5837L12.0355,16.5962L8.5,13.0607L9.5607,12L11.25,13.6894V9Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</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:pathData="M22,4.5H16.35C16.1356,3.5056 15.5869,2.6147 14.7954,1.9756C14.0038,1.3366 13.0173,0.9881 12,0.9881C10.9827,0.9881 9.9962,1.3366 9.2046,1.9756C8.4131,2.6147 7.8644,3.5056 7.65,4.5H2V6H3.5L4.86,20C4.9216,20.5507 5.1842,21.0593 5.5975,21.4284C6.0109,21.7974 6.5459,22.001 7.1,22H16.9C17.4541,22.001 17.9891,21.7974 18.4025,21.4284C18.8158,21.0593 19.0784,20.5507 19.14,20L20.5,6H22V4.5ZM12,2.5C12.6189,2.5017 13.2222,2.6949 13.7271,3.0529C14.2319,3.411 14.6137,3.9165 14.82,4.5H9.18C9.3863,3.9165 9.7681,3.411 10.2729,3.0529C10.7778,2.6949 11.3811,2.5017 12,2.5V2.5ZM17.65,19.83C17.6281,20.0139 17.5398,20.1834 17.4017,20.3068C17.2636,20.4302 17.0852,20.4989 16.9,20.5H7.1C6.9148,20.4989 6.7364,20.4302 6.5983,20.3068C6.4602,20.1834 6.3719,20.0139 6.35,19.83L5,6H19L17.65,19.83ZM11.25,18V8H12.75V18H11.25ZM14.5,18L15,8H16.5L16,18H14.5ZM8,18L7.5,8H9L9.5,18H8Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
|
@ -3,11 +3,8 @@
|
|||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h24v24h-24z"/>
|
||||
<path
|
||||
android:pathData="M19.5223,13.9603C19.5223,12.3268 17.8418,10.9401 15.3681,10.2408L15.3681,7.3969C16.0561,7.1171 16.6526,6.6511 17.0906,6.0512C17.5286,5.4513 17.7908,4.7412 17.8477,4.0006C17.8477,3.084 15.2447,2.3377 12.0305,2.3436C8.8164,2.3495 6.2251,3.0722 6.2133,4.0006C6.2703,4.7412 6.5324,5.4513 6.9704,6.0512C7.4084,6.6511 8.0049,7.1171 8.693,7.3969L8.7165,10.2408C6.2545,10.9166 4.5622,12.3268 4.5622,13.9603C4.5622,15.5938 7.5824,16.7338 11.4194,16.8571L11.4194,22.7331L12.0423,23.9318L12.6651,22.6861L12.6651,16.8101C16.5021,16.7338 19.5223,15.4881 19.5223,13.9603ZM12.0423,15.6232C8.0466,15.6232 5.9372,14.4069 5.8079,13.9603C5.8138,13.0025 7.1359,11.9742 9.0514,11.4454L9.9681,11.1869L9.9857,6.5978L9.2982,6.2511C8.8704,6.0808 8.4878,5.814 8.18,5.4715C7.8722,5.1291 7.6476,4.7202 7.5237,4.2768C8.9716,3.725 10.5181,3.4789 12.0658,3.554C13.6135,3.4789 15.1599,3.725 16.6079,4.2768C16.484,4.7202 16.2594,5.1291 15.9516,5.4715C15.6438,5.814 15.2611,6.0808 14.8333,6.2511L14.0989,6.5978L14.0989,11.1692L15.0155,11.4278C16.9487,11.9742 18.2708,13.0025 18.2766,13.9368C18.1474,14.4069 16.0379,15.6232 12.0423,15.6232Z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M14.6483,3.9356C15.0147,3.7432 15.3295,3.5144 15.5823,3.2596H7.9194C8.1723,3.5144 8.4922,3.7432 8.8534,3.9356L9.6842,4.3724V5.3188V9.0472V10.1184L8.6934,10.5032C7.2744,11.0544 6.2062,12.0008 5.6902,13.1396H17.8115C17.2955,12.0008 16.2274,11.0544 14.8083,10.5032L13.8175,10.1184V9.0472V5.3188V4.3724L14.6483,3.9356ZM6.779,1.6996H16.7227C17.3729,1.6996 17.8373,2.36 17.6,2.9736C17.2233,3.946 16.4131,4.7624 15.3604,5.3188V9.0472C17.342,9.8168 18.8694,11.278 19.4422,13.0824C19.695,13.878 19.0861,14.6996 18.2502,14.6996H12.5V21.0816L11.75,22.5L11,21.0816V14.6996H5.2464C4.4156,14.6996 3.8016,13.878 4.0596,13.0772C4.6324,11.2728 6.1598,9.8116 8.1413,9.042V5.3136C7.0835,4.7624 6.2785,3.9408 5.9018,2.9684C5.6644,2.36 6.1288,1.6996 6.779,1.6996Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<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="M4.3928,17.0682L4.453,16.707L4.2052,16.4375C2.9653,15.0885 2.2688,13.3283 2.25,11.4963C2.2523,7.0454 6.5031,3.25 12,3.25C17.429,3.25 21.75,7.0506 21.75,11.5C21.75,15.9524 17.4986,19.7498 12.0004,19.75C10.841,19.7493 9.6885,19.5697 8.5838,19.2174L8.3509,19.1432L8.1189,19.2205L3.7942,20.6617L4.3928,17.0682Z"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"/>
|
||||
</vector>
|
|
@ -1,5 +1,9 @@
|
|||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFFFF" android:pathData="M8.5,4.75L22,4.75v1.5L8.5,6.25ZM8.5,12.75L22,12.75v-1.5L8.5,11.25ZM8.5,19.25L22,19.25v-1.5L8.5,17.75ZM4.5,4.5a1,1 0,1 0,1 1,1 1,0 0,0 -1,-1M4.5,3A2.5,2.5 0,1 1,2 5.5,2.5 2.5,0 0,1 4.5,3ZM4.5,11a1,1 0,1 0,1 1,1 1,0 0,0 -1,-1m0,-1.5A2.5,2.5 0,1 1,2 12,2.5 2.5,0 0,1 4.5,9.5ZM4.5,17.5a1,1 0,1 0,1 1,1 1,0 0,0 -1,-1m0,-1.5A2.5,2.5 0,1 1,2 18.5,2.5 2.5,0 0,1 4.5,16Z"/>
|
||||
<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="M12,2.5C13.8789,2.5 15.7156,3.0572 17.2779,4.101C18.8402,5.1449 20.0578,6.6286 20.7769,8.3645C21.4959,10.1004 21.684,12.0105 21.3175,13.8534C20.9509,15.6962 20.0461,17.3889 18.7175,18.7175C17.3889,20.0461 15.6962,20.9509 13.8534,21.3175C12.0105,21.684 10.1004,21.4959 8.3645,20.7769C6.6286,20.0578 5.1449,18.8402 4.101,17.2779C3.0572,15.7157 2.5,13.8789 2.5,12C2.5029,9.4813 3.5047,7.0667 5.2857,5.2857C7.0667,3.5047 9.4813,2.5029 12,2.5V2.5ZM12,1C9.8244,1 7.6977,1.6451 5.8887,2.8538C4.0798,4.0625 2.6699,5.7805 1.8373,7.7905C1.0048,9.8005 0.7869,12.0122 1.2114,14.146C1.6358,16.2798 2.6834,18.2398 4.2218,19.7782C5.7602,21.3166 7.7202,22.3642 9.854,22.7886C11.9878,23.2131 14.1995,22.9952 16.2095,22.1627C18.2195,21.3301 19.9375,19.9202 21.1462,18.1113C22.3549,16.3023 23,14.1756 23,12C23,9.0826 21.8411,6.2847 19.7782,4.2218C17.7153,2.1589 14.9174,1 12,1V1ZM17.834,9.4L16.773,8.338L10.232,14.879L7.232,11.879L6.171,12.939L10.232,17L17.834,9.4Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<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="M16.605,3.5C16.745,3.5 16.88,3.56 16.975,3.665L19.37,6.33C19.455,6.425 19.5,6.545 19.5,6.665V19C19.5,19.275 19.275,19.5 19,19.5H5C4.725,19.5 4.5,19.275 4.5,19V6.385C4.5,6.255 4.55,6.13 4.645,6.035L6.985,3.65C7.075,3.555 7.205,3.5 7.34,3.5H16.605ZM16.605,2H7.34C6.805,2 6.29,2.215 5.91,2.6L3.57,4.985C3.205,5.36 3,5.86 3,6.385V19C3,20.105 3.895,21 5,21H19C20.105,21 21,20.105 21,19V6.665C21,6.17 20.82,5.695 20.49,5.33L18.095,2.665C17.715,2.24 17.175,2 16.605,2Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M20,5.5H4V7H20V5.5Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M11.3252,16.6644H12.8252V10.1644H11.3252V16.6644Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M14.5145,13.6645L15.5752,12.6038L12.0397,9.0683L10.979,10.1289L14.5145,13.6645Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M9.5397,13.6645L8.4791,12.6038L12.0146,9.0683L13.0753,10.1289L9.5397,13.6645Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
|
@ -3,15 +3,8 @@
|
|||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h24v24h-24z"/>
|
||||
<path
|
||||
android:pathData="M17.8973,11.368C18.9291,12.0782 19.5428,12.9757 19.5428,13.9633C19.5428,15.4926 16.5195,16.7396 12.6787,16.816V22.6978L12.0552,23.9448L11.4318,22.7449L11.4318,16.8631C11.4051,16.8622 11.3784,16.8613 11.3518,16.8603L12.8397,15.6118C16.331,15.4668 18.1752,14.3786 18.2958,13.9398C18.2921,13.3517 17.7674,12.7264 16.8972,12.2072L17.8973,11.368ZM16.4669,10.6102C16.127,10.4716 15.765,10.3478 15.3843,10.2402V7.3934C16.0731,7.1133 16.6702,6.6468 17.1086,6.0463C17.5471,5.4458 17.8095,4.735 17.8665,3.9937C17.8665,3.0761 15.2608,2.3291 12.0435,2.335C8.8261,2.3409 6.2323,3.0644 6.2205,3.9937C6.2775,4.735 6.5399,5.4458 6.9783,6.0463C7.4168,6.6468 8.0139,7.1133 8.7026,7.3934L8.7261,10.2402C6.2617,10.9166 4.5677,12.3282 4.5677,13.9633C4.5677,15.2716 6.5029,16.2635 9.2437,16.6711L10.5586,15.5679C7.5286,15.3174 5.9268,14.3509 5.8147,13.9633C5.8205,13.0046 7.1439,11.9753 9.0614,11.4459L9.979,11.1871L9.9966,6.5935L9.3084,6.2464C8.8802,6.0759 8.4972,5.8089 8.1891,5.4661C7.881,5.1233 7.6562,4.714 7.5321,4.2701C8.9815,3.7178 10.5295,3.4715 12.0788,3.5467C13.628,3.4715 15.176,3.7178 16.6254,4.2701C16.5014,4.714 16.2766,5.1233 15.9685,5.4661C15.6604,5.8089 15.2773,6.0759 14.8491,6.2464L14.1139,6.5935V11.1695L15.0314,11.4283C15.1464,11.4608 15.2592,11.495 15.3698,11.5308L16.4669,10.6102Z"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M3.9071,21.1491l-0.9642,-1.1491l19.1511,-16.0697l0.9642,1.1491z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M14.6483,3.9356C15.0147,3.7432 15.3295,3.5144 15.5823,3.2596H7.9194C8.1723,3.5144 8.4922,3.7432 8.8534,3.9356L9.6842,4.3724V5.3188V9.0472V10.1184L8.6934,10.5032C7.2744,11.0544 6.2062,12.0008 5.6902,13.1396H8.8423L13.8175,8.9649V5.3188V4.3724L14.6483,3.9356ZM15.3604,7.6702V5.3188C16.4131,4.7624 17.2233,3.946 17.6,2.9736C17.8373,2.36 17.3729,1.6996 16.7227,1.6996H6.779C6.1288,1.6996 5.6644,2.36 5.9018,2.9684C6.2785,3.9408 7.0834,4.7624 8.1413,5.3136V9.042C6.1598,9.8116 4.6323,11.2728 4.0596,13.0772C3.8015,13.878 4.4156,14.6996 5.2464,14.6996H6.9832L2.0358,18.8509L3,20L21.3851,4.5731L20.4209,3.424L15.3604,7.6702ZM11,15.2068L13.4635,13.1396H17.8115C17.4428,12.3259 16.7923,11.6105 15.9333,11.0672L17.1678,10.0313C18.2521,10.8263 19.0598,11.8779 19.4422,13.0824C19.695,13.878 19.0861,14.6996 18.2502,14.6996H12.5V21.0816L11.75,22.5L11,21.0816V15.2068Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<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="M22.1528,9.2109C22.9843,8.3944 23.5,7.2574 23.5,6C23.5,3.5147 21.4853,1.5 19,1.5C17.6424,1.5 16.4251,2.1012 15.6,3.052C14.4733,2.6949 13.2597,2.5 12,2.5C6.2,2.5 1.5,6.529 1.5,11.5C1.5197,13.5188 2.2868,15.4586 3.653,16.945L3.014,20.781C2.924,21.323 3.277,21.625 3.798,21.451L8.356,19.932C9.5342,20.3077 10.7633,20.4993 12,20.5C17.8,20.5 22.5,16.471 22.5,11.5C22.5,10.709 22.3791,9.9418 22.1528,9.2109ZM20.8378,10.1088C20.9444,10.5638 21,11.0293 21,11.5C21,15.4338 17.1972,18.9996 12.0009,19C10.9186,18.9994 9.8428,18.8317 8.8117,18.5029L8.3457,18.3543L7.8818,18.5089L4.7387,19.5564L5.1326,17.1915L5.253,16.4691L4.7573,15.9299C3.6438,14.7184 3.0179,13.1379 3,11.4927C3.0047,7.5616 6.8064,4 12,4C12.9872,4 13.9276,4.1322 14.8028,4.3738C14.6073,4.8781 14.5,5.4265 14.5,6C14.5,8.4853 16.5147,10.5 19,10.5C19.6547,10.5 20.2767,10.3602 20.8378,10.1088ZM22,6C22,7.6568 20.6569,9 19,9C17.3431,9 16,7.6568 16,6C16,4.3432 17.3431,3 19,3C20.6569,3 22,4.3432 22,6Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</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,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/signal_context_menu_list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="200dp" />
|
|
@ -0,0 +1,30 @@
|
|||
<?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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="13dp"
|
||||
android:paddingBottom="13dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/signal_context_menu_item_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
tools:src="@drawable/ic_archive_24dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/signal_context_menu_item_title"
|
||||
android:textAppearance="@style/TextAppearance.Signal.Body1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
tools:text="Archive" />
|
||||
|
||||
</LinearLayout>
|
|
@ -209,4 +209,6 @@
|
|||
<dimen name="verify_identity_vertical_margin">16dp</dimen>
|
||||
|
||||
<integer name="badge_columns">3</integer>
|
||||
|
||||
<dimen name="signal_context_menu_corner_radius">18dp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -367,6 +367,16 @@
|
|||
<item quantity="one">Moved conversation to inbox</item>
|
||||
<item quantity="other">Moved %d conversations to inbox</item>
|
||||
</plurals>
|
||||
<string name="ConversationListFragment_read">Read</string>
|
||||
<string name="ConversationListFragment_unread">Unread</string>
|
||||
<string name="ConversationListFragment_pin">Pin</string>
|
||||
<string name="ConversationListFragment_unpin">Unpin</string>
|
||||
<string name="ConversationListFragment_mute">Mute</string>
|
||||
<string name="ConversationListFragment_unmute">Unmute</string>
|
||||
<string name="ConversationListFragment_select">Select</string>
|
||||
<string name="ConversationListFragment_archive">Archive</string>
|
||||
<string name="ConversationListFragment_unarchive">Unarchive</string>
|
||||
<string name="ConversationListFragment_delete">Delete</string>
|
||||
|
||||
<!-- ConversationListItem -->
|
||||
<string name="ConversationListItem_key_exchange_message">Key exchange message</string>
|
||||
|
|
Ładowanie…
Reference in New Issue