mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 18:30:20 +01:00
Update spam UX and reporting flows.
This commit is contained in:
committed by
Clark Chen
parent
a4fde60c1c
commit
aa76cefb1c
@@ -28,7 +28,9 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.signal.core.util.DimensionUnit
|
||||
import org.signal.core.util.Result
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.concurrent.addTo
|
||||
import org.signal.core.util.getParcelableArrayListExtraCompat
|
||||
import org.thoughtcrime.securesms.AvatarPreviewActivity
|
||||
import org.thoughtcrime.securesms.BlockUnblockDialog
|
||||
@@ -74,6 +76,7 @@ import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupInviteSentD
|
||||
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupsLearnMoreBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.mediaoverview.MediaOverviewActivity
|
||||
import org.thoughtcrime.securesms.mediapreview.MediaIntentFactory
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestRepository
|
||||
import org.thoughtcrime.securesms.profiles.edit.CreateProfileActivity
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientExporter
|
||||
@@ -112,17 +115,17 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
private val alertTint by lazy { ContextCompat.getColor(requireContext(), R.color.signal_alert_primary) }
|
||||
private val alertDisabledTint by lazy { ContextCompat.getColor(requireContext(), R.color.signal_alert_primary_50) }
|
||||
private val blockIcon by lazy {
|
||||
ContextUtil.requireDrawable(requireContext(), R.drawable.ic_block_tinted_24).apply {
|
||||
ContextUtil.requireDrawable(requireContext(), R.drawable.symbol_block_24).apply {
|
||||
colorFilter = PorterDuffColorFilter(alertTint, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private val unblockIcon by lazy {
|
||||
ContextUtil.requireDrawable(requireContext(), R.drawable.ic_block_tinted_24)
|
||||
ContextUtil.requireDrawable(requireContext(), R.drawable.symbol_block_24)
|
||||
}
|
||||
|
||||
private val leaveIcon by lazy {
|
||||
ContextUtil.requireDrawable(requireContext(), R.drawable.ic_leave_tinted_24).apply {
|
||||
ContextUtil.requireDrawable(requireContext(), R.drawable.symbol_leave_24).apply {
|
||||
colorFilter = PorterDuffColorFilter(alertTint, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
@@ -135,7 +138,8 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
recipientId = args.recipientId,
|
||||
groupId = ParcelableGroupId.get(groupId),
|
||||
callMessageIds = args.callMessageIds ?: longArrayOf(),
|
||||
repository = ConversationSettingsRepository(requireContext())
|
||||
repository = ConversationSettingsRepository(requireContext()),
|
||||
messageRequestRepository = MessageRequestRepository(requireContext())
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -798,6 +802,49 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val reportSpamTint = if (state.isDeprecatedOrUnregistered) R.color.signal_alert_primary_50 else R.color.signal_alert_primary
|
||||
clickPref(
|
||||
title = DSLSettingsText.from(R.string.ConversationFragment_report_spam, ContextCompat.getColor(requireContext(), reportSpamTint)),
|
||||
icon = DSLSettingsIcon.from(R.drawable.symbol_spam_24, reportSpamTint),
|
||||
isEnabled = !state.isDeprecatedOrUnregistered,
|
||||
onClick = {
|
||||
BlockUnblockDialog.showReportSpamFor(
|
||||
requireContext(),
|
||||
viewLifecycleOwner.lifecycle,
|
||||
state.recipient,
|
||||
{
|
||||
viewModel
|
||||
.onReportSpam()
|
||||
.subscribeBy {
|
||||
Toast.makeText(requireContext(), R.string.ConversationFragment_reported_as_spam, Toast.LENGTH_SHORT).show()
|
||||
onToolbarNavigationClicked()
|
||||
}
|
||||
.addTo(lifecycleDisposable)
|
||||
},
|
||||
if (state.recipient.isBlocked) {
|
||||
null
|
||||
} else {
|
||||
Runnable {
|
||||
viewModel
|
||||
.onBlockAndReportSpam()
|
||||
.subscribeBy { result ->
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
Toast.makeText(requireContext(), R.string.ConversationFragment_reported_as_spam_and_blocked, Toast.LENGTH_SHORT).show()
|
||||
onToolbarNavigationClicked()
|
||||
}
|
||||
is Result.Failure -> {
|
||||
Toast.makeText(requireContext(), GroupErrors.getUserDisplayMessage(result.failure), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
.addTo(lifecycleDisposable)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.thoughtcrime.securesms.components.settings.conversation
|
||||
|
||||
import android.database.Cursor
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
@@ -8,11 +7,13 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.lifecycle.map
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import io.reactivex.rxjava3.subjects.Subject
|
||||
import org.signal.core.util.Result
|
||||
import org.signal.core.util.ThreadUtil
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.signal.core.util.readToList
|
||||
@@ -25,8 +26,10 @@ import org.thoughtcrime.securesms.database.model.StoryViewState
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.LiveGroup
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupAddMembersResult
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestRepository
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil
|
||||
@@ -37,6 +40,7 @@ import org.thoughtcrime.securesms.util.livedata.Store
|
||||
sealed class ConversationSettingsViewModel(
|
||||
private val callMessageIds: LongArray,
|
||||
private val repository: ConversationSettingsRepository,
|
||||
private val messageRequestRepository: MessageRequestRepository,
|
||||
specificSettingsState: SpecificSettingsState
|
||||
) : ViewModel() {
|
||||
|
||||
@@ -90,6 +94,27 @@ sealed class ConversationSettingsViewModel(
|
||||
sharedMediaUpdateTrigger.postValue(Unit)
|
||||
}
|
||||
|
||||
fun onReportSpam(): Maybe<Unit> {
|
||||
return if (store.state.threadId > 0 && store.state.recipient != Recipient.UNKNOWN) {
|
||||
messageRequestRepository.reportSpamMessageRequest(store.state.recipient.id, store.state.threadId)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.toSingle { Unit }
|
||||
.toMaybe()
|
||||
} else {
|
||||
Maybe.empty()
|
||||
}
|
||||
}
|
||||
|
||||
fun onBlockAndReportSpam(): Maybe<Result<Unit, GroupChangeFailureReason>> {
|
||||
return if (store.state.threadId > 0 && store.state.recipient != Recipient.UNKNOWN) {
|
||||
messageRequestRepository.blockAndReportSpamMessageRequest(store.state.recipient.id, store.state.threadId)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.toMaybe()
|
||||
} else {
|
||||
Maybe.empty()
|
||||
}
|
||||
}
|
||||
|
||||
open fun refreshRecipient(): Unit = error("This ViewModel does not support this interaction")
|
||||
|
||||
abstract fun setMuteUntil(muteUntil: Long)
|
||||
@@ -112,19 +137,15 @@ sealed class ConversationSettingsViewModel(
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
private fun Cursor?.ensureClosed() {
|
||||
if (this != null && !this.isClosed) {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
|
||||
private class RecipientSettingsViewModel(
|
||||
private val recipientId: RecipientId,
|
||||
private val callMessageIds: LongArray,
|
||||
private val repository: ConversationSettingsRepository
|
||||
private val repository: ConversationSettingsRepository,
|
||||
messageRequestRepository: MessageRequestRepository
|
||||
) : ConversationSettingsViewModel(
|
||||
callMessageIds,
|
||||
repository,
|
||||
messageRequestRepository,
|
||||
SpecificSettingsState.RecipientSettingsState()
|
||||
) {
|
||||
|
||||
@@ -252,8 +273,9 @@ sealed class ConversationSettingsViewModel(
|
||||
private class GroupSettingsViewModel(
|
||||
private val groupId: GroupId,
|
||||
private val callMessageIds: LongArray,
|
||||
private val repository: ConversationSettingsRepository
|
||||
) : ConversationSettingsViewModel(callMessageIds, repository, SpecificSettingsState.GroupSettingsState(groupId)) {
|
||||
private val repository: ConversationSettingsRepository,
|
||||
messageRequestRepository: MessageRequestRepository
|
||||
) : ConversationSettingsViewModel(callMessageIds, repository, messageRequestRepository, SpecificSettingsState.GroupSettingsState(groupId)) {
|
||||
|
||||
private val liveGroup = LiveGroup(groupId)
|
||||
|
||||
@@ -465,15 +487,16 @@ sealed class ConversationSettingsViewModel(
|
||||
private val recipientId: RecipientId? = null,
|
||||
private val groupId: GroupId? = null,
|
||||
private val callMessageIds: LongArray,
|
||||
private val repository: ConversationSettingsRepository
|
||||
private val repository: ConversationSettingsRepository,
|
||||
private val messageRequestRepository: MessageRequestRepository
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return requireNotNull(
|
||||
modelClass.cast(
|
||||
when {
|
||||
recipientId != null -> RecipientSettingsViewModel(recipientId, callMessageIds, repository)
|
||||
groupId != null -> GroupSettingsViewModel(groupId, callMessageIds, repository)
|
||||
recipientId != null -> RecipientSettingsViewModel(recipientId, callMessageIds, repository, messageRequestRepository)
|
||||
groupId != null -> GroupSettingsViewModel(groupId, callMessageIds, repository, messageRequestRepository)
|
||||
else -> error("One of RecipientId or GroupId required.")
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user