Identity: cleanup Epoxy items

This commit is contained in:
Benoit Marty 2020-05-10 23:15:25 +02:00
parent ae0d09a049
commit bdfcf5c67c
22 changed files with 588 additions and 531 deletions

View File

@ -44,6 +44,8 @@ class DiscoverySettingsController @Inject constructor(
var listener: Listener? = null var listener: Listener? = null
private val codes = mutableMapOf<ThreePid, String>()
override fun buildModels(data: DiscoverySettingsState) { override fun buildModels(data: DiscoverySettingsState) {
when (data.identityServer) { when (data.identityServer) {
is Loading -> { is Loading -> {
@ -59,9 +61,7 @@ class DiscoverySettingsController @Inject constructor(
} }
is Success -> { is Success -> {
buildIdentityServerSection(data) buildIdentityServerSection(data)
val hasIdentityServer = data.identityServer().isNullOrBlank().not() val hasIdentityServer = data.identityServer().isNullOrBlank().not()
if (hasIdentityServer) { if (hasIdentityServer) {
buildMailSection(data) buildMailSection(data)
buildPhoneNumberSection(data) buildPhoneNumberSection(data)
@ -70,226 +70,17 @@ class DiscoverySettingsController @Inject constructor(
} }
} }
private fun buildPhoneNumberSection(data: DiscoverySettingsState) {
settingsSectionTitle {
id("msisdn")
titleResId(R.string.settings_discovery_msisdn_title)
}
when (data.phoneNumbersList) {
is Incomplete -> {
loadingItem {
id("msisdnLoading")
}
}
is Fail -> {
settingsInfoItem {
id("msisdnListError")
helperText(data.phoneNumbersList.error.message)
}
}
is Success -> {
val phones = data.phoneNumbersList.invoke()
if (phones.isEmpty()) {
settingsInfoItem {
id("no_msisdn")
helperText(stringProvider.getString(R.string.settings_discovery_no_msisdn))
}
} else {
phones.forEach { piState ->
val phoneNumber = try {
PhoneNumberUtil.getInstance().parse("+${piState.threePid.value}", null)
} catch (t: Throwable) {
Timber.e(t, "Unable to parse the phone number")
null
}
?.let {
PhoneNumberUtil.getInstance().format(it, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL)
}
settingsTextButtonItem {
id(piState.threePid.value)
title(phoneNumber)
colorProvider(colorProvider)
stringProvider(stringProvider)
when (piState.isShared) {
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 { listener?.onTapRetryToRetrieveBindings() }
}
is Success -> when (piState.isShared()) {
SharedState.SHARED,
SharedState.NOT_SHARED -> {
checked(piState.isShared() == SharedState.SHARED)
buttonType(SettingsTextButtonItem.ButtonType.SWITCH)
switchChangeListener { _, checked ->
if (checked) {
listener?.onTapShare(piState.threePid)
} else {
listener?.onTapRevoke(piState.threePid)
}
}
}
SharedState.BINDING_IN_PROGRESS -> {
buttonType(SettingsTextButtonItem.ButtonType.NORMAL)
buttonTitle(null)
}
}
}
}
when (piState.isShared()) {
SharedState.BINDING_IN_PROGRESS -> {
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
&& error.httpCode == HttpsURLConnection.HTTP_INTERNAL_ERROR /* 500 */) {
stringProvider.getString(R.string.settings_text_message_sent_wrong_code)
} else {
errorFormatter.toHumanReadable(error)
}
} else {
null
}
settingsItemEditText {
id("tverif" + piState.threePid.value)
descriptionText(stringProvider.getString(R.string.settings_text_message_sent, phoneNumber))
errorText(errorText)
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
}
}
}
}
}
private fun buildMailSection(data: DiscoverySettingsState) {
settingsSectionTitle {
id("emails")
titleResId(R.string.settings_discovery_emails_title)
}
when (data.emailList) {
is Incomplete -> {
loadingItem {
id("mailLoading")
}
}
is Fail -> {
settingsInfoItem {
id("mailListError")
helperText(data.emailList.error.message)
}
}
is Success -> {
val emails = data.emailList.invoke()
if (emails.isEmpty()) {
settingsInfoItem {
id("no_emails")
helperText(stringProvider.getString(R.string.settings_discovery_no_mails))
}
} else {
emails.forEach { piState ->
settingsTextButtonItem {
id(piState.threePid.value)
title(piState.threePid.value)
colorProvider(colorProvider)
stringProvider(stringProvider)
when (piState.isShared) {
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 { listener?.onTapRetryToRetrieveBindings() }
showBottomButtons(false)
}
is Success -> when (piState.isShared()) {
SharedState.SHARED,
SharedState.NOT_SHARED -> {
checked(piState.isShared() == SharedState.SHARED)
buttonType(SettingsTextButtonItem.ButtonType.SWITCH)
switchChangeListener { _, checked ->
if (checked) {
listener?.onTapShare(piState.threePid)
} else {
listener?.onTapRevoke(piState.threePid)
}
}
}
SharedState.BINDING_IN_PROGRESS -> {
buttonType(SettingsTextButtonItem.ButtonType.NORMAL)
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)
}
}
}
}
}
}
}
}
}
}
}
private fun buildIdentityServerSection(data: DiscoverySettingsState) { private fun buildIdentityServerSection(data: DiscoverySettingsState) {
val identityServer = data.identityServer() ?: stringProvider.getString(R.string.none) val identityServer = data.identityServer() ?: stringProvider.getString(R.string.none)
settingsSectionTitle { settingsSectionTitleItem {
id("idsTitle") id("idsTitle")
titleResId(R.string.identity_server) titleResId(R.string.identity_server)
} }
settingsItem { settingsItem {
id("idServer") id("idServer")
description(identityServer) title(identityServer)
} }
settingsInfoItem { settingsInfoItem {
@ -316,7 +107,7 @@ class DiscoverySettingsController @Inject constructor(
} else { } else {
buttonTitleId(R.string.add_identity_server) buttonTitleId(R.string.add_identity_server)
} }
buttonStyle(SettingsTextButtonItem.ButtonStyle.POSITIVE) buttonStyle(SettingsTextButtonSingleLineItem.ButtonStyle.POSITIVE)
buttonClickListener(View.OnClickListener { buttonClickListener(View.OnClickListener {
listener?.onTapChangeIdentityServer() listener?.onTapChangeIdentityServer()
}) })
@ -331,7 +122,7 @@ class DiscoverySettingsController @Inject constructor(
id("remove") id("remove")
colorProvider(colorProvider) colorProvider(colorProvider)
buttonTitleId(R.string.disconnect_identity_server) buttonTitleId(R.string.disconnect_identity_server)
buttonStyle(SettingsTextButtonItem.ButtonStyle.DESTRUCTIVE) buttonStyle(SettingsTextButtonSingleLineItem.ButtonStyle.DESTRUCTIVE)
buttonClickListener(View.OnClickListener { buttonClickListener(View.OnClickListener {
listener?.onTapDisconnectIdentityServer() listener?.onTapDisconnectIdentityServer()
}) })
@ -339,6 +130,273 @@ class DiscoverySettingsController @Inject constructor(
} }
} }
private fun buildMailSection(data: DiscoverySettingsState) {
settingsSectionTitleItem {
id("emails")
titleResId(R.string.settings_discovery_emails_title)
}
when (data.emailList) {
is Incomplete -> {
loadingItem {
id("mailLoading")
}
}
is Fail -> {
settingsInfoItem {
id("mailListError")
helperText(data.emailList.error.message)
}
}
is Success -> {
val emails = data.emailList.invoke()
if (emails.isEmpty()) {
settingsInfoItem {
id("no_emails")
helperText(stringProvider.getString(R.string.settings_discovery_no_mails))
}
} else {
emails.forEach { buildEmail(it) }
}
}
}
}
private fun buildEmail(pidInfo: PidInfo) {
settingsTextButtonSingleLineItem {
id(pidInfo.threePid.value)
title(pidInfo.threePid.value)
colorProvider(colorProvider)
stringProvider(stringProvider)
when (pidInfo.isShared) {
is Loading -> {
buttonIndeterminate(true)
}
is Fail -> {
buttonStyle(SettingsTextButtonSingleLineItem.ButtonStyle.DESTRUCTIVE)
buttonTitle(stringProvider.getString(R.string.global_retry))
iconMode(IconMode.Error)
buttonClickListener { listener?.onTapRetryToRetrieveBindings() }
}
is Success -> when (pidInfo.isShared()) {
SharedState.SHARED,
SharedState.NOT_SHARED -> {
checked(pidInfo.isShared() == SharedState.SHARED)
buttonType(SettingsTextButtonSingleLineItem.ButtonType.SWITCH)
switchChangeListener { _, checked ->
if (checked) {
listener?.onTapShare(pidInfo.threePid)
} else {
listener?.onTapRevoke(pidInfo.threePid)
}
}
}
SharedState.BINDING_IN_PROGRESS -> {
buttonType(SettingsTextButtonSingleLineItem.ButtonType.NO_BUTTON)
when (pidInfo.finalRequest) {
is Incomplete -> iconMode(IconMode.Info)
is Fail -> iconMode(IconMode.Error)
else -> iconMode(IconMode.None)
}
}
}
}
}
if (pidInfo.isShared is Fail) {
settingsInformationItem {
id("info${pidInfo.threePid.value}")
colorProvider(colorProvider)
infoMessageColorId(R.color.vector_error_color)
infoMessage(pidInfo.isShared.error.message ?: "")
}
buildContinueCancel(pidInfo.threePid)
}
if (pidInfo.isShared() == SharedState.BINDING_IN_PROGRESS) {
when (pidInfo.finalRequest) {
is Uninitialized -> {
settingsInformationItem {
id("info${pidInfo.threePid.value}")
colorProvider(colorProvider)
infoMessage(stringProvider.getString(R.string.settings_discovery_confirm_mail, pidInfo.threePid.value))
infoMessageColorId(R.color.vector_info_color)
}
buildContinueCancel(pidInfo.threePid)
}
is Loading -> {
settingsInformationItem {
id("info${pidInfo.threePid.value}")
colorProvider(colorProvider)
infoMessage(stringProvider.getString(R.string.settings_discovery_confirm_mail, pidInfo.threePid.value))
infoMessageColorId(R.color.vector_info_color)
}
settingsProgressItem {
id("progress${pidInfo.threePid.value}")
}
}
is Fail -> {
settingsInformationItem {
id("info${pidInfo.threePid.value}")
colorProvider(colorProvider)
infoMessage(stringProvider.getString(R.string.settings_discovery_confirm_mail_not_clicked, pidInfo.threePid.value))
infoMessageColorId(R.color.riotx_destructive_accent)
}
buildContinueCancel(pidInfo.threePid)
}
is Success -> Unit /* Cannot happen */
}
}
}
private fun buildPhoneNumberSection(data: DiscoverySettingsState) {
settingsSectionTitleItem {
id("msisdn")
titleResId(R.string.settings_discovery_msisdn_title)
}
when (data.phoneNumbersList) {
is Incomplete -> {
loadingItem {
id("msisdnLoading")
}
}
is Fail -> {
settingsInfoItem {
id("msisdnListError")
helperText(data.phoneNumbersList.error.message)
}
}
is Success -> {
val phones = data.phoneNumbersList.invoke()
if (phones.isEmpty()) {
settingsInfoItem {
id("no_msisdn")
helperText(stringProvider.getString(R.string.settings_discovery_no_msisdn))
}
} else {
phones.forEach { buildMsisdn(it) }
}
}
}
}
private fun buildMsisdn(pidInfo: PidInfo) {
val phoneNumber = try {
PhoneNumberUtil.getInstance().parse("+${pidInfo.threePid.value}", null)
} catch (t: Throwable) {
Timber.e(t, "Unable to parse the phone number")
null
}
?.let {
PhoneNumberUtil.getInstance().format(it, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL)
}
?: pidInfo.threePid.value
settingsTextButtonSingleLineItem {
id(pidInfo.threePid.value)
title(phoneNumber)
colorProvider(colorProvider)
stringProvider(stringProvider)
when (pidInfo.isShared) {
is Loading -> {
buttonIndeterminate(true)
}
is Fail -> {
buttonType(SettingsTextButtonSingleLineItem.ButtonType.NORMAL)
buttonStyle(SettingsTextButtonSingleLineItem.ButtonStyle.DESTRUCTIVE)
buttonTitle(stringProvider.getString(R.string.global_retry))
iconMode(IconMode.Error)
buttonClickListener { listener?.onTapRetryToRetrieveBindings() }
}
is Success -> when (pidInfo.isShared()) {
SharedState.SHARED,
SharedState.NOT_SHARED -> {
checked(pidInfo.isShared() == SharedState.SHARED)
buttonType(SettingsTextButtonSingleLineItem.ButtonType.SWITCH)
switchChangeListener { _, checked ->
if (checked) {
listener?.onTapShare(pidInfo.threePid)
} else {
listener?.onTapRevoke(pidInfo.threePid)
}
}
}
SharedState.BINDING_IN_PROGRESS -> {
buttonType(SettingsTextButtonSingleLineItem.ButtonType.NO_BUTTON)
}
}
}
}
if (pidInfo.isShared is Fail) {
settingsInformationItem {
id("info${pidInfo.threePid.value}")
colorProvider(colorProvider)
infoMessageColorId(R.color.vector_error_color)
infoMessage(pidInfo.isShared.error.message ?: "")
}
}
when (pidInfo.isShared()) {
SharedState.BINDING_IN_PROGRESS -> {
val errorText = if (pidInfo.finalRequest is Fail) {
val error = pidInfo.finalRequest.error
// Deal with error 500
//Ref: https://github.com/matrix-org/sydent/issues/292
if (error is Failure.ServerError
&& error.httpCode == HttpsURLConnection.HTTP_INTERNAL_ERROR /* 500 */) {
stringProvider.getString(R.string.settings_text_message_sent_wrong_code)
} else {
errorFormatter.toHumanReadable(error)
}
} else {
null
}
settingsEditTextItem {
id("msisdnVerification${pidInfo.threePid.value}")
descriptionText(stringProvider.getString(R.string.settings_text_message_sent, phoneNumber))
errorText(errorText)
inProgress(pidInfo.finalRequest is Loading)
interactionListener(object : SettingsEditTextItem.Listener {
override fun onValidate() {
val code = codes[pidInfo.threePid]
if (pidInfo.threePid is ThreePid.Msisdn && code != null) {
listener?.sendMsisdnVerificationCode(pidInfo.threePid, code)
}
}
override fun onCodeChange(code: String) {
codes[pidInfo.threePid] = code
}
})
}
buildContinueCancel(pidInfo.threePid)
}
else -> Unit
}.exhaustive
}
private fun buildContinueCancel(threePid: ThreePid) {
settingsContinueCancelItem {
id("bottom${threePid.value}")
interactionListener(object : SettingsContinueCancelItem.Listener {
override fun onContinue() {
when (threePid) {
is ThreePid.Email -> {
listener?.checkEmailVerification(threePid)
}
is ThreePid.Msisdn -> {
val code = codes[threePid]
if (code != null) {
listener?.sendMsisdnVerificationCode(threePid, code)
}
}
}
}
override fun onCancel() {
listener?.cancelBinding(threePid)
}
})
}
}
interface Listener { interface Listener {
fun onSelectIdentityServer() fun onSelectIdentityServer()
fun onTapRevoke(threePid: ThreePid) fun onTapRevoke(threePid: ThreePid)

View File

@ -278,9 +278,11 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
} }
private fun cancelBinding(action: DiscoverySettingsAction.CancelBinding) { private fun cancelBinding(action: DiscoverySettingsAction.CancelBinding) {
// TODO: remove the callback
identityService.cancelBindThreePid(action.threePid, object : MatrixCallback<Unit> { identityService.cancelBindThreePid(action.threePid, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
changeThreePidState(action.threePid, Success(SharedState.NOT_SHARED)) changeThreePidState(action.threePid, Success(SharedState.NOT_SHARED))
changeThreePidSubmitState(action.threePid, Uninitialized)
} }
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* 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 im.vector.riotx.features.discovery
enum class IconMode {
None,
Info,
Error
}

View File

@ -40,7 +40,7 @@ abstract class SettingsButtonItem : EpoxyModelWithHolder<SettingsButtonItem.Hold
var buttonTitleId: Int? = null var buttonTitleId: Int? = null
@EpoxyAttribute @EpoxyAttribute
var buttonStyle: SettingsTextButtonItem.ButtonStyle = SettingsTextButtonItem.ButtonStyle.POSITIVE var buttonStyle: SettingsTextButtonSingleLineItem.ButtonStyle = SettingsTextButtonSingleLineItem.ButtonStyle.POSITIVE
@EpoxyAttribute @EpoxyAttribute
var buttonClickListener: View.OnClickListener? = null var buttonClickListener: View.OnClickListener? = null
@ -54,10 +54,10 @@ abstract class SettingsButtonItem : EpoxyModelWithHolder<SettingsButtonItem.Hold
} }
when (buttonStyle) { when (buttonStyle) {
SettingsTextButtonItem.ButtonStyle.POSITIVE -> { SettingsTextButtonSingleLineItem.ButtonStyle.POSITIVE -> {
holder.button.setTextColor(colorProvider.getColor(R.color.riotx_accent)) holder.button.setTextColor(colorProvider.getColor(R.color.riotx_accent))
} }
SettingsTextButtonItem.ButtonStyle.DESTRUCTIVE -> { SettingsTextButtonSingleLineItem.ButtonStyle.DESTRUCTIVE -> {
holder.button.setTextColor(colorProvider.getColor(R.color.riotx_destructive_accent)) holder.button.setTextColor(colorProvider.getColor(R.color.riotx_destructive_accent))
} }
} }

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* 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 im.vector.riotx.features.discovery
import android.widget.Button
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.VectorEpoxyHolder
@EpoxyModelClass(layout = R.layout.item_settings_continue_cancel)
abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinueCancelItem.Holder>() {
@EpoxyAttribute
var interactionListener: Listener? = null
override fun bind(holder: Holder) {
super.bind(holder)
holder.cancelButton.setOnClickListener {
interactionListener?.onCancel()
}
holder.continueButton.setOnClickListener {
interactionListener?.onContinue()
}
}
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

@ -15,13 +15,10 @@
*/ */
package im.vector.riotx.features.discovery package im.vector.riotx.features.discovery
import android.view.View
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.widget.Button
import android.widget.EditText import android.widget.EditText
import android.widget.TextView import android.widget.TextView
import androidx.core.view.isInvisible import androidx.core.widget.doOnTextChanged
import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder import com.airbnb.epoxy.EpoxyModelWithHolder
@ -31,7 +28,7 @@ import im.vector.riotx.core.epoxy.VectorEpoxyHolder
import im.vector.riotx.core.extensions.setTextOrHide import im.vector.riotx.core.extensions.setTextOrHide
@EpoxyModelClass(layout = R.layout.item_settings_edit_text) @EpoxyModelClass(layout = R.layout.item_settings_edit_text)
abstract class SettingsItemEditText : EpoxyModelWithHolder<SettingsItemEditText.Holder>() { abstract class SettingsEditTextItem : EpoxyModelWithHolder<SettingsEditTextItem.Holder>() {
@EpoxyAttribute var descriptionText: String? = null @EpoxyAttribute var descriptionText: String? = null
@EpoxyAttribute var errorText: String? = null @EpoxyAttribute var errorText: String? = null
@ -44,14 +41,6 @@ abstract class SettingsItemEditText : EpoxyModelWithHolder<SettingsItemEditText.
super.bind(holder) super.bind(holder)
holder.textView.setTextOrHide(descriptionText) holder.textView.setTextOrHide(descriptionText)
holder.validateButton.setOnClickListener {
val code = holder.editText.text.toString()
interactionListener?.onValidate(code)
}
holder.cancelButton.setOnClickListener {
interactionListener?.onCancel()
}
holder.editText.isEnabled = !inProgress holder.editText.isEnabled = !inProgress
@ -61,13 +50,12 @@ abstract class SettingsItemEditText : EpoxyModelWithHolder<SettingsItemEditText.
holder.textInputLayout.error = errorText holder.textInputLayout.error = errorText
} }
holder.validateButton.isInvisible = inProgress holder.editText.doOnTextChanged { code, _, _, _ ->
holder.progress.isVisible = inProgress code?.let { interactionListener?.onCodeChange(it.toString()) }
}
holder.editText.setOnEditorActionListener { tv, actionId, _ -> holder.editText.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) { if (actionId == EditorInfo.IME_ACTION_DONE) {
val code = tv.text.toString() interactionListener?.onValidate()
interactionListener?.onValidate(code)
return@setOnEditorActionListener true return@setOnEditorActionListener true
} }
return@setOnEditorActionListener false return@setOnEditorActionListener false
@ -75,16 +63,13 @@ abstract class SettingsItemEditText : EpoxyModelWithHolder<SettingsItemEditText.
} }
class Holder : VectorEpoxyHolder() { class Holder : VectorEpoxyHolder() {
val textView by bind<TextView>(R.id.settings_item_description) val textView by bind<TextView>(R.id.settings_item_edit_text_description)
val editText by bind<EditText>(R.id.settings_item_edittext) val editText by bind<EditText>(R.id.settings_item_edit_text)
val textInputLayout by bind<TextInputLayout>(R.id.settings_item_enter_til) val textInputLayout by bind<TextInputLayout>(R.id.settings_item_edit_text_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 { interface Listener {
fun onValidate(code: String) fun onValidate()
fun onCancel() fun onCodeChange(code: String)
} }
} }

View File

@ -1,70 +0,0 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* 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 im.vector.riotx.features.discovery
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.view.isVisible
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.VectorEpoxyHolder
import im.vector.riotx.core.extensions.setTextOrHide
@EpoxyModelClass(layout = R.layout.item_settings_radio_single_line)
abstract class SettingsImageItem : EpoxyModelWithHolder<SettingsImageItem.Holder>() {
@EpoxyAttribute
var title: String? = null
@EpoxyAttribute
@StringRes
var titleResId: Int? = null
@EpoxyAttribute
@DrawableRes
var endIconResourceId: Int = -1
@EpoxyAttribute
var itemClickListener: View.OnClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
if (titleResId != null) {
holder.textView.setText(titleResId!!)
} else {
holder.textView.setTextOrHide(title)
}
if (endIconResourceId != -1) {
holder.accessoryImage.setImageResource(endIconResourceId)
holder.accessoryImage.isVisible = true
} else {
holder.accessoryImage.isVisible = false
}
holder.view.setOnClickListener(itemClickListener)
}
class Holder : VectorEpoxyHolder() {
val textView by bind<TextView>(R.id.settings_item_text)
val accessoryImage by bind<ImageView>(R.id.settings_item_image)
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* 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 im.vector.riotx.features.discovery
import android.widget.TextView
import androidx.annotation.ColorRes
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.VectorEpoxyHolder
import im.vector.riotx.core.resources.ColorProvider
@EpoxyModelClass(layout = R.layout.item_settings_information)
abstract class SettingsInformationItem : EpoxyModelWithHolder<SettingsInformationItem.Holder>() {
@EpoxyAttribute
lateinit var colorProvider: ColorProvider
// TODO Rename message
@EpoxyAttribute
lateinit var infoMessage: String
@EpoxyAttribute
@ColorRes
var infoMessageColorId: Int = R.color.vector_error_color
override fun bind(holder: Holder) {
super.bind(holder)
holder.textView.text = infoMessage
val errorColor = colorProvider.getColor(infoMessageColorId)
holder.textView.setTextColor(errorColor)
}
class Holder : VectorEpoxyHolder() {
val textView by bind<TextView>(R.id.settings_item_information)
}
}

View File

@ -61,15 +61,6 @@ abstract class SettingsItem : EpoxyModelWithHolder<SettingsItem.Holder>() {
holder.descriptionText.setTextOrHide(description) holder.descriptionText.setTextOrHide(description)
} }
//If there is only a description, use primary color
// holder.descriptionText.setTextColor(
// if (holder.titleText.text.isNullOrBlank()) {
// ThemeUtils.getColor(holder.main.context, android.R.attr.textColorPrimary)
// } else {
// ThemeUtils.getColor(holder.main.context, android.R.attr.textColorSecondary)
// }
// )
holder.switchButton.isVisible = false holder.switchButton.isVisible = false
holder.view.setOnClickListener(itemClickListener) holder.view.setOnClickListener(itemClickListener)

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* 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 im.vector.riotx.features.discovery
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.riotx.R
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
@EpoxyModelClass(layout = R.layout.item_settings_progress)
abstract class SettingsProgressItem : EpoxyModelWithHolder<SettingsProgressItem.Holder>() {
class Holder : VectorEpoxyHolder()
}

View File

@ -25,7 +25,7 @@ import im.vector.riotx.core.epoxy.VectorEpoxyHolder
import im.vector.riotx.core.extensions.setTextOrHide import im.vector.riotx.core.extensions.setTextOrHide
@EpoxyModelClass(layout = R.layout.item_settings_section_title) @EpoxyModelClass(layout = R.layout.item_settings_section_title)
abstract class SettingsSectionTitle : EpoxyModelWithHolder<SettingsSectionTitle.Holder>() { abstract class SettingsSectionTitleItem : EpoxyModelWithHolder<SettingsSectionTitleItem.Holder>() {
@EpoxyAttribute @EpoxyAttribute
var title: String? = null var title: String? = null

View File

@ -20,7 +20,6 @@ import android.widget.CompoundButton
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.Switch import android.widget.Switch
import android.widget.TextView import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
@ -32,13 +31,14 @@ import im.vector.riotx.R
import im.vector.riotx.core.epoxy.ClickListener import im.vector.riotx.core.epoxy.ClickListener
import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyHolder
import im.vector.riotx.core.epoxy.onClick import im.vector.riotx.core.epoxy.onClick
import im.vector.riotx.core.extensions.exhaustive
import im.vector.riotx.core.extensions.setTextOrHide import im.vector.riotx.core.extensions.setTextOrHide
import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.resources.ColorProvider
import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.StringProvider
import im.vector.riotx.features.themes.ThemeUtils import im.vector.riotx.features.themes.ThemeUtils
@EpoxyModelClass(layout = R.layout.item_settings_button_single_line) @EpoxyModelClass(layout = R.layout.item_settings_button_single_line)
abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonItem.Holder>() { abstract class SettingsTextButtonSingleLineItem : EpoxyModelWithHolder<SettingsTextButtonSingleLineItem.Holder>() {
enum class ButtonStyle { enum class ButtonStyle {
POSITIVE, POSITIVE,
@ -46,6 +46,7 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
} }
enum class ButtonType { enum class ButtonType {
NO_BUTTON,
NORMAL, NORMAL,
SWITCH SWITCH
} }
@ -63,6 +64,9 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
@StringRes @StringRes
var titleResId: Int? = null var titleResId: Int? = null
@EpoxyAttribute
var iconMode: IconMode = IconMode.None
@EpoxyAttribute @EpoxyAttribute
var buttonTitle: String? = null var buttonTitle: String? = null
@ -82,35 +86,12 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
@EpoxyAttribute @EpoxyAttribute
var checked: Boolean? = null var checked: Boolean? = null
@EpoxyAttribute
var showBottomLoading: Boolean = false
@EpoxyAttribute
var showBottomButtons: Boolean = false
@EpoxyAttribute @EpoxyAttribute
var buttonClickListener: ClickListener? = null var buttonClickListener: ClickListener? = null
@EpoxyAttribute
var continueClickListener: ClickListener? = null
@EpoxyAttribute
var cancelClickListener: ClickListener? = null
@EpoxyAttribute @EpoxyAttribute
var switchChangeListener: CompoundButton.OnCheckedChangeListener? = null var switchChangeListener: CompoundButton.OnCheckedChangeListener? = null
@EpoxyAttribute
var infoMessage: String? = null
@EpoxyAttribute
@StringRes
var infoMessageId: Int? = null
@EpoxyAttribute
@ColorRes
var infoMessageTintColorId: Int = R.color.vector_error_color
override fun bind(holder: Holder) { override fun bind(holder: Holder) {
super.bind(holder) super.bind(holder)
@ -126,21 +107,19 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
holder.mainButton.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) { if (buttonIndeterminate) {
holder.spinner.isVisible = true holder.progress.isVisible = true
holder.mainButton.isInvisible = true holder.mainButton.isInvisible = true
holder.switchButton.isInvisible = true holder.switchButton.isInvisible = true
holder.switchButton.setOnCheckedChangeListener(null) holder.switchButton.setOnCheckedChangeListener(null)
holder.mainButton.setOnClickListener(null) holder.mainButton.setOnClickListener(null)
} else { } else {
holder.spinner.isVisible = false holder.progress.isVisible = false
when (buttonType) { when (buttonType) {
ButtonType.NO_BUTTON -> {
holder.mainButton.isVisible = false
holder.switchButton.isVisible = false
}
ButtonType.NORMAL -> { ButtonType.NORMAL -> {
holder.mainButton.isVisible = true holder.mainButton.isVisible = true
holder.switchButton.isVisible = false holder.switchButton.isVisible = false
@ -151,34 +130,39 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
ButtonStyle.DESTRUCTIVE -> { ButtonStyle.DESTRUCTIVE -> {
holder.mainButton.setTextColor(colorProvider.getColor(R.color.vector_error_color)) holder.mainButton.setTextColor(colorProvider.getColor(R.color.vector_error_color))
} }
} }.exhaustive
holder.mainButton.onClick(buttonClickListener) holder.mainButton.onClick(buttonClickListener)
} }
ButtonType.SWITCH -> { ButtonType.SWITCH -> {
holder.mainButton.isInvisible = true holder.mainButton.isVisible = false
holder.switchButton.isVisible = true holder.switchButton.isVisible = true
//set to null before changing the state //set to null before changing the state
holder.switchButton.setOnCheckedChangeListener(null) holder.switchButton.setOnCheckedChangeListener(null)
checked?.let { holder.switchButton.isChecked = it } checked?.let { holder.switchButton.isChecked = it }
holder.switchButton.setOnCheckedChangeListener(switchChangeListener) holder.switchButton.setOnCheckedChangeListener(switchChangeListener)
} }
} }.exhaustive
} }
val errorMessage = infoMessageId?.let { stringProvider.getString(it) } ?: infoMessage
if (errorMessage != null) { when (iconMode) {
holder.errorTextView.isVisible = true IconMode.None -> {
holder.errorTextView.setTextOrHide(errorMessage) holder.textView.setCompoundDrawables(null, null, null, null)
val errorColor = colorProvider.getColor(infoMessageTintColorId) }
IconMode.Info -> {
val errorColor = colorProvider.getColor(R.color.notification_accent_color)
ContextCompat.getDrawable(holder.view.context, R.drawable.ic_notification_privacy_warning)?.apply { ContextCompat.getDrawable(holder.view.context, R.drawable.ic_notification_privacy_warning)?.apply {
ThemeUtils.tintDrawableWithColor(this, errorColor) ThemeUtils.tintDrawableWithColor(this, errorColor)
holder.textView.setCompoundDrawablesWithIntrinsicBounds(this, null, null, null) holder.textView.setCompoundDrawablesWithIntrinsicBounds(this, null, null, null)
} }
holder.errorTextView.setTextColor(errorColor) }
} else { IconMode.Error -> {
holder.errorTextView.isVisible = false val errorColor = colorProvider.getColor(R.color.vector_error_color)
holder.errorTextView.text = null ContextCompat.getDrawable(holder.view.context, R.drawable.ic_notification_privacy_warning)?.apply {
holder.textView.setCompoundDrawables(null, null, null, null) ThemeUtils.tintDrawableWithColor(this, errorColor)
holder.textView.setCompoundDrawablesWithIntrinsicBounds(this, null, null, null)
}
}
} }
} }
@ -186,10 +170,6 @@ abstract class SettingsTextButtonItem : EpoxyModelWithHolder<SettingsTextButtonI
val textView by bind<TextView>(R.id.settings_item_text) val textView by bind<TextView>(R.id.settings_item_text)
val mainButton 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 switchButton by bind<Switch>(R.id.settings_item_switch)
val spinner by bind<ProgressBar>(R.id.settings_item_button_spinner) val progress by bind<ProgressBar>(R.id.settings_item_progress)
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)
} }
} }

View File

@ -18,7 +18,7 @@ package im.vector.riotx.features.terms
import android.view.View import android.view.View
import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.epoxy.TypedEpoxyController
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.features.discovery.settingsSectionTitle import im.vector.riotx.features.discovery.settingsSectionTitleItem
import javax.inject.Inject import javax.inject.Inject
class TermsController @Inject constructor() : TypedEpoxyController<List<Term>>() { class TermsController @Inject constructor() : TypedEpoxyController<List<Term>>() {
@ -28,7 +28,7 @@ class TermsController @Inject constructor() : TypedEpoxyController<List<Term>>()
override fun buildModels(data: List<Term>?) { override fun buildModels(data: List<Term>?) {
data?.let { data?.let {
settingsSectionTitle { settingsSectionTitleItem {
id("header") id("header")
titleResId(R.string.widget_integration_review_terms) titleResId(R.string.widget_integration_review_terms)
} }

View File

@ -3,8 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:background="?vctr_list_header_background_color" android:layout_height="match_parent"
android:layout_height="match_parent"> android:background="?riotx_background">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView" android:id="@+id/recyclerView"

View File

@ -2,8 +2,9 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:minHeight="64dp" android:layout_height="wrap_content"
android:layout_height="wrap_content"> android:background="?riotx_background"
android:minHeight="64dp">
<Button <Button
android:id="@+id/settings_item_button" android:id="@+id/settings_item_button"

View File

@ -4,9 +4,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/colorBackgroundFloating" android:background="?riotx_background"
android:foreground="?attr/selectableItemBackground" android:minHeight="68dp"
android:orientation="vertical"
android:paddingStart="@dimen/layout_horizontal_margin" android:paddingStart="@dimen/layout_horizontal_margin"
android:paddingTop="@dimen/layout_vertical_margin" android:paddingTop="@dimen/layout_vertical_margin"
android:paddingEnd="@dimen/layout_horizontal_margin" android:paddingEnd="@dimen/layout_horizontal_margin"
@ -16,17 +15,14 @@
android:id="@+id/settings_item_text" android:id="@+id/settings_item_text"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="vertical"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="15sp" android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="@+id/settings_item_button" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/settings_item_button" app:layout_constraintEnd_toStartOf="@+id/settings_item_button"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/settings_item_button" app:layout_constraintTop_toTopOf="parent"
tools:drawableLeft="@drawable/ic_notification_privacy_warning" tools:drawableLeft="@drawable/ic_notification_privacy_warning"
tools:drawableStart="@drawable/ic_notification_privacy_warning" tools:drawableStart="@drawable/ic_notification_privacy_warning"
tools:drawableTint="@color/vector_error_color" tools:drawableTint="@color/vector_error_color"
@ -37,23 +33,24 @@
style="@style/VectorButtonStyleText" style="@style/VectorButtonStyleText"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="invisible" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="@string/share" tools:text="@string/global_retry"
tools:visibility="visible" /> tools:visibility="visible" />
<ProgressBar <ProgressBar
android:id="@+id/settings_item_button_spinner" android:id="@+id/settings_item_progress"
style="?android:attr/progressBarStyle" style="?android:attr/progressBarStyle"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:layout_marginEnd="16dp"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/settings_item_button" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/settings_item_button" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/settings_item_button" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toTopOf="@+id/settings_item_button" tools:visibility="visible" />
tools:visibility="invisible" />
<Switch <Switch
android:id="@+id/settings_item_switch" android:id="@+id/settings_item_switch"
@ -61,55 +58,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/settings_item_button" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/settings_item_button" app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" /> tools:visibility="visible" />
<TextView
android:id="@+id/settings_item_error_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="8dp"
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>
<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> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?riotx_background"
android:paddingStart="@dimen/layout_horizontal_margin"
android:paddingEnd="@dimen/layout_horizontal_margin">
<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_toTopOf="parent" />
<Button
android:id="@+id/settings_item_continue_button"
style="@style/VectorButtonStyleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/_continue"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -5,13 +5,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/colorBackgroundFloating" android:background="?attr/colorBackgroundFloating"
android:orientation="vertical"
android:paddingStart="@dimen/layout_horizontal_margin" android:paddingStart="@dimen/layout_horizontal_margin"
android:paddingEnd="@dimen/layout_horizontal_margin" android:paddingEnd="@dimen/layout_horizontal_margin">
android:paddingBottom="@dimen/layout_vertical_margin">
<TextView <TextView
android:id="@+id/settings_item_description" android:id="@+id/settings_item_edit_text_description"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
@ -23,17 +21,17 @@
tools:text="@string/settings_text_message_sent" /> tools:text="@string/settings_text_message_sent" />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/settings_item_enter_til" android:id="@+id/settings_item_edit_text_til"
style="@style/VectorTextInputLayout" style="@style/VectorTextInputLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:errorEnabled="true" app:errorEnabled="true"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/settings_item_description"> app:layout_constraintTop_toBottomOf="@+id/settings_item_edit_text_description">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/settings_item_edittext" android:id="@+id/settings_item_edit_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:imeOptions="actionDone|flagNoPersonalizedLearning" android:imeOptions="actionDone|flagNoPersonalizedLearning"
@ -44,33 +42,4 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/settings_item_enter_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_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"
android:layout_width="20dp"
android:layout_height="20dp"
app:layout_constraintBottom_toBottomOf="@+id/settings_item_enter_button"
app:layout_constraintEnd_toEndOf="@+id/settings_item_enter_button"
app:layout_constraintStart_toStartOf="@+id/settings_item_enter_button"
app:layout_constraintTop_toTopOf="@+id/settings_item_enter_button" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<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"
android:background="?riotx_background"
android:foreground="?attr/selectableItemBackground"
android:paddingStart="@dimen/layout_horizontal_margin"
android:paddingEnd="@dimen/layout_horizontal_margin">
<TextView
android:id="@+id/settings_item_information"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/settings_discovery_confirm_mail"
tools:textColor="@color/vector_info_color" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?riotx_background"
android:minHeight="48dp"
android:paddingStart="@dimen/layout_horizontal_margin"
android:paddingEnd="@dimen/layout_horizontal_margin">
<ProgressBar
android:id="@+id/settings_item_enter_progress"
style="?android:attr/progressBarStyle"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="26dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorBackgroundFloating"
android:orientation="horizontal"
android:paddingStart="@dimen/layout_horizontal_margin"
android:paddingTop="@dimen/layout_vertical_margin"
android:paddingEnd="@dimen/layout_horizontal_margin"
android:paddingBottom="@dimen/layout_vertical_margin">
<FrameLayout
android:layout_width="40dp"
android:layout_height="40dp">
<ImageView
android:id="@+id/settings_item_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
tools:src="@drawable/unit_test" />
</FrameLayout>
<TextView
android:id="@+id/settings_item_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_weight="1"
android:orientation="vertical"
android:textColor="?android:textColorPrimary"
android:textSize="15sp"
tools:text="An option" />
</LinearLayout>

View File

@ -4,12 +4,12 @@
android:id="@+id/settings_section_title_text" android:id="@+id/settings_section_title_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_vertical_margin" android:background="?vctr_list_header_background_color"
android:layout_marginBottom="@dimen/layout_vertical_margin"
android:orientation="vertical"
android:paddingStart="@dimen/layout_horizontal_margin" android:paddingStart="@dimen/layout_horizontal_margin"
android:paddingTop="@dimen/layout_vertical_margin"
android:paddingEnd="@dimen/layout_horizontal_margin" android:paddingEnd="@dimen/layout_horizontal_margin"
android:textColor="?android:textColorPrimary" android:paddingBottom="@dimen/layout_vertical_margin"
android:textColor="?riotx_text_primary"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="Title" /> tools:text="Title" />