Add some guard, and allow to cancel adding 3pid

This commit is contained in:
Benoit Marty 2020-08-28 17:55:38 +02:00
parent f6f9373aeb
commit 1af45ede62
9 changed files with 126 additions and 71 deletions

View file

@ -107,6 +107,12 @@ interface ProfileService {
accountPassword: String?,
matrixCallback: MatrixCallback<Unit>): Cancelable
/**
* Cancel adding a threepid. It will remove data store locally about this ThreePid
*/
fun cancelAddingThreePid(threePid: ThreePid,
matrixCallback: MatrixCallback<Unit>): Cancelable
/**
* Delete a 3Pids.
*/

View file

@ -163,7 +163,25 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
accountPassword: String?,
matrixCallback: MatrixCallback<Unit>): Cancelable {
return finalizeAddingThreePidTask
.configureWith(FinalizeAddingThreePidTask.Params(threePid, uiaSession, accountPassword)) {
.configureWith(FinalizeAddingThreePidTask.Params(
threePid = threePid,
session = uiaSession,
accountPassword = accountPassword,
userWantsToCancel = false
)) {
callback = alsoRefresh(matrixCallback)
}
.executeBy(taskExecutor)
}
override fun cancelAddingThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable {
return finalizeAddingThreePidTask
.configureWith(FinalizeAddingThreePidTask.Params(
threePid = threePid,
session = null,
accountPassword = null,
userWantsToCancel = true
)) {
callback = alsoRefresh(matrixCallback)
}
.executeBy(taskExecutor)

View file

@ -36,7 +36,8 @@ internal abstract class FinalizeAddingThreePidTask : Task<FinalizeAddingThreePid
data class Params(
val threePid: ThreePid,
val session: String?,
val accountPassword: String?
val accountPassword: String?,
val userWantsToCancel: Boolean
)
}
@ -48,6 +49,7 @@ internal class DefaultFinalizeAddingThreePidTask @Inject constructor(
private val eventBus: EventBus) : FinalizeAddingThreePidTask() {
override suspend fun execute(params: Params) {
if (params.userWantsToCancel.not()) {
// Get the required pending data
val pendingThreePids = monarchy.fetchAllMappedSync(
{ it.where(PendingThreePidEntity::class.java) },
@ -76,7 +78,12 @@ internal class DefaultFinalizeAddingThreePidTask @Inject constructor(
?.let { Failure.RegistrationFlowError(it) }
?: throwable
}
}
cleanupDatabase(params)
}
private suspend fun cleanupDatabase(params: Params) {
// Delete the pending three pid
monarchy.awaitTransaction { realm ->
realm.where(PendingThreePidEntity::class.java)

View file

@ -341,8 +341,7 @@ class DiscoverySettingsController @Inject constructor(
private fun buildContinueCancel(threePid: ThreePid) {
settingsContinueCancelItem {
id("bottom${threePid.value}")
interactionListener(object : SettingsContinueCancelItem.Listener {
override fun onContinue() {
continueOnClick {
when (threePid) {
is ThreePid.Email -> {
listener?.checkEmailVerification(threePid)
@ -355,11 +354,9 @@ class DiscoverySettingsController @Inject constructor(
}
}
}
override fun onCancel() {
cancelOnClick {
listener?.cancelBinding(threePid)
}
})
}
}

View file

@ -20,33 +20,28 @@ import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.app.R
import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.onClick
@EpoxyModelClass(layout = R.layout.item_settings_continue_cancel)
abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinueCancelItem.Holder>() {
@EpoxyAttribute
var interactionListener: Listener? = null
var continueOnClick: ClickListener? = null
@EpoxyAttribute
var cancelOnClick: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
holder.cancelButton.setOnClickListener {
interactionListener?.onCancel()
}
holder.continueButton.setOnClickListener {
interactionListener?.onContinue()
}
holder.cancelButton.onClick(cancelOnClick)
holder.continueButton.onClick(continueOnClick)
}
class Holder : VectorEpoxyHolder() {
val cancelButton by bind<Button>(R.id.settings_item_cancel_button)
val continueButton by bind<Button>(R.id.settings_item_continue_button)
}
interface Listener {
fun onContinue()
fun onCancel()
}
}

View file

@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.identity.ThreePid
sealed class ThreePidsSettingsAction : VectorViewModelAction {
data class AddThreePid(val threePid: ThreePid) : ThreePidsSettingsAction()
data class ContinueThreePid(val threePid: ThreePid) : ThreePidsSettingsAction()
data class CancelThreePid(val threePid: ThreePid) : ThreePidsSettingsAction()
data class AccountPassword(val password: String) : ThreePidsSettingsAction()
data class DeleteThreePid(val threePid: ThreePid) : ThreePidsSettingsAction()
}

View file

@ -30,6 +30,8 @@ import im.vector.app.core.ui.list.GenericItem
import im.vector.app.core.ui.list.genericButtonItem
import im.vector.app.core.ui.list.genericFooterItem
import im.vector.app.core.ui.list.genericItem
import im.vector.app.features.discovery.settingsContinueCancelItem
import im.vector.app.features.discovery.settingsInformationItem
import im.vector.app.features.discovery.settingsSectionTitleItem
import org.matrix.android.sdk.api.session.identity.ThreePid
import javax.inject.Inject
@ -43,6 +45,7 @@ class ThreePidsSettingsController @Inject constructor(
fun addEmail()
fun addMsisdn()
fun continueThreePid(threePid: ThreePid)
fun cancelThreePid(threePid: ThreePid)
fun deleteThreePid(threePid: ThreePid)
}
@ -80,12 +83,12 @@ class ThreePidsSettingsController @Inject constructor(
title(stringProvider.getString(R.string.settings_emails))
}
emails.forEach { buildThreePid("email_", it) }
emails.forEach { buildThreePid("email ", it) }
// Pending threePids
pendingThreePids.invoke()
?.filterIsInstance(ThreePid.Email::class.java)
?.forEach { buildPendingThreePid("email_", it) }
?.forEach { buildPendingThreePid("email ", it) }
genericButtonItem {
id("addEmail")
@ -99,12 +102,12 @@ class ThreePidsSettingsController @Inject constructor(
title(stringProvider.getString(R.string.settings_phone_numbers))
}
msisdn.forEach { buildThreePid("msisdn_", it) }
msisdn.forEach { buildThreePid("msisdn ", it) }
// Pending threePids
pendingThreePids.invoke()
?.filterIsInstance(ThreePid.Msisdn::class.java)
?.forEach { buildPendingThreePid("msisdn_", it) }
?.forEach { buildPendingThreePid("msisdn ", it) }
genericButtonItem {
id("addMsisdn")
@ -131,15 +134,20 @@ class ThreePidsSettingsController @Inject constructor(
genericItem {
id(idPrefix + threePid.value)
title(threePid.value)
}
if (threePid is ThreePid.Email) {
description(stringProvider.getString(R.string.account_email_validation_message))
settingsInformationItem {
id("info" + idPrefix + threePid.value)
message(stringProvider.getString(R.string.account_email_validation_message))
colorProvider(colorProvider)
}
buttonAction(
GenericItem.Action(stringProvider.getString(R.string._continue))
.apply {
perform = Runnable { interactionListener?.continueThreePid(threePid) }
}
)
settingsContinueCancelItem {
id("cont" + idPrefix + threePid.value)
continueOnClick { interactionListener?.continueThreePid(threePid) }
cancelOnClick { interactionListener?.cancelThreePid(threePid) }
}
}
}

View file

@ -125,6 +125,10 @@ class ThreePidsSettingsFragment @Inject constructor(
viewModel.handle(ThreePidsSettingsAction.ContinueThreePid(threePid))
}
override fun cancelThreePid(threePid: ThreePid) {
viewModel.handle(ThreePidsSettingsAction.CancelThreePid(threePid))
}
override fun deleteThreePid(threePid: ThreePid) {
AlertDialog.Builder(requireActivity())
.setMessage(getString(R.string.settings_remove_three_pid_confirmation_content, threePid.value))

View file

@ -23,8 +23,10 @@ import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
@ -35,7 +37,8 @@ import org.matrix.android.sdk.rx.rx
class ThreePidsSettingsViewModel @AssistedInject constructor(
@Assisted initialState: ThreePidsSettingsViewState,
private val session: Session
private val session: Session,
private val stringProvider: StringProvider
) : VectorViewModel<ThreePidsSettingsViewState, ThreePidsSettingsAction, ThreePidsSettingsViewEvents>(initialState) {
// UIA session
@ -128,6 +131,7 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
when (action) {
is ThreePidsSettingsAction.AddThreePid -> handleAddThreePid(action)
is ThreePidsSettingsAction.ContinueThreePid -> handleContinueThreePid(action)
is ThreePidsSettingsAction.CancelThreePid -> handleCancelThreePid(action)
is ThreePidsSettingsAction.AccountPassword -> handleAccountPassword(action)
is ThreePidsSettingsAction.DeleteThreePid -> handleDeleteThreePid(action)
}.exhaustive
@ -135,10 +139,18 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
private fun handleAddThreePid(action: ThreePidsSettingsAction.AddThreePid) {
isLoading(true)
withState { state ->
val allThreePids = state.threePids.invoke().orEmpty() + state.pendingThreePids.invoke().orEmpty()
if (allThreePids.any { it.value == action.threePid.value }) {
_viewEvents.post(ThreePidsSettingsViewEvents.Failure(IllegalArgumentException(stringProvider.getString(R.string.auth_email_already_defined))))
} else {
viewModelScope.launch {
session.addThreePid(action.threePid, loadingCallback)
}
}
}
}
private fun handleContinueThreePid(action: ThreePidsSettingsAction.ContinueThreePid) {
isLoading(true)
@ -148,6 +160,13 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
}
}
private fun handleCancelThreePid(action: ThreePidsSettingsAction.CancelThreePid) {
isLoading(true)
viewModelScope.launch {
session.cancelAddingThreePid(action.threePid, loadingCallback)
}
}
private fun handleAccountPassword(action: ThreePidsSettingsAction.AccountPassword) {
val safeSession = pendingSession ?: return Unit
.also { _viewEvents.post(ThreePidsSettingsViewEvents.Failure(IllegalStateException("No pending session"))) }