From 30d748e1476a7dc9f7cf5f4ee00d65db22544deb Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 19 May 2023 23:44:07 +0930 Subject: [PATCH 1/6] Disable unblock button --- .../securesms/database/RecipientDatabase.java | 2 +- .../securesms/database/Storage.kt | 2 +- .../preferences/BlockedContactsActivity.kt | 78 ++++++------------- .../preferences/BlockedContactsAdapter.kt | 16 ++-- .../preferences/BlockedContactsViewModel.kt | 68 +++++++++++++--- app/src/main/res/color/button_destructive.xml | 5 ++ ...ctive_outline_button_medium_background.xml | 2 +- app/src/main/res/values/styles.xml | 2 +- .../libsession/database/StorageProtocol.kt | 2 +- 9 files changed, 98 insertions(+), 79 deletions(-) create mode 100644 app/src/main/res/color/button_destructive.xml diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java index af2faaaca9..e3570fd283 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java @@ -276,7 +276,7 @@ public class RecipientDatabase extends Database { notifyRecipientListeners(); } - public void setBlocked(@NonNull List recipients, boolean blocked) { + public void setBlocked(@NonNull Iterable recipients, boolean blocked) { SQLiteDatabase db = getWritableDatabase(); db.beginTransaction(); try { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 33896803b8..ed6510f741 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -1010,7 +1010,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, DatabaseComponent.get(context).reactionDatabase().deleteMessageReactions(MessageId(messageId, mms)) } - override fun unblock(toUnblock: List) { + override fun unblock(toUnblock: Iterable) { val recipientDb = DatabaseComponent.get(context).recipientDatabase() recipientDb.setBlocked(toUnblock, false) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt index 504194d3a4..9b8d800dd5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt @@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.preferences import android.app.AlertDialog import android.os.Bundle -import android.view.View import androidx.activity.viewModels import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint @@ -11,58 +10,31 @@ import network.loki.messenger.databinding.ActivityBlockedContactsBinding import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity @AndroidEntryPoint -class BlockedContactsActivity: PassphraseRequiredActionBarActivity(), View.OnClickListener { +class BlockedContactsActivity: PassphraseRequiredActionBarActivity() { lateinit var binding: ActivityBlockedContactsBinding val viewModel: BlockedContactsViewModel by viewModels() - val adapter = BlockedContactsAdapter() + val adapter: BlockedContactsAdapter by lazy { BlockedContactsAdapter(viewModel) } - override fun onClick(v: View?) { - if (v === binding.unblockButton && adapter.getSelectedItems().isNotEmpty()) { - val contactsToUnblock = adapter.getSelectedItems() - // show dialog - val title = if (contactsToUnblock.size == 1) { - getString(R.string.Unblock_dialog__title_single, contactsToUnblock.first().name) - } else { - getString(R.string.Unblock_dialog__title_multiple) + fun unblock() { + // show dialog + val title = viewModel.getTitle(this) + + val message = viewModel.getMessage(this) + + AlertDialog.Builder(this) + .setTitle(title) + .setMessage(message) + .setPositiveButton(R.string.continue_2) { d, _ -> + viewModel.unblock() + d.dismiss() } - - val message = if (contactsToUnblock.size == 1) { - getString(R.string.Unblock_dialog__message, contactsToUnblock.first().name) - } else { - val stringBuilder = StringBuilder() - val iterator = contactsToUnblock.iterator() - var numberAdded = 0 - while (iterator.hasNext() && numberAdded < 3) { - val nextRecipient = iterator.next() - if (numberAdded > 0) stringBuilder.append(", ") - - stringBuilder.append(nextRecipient.name) - numberAdded++ - } - val overflow = contactsToUnblock.size - numberAdded - if (overflow > 0) { - stringBuilder.append(" ") - val string = resources.getQuantityString(R.plurals.Unblock_dialog__message_multiple_overflow, overflow) - stringBuilder.append(string.format(overflow)) - } - getString(R.string.Unblock_dialog__message, stringBuilder.toString()) + .setNegativeButton(R.string.cancel) { d, _ -> + d.dismiss() } - - AlertDialog.Builder(this) - .setTitle(title) - .setMessage(message) - .setPositiveButton(R.string.continue_2) { d, _ -> - viewModel.unblock(contactsToUnblock) - d.dismiss() - } - .setNegativeButton(R.string.cancel) { d, _ -> - d.dismiss() - } - .show() - } + .show() } override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) { @@ -73,15 +45,15 @@ class BlockedContactsActivity: PassphraseRequiredActionBarActivity(), View.OnCli binding.recyclerView.adapter = adapter viewModel.subscribe(this) - .observe(this) { newState -> - adapter.submitList(newState.blockedContacts) - val isEmpty = newState.blockedContacts.isEmpty() - binding.emptyStateMessageTextView.isVisible = isEmpty - binding.nonEmptyStateGroup.isVisible = !isEmpty + .observe(this) { state -> + adapter.submitList(state.blockedContacts) + binding.emptyStateMessageTextView.isVisible = state.emptyStateMessageTextViewVisible + binding.nonEmptyStateGroup.isVisible = state.nonEmptyStateGroupVisible + binding.unblockButton.isEnabled = state.unblockButtonEnabled } - binding.unblockButton.setOnClickListener(this) + binding.unblockButton.setOnClickListener { unblock() } } - -} \ No newline at end of file +} + \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt index 50af49b557..d400ab915c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt @@ -11,16 +11,14 @@ import network.loki.messenger.databinding.BlockedContactLayoutBinding import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.mms.GlideApp -class BlockedContactsAdapter: ListAdapter(RecipientDiffer()) { +class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdapter(RecipientDiffer()) { class RecipientDiffer: DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem === newItem override fun areContentsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem == newItem } - private val selectedItems = mutableListOf() - - fun getSelectedItems() = selectedItems + fun getSelectedItems() = viewModel.state.selectedItems override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val itemView = LayoutInflater.from(parent.context).inflate(R.layout.blocked_contact_layout, parent, false) @@ -28,19 +26,15 @@ class BlockedContactsAdapter: ListAdapter(capacity = Channel.CONFLATED) - private val _contacts = MutableLiveData(BlockedContactsViewState(emptyList())) + private val _state = MutableLiveData(BlockedContactsViewState(emptyList(), emptySet())) + + val state get() = _state.value!! fun subscribe(context: Context): LiveData { executor.launch(IO) { @@ -45,21 +48,66 @@ class BlockedContactsViewModel @Inject constructor(private val storage: Storage) } executor.launch(IO) { for (update in listUpdateChannel) { - val blockedContactState = BlockedContactsViewState(storage.blockedContacts().sortedBy { it.name }) + val blockedContactState = state.copy( + blockedContacts = storage.blockedContacts().sortedBy { it.name } + ) withContext(Main) { - _contacts.value = blockedContactState + _state.value = blockedContactState } } } - return _contacts + return _state } - fun unblock(toUnblock: List) { - storage.unblock(toUnblock) + fun unblock() { + storage.unblock(state.selectedItems) + _state.value = state.copy(selectedItems = emptySet()) + } + + fun select(selectedItem: Recipient, isSelected: Boolean) { + _state.value = state.run { + if (isSelected) copy(selectedItems = selectedItems + selectedItem) + else copy(selectedItems = selectedItems - selectedItem) + } + } + + fun getTitle(context: Context): String = + if (state.selectedItems.size == 1) { + context.getString(R.string.Unblock_dialog__title_single, state.selectedItems.first().name) + } else { + context.getString(R.string.Unblock_dialog__title_multiple) + } + + fun getMessage(context: Context): String { + if (state.selectedItems.size == 1) { + return context.getString(R.string.Unblock_dialog__message, state.selectedItems.first().name) + } + val stringBuilder = StringBuilder() + val iterator = state.selectedItems.iterator() + var numberAdded = 0 + while (iterator.hasNext() && numberAdded < 3) { + val nextRecipient = iterator.next() + if (numberAdded > 0) stringBuilder.append(", ") + + stringBuilder.append(nextRecipient.name) + numberAdded++ + } + val overflow = state.selectedItems.size - numberAdded + if (overflow > 0) { + stringBuilder.append(" ") + val string = context.resources.getQuantityString(R.plurals.Unblock_dialog__message_multiple_overflow, overflow) + stringBuilder.append(string.format(overflow)) + } + return context.getString(R.string.Unblock_dialog__message, stringBuilder.toString()) } data class BlockedContactsViewState( - val blockedContacts: List - ) - -} \ No newline at end of file + val blockedContacts: List, + val selectedItems: Set + ) { + val isEmpty get() = blockedContacts.isEmpty() + val unblockButtonEnabled get() = selectedItems.isNotEmpty() + val emptyStateMessageTextViewVisible get() = blockedContacts.isEmpty() + val nonEmptyStateGroupVisible get() = blockedContacts.isNotEmpty() + } +} diff --git a/app/src/main/res/color/button_destructive.xml b/app/src/main/res/color/button_destructive.xml new file mode 100644 index 0000000000..cefbfed23a --- /dev/null +++ b/app/src/main/res/color/button_destructive.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/destructive_outline_button_medium_background.xml b/app/src/main/res/drawable/destructive_outline_button_medium_background.xml index 7db4da2ec4..ac41ee6217 100644 --- a/app/src/main/res/drawable/destructive_outline_button_medium_background.xml +++ b/app/src/main/res/drawable/destructive_outline_button_medium_background.xml @@ -7,5 +7,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9fa6059885..f4b9d6dbaa 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -113,7 +113,7 @@ diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt index 48d15a18ac..dc78aec1e2 100644 --- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt @@ -202,6 +202,6 @@ interface StorageProtocol { fun removeReaction(emoji: String, messageTimestamp: Long, author: String, notifyUnread: Boolean) fun updateReactionIfNeeded(message: Message, sender: String, openGroupSentTimestamp: Long) fun deleteReactions(messageId: Long, mms: Boolean) - fun unblock(toUnblock: List) + fun unblock(toUnblock: Iterable) fun blockedContacts(): List } From 8ef6ec2125ff93540021365049aa5932ede0c695 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 22 May 2023 14:57:36 +0930 Subject: [PATCH 2/6] . --- .../securesms/preferences/BlockedContactsAdapter.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt index d400ab915c..26632e5aa6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt @@ -18,8 +18,6 @@ class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdap override fun areContentsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem == newItem } - fun getSelectedItems() = viewModel.state.selectedItems - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val itemView = LayoutInflater.from(parent.context).inflate(R.layout.blocked_contact_layout, parent, false) return ViewHolder(itemView) From 4f2ef7f2af5458e829325acc9141de021b3ff60a Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 22 May 2023 15:46:12 +0930 Subject: [PATCH 3/6] Add SelectableItem<> --- .../preferences/BlockedContactsActivity.kt | 11 ++--- .../preferences/BlockedContactsAdapter.kt | 45 +++++++++---------- .../preferences/BlockedContactsViewModel.kt | 10 +++++ .../securesms/util/adapter/SelectableItem.kt | 3 ++ 4 files changed, 36 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/util/adapter/SelectableItem.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt index 9b8d800dd5..d2db4fca43 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt @@ -27,13 +27,8 @@ class BlockedContactsActivity: PassphraseRequiredActionBarActivity() { AlertDialog.Builder(this) .setTitle(title) .setMessage(message) - .setPositiveButton(R.string.continue_2) { d, _ -> - viewModel.unblock() - d.dismiss() - } - .setNegativeButton(R.string.cancel) { d, _ -> - d.dismiss() - } + .setPositiveButton(R.string.continue_2) { _, _ -> viewModel.unblock() } + .setNegativeButton(R.string.cancel) { _, _ -> } .show() } @@ -46,7 +41,7 @@ class BlockedContactsActivity: PassphraseRequiredActionBarActivity() { viewModel.subscribe(this) .observe(this) { state -> - adapter.submitList(state.blockedContacts) + adapter.submitList(state.items) binding.emptyStateMessageTextView.isVisible = state.emptyStateMessageTextViewVisible binding.nonEmptyStateGroup.isVisible = state.nonEmptyStateGroupVisible binding.unblockButton.isEnabled = state.unblockButtonEnabled diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt index 26632e5aa6..6c13133a4e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt @@ -10,30 +10,26 @@ import network.loki.messenger.R import network.loki.messenger.databinding.BlockedContactLayoutBinding import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.mms.GlideApp +import org.thoughtcrime.securesms.util.adapter.SelectableItem -class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdapter(RecipientDiffer()) { +typealias SelectableRecipient = SelectableItem - class RecipientDiffer: DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem === newItem - override fun areContentsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem == newItem +class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdapter(RecipientDiffer()) { + + class RecipientDiffer: DiffUtil.ItemCallback() { + override fun areItemsTheSame(old: SelectableRecipient, new: SelectableRecipient) = old.item.address == new.item.address + override fun areContentsTheSame(old: SelectableRecipient, new: SelectableRecipient) = old.isSelected == new.isSelected + override fun getChangePayload(old: SelectableRecipient, new: SelectableRecipient) = new.isSelected } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val itemView = LayoutInflater.from(parent.context).inflate(R.layout.blocked_contact_layout, parent, false) - return ViewHolder(itemView) - } - - private fun toggleSelection(recipient: Recipient, isSelected: Boolean, position: Int) { - viewModel.select(recipient, isSelected) - notifyItemChanged(position) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = + LayoutInflater.from(parent.context) + .inflate(R.layout.blocked_contact_layout, parent, false) + .let(::ViewHolder) override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val recipient = getItem(position) - val isSelected = recipient in viewModel.state.selectedItems - holder.bind(recipient, isSelected) { - toggleSelection(recipient, !isSelected, position) - } + val selectable = getItem(position) + holder.bind(selectable, viewModel::toggle) } override fun onViewRecycled(holder: ViewHolder) { @@ -46,15 +42,14 @@ class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdap val glide = GlideApp.with(itemView) val binding = BlockedContactLayoutBinding.bind(itemView) - fun bind(recipient: Recipient, isSelected: Boolean, toggleSelection: () -> Unit) { - binding.recipientName.text = recipient.name + fun bind(selectable: SelectableRecipient, toggle: (SelectableRecipient) -> Unit) { + binding.recipientName.text = selectable.item.name with (binding.profilePictureView.root) { glide = this@ViewHolder.glide - update(recipient) + update(selectable.item) } - binding.root.setOnClickListener { toggleSelection() } - binding.selectButton.isSelected = isSelected + binding.root.setOnClickListener { toggle(selectable) } + binding.selectButton.isSelected = selectable.isSelected } } - -} \ No newline at end of file +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt index baafa16455..0b13201220 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt @@ -21,6 +21,7 @@ import network.loki.messenger.R import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.database.DatabaseContentProviders import org.thoughtcrime.securesms.database.Storage +import org.thoughtcrime.securesms.util.adapter.SelectableItem import javax.inject.Inject @HiltViewModel @@ -101,10 +102,19 @@ class BlockedContactsViewModel @Inject constructor(private val storage: Storage) return context.getString(R.string.Unblock_dialog__message, stringBuilder.toString()) } + fun toggle(selectable: SelectableItem) { + _state.value = state.run { + if (selectable.isSelected) copy(selectedItems = selectedItems - selectable.item) + else copy(selectedItems = selectedItems + selectable.item) + } + } + data class BlockedContactsViewState( val blockedContacts: List, val selectedItems: Set ) { + val items = blockedContacts.map { SelectableItem(it, it in selectedItems) } + val isEmpty get() = blockedContacts.isEmpty() val unblockButtonEnabled get() = selectedItems.isNotEmpty() val emptyStateMessageTextViewVisible get() = blockedContacts.isEmpty() diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/adapter/SelectableItem.kt b/app/src/main/java/org/thoughtcrime/securesms/util/adapter/SelectableItem.kt new file mode 100644 index 0000000000..88b41d11cd --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/adapter/SelectableItem.kt @@ -0,0 +1,3 @@ +package org.thoughtcrime.securesms.util.adapter + +data class SelectableItem(val item: T, val isSelected: Boolean) From 76466e57de067be98c229436b7c212021f02e640 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 22 May 2023 17:03:26 +0930 Subject: [PATCH 4/6] Fix ripple --- app/src/main/res/layout/blocked_contact_layout.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/blocked_contact_layout.xml b/app/src/main/res/layout/blocked_contact_layout.xml index 673779cfd0..40d7f40dd3 100644 --- a/app/src/main/res/layout/blocked_contact_layout.xml +++ b/app/src/main/res/layout/blocked_contact_layout.xml @@ -7,6 +7,7 @@ android:paddingHorizontal="@dimen/medium_spacing" android:paddingVertical="@dimen/small_spacing" android:gravity="center_vertical" + android:background="?selectableItemBackground" android:id="@+id/backgroundContainer"> Date: Mon, 22 May 2023 22:20:52 +0930 Subject: [PATCH 5/6] polish --- .../preferences/BlockedContactsAdapter.kt | 10 ++++++ .../preferences/BlockedContactsViewModel.kt | 2 +- ...ctive_outline_button_medium_background.xml | 22 ++++++------ ...inent_outline_button_medium_background.xml | 22 ++++++------ .../res/layout/activity_blocked_contacts.xml | 35 ++++++++++++------- 5 files changed, 57 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt index 6c13133a4e..1bd3b28610 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt @@ -32,6 +32,12 @@ class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdap holder.bind(selectable, viewModel::toggle) } + override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: MutableList) { + val selectable = getItem(position) + if (payloads.isEmpty()) holder.bind(selectable, viewModel::toggle) + else holder.select(selectable.isSelected) + } + override fun onViewRecycled(holder: ViewHolder) { super.onViewRecycled(holder) holder.binding.profilePictureView.root.recycle() @@ -51,5 +57,9 @@ class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdap binding.root.setOnClickListener { toggle(selectable) } binding.selectButton.isSelected = selectable.isSelected } + + fun select(isSelected: Boolean) { + binding.selectButton.isSelected = isSelected + } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt index 0b13201220..0c93b2cc09 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt @@ -104,7 +104,7 @@ class BlockedContactsViewModel @Inject constructor(private val storage: Storage) fun toggle(selectable: SelectableItem) { _state.value = state.run { - if (selectable.isSelected) copy(selectedItems = selectedItems - selectable.item) + if (selectable.item in selectedItems) copy(selectedItems = selectedItems - selectable.item) else copy(selectedItems = selectedItems + selectable.item) } } diff --git a/app/src/main/res/drawable/destructive_outline_button_medium_background.xml b/app/src/main/res/drawable/destructive_outline_button_medium_background.xml index ac41ee6217..c6e01ef98e 100644 --- a/app/src/main/res/drawable/destructive_outline_button_medium_background.xml +++ b/app/src/main/res/drawable/destructive_outline_button_medium_background.xml @@ -1,11 +1,13 @@ - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/app/src/main/res/drawable/prominent_outline_button_medium_background.xml b/app/src/main/res/drawable/prominent_outline_button_medium_background.xml index ee3bec8f7f..4bde2f855c 100644 --- a/app/src/main/res/drawable/prominent_outline_button_medium_background.xml +++ b/app/src/main/res/drawable/prominent_outline_button_medium_background.xml @@ -1,11 +1,13 @@ - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/app/src/main/res/layout/activity_blocked_contacts.xml b/app/src/main/res/layout/activity_blocked_contacts.xml index 69d0043009..f02ad7cb31 100644 --- a/app/src/main/res/layout/activity_blocked_contacts.xml +++ b/app/src/main/res/layout/activity_blocked_contacts.xml @@ -4,28 +4,37 @@ android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> - - + android:layout_width="match_parent" + android:layout_height="0dp"> + + + + + @@ -38,7 +47,7 @@ android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="@+id/recyclerView" + app:layout_constraintTop_toBottomOf="@+id/cardView" android:id="@+id/unblockButton" app:layout_constraintBottom_toBottomOf="parent" android:layout_marginVertical="@dimen/large_spacing" @@ -49,6 +58,6 @@ android:id="@+id/nonEmptyStateGroup" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:constraint_referenced_ids="unblockButton,recyclerView"/> + app:constraint_referenced_ids="unblockButton,cardView"/> \ No newline at end of file From a295dfb248ec1bee54d4dfb8ec7eb1289535efa3 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 23 May 2023 14:56:03 +0930 Subject: [PATCH 6/6] Cleanup --- .../securesms/preferences/BlockedContactsAdapter.kt | 8 +++----- .../securesms/preferences/BlockedContactsViewModel.kt | 7 +++---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt index 1bd3b28610..a75d53c4f1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt @@ -28,14 +28,12 @@ class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdap .let(::ViewHolder) override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val selectable = getItem(position) - holder.bind(selectable, viewModel::toggle) + holder.bind(getItem(position), viewModel::toggle) } override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: MutableList) { - val selectable = getItem(position) - if (payloads.isEmpty()) holder.bind(selectable, viewModel::toggle) - else holder.select(selectable.isSelected) + if (payloads.isEmpty()) holder.bind(getItem(position), viewModel::toggle) + else holder.select(getItem(position).isSelected) } override fun onViewRecycled(holder: ViewHolder) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt index 0c93b2cc09..b5d7995506 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt @@ -31,7 +31,7 @@ class BlockedContactsViewModel @Inject constructor(private val storage: Storage) private val listUpdateChannel = Channel(capacity = Channel.CONFLATED) - private val _state = MutableLiveData(BlockedContactsViewState(emptyList(), emptySet())) + private val _state = MutableLiveData(BlockedContactsViewState()) val state get() = _state.value!! @@ -110,12 +110,11 @@ class BlockedContactsViewModel @Inject constructor(private val storage: Storage) } data class BlockedContactsViewState( - val blockedContacts: List, - val selectedItems: Set + val blockedContacts: List = emptyList(), + val selectedItems: Set = emptySet() ) { val items = blockedContacts.map { SelectableItem(it, it in selectedItems) } - val isEmpty get() = blockedContacts.isEmpty() val unblockButtonEnabled get() = selectedItems.isNotEmpty() val emptyStateMessageTextViewVisible get() = blockedContacts.isEmpty() val nonEmptyStateGroupVisible get() = blockedContacts.isNotEmpty()