Replace default action message request behavior (#927)

* refactor: add a block action and change default message request behavior to decline/delete

* refactor: move log calls, add block & delete menu option

* refactor: migrate some more actions into ConversationActivityV2.kt and only show message request incoming menu if it's an incoming message request

* refactor: change block behaviour to be in the message request actions

* refactor: use block user copy

* refactor: parameters for ConversationMenuHelper interface cleaned up
This commit is contained in:
Harris 2022-09-13 15:06:46 +10:00 committed by GitHub
parent aa43ab2a2e
commit 9f8ed4daf2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 228 additions and 98 deletions

View File

@ -1,8 +1,8 @@
package org.thoughtcrime.securesms
import android.util.Log
import nl.komponents.kovenant.Kovenant
import nl.komponents.kovenant.jvm.asDispatcher
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.ThreadUtils
import java.util.concurrent.Executors

View File

@ -19,7 +19,6 @@ import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.util.Log
import android.util.Pair
import android.util.TypedValue
import android.view.ActionMode
@ -56,6 +55,7 @@ import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.mentions.Mention
import org.session.libsession.messaging.mentions.MentionsManager
import org.session.libsession.messaging.messages.control.DataExtractionNotification
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage
import org.session.libsession.messaging.messages.visible.Reaction
@ -79,9 +79,11 @@ import org.session.libsession.utilities.recipients.RecipientModifiedListener
import org.session.libsignal.crypto.MnemonicCodec
import org.session.libsignal.utilities.IdPrefix
import org.session.libsignal.utilities.ListenableFuture
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.guava.Optional
import org.session.libsignal.utilities.hexEncodedPrivateKey
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.ExpirationDialog
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.audio.AudioRecorder
import org.thoughtcrime.securesms.contacts.SelectContactsActivity.Companion.selectedContactsKey
@ -116,6 +118,7 @@ import org.thoughtcrime.securesms.database.LokiThreadDatabase
import org.thoughtcrime.securesms.database.MmsDatabase
import org.thoughtcrime.securesms.database.MmsSmsDatabase
import org.thoughtcrime.securesms.database.ReactionDatabase
import org.thoughtcrime.securesms.database.RecipientDatabase
import org.thoughtcrime.securesms.database.SessionContactDatabase
import org.thoughtcrime.securesms.database.SmsDatabase
import org.thoughtcrime.securesms.database.Storage
@ -168,7 +171,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
InputBarRecordingViewDelegate, AttachmentManager.AttachmentListener, ActivityDispatcher,
ConversationActionModeCallbackDelegate, VisibleMessageViewDelegate, RecipientModifiedListener,
SearchBottomBar.EventListener, LoaderManager.LoaderCallbacks<Cursor>,
OnReactionSelectedListener, ReactWithAnyEmojiDialogFragment.Callback, ReactionsDialogFragment.Callback {
OnReactionSelectedListener, ReactWithAnyEmojiDialogFragment.Callback, ReactionsDialogFragment.Callback,
ConversationMenuHelper.ConversationMenuListener {
private var binding: ActivityConversationV2Binding? = null
@ -178,6 +182,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
@Inject lateinit var lokiThreadDb: LokiThreadDatabase
@Inject lateinit var sessionContactDb: SessionContactDatabase
@Inject lateinit var groupDb: GroupDatabase
@Inject lateinit var recipientDb: RecipientDatabase
@Inject lateinit var lokiApiDb: LokiAPIDatabase
@Inject lateinit var smsDb: SmsDatabase
@Inject lateinit var mmsDb: MmsDatabase
@ -605,17 +610,15 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
val recipient = viewModel.recipient ?: return false
if (!isMessageRequestThread()) {
val recipient = viewModel.recipient
if (recipient != null) {
ConversationMenuHelper.onPrepareOptionsMenu(
menu,
menuInflater,
recipient,
viewModel.threadId,
this
) { onOptionsItemSelected(it) }
}
ConversationMenuHelper.onPrepareOptionsMenu(
menu,
menuInflater,
recipient,
viewModel.threadId,
this
) { onOptionsItemSelected(it) }
}
super.onPrepareOptionsMenu(menu)
return true
@ -666,6 +669,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
binding?.acceptMessageRequestButton?.setOnClickListener {
acceptMessageRequest()
}
binding?.messageRequestBlock?.setOnClickListener {
block(deleteThread = true)
}
binding?.declineMessageRequestButton?.setOnClickListener {
viewModel.declineMessageRequest()
lifecycleScope.launch(Dispatchers.IO) {
@ -937,6 +943,58 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
} ?: false
}
override fun block(deleteThread: Boolean) {
val title = R.string.RecipientPreferenceActivity_block_this_contact_question
val message = R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact
AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { _, _ ->
viewModel.block()
if (deleteThread) {
viewModel.deleteThread()
finish()
}
}.show()
}
override fun copySessionID(sessionId: String) {
val clip = ClipData.newPlainText("Session ID", sessionId)
val manager = getSystemService(PassphraseRequiredActionBarActivity.CLIPBOARD_SERVICE) as ClipboardManager
manager.setPrimaryClip(clip)
Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
}
override fun showExpiringMessagesDialog(thread: Recipient) {
if (thread.isClosedGroupRecipient) {
val group = groupDb.getGroup(thread.address.toGroupString()).orNull()
if (group?.isActive == false) { return }
}
ExpirationDialog.show(this, thread.expireMessages) { expirationTime: Int ->
recipientDb.setExpireMessages(thread, expirationTime)
val message = ExpirationTimerUpdate(expirationTime)
message.recipient = thread.address.serialize()
message.sentTimestamp = System.currentTimeMillis()
val expiringMessageManager = ApplicationContext.getInstance(this).expiringMessageManager
expiringMessageManager.setExpirationTimer(message)
MessageSender.send(message, thread.address)
invalidateOptionsMenu()
}
}
override fun unblock() {
val title = R.string.ConversationActivity_unblock_this_contact_question
val message = R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact
AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.ConversationActivity_unblock) { _, _ ->
viewModel.unblock()
}.show()
}
// `position` is the adapter position; not the visual position
private fun handlePress(message: MessageRecord, position: Int, view: VisibleMessageView, event: MotionEvent) {
val actionMode = this.actionMode

View File

@ -64,13 +64,24 @@ class ConversationViewModel(
repository.inviteContacts(threadId, contacts)
}
fun block() {
val recipient = recipient ?: return Log.w("Loki", "Recipient was null for block action")
if (recipient.isContactRecipient) {
repository.setBlocked(recipient, true)
}
}
fun unblock() {
val recipient = recipient ?: return Log.w("Loki", "Recipient was null for unblock action")
if (recipient.isContactRecipient) {
repository.unblock(recipient)
repository.setBlocked(recipient, false)
}
}
fun deleteThread() = viewModelScope.launch {
repository.deleteThread(threadId)
}
fun deleteLocally(message: MessageRecord) {
val recipient = recipient ?: return Log.w("Loki", "Recipient was null for delete locally action")
repository.deleteLocally(recipient, message)
@ -130,8 +141,7 @@ class ConversationViewModel(
}
fun declineMessageRequest() {
val recipient = recipient ?: return Log.w("Loki", "Recipient was null for decline message request action")
repository.declineMessageRequest(threadId, recipient)
repository.declineMessageRequest(threadId)
}
private fun showMessage(message: String) {

View File

@ -1,8 +1,6 @@
package org.thoughtcrime.securesms.conversation.v2.menus
import android.annotation.SuppressLint
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
@ -24,7 +22,6 @@ import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import network.loki.messenger.R
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.sending_receiving.leave
import org.session.libsession.utilities.ExpirationUtil
@ -33,11 +30,8 @@ import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.utilities.guava.Optional
import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.ExpirationDialog
import org.thoughtcrime.securesms.MediaOverviewActivity
import org.thoughtcrime.securesms.MuteDialog
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.ShortcutLauncherActivity
import org.thoughtcrime.securesms.calls.WebRtcCallActivity
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
@ -156,7 +150,8 @@ object ConversationMenuHelper {
R.id.menu_expiring_messages -> { showExpiringMessagesDialog(context, thread) }
R.id.menu_expiring_messages_off -> { showExpiringMessagesDialog(context, thread) }
R.id.menu_unblock -> { unblock(context, thread) }
R.id.menu_block -> { block(context, thread) }
R.id.menu_block -> { block(context, thread, deleteThread = false) }
R.id.menu_block_delete -> { blockAndDelete(context, thread) }
R.id.menu_copy_session_id -> { copySessionID(context, thread) }
R.id.menu_edit_group -> { editClosedGroup(context, thread) }
R.id.menu_leave_group -> { leaveClosedGroup(context, thread) }
@ -246,59 +241,32 @@ object ConversationMenuHelper {
}
private fun showExpiringMessagesDialog(context: Context, thread: Recipient) {
if (thread.isClosedGroupRecipient) {
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
if (group?.isActive == false) { return }
}
ExpirationDialog.show(context, thread.expireMessages) { expirationTime: Int ->
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(thread, expirationTime)
val message = ExpirationTimerUpdate(expirationTime)
message.recipient = thread.address.serialize()
message.sentTimestamp = System.currentTimeMillis()
val expiringMessageManager = ApplicationContext.getInstance(context).expiringMessageManager
expiringMessageManager.setExpirationTimer(message)
MessageSender.send(message, thread.address)
val activity = context as AppCompatActivity
activity.invalidateOptionsMenu()
}
val listener = context as? ConversationMenuListener ?: return
listener.showExpiringMessagesDialog(thread)
}
private fun unblock(context: Context, thread: Recipient) {
if (!thread.isContactRecipient) { return }
val title = R.string.ConversationActivity_unblock_this_contact_question
val message = R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact
AlertDialog.Builder(context)
.setTitle(title)
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.ConversationActivity_unblock) { _, _ ->
DatabaseComponent.get(context).recipientDatabase()
.setBlocked(thread, false)
}.show()
val listener = context as? ConversationMenuListener ?: return
listener.unblock()
}
private fun block(context: Context, thread: Recipient) {
private fun block(context: Context, thread: Recipient, deleteThread: Boolean) {
if (!thread.isContactRecipient) { return }
val title = R.string.RecipientPreferenceActivity_block_this_contact_question
val message = R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact
AlertDialog.Builder(context)
.setTitle(title)
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { _, _ ->
DatabaseComponent.get(context).recipientDatabase()
.setBlocked(thread, true)
}.show()
val listener = context as? ConversationMenuListener ?: return
listener.block(deleteThread)
}
private fun blockAndDelete(context: Context, thread: Recipient) {
if (!thread.isContactRecipient) { return }
val listener = context as? ConversationMenuListener ?: return
listener.block(deleteThread = true)
}
private fun copySessionID(context: Context, thread: Recipient) {
if (!thread.isContactRecipient) { return }
val sessionID = thread.address.toString()
val clip = ClipData.newPlainText("Session ID", sessionID)
val activity = context as AppCompatActivity
val manager = activity.getSystemService(PassphraseRequiredActionBarActivity.CLIPBOARD_SERVICE) as ClipboardManager
manager.setPrimaryClip(clip)
Toast.makeText(context, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
val listener = context as? ConversationMenuListener ?: return
listener.copySessionID(thread.address.toString())
}
private fun editClosedGroup(context: Context, thread: Recipient) {
@ -371,4 +339,11 @@ object ConversationMenuHelper {
}
}
interface ConversationMenuListener {
fun block(deleteThread: Boolean = false)
fun unblock()
fun copySessionID(sessionId: String)
fun showExpiringMessagesDialog(thread: Recipient)
}
}

View File

@ -1,21 +1,13 @@
package org.thoughtcrime.securesms.conversation.v2.utilities
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Interpolator
import android.graphics.Paint
import android.graphics.Rect
import android.os.SystemClock
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.Animation
import android.view.animation.AnimationSet
import android.view.animation.AnimationUtils
import androidx.core.content.res.ResourcesCompat
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import network.loki.messenger.R
import kotlin.math.sin

View File

@ -76,19 +76,34 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
push(intent)
}
override fun onLongConversationClick(thread: ThreadRecord) {
override fun onBlockConversationClick(thread: ThreadRecord) {
val dialog = AlertDialog.Builder(this)
dialog.setMessage(resources.getString(R.string.message_requests_delete_message))
dialog.setPositiveButton(R.string.yes) { _, _ ->
viewModel.deleteMessageRequest(thread)
LoaderManager.getInstance(this).restartLoader(0, null, this)
lifecycleScope.launch(Dispatchers.IO) {
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@MessageRequestsActivity)
dialog.setTitle(R.string.RecipientPreferenceActivity_block_this_contact_question)
.setMessage(R.string.message_requests_block_message)
.setPositiveButton(R.string.recipient_preferences__block) { _, _ ->
viewModel.blockMessageRequest(thread)
LoaderManager.getInstance(this).restartLoader(0, null, this)
}
.setNegativeButton(R.string.no) { _, _ ->
// Do nothing
}
dialog.create().show()
}
override fun onDeleteConversationClick(thread: ThreadRecord) {
val dialog = AlertDialog.Builder(this)
dialog.setTitle(R.string.decline)
.setMessage(resources.getString(R.string.message_requests_decline_message))
.setPositiveButton(R.string.decline) { _,_ ->
viewModel.deleteMessageRequest(thread)
LoaderManager.getInstance(this).restartLoader(0, null, this)
lifecycleScope.launch(Dispatchers.IO) {
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@MessageRequestsActivity)
}
}
.setNegativeButton(R.string.no) { _, _ ->
// Do nothing
}
}
dialog.setNegativeButton(R.string.no) { _, _ ->
// Do nothing
}
dialog.create().show()
}

View File

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.messagerequests
import android.content.Context
import android.content.res.ColorStateList
import android.database.Cursor
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
@ -8,6 +9,7 @@ import android.view.ViewGroup
import android.widget.PopupMenu
import androidx.recyclerview.widget.RecyclerView
import network.loki.messenger.R
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
@ -49,7 +51,9 @@ class MessageRequestsAdapter(
popupMenu.menuInflater.inflate(R.menu.menu_message_request, popupMenu.menu)
popupMenu.setOnMenuItemClickListener { menuItem ->
if (menuItem.itemId == R.id.menu_delete_message_request) {
listener.onLongConversationClick(view.thread!!)
listener.onDeleteConversationClick(view.thread!!)
} else if (menuItem.itemId == R.id.menu_block_message_request) {
listener.onBlockConversationClick(view.thread!!)
}
true
}
@ -57,6 +61,7 @@ class MessageRequestsAdapter(
val item = popupMenu.menu.getItem(i)
val s = SpannableString(item.title)
s.setSpan(ForegroundColorSpan(context.getColor(R.color.destructive)), 0, s.length, 0)
item.iconTintList = ColorStateList.valueOf(context.getColor(R.color.destructive))
item.title = s
}
popupMenu.forceShowIcon()
@ -70,5 +75,6 @@ class MessageRequestsAdapter(
interface ConversationClickListener {
fun onConversationClick(thread: ThreadRecord)
fun onLongConversationClick(thread: ThreadRecord)
fun onBlockConversationClick(thread: ThreadRecord)
fun onDeleteConversationClick(thread: ThreadRecord)
}

View File

@ -13,6 +13,14 @@ class MessageRequestsViewModel @Inject constructor(
private val repository: ConversationRepository
) : ViewModel() {
fun blockMessageRequest(thread: ThreadRecord) = viewModelScope.launch {
val recipient = thread.recipient
if (recipient.isContactRecipient) {
repository.setBlocked(recipient, true)
deleteMessageRequest(thread)
}
}
fun deleteMessageRequest(thread: ThreadRecord) = viewModelScope.launch {
repository.deleteMessageRequest(thread)
}

View File

@ -37,7 +37,7 @@ interface ConversationRepository {
fun saveDraft(threadId: Long, text: String)
fun getDraft(threadId: Long): String?
fun inviteContacts(threadId: Long, contacts: List<Recipient>)
fun unblock(recipient: Recipient)
fun setBlocked(recipient: Recipient, blocked: Boolean)
fun deleteLocally(recipient: Recipient, message: MessageRecord)
fun setApproved(recipient: Recipient, isApproved: Boolean)
@ -58,13 +58,15 @@ interface ConversationRepository {
suspend fun banAndDeleteAll(threadId: Long, recipient: Recipient): ResultOf<Unit>
suspend fun deleteThread(threadId: Long): ResultOf<Unit>
suspend fun deleteMessageRequest(thread: ThreadRecord): ResultOf<Unit>
suspend fun clearAllMessageRequests(): ResultOf<Unit>
suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient): ResultOf<Unit>
fun declineMessageRequest(threadId: Long, recipient: Recipient)
fun declineMessageRequest(threadId: Long)
fun hasReceived(threadId: Long): Boolean
@ -125,8 +127,8 @@ class DefaultConversationRepository @Inject constructor(
}
}
override fun unblock(recipient: Recipient) {
recipientDb.setBlocked(recipient, false)
override fun setBlocked(recipient: Recipient, blocked: Boolean) {
recipientDb.setBlocked(recipient, blocked)
}
override fun deleteLocally(recipient: Recipient, message: MessageRecord) {
@ -248,9 +250,15 @@ class DefaultConversationRepository @Inject constructor(
}
}
override suspend fun deleteThread(threadId: Long): ResultOf<Unit> {
sessionJobDb.cancelPendingMessageSendJobs(threadId)
threadDb.deleteConversation(threadId)
return ResultOf.Success(Unit)
}
override suspend fun deleteMessageRequest(thread: ThreadRecord): ResultOf<Unit> {
sessionJobDb.cancelPendingMessageSendJobs(thread.threadId)
recipientDb.setBlocked(thread.recipient, true)
threadDb.deleteConversation(thread.threadId)
return ResultOf.Success(Unit)
}
@ -275,8 +283,9 @@ class DefaultConversationRepository @Inject constructor(
}
}
override fun declineMessageRequest(threadId: Long, recipient: Recipient) {
recipientDb.setBlocked(recipient, true)
override fun declineMessageRequest(threadId: Long) {
sessionJobDb.cancelPendingMessageSendJobs(threadId)
threadDb.deleteConversation(threadId)
}
override fun hasReceived(threadId: Long): Boolean {

View File

@ -201,6 +201,17 @@
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/messageRequestBlock"
android:layout_gravity="center"
android:textColor="@color/destructive"
android:paddingHorizontal="@dimen/massive_spacing"
android:paddingVertical="@dimen/small_spacing"
android:textSize="@dimen/text_size"
android:text="@string/activity_conversation_block_user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/sendAcceptsTextView"
android:layout_width="wrap_content"

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@android:style/Widget.ActionButton"
android:orientation="horizontal"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_margin="@dimen/very_small_spacing"
android:layout_width="13dp"
android:layout_height="13dp"
android:src="@drawable/ic_baseline_block_24"
app:tint="@color/destructive" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/destructive"
android:textSize="16sp"
android:text="@string/recipient_preferences__block"
/>
</LinearLayout>

View File

@ -0,0 +1,11 @@
<?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
app:actionLayout="@layout/layout_conversation_block_icon"
app:showAsAction="always"
android:title="@string/recipient_preferences__block"
android:id="@+id/menu_block_delete" />
</menu>

View File

@ -4,6 +4,11 @@
<item
android:id="@+id/menu_delete_message_request"
android:icon="@drawable/ic_delete_24"
android:title="@string/delete"/>
android:title="@string/decline"/>
<item
android:id="@+id/menu_block_message_request"
android:icon="@drawable/ic_baseline_block_24"
android:title="@string/RecipientPreferenceActivity_block"/>
</menu>

View File

@ -41,6 +41,7 @@
<dimen name="input_bar_button_expanded_size">48dp</dimen>
<!-- Distances -->
<dimen name="very_small_spacing">4dp</dimen>
<dimen name="small_spacing">8dp</dimen>
<dimen name="medium_spacing">16dp</dimen>
<dimen name="large_spacing">24dp</dimen>

View File

@ -865,6 +865,7 @@
<string name="dialog_download_button_title">Download</string>
<string name="activity_conversation_blocked_banner_text">%s is blocked. Unblock them?</string>
<string name="activity_conversation_block_user">Block User</string>
<string name="activity_conversation_attachment_prep_failed">Failed to prepare attachment for sending.</string>
<string name="media">Media</string>
@ -894,7 +895,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="message_requests_clear_all">Clear All</string>
<string name="message_requests_delete_message">Are you sure you want to delete this message request?</string>
<string name="message_requests_decline_message">Are you sure you want to decline this message request?</string>
<string name="message_requests_block_message">Are you sure you want to block this message request?</string>
<string name="message_requests_deleted">Message request deleted</string>
<string name="message_requests_clear_all_message">Are you sure you want to clear all message requests?</string>
<string name="message_requests_cleared">Message requests deleted</string>

View File

@ -81,7 +81,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
viewModel.unblock()
verify(repository).unblock(recipient)
verify(repository).setBlocked(recipient, false)
}
@Test
@ -173,7 +173,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
fun `should decline message request`() {
viewModel.declineMessageRequest()
verify(repository).declineMessageRequest(threadId, recipient)
verify(repository).declineMessageRequest(threadId)
}
@Test

View File

@ -1,6 +1,5 @@
package org.session.libsession.messaging.sending_receiving
import android.util.Log
import com.goterl.lazysodium.LazySodiumAndroid
import com.goterl.lazysodium.SodiumAndroid
import com.goterl.lazysodium.interfaces.Box
@ -12,6 +11,7 @@ import org.session.libsession.messaging.utilities.SodiumUtilities
import org.session.libsignal.crypto.ecc.ECKeyPair
import org.session.libsignal.utilities.Hex
import org.session.libsignal.utilities.IdPrefix
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.hexEncodedPublicKey
import org.session.libsignal.utilities.removingIdPrefixIfNeeded