From 30d748e1476a7dc9f7cf5f4ee00d65db22544deb Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 19 May 2023 23:44:07 +0930 Subject: [PATCH] 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 }