Identity: cancel binding WIP
This commit is contained in:
parent
69759b7415
commit
ae0d09a049
|
@ -40,15 +40,19 @@ interface IdentityService {
|
|||
fun setNewIdentityServer(url: String?, callback: MatrixCallback<String?>): Cancelable
|
||||
|
||||
/**
|
||||
* This will ask the identity server to send an email or an SMS to let the user confirm he owns the ThreePid,
|
||||
* and then the threePid will be associated with the matrix account
|
||||
* This will ask the identity server to send an email or an SMS to let the user confirm he owns the ThreePid
|
||||
*/
|
||||
fun startBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* This will perform the actual association of ThreePid and Matrix account
|
||||
* This will cancel a pending binding of threePid.
|
||||
*/
|
||||
fun finalizeBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
|
||||
fun cancelBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* This will ask the identity server to send an new email or a new SMS to let the user confirm he owns the ThreePid
|
||||
*/
|
||||
fun sendAgainValidationCode(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Submit the code that the identity server has sent to the user (in email or SMS)
|
||||
|
@ -58,6 +62,12 @@ interface IdentityService {
|
|||
fun submitValidationToken(threePid: ThreePid, code: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* This will perform the actual association of ThreePid and Matrix account
|
||||
*/
|
||||
fun finalizeBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Unbind a threePid
|
||||
* The request will actually be done on the homeserver
|
||||
*/
|
||||
fun unbindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
|
|
@ -123,7 +123,19 @@ internal class DefaultIdentityService @Inject constructor(
|
|||
|
||||
override fun startBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return GlobalScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||
identityRequestTokenForBindingTask.execute(IdentityRequestTokenForBindingTask.Params(threePid))
|
||||
identityRequestTokenForBindingTask.execute(IdentityRequestTokenForBindingTask.Params(threePid, false))
|
||||
}
|
||||
}
|
||||
|
||||
override fun cancelBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return GlobalScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||
identityServiceStore.deletePendingBinding(threePid)
|
||||
}
|
||||
}
|
||||
|
||||
override fun sendAgainValidationCode(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return GlobalScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||
identityRequestTokenForBindingTask.execute(IdentityRequestTokenForBindingTask.Params(threePid, true))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import im.vector.matrix.android.api.session.identity.IdentityServiceError
|
||||
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||
import im.vector.matrix.android.api.session.identity.getCountryCode
|
||||
import im.vector.matrix.android.internal.di.UserId
|
||||
|
@ -30,7 +31,9 @@ import javax.inject.Inject
|
|||
|
||||
internal interface IdentityRequestTokenForBindingTask : Task<IdentityRequestTokenForBindingTask.Params, Unit> {
|
||||
data class Params(
|
||||
val threePid: ThreePid
|
||||
val threePid: ThreePid,
|
||||
// True to request the identity server to send again the email or the SMS
|
||||
val sendAgain: Boolean
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -45,6 +48,10 @@ internal class DefaultIdentityRequestTokenForBindingTask @Inject constructor(
|
|||
|
||||
val pendingBindingEntity = identityServiceStore.getPendingBinding(params.threePid)
|
||||
|
||||
if (params.sendAgain && pendingBindingEntity == null) {
|
||||
throw IdentityServiceError.NoCurrentBindingError
|
||||
}
|
||||
|
||||
val clientSecret = pendingBindingEntity?.clientSecret ?: UUID.randomUUID().toString()
|
||||
val sendAttempt = pendingBindingEntity?.sendAttempt?.inc() ?: 1
|
||||
|
||||
|
|
|
@ -32,10 +32,7 @@ internal fun IdentityPendingBindingEntity.Companion.getOrCreate(realm: Realm, th
|
|||
}
|
||||
|
||||
internal fun IdentityPendingBindingEntity.Companion.delete(realm: Realm, threePid: ThreePid) {
|
||||
realm.where<IdentityPendingBindingEntity>()
|
||||
.equalTo(IdentityPendingBindingEntityFields.THREE_PID, threePid.toPrimaryKey())
|
||||
.findAll()
|
||||
.deleteAllFromRealm()
|
||||
get(realm, threePid)?.deleteFromRealm()
|
||||
}
|
||||
|
||||
internal fun IdentityPendingBindingEntity.Companion.deleteAll(realm: Realm) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.airbnb.mvrx.Fail
|
|||
import com.airbnb.mvrx.Incomplete
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.session.identity.SharedState
|
||||
|
@ -28,6 +29,7 @@ import im.vector.matrix.android.api.session.identity.ThreePid
|
|||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.epoxy.loadingItem
|
||||
import im.vector.riotx.core.error.ErrorFormatter
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.resources.ColorProvider
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import timber.log.Timber
|
||||
|
@ -111,15 +113,15 @@ class DiscoverySettingsController @Inject constructor(
|
|||
colorProvider(colorProvider)
|
||||
stringProvider(stringProvider)
|
||||
when (piState.isShared) {
|
||||
is Loading -> buttonIndeterminate(true)
|
||||
is Loading -> {
|
||||
buttonIndeterminate(true)
|
||||
}
|
||||
is Fail -> {
|
||||
buttonType(SettingsTextButtonItem.ButtonType.NORMAL)
|
||||
buttonStyle(SettingsTextButtonItem.ButtonStyle.DESTRUCTIVE)
|
||||
buttonTitle(stringProvider.getString(R.string.global_retry))
|
||||
infoMessage(piState.isShared.error.message)
|
||||
buttonClickListener(View.OnClickListener {
|
||||
listener?.onTapRetryToRetrieveBindings()
|
||||
})
|
||||
buttonClickListener { listener?.onTapRetryToRetrieveBindings() }
|
||||
}
|
||||
is Success -> when (piState.isShared()) {
|
||||
SharedState.SHARED,
|
||||
|
@ -143,8 +145,8 @@ class DiscoverySettingsController @Inject constructor(
|
|||
}
|
||||
when (piState.isShared()) {
|
||||
SharedState.BINDING_IN_PROGRESS -> {
|
||||
val errorText = if (piState.isTokenSubmitted is Fail) {
|
||||
val error = piState.isTokenSubmitted.error
|
||||
val errorText = if (piState.finalRequest is Fail) {
|
||||
val error = piState.finalRequest.error
|
||||
// Deal with error 500
|
||||
//Ref: https://github.com/matrix-org/sydent/issues/292
|
||||
if (error is Failure.ServerError
|
||||
|
@ -160,18 +162,22 @@ class DiscoverySettingsController @Inject constructor(
|
|||
id("tverif" + piState.threePid.value)
|
||||
descriptionText(stringProvider.getString(R.string.settings_text_message_sent, phoneNumber))
|
||||
errorText(errorText)
|
||||
inProgress(piState.isTokenSubmitted is Loading)
|
||||
inProgress(piState.finalRequest is Loading)
|
||||
interactionListener(object : SettingsItemEditText.Listener {
|
||||
override fun onValidate(code: String) {
|
||||
if (piState.threePid is ThreePid.Msisdn) {
|
||||
listener?.sendMsisdnVerificationCode(piState.threePid, code)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancel() {
|
||||
listener?.cancelBinding(piState.threePid)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,15 +216,17 @@ class DiscoverySettingsController @Inject constructor(
|
|||
colorProvider(colorProvider)
|
||||
stringProvider(stringProvider)
|
||||
when (piState.isShared) {
|
||||
is Loading -> buttonIndeterminate(true)
|
||||
is Loading -> {
|
||||
buttonIndeterminate(true)
|
||||
showBottomButtons(false)
|
||||
}
|
||||
is Fail -> {
|
||||
buttonType(SettingsTextButtonItem.ButtonType.NORMAL)
|
||||
buttonStyle(SettingsTextButtonItem.ButtonStyle.DESTRUCTIVE)
|
||||
buttonTitle(stringProvider.getString(R.string.global_retry))
|
||||
infoMessage(piState.isShared.error.message)
|
||||
buttonClickListener(View.OnClickListener {
|
||||
listener?.onTapRetryToRetrieveBindings()
|
||||
})
|
||||
buttonClickListener { listener?.onTapRetryToRetrieveBindings() }
|
||||
showBottomButtons(false)
|
||||
}
|
||||
is Success -> when (piState.isShared()) {
|
||||
SharedState.SHARED,
|
||||
|
@ -235,14 +243,32 @@ class DiscoverySettingsController @Inject constructor(
|
|||
}
|
||||
SharedState.BINDING_IN_PROGRESS -> {
|
||||
buttonType(SettingsTextButtonItem.ButtonType.NORMAL)
|
||||
buttonTitleId(R.string._continue)
|
||||
infoMessageTintColorId(R.color.vector_info_color)
|
||||
infoMessage(stringProvider.getString(R.string.settings_discovery_confirm_mail, piState.threePid.value))
|
||||
buttonClickListener(View.OnClickListener {
|
||||
buttonTitle(null)
|
||||
showBottomButtons(true)
|
||||
when (piState.finalRequest) {
|
||||
is Uninitialized -> {
|
||||
infoMessage(stringProvider.getString(R.string.settings_discovery_confirm_mail, piState.threePid.value))
|
||||
infoMessageTintColorId(R.color.vector_info_color)
|
||||
showBottomLoading(false)
|
||||
}
|
||||
is Loading -> {
|
||||
infoMessage(stringProvider.getString(R.string.settings_discovery_confirm_mail, piState.threePid.value))
|
||||
infoMessageTintColorId(R.color.vector_info_color)
|
||||
showBottomLoading(true)
|
||||
}
|
||||
is Fail -> {
|
||||
infoMessage(stringProvider.getString(R.string.settings_discovery_confirm_mail_not_clicked, piState.threePid.value))
|
||||
infoMessageTintColorId(R.color.riotx_destructive_accent)
|
||||
showBottomLoading(false)
|
||||
}
|
||||
is Success -> Unit /* Cannot happen */
|
||||
}
|
||||
cancelClickListener { listener?.cancelBinding(piState.threePid) }
|
||||
continueClickListener {
|
||||
if (piState.threePid is ThreePid.Email) {
|
||||
listener?.checkEmailVerification(piState.threePid)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -318,6 +344,7 @@ class DiscoverySettingsController @Inject constructor(
|
|||
fun onTapRevoke(threePid: ThreePid)
|
||||
fun onTapShare(threePid: ThreePid)
|
||||
fun checkEmailVerification(threePid: ThreePid.Email)
|
||||
fun cancelBinding(threePid: ThreePid)
|
||||
fun sendMsisdnVerificationCode(threePid: ThreePid.Msisdn, code: String)
|
||||
fun onTapChangeIdentityServer()
|
||||
fun onTapDisconnectIdentityServer()
|
||||
|
|
|
@ -130,6 +130,10 @@ class DiscoverySettingsFragment @Inject constructor(
|
|||
viewModel.handle(DiscoverySettingsAction.SubmitMsisdnToken(threePid, code))
|
||||
}
|
||||
|
||||
override fun cancelBinding(threePid: ThreePid) {
|
||||
viewModel.handle(DiscoverySettingsAction.CancelBinding(threePid))
|
||||
}
|
||||
|
||||
override fun onTapChangeIdentityServer() = withState(viewModel) { state ->
|
||||
//we should prompt if there are bound items with current is
|
||||
val pidList = state.emailList().orEmpty() + state.phoneNumbersList().orEmpty()
|
||||
|
|
|
@ -44,7 +44,8 @@ data class PidInfo(
|
|||
// Retrieved from IdentityServer, or transient state
|
||||
val isShared: Async<SharedState>,
|
||||
// Contains information about a current request to submit the token (for instance SMS code received by SMS)
|
||||
val isTokenSubmitted: Async<Unit> = Uninitialized
|
||||
// Or a current binding finalization, for email
|
||||
val finalRequest: Async<Unit> = Uninitialized
|
||||
)
|
||||
|
||||
data class DiscoverySettingsState(
|
||||
|
@ -64,6 +65,7 @@ sealed class DiscoverySettingsAction : VectorViewModelAction {
|
|||
data class ShareThreePid(val threePid: ThreePid) : DiscoverySettingsAction()
|
||||
data class FinalizeBind3pid(val threePid: ThreePid) : DiscoverySettingsAction()
|
||||
data class SubmitMsisdnToken(val threePid: ThreePid.Msisdn, val code: String) : DiscoverySettingsAction()
|
||||
data class CancelBinding(val threePid: ThreePid) : DiscoverySettingsAction()
|
||||
}
|
||||
|
||||
sealed class DiscoverySettingsViewEvents : VectorViewEvents {
|
||||
|
@ -133,6 +135,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
|||
is DiscoverySettingsAction.ShareThreePid -> shareThreePid(action)
|
||||
is DiscoverySettingsAction.FinalizeBind3pid -> finalizeBind3pid(action)
|
||||
is DiscoverySettingsAction.SubmitMsisdnToken -> submitMsisdnToken(action)
|
||||
is DiscoverySettingsAction.CancelBinding -> cancelBinding(action)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
|
@ -214,7 +217,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
|||
emailList = Success(
|
||||
currentMails.map {
|
||||
if (it.threePid == threePid) {
|
||||
it.copy(isTokenSubmitted = submitState)
|
||||
it.copy(finalRequest = submitState)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
|
@ -223,7 +226,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
|||
phoneNumbersList = Success(
|
||||
phones.map {
|
||||
if (it.threePid == threePid) {
|
||||
it.copy(isTokenSubmitted = submitState)
|
||||
it.copy(finalRequest = submitState)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
|
@ -274,6 +277,18 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
|||
})
|
||||
}
|
||||
|
||||
private fun cancelBinding(action: DiscoverySettingsAction.CancelBinding) {
|
||||
identityService.cancelBindThreePid(action.threePid, object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
changeThreePidState(action.threePid, Success(SharedState.NOT_SHARED))
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
// This could never fail
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun startListenToIdentityManager() {
|
||||
identityService.addListener(identityServerManagerListener)
|
||||
}
|
||||
|
@ -362,25 +377,23 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
|||
private fun finalizeBind3pid(action: DiscoverySettingsAction.FinalizeBind3pid) = withState { state ->
|
||||
val threePid = when (action.threePid) {
|
||||
is ThreePid.Email -> {
|
||||
changeThreePidState(action.threePid, Loading())
|
||||
state.emailList()?.find { it.threePid.value == action.threePid.email }?.threePid ?: return@withState
|
||||
}
|
||||
is ThreePid.Msisdn -> {
|
||||
changeThreePidState(action.threePid, Loading())
|
||||
state.phoneNumbersList()?.find { it.threePid.value == action.threePid.msisdn }?.threePid ?: return@withState
|
||||
}
|
||||
}
|
||||
|
||||
changeThreePidSubmitState(action.threePid, Loading())
|
||||
|
||||
identityService.finalizeBindThreePid(threePid, object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
changeThreePidSubmitState(action.threePid, Uninitialized)
|
||||
changeThreePidState(action.threePid, Success(SharedState.SHARED))
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
_viewEvents.post(DiscoverySettingsViewEvents.Failure(failure))
|
||||
|
||||
// Restore previous state after an error
|
||||
changeThreePidState(action.threePid, Success(SharedState.BINDING_IN_PROGRESS))
|
||||
changeThreePidSubmitState(action.threePid, Fail(failure))
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -49,6 +49,10 @@ abstract class SettingsItemEditText : EpoxyModelWithHolder<SettingsItemEditText.
|
|||
interactionListener?.onValidate(code)
|
||||
}
|
||||
|
||||
holder.cancelButton.setOnClickListener {
|
||||
interactionListener?.onCancel()
|
||||
}
|
||||
|
||||
holder.editText.isEnabled = !inProgress
|
||||
|
||||
if (errorText.isNullOrBlank()) {
|
||||
|
@ -75,10 +79,12 @@ abstract class SettingsItemEditText : EpoxyModelWithHolder<SettingsItemEditText.
|
|||
val editText by bind<EditText>(R.id.settings_item_edittext)
|
||||
val textInputLayout by bind<TextInputLayout>(R.id.settings_item_enter_til)
|
||||
val validateButton by bind<Button>(R.id.settings_item_enter_button)
|
||||
val cancelButton by bind<Button>(R.id.settings_item_enter_cancel_button)
|
||||
val progress by bind<View>(R.id.settings_item_enter_progress)
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onValidate(code: String)
|
||||
fun onCancel()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package im.vector.riotx.features.discovery
|
||||
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.ProgressBar
|
||||
|
@ -30,7 +29,9 @@ import com.airbnb.epoxy.EpoxyAttribute
|
|||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import com.airbnb.epoxy.EpoxyModelWithHolder
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.epoxy.ClickListener
|
||||
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.riotx.core.epoxy.onClick
|
||||
import im.vector.riotx.core.extensions.setTextOrHide
|
||||
import im.vector.riotx.core.resources.ColorProvider
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
|
@ -82,7 +83,19 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
|
|||
var checked: Boolean? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var buttonClickListener: View.OnClickListener? = null
|
||||
var showBottomLoading: Boolean = false
|
||||
|
||||
@EpoxyAttribute
|
||||
var showBottomButtons: Boolean = false
|
||||
|
||||
@EpoxyAttribute
|
||||
var buttonClickListener: ClickListener? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var continueClickListener: ClickListener? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var cancelClickListener: ClickListener? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var switchChangeListener: CompoundButton.OnCheckedChangeListener? = null
|
||||
|
@ -108,35 +121,41 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
|
|||
}
|
||||
|
||||
if (buttonTitleId != null) {
|
||||
holder.button.setText(buttonTitleId!!)
|
||||
holder.mainButton.setText(buttonTitleId!!)
|
||||
} else {
|
||||
holder.button.setTextOrHide(buttonTitle)
|
||||
holder.mainButton.setTextOrHide(buttonTitle)
|
||||
}
|
||||
|
||||
holder.bottomLoading.isVisible = showBottomLoading
|
||||
holder.continueButton.isInvisible = showBottomLoading || !showBottomButtons
|
||||
holder.cancelButton.isVisible = !showBottomLoading && showBottomButtons
|
||||
holder.continueButton.onClick(continueClickListener)
|
||||
holder.cancelButton.onClick(cancelClickListener)
|
||||
|
||||
if (buttonIndeterminate) {
|
||||
holder.spinner.isVisible = true
|
||||
holder.button.isInvisible = true
|
||||
holder.mainButton.isInvisible = true
|
||||
holder.switchButton.isInvisible = true
|
||||
holder.switchButton.setOnCheckedChangeListener(null)
|
||||
holder.button.setOnClickListener(null)
|
||||
holder.mainButton.setOnClickListener(null)
|
||||
} else {
|
||||
holder.spinner.isVisible = false
|
||||
when (buttonType) {
|
||||
ButtonType.NORMAL -> {
|
||||
holder.button.isVisible = true
|
||||
holder.mainButton.isVisible = true
|
||||
holder.switchButton.isVisible = false
|
||||
when (buttonStyle) {
|
||||
ButtonStyle.POSITIVE -> {
|
||||
holder.button.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorAccent))
|
||||
holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorAccent))
|
||||
}
|
||||
ButtonStyle.DESTRUCTIVE -> {
|
||||
holder.button.setTextColor(colorProvider.getColor(R.color.vector_error_color))
|
||||
holder.mainButton.setTextColor(colorProvider.getColor(R.color.vector_error_color))
|
||||
}
|
||||
}
|
||||
holder.button.setOnClickListener(buttonClickListener)
|
||||
holder.mainButton.onClick(buttonClickListener)
|
||||
}
|
||||
ButtonType.SWITCH -> {
|
||||
holder.button.isVisible = false
|
||||
holder.mainButton.isInvisible = true
|
||||
holder.switchButton.isVisible = true
|
||||
//set to null before changing the state
|
||||
holder.switchButton.setOnCheckedChangeListener(null)
|
||||
|
@ -165,9 +184,12 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
|
|||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val textView by bind<TextView>(R.id.settings_item_text)
|
||||
val button by bind<Button>(R.id.settings_item_button)
|
||||
val mainButton by bind<Button>(R.id.settings_item_button)
|
||||
val switchButton by bind<Switch>(R.id.settings_item_switch)
|
||||
val spinner by bind<ProgressBar>(R.id.settings_item_button_spinner)
|
||||
val errorTextView by bind<TextView>(R.id.settings_item_error_message)
|
||||
val continueButton by bind<Button>(R.id.settings_item_continue_button)
|
||||
val cancelButton by bind<Button>(R.id.settings_item_cancel_button)
|
||||
val bottomLoading by bind<ProgressBar>(R.id.settings_item_bottom_loading)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -11,63 +12,59 @@
|
|||
android:paddingEnd="@dimen/layout_horizontal_margin"
|
||||
android:paddingBottom="@dimen/layout_vertical_margin">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
<TextView
|
||||
android:id="@+id/settings_item_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/settings_item_button"
|
||||
app:layout_constraintEnd_toStartOf="@+id/settings_item_button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/settings_item_button"
|
||||
tools:drawableLeft="@drawable/ic_notification_privacy_warning"
|
||||
tools:drawableStart="@drawable/ic_notification_privacy_warning"
|
||||
tools:drawableTint="@color/vector_error_color"
|
||||
tools:text="foo@bar.test" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/settings_item_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="15sp"
|
||||
tools:drawableLeft="@drawable/ic_notification_privacy_warning"
|
||||
tools:drawableStart="@drawable/ic_notification_privacy_warning"
|
||||
tools:drawableTint="@color/vector_error_color"
|
||||
tools:text="foo@bar.test" />
|
||||
<Button
|
||||
android:id="@+id/settings_item_button"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/share"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:minWidth="70dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/settings_item_button"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"
|
||||
tools:text="@string/share"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/settings_item_button_spinner"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="invisible" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/settings_item_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
<ProgressBar
|
||||
android:id="@+id/settings_item_button_spinner"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/settings_item_button"
|
||||
app:layout_constraintEnd_toEndOf="@+id/settings_item_button"
|
||||
app:layout_constraintStart_toStartOf="@+id/settings_item_button"
|
||||
app:layout_constraintTop_toTopOf="@+id/settings_item_button"
|
||||
tools:visibility="invisible" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/settings_item_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/settings_item_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/settings_item_button"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/settings_item_error_message"
|
||||
|
@ -77,10 +74,42 @@
|
|||
android:gravity="center_vertical"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@+id/settings_item_button"
|
||||
tools:drawableStart="@drawable/ic_notification_privacy_warning"
|
||||
tools:text="Error Message"
|
||||
tools:textColor="@color/vector_info_color"
|
||||
tools:visibility="visible">
|
||||
|
||||
</TextView>
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/settings_item_continue_button"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:text="@string/_continue"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/settings_item_error_message" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/settings_item_bottom_loading"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/settings_item_continue_button"
|
||||
app:layout_constraintEnd_toEndOf="@+id/settings_item_continue_button"
|
||||
app:layout_constraintStart_toStartOf="@+id/settings_item_continue_button"
|
||||
app:layout_constraintTop_toTopOf="@+id/settings_item_continue_button" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/settings_item_cancel_button"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel"
|
||||
android:textColor="@color/riotx_destructive_accent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/settings_item_error_message" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -54,6 +54,15 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/settings_item_enter_til" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/settings_item_enter_cancel_button"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/settings_item_enter_til" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/settings_item_enter_progress"
|
||||
style="?android:attr/progressBarStyle"
|
||||
|
|
|
@ -1733,6 +1733,7 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming
|
|||
<string name="settings_discovery_disconnect_identity_server_info">Disconnecting from your identity server will mean you won’t be discoverable by other users and you won’t be able to invite others by email or phone.</string>
|
||||
<string name="settings_discovery_msisdn_title">Discoverable phone numbers</string>
|
||||
<string name="settings_discovery_confirm_mail">We sent you a confirm email to %s, check your email and click on the confirmation link</string>
|
||||
<string name="settings_discovery_confirm_mail_not_clicked">We sent you a confirm email to %s, please first check your email and click on the confirmation link</string>
|
||||
<string name="settings_discovery_mail_pending">Pending</string>
|
||||
|
||||
<string name="settings_discovery_enter_identity_server">Enter a new identity server</string>
|
||||
|
|
Loading…
Reference in New Issue