Add phone numbers to account
This commit is contained in:
parent
931eeac548
commit
bf5c1e9d8f
@ -2,7 +2,7 @@ Changes in Element 1.0.6 (2020-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- List phone numbers and emails added to the Matrix account, and add Email to account (#44)
|
||||
- List phone numbers and emails added to the Matrix account, and add Email adn phone numbers to account (#44, #45)
|
||||
|
||||
Improvements 🙌:
|
||||
- You can now join room through permalink and within room directory search
|
||||
|
@ -99,6 +99,11 @@ interface ProfileService {
|
||||
*/
|
||||
fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Validate a code received by text message
|
||||
*/
|
||||
fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid
|
||||
*/
|
||||
|
@ -46,6 +46,7 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
|
||||
private val setDisplayNameTask: SetDisplayNameTask,
|
||||
private val setAvatarUrlTask: SetAvatarUrlTask,
|
||||
private val addThreePidTask: AddThreePidTask,
|
||||
private val validateSmsCodeTask: ValidateSmsCodeTask,
|
||||
private val finalizeAddingThreePidTask: FinalizeAddingThreePidTask,
|
||||
private val deleteThreePidTask: DeleteThreePidTask,
|
||||
private val pendingThreePidMapper: PendingThreePidMapper,
|
||||
@ -158,6 +159,14 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
|
||||
return validateSmsCodeTask
|
||||
.configureWith(ValidateSmsCodeTask.Params(threePid, code)) {
|
||||
callback = matrixCallback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun finalizeAddingThreePid(threePid: ThreePid,
|
||||
uiaSession: String?,
|
||||
accountPassword: String?,
|
||||
|
@ -19,6 +19,8 @@
|
||||
package org.matrix.android.sdk.internal.session.profile
|
||||
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.internal.auth.registration.SuccessResult
|
||||
import org.matrix.android.sdk.internal.auth.registration.ValidationCodeBody
|
||||
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
@ -26,6 +28,7 @@ import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.PUT
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Url
|
||||
|
||||
internal interface ProfileAPI {
|
||||
/**
|
||||
@ -83,6 +86,13 @@ internal interface ProfileAPI {
|
||||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/msisdn/requestToken")
|
||||
fun addMsisdn(@Body body: AddMsisdnBody): Call<AddMsisdnResponse>
|
||||
|
||||
/**
|
||||
* Validate Msisdn code (same model than for Identity server API)
|
||||
*/
|
||||
@POST
|
||||
fun validateMsisdn(@Url url: String,
|
||||
@Body params: ValidationCodeBody): Call<SuccessResult>
|
||||
|
||||
/**
|
||||
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-add
|
||||
*/
|
||||
|
@ -62,6 +62,9 @@ internal abstract class ProfileModule {
|
||||
@Binds
|
||||
abstract fun bindAddThreePidTask(task: DefaultAddThreePidTask): AddThreePidTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindValidateSmsCodeTask(task: DefaultValidateSmsCodeTask): ValidateSmsCodeTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindFinalizeAddingThreePidTask(task: DefaultFinalizeAddingThreePidTask): FinalizeAddingThreePidTask
|
||||
|
||||
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.session.profile
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||
import org.matrix.android.sdk.internal.auth.registration.SuccessResult
|
||||
import org.matrix.android.sdk.internal.auth.registration.ValidationCodeBody
|
||||
import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface ValidateSmsCodeTask : Task<ValidateSmsCodeTask.Params, Unit> {
|
||||
data class Params(
|
||||
val threePid: ThreePid.Msisdn,
|
||||
val code: String
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultValidateSmsCodeTask @Inject constructor(
|
||||
private val profileAPI: ProfileAPI,
|
||||
@SessionDatabase
|
||||
private val monarchy: Monarchy,
|
||||
private val pendingThreePidMapper: PendingThreePidMapper,
|
||||
private val eventBus: EventBus
|
||||
) : ValidateSmsCodeTask {
|
||||
|
||||
override suspend fun execute(params: ValidateSmsCodeTask.Params) {
|
||||
// Search the pending ThreePid
|
||||
val pendingThreePids = monarchy.fetchAllMappedSync(
|
||||
{ it.where(PendingThreePidEntity::class.java) },
|
||||
{ pendingThreePidMapper.map(it) }
|
||||
)
|
||||
.firstOrNull { it.threePid == params.threePid }
|
||||
?: throw IllegalArgumentException("unknown threepid")
|
||||
|
||||
val url = pendingThreePids.submitUrl ?: throw IllegalArgumentException("invalid threepid")
|
||||
val body = ValidationCodeBody(
|
||||
clientSecret = pendingThreePids.clientSecret,
|
||||
sid = pendingThreePids.sid,
|
||||
code = params.code
|
||||
)
|
||||
val result = executeRequest<SuccessResult>(eventBus) {
|
||||
apiCall = profileAPI.validateMsisdn(url, body)
|
||||
}
|
||||
|
||||
if (!result.isSuccess()) {
|
||||
throw Failure.SuccessError
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||
sealed class ThreePidsSettingsAction : VectorViewModelAction {
|
||||
data class ChangeState(val newState: ThreePidsSettingsState) : ThreePidsSettingsAction()
|
||||
data class AddThreePid(val threePid: ThreePid) : ThreePidsSettingsAction()
|
||||
data class SubmitCode(val threePid: ThreePid.Msisdn, val code: String) : ThreePidsSettingsAction()
|
||||
data class ContinueThreePid(val threePid: ThreePid) : ThreePidsSettingsAction()
|
||||
data class CancelThreePid(val threePid: ThreePid) : ThreePidsSettingsAction()
|
||||
data class AccountPassword(val password: String) : ThreePidsSettingsAction()
|
||||
|
@ -50,6 +50,7 @@ class ThreePidsSettingsController @Inject constructor(
|
||||
fun cancelAdding()
|
||||
fun doAddEmail(email: String)
|
||||
fun doAddMsisdn(msisdn: String)
|
||||
fun submitCode(threePid: ThreePid.Msisdn, code: String)
|
||||
fun continueThreePid(threePid: ThreePid)
|
||||
fun cancelThreePid(threePid: ThreePid)
|
||||
fun deleteThreePid(threePid: ThreePid)
|
||||
@ -57,8 +58,12 @@ class ThreePidsSettingsController @Inject constructor(
|
||||
|
||||
var interactionListener: InteractionListener? = null
|
||||
|
||||
// For phone number or email (exclusive)
|
||||
private var currentInputValue = ""
|
||||
|
||||
// For validation code
|
||||
private val currentCodes = mutableMapOf<ThreePid, String>()
|
||||
|
||||
override fun buildModels(data: ThreePidsSettingsViewState?) {
|
||||
if (data == null) return
|
||||
|
||||
@ -210,18 +215,38 @@ class ThreePidsSettingsController @Inject constructor(
|
||||
title(threePid.getFormattedValue())
|
||||
}
|
||||
|
||||
if (threePid is ThreePid.Email) {
|
||||
settingsInformationItem {
|
||||
id("info" + idPrefix + threePid.value)
|
||||
message(stringProvider.getString(R.string.account_email_validation_message))
|
||||
colorProvider(colorProvider)
|
||||
when (threePid) {
|
||||
is ThreePid.Email -> {
|
||||
settingsInformationItem {
|
||||
id("info" + idPrefix + threePid.value)
|
||||
message(stringProvider.getString(R.string.account_email_validation_message))
|
||||
colorProvider(colorProvider)
|
||||
}
|
||||
settingsContinueCancelItem {
|
||||
id("cont" + idPrefix + threePid.value)
|
||||
continueOnClick { interactionListener?.continueThreePid(threePid) }
|
||||
cancelOnClick { interactionListener?.cancelThreePid(threePid) }
|
||||
}
|
||||
}
|
||||
is ThreePid.Msisdn -> {
|
||||
settingsInformationItem {
|
||||
id("info" + idPrefix + threePid.value)
|
||||
message(stringProvider.getString(R.string.settings_text_message_sent, threePid.getFormattedValue()))
|
||||
colorProvider(colorProvider)
|
||||
}
|
||||
formEditTextItem {
|
||||
id("msisdnVerification${threePid.value}")
|
||||
inputType(InputType.TYPE_CLASS_NUMBER)
|
||||
hint(stringProvider.getString(R.string.settings_text_message_sent_hint))
|
||||
showBottomSeparator(false)
|
||||
onTextChange { currentCodes[threePid] = it }
|
||||
}
|
||||
settingsContinueCancelItem {
|
||||
id("cont" + idPrefix + threePid.value)
|
||||
continueOnClick { interactionListener?.submitCode(threePid, currentCodes[threePid] ?: "") }
|
||||
cancelOnClick { interactionListener?.cancelThreePid(threePid) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settingsContinueCancelItem {
|
||||
id("cont" + idPrefix + threePid.value)
|
||||
continueOnClick { interactionListener?.continueThreePid(threePid) }
|
||||
cancelOnClick { interactionListener?.cancelThreePid(threePid) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +132,12 @@ class ThreePidsSettingsFragment @Inject constructor(
|
||||
viewModel.handle(ThreePidsSettingsAction.AddThreePid(ThreePid.Msisdn(safeMsisdn)))
|
||||
}
|
||||
|
||||
override fun submitCode(threePid: ThreePid.Msisdn, code: String) {
|
||||
viewModel.handle(ThreePidsSettingsAction.SubmitCode(threePid, code))
|
||||
// Hide the keyboard
|
||||
view?.hideKeyboard()
|
||||
}
|
||||
|
||||
override fun cancelAdding() {
|
||||
viewModel.handle(ThreePidsSettingsAction.ChangeState(ThreePidsSettingsState.Idle))
|
||||
// Hide the keyboard
|
||||
|
@ -131,6 +131,7 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
|
||||
when (action) {
|
||||
is ThreePidsSettingsAction.AddThreePid -> handleAddThreePid(action)
|
||||
is ThreePidsSettingsAction.ContinueThreePid -> handleContinueThreePid(action)
|
||||
is ThreePidsSettingsAction.SubmitCode -> handleSubmitCode(action)
|
||||
is ThreePidsSettingsAction.CancelThreePid -> handleCancelThreePid(action)
|
||||
is ThreePidsSettingsAction.AccountPassword -> handleAccountPassword(action)
|
||||
is ThreePidsSettingsAction.DeleteThreePid -> handleDeleteThreePid(action)
|
||||
@ -138,6 +139,27 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleSubmitCode(action: ThreePidsSettingsAction.SubmitCode) {
|
||||
isLoading(true)
|
||||
viewModelScope.launch {
|
||||
// First submit the code
|
||||
session.submitSmsCode(action.threePid, action.code, object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
// then finalize
|
||||
pendingThreePid = action.threePid
|
||||
session.finalizeAddingThreePid(action.threePid, null, null, loadingCallback)
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
// Wrong code?
|
||||
isLoading(false)
|
||||
_viewEvents.post(ThreePidsSettingsViewEvents.Failure(failure))
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleChangeState(action: ThreePidsSettingsAction.ChangeState) {
|
||||
setState {
|
||||
copy(
|
||||
@ -152,7 +174,12 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
|
||||
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))))
|
||||
_viewEvents.post(ThreePidsSettingsViewEvents.Failure(IllegalArgumentException(stringProvider.getString(
|
||||
when (action.threePid) {
|
||||
is ThreePid.Email -> R.string.auth_email_already_defined
|
||||
is ThreePid.Msisdn -> R.string.auth_msisdn_already_defined
|
||||
}
|
||||
))))
|
||||
} else {
|
||||
viewModelScope.launch {
|
||||
session.addThreePid(action.threePid, object : MatrixCallback<Unit> {
|
||||
|
@ -281,6 +281,7 @@
|
||||
<string name="auth_invalid_email">"This doesn’t look like a valid email address"</string>
|
||||
<string name="auth_invalid_phone">"This doesn’t look like a valid phone number"</string>
|
||||
<string name="auth_email_already_defined">This email address is already defined.</string>
|
||||
<string name="auth_msisdn_already_defined">This phone number is already defined.</string>
|
||||
<string name="auth_missing_email">Missing email address</string>
|
||||
<string name="auth_missing_phone">Missing phone number</string>
|
||||
<string name="auth_missing_email_or_phone">Missing email address or phone number</string>
|
||||
@ -1765,6 +1766,7 @@
|
||||
<string name="settings_discovery_no_terms_title">Identity server has no terms of services</string>
|
||||
<string name="settings_discovery_no_terms">The identity server you have chosen does not have any terms of services. Only continue if you trust the owner of the service</string>
|
||||
<string name="settings_text_message_sent">A text message has been sent to %s. Please enter the verification code it contains.</string>
|
||||
<string name="settings_text_message_sent_hint">Code</string>
|
||||
<string name="settings_text_message_sent_wrong_code">The verification code is not correct.</string>
|
||||
|
||||
<string name="settings_discovery_disconnect_with_bound_pid">You are currently sharing email addresses or phone numbers on the identity server %1$s. You will need to reconnect to %2$s to stop sharing them.</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user