Migrate to ViewBindings (#1072) - WIP
This commit is contained in:
parent
409d7e50bb
commit
7de2494af2
|
@ -39,7 +39,7 @@ class BottomSheetActionButton @JvmOverloads constructor(
|
|||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : FrameLayout(context, attrs, defStyleAttr) {
|
||||
private val views : ItemVerificationActionBinding
|
||||
val views : ItemVerificationActionBinding
|
||||
|
||||
var title: String? = null
|
||||
set(value) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import androidx.core.text.italic
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.error.ResourceLimitErrorFormatter
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.databinding.ViewNotificationAreaBinding
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
|
||||
import me.gujun.android.span.span
|
||||
|
@ -48,6 +49,8 @@ class NotificationAreaView @JvmOverloads constructor(
|
|||
var delegate: Delegate? = null
|
||||
private var state: State = State.Initial
|
||||
|
||||
private lateinit var views : ViewNotificationAreaBinding
|
||||
|
||||
init {
|
||||
setupView()
|
||||
}
|
||||
|
@ -78,27 +81,28 @@ class NotificationAreaView @JvmOverloads constructor(
|
|||
|
||||
private fun setupView() {
|
||||
inflate(context, R.layout.view_notification_area, this)
|
||||
views = ViewNotificationAreaBinding.bind(this)
|
||||
minimumHeight = DimensionConverter(resources).dpToPx(48)
|
||||
}
|
||||
|
||||
private fun cleanUp() {
|
||||
roomNotificationMessage.setOnClickListener(null)
|
||||
roomNotificationIcon.setOnClickListener(null)
|
||||
views.roomNotificationMessage.setOnClickListener(null)
|
||||
views.roomNotificationIcon.setOnClickListener(null)
|
||||
setBackgroundColor(Color.TRANSPARENT)
|
||||
roomNotificationMessage.text = null
|
||||
roomNotificationIcon.setImageResource(0)
|
||||
views.roomNotificationMessage.text = null
|
||||
views.roomNotificationIcon.setImageResource(0)
|
||||
}
|
||||
|
||||
private fun renderNoPermissionToPost() {
|
||||
visibility = View.VISIBLE
|
||||
roomNotificationIcon.setImageDrawable(null)
|
||||
views.roomNotificationIcon.setImageDrawable(null)
|
||||
val message = span {
|
||||
italic {
|
||||
+resources.getString(R.string.room_do_not_have_permission_to_post)
|
||||
}
|
||||
}
|
||||
roomNotificationMessage.text = message
|
||||
roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_secondary))
|
||||
views.roomNotificationMessage.text = message
|
||||
views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_secondary))
|
||||
}
|
||||
|
||||
private fun renderResourceLimitExceededError(state: State.ResourceLimitExceededError) {
|
||||
|
@ -114,16 +118,16 @@ class NotificationAreaView @JvmOverloads constructor(
|
|||
formatterMode = ResourceLimitErrorFormatter.Mode.Hard
|
||||
}
|
||||
val message = resourceLimitErrorFormatter.format(state.matrixError, formatterMode, clickable = true)
|
||||
roomNotificationMessage.setTextColor(Color.WHITE)
|
||||
roomNotificationMessage.text = message
|
||||
roomNotificationMessage.movementMethod = LinkMovementMethod.getInstance()
|
||||
roomNotificationMessage.setLinkTextColor(Color.WHITE)
|
||||
views.roomNotificationMessage.setTextColor(Color.WHITE)
|
||||
views.roomNotificationMessage.text = message
|
||||
views.roomNotificationMessage.movementMethod = LinkMovementMethod.getInstance()
|
||||
views.roomNotificationMessage.setLinkTextColor(Color.WHITE)
|
||||
setBackgroundColor(ContextCompat.getColor(context, backgroundColor))
|
||||
}
|
||||
|
||||
private fun renderTombstone(state: State.Tombstone) {
|
||||
visibility = View.VISIBLE
|
||||
roomNotificationIcon.setImageResource(R.drawable.error)
|
||||
views.roomNotificationIcon.setImageResource(R.drawable.error)
|
||||
val message = span {
|
||||
+resources.getString(R.string.room_tombstone_versioned_description)
|
||||
+"\n"
|
||||
|
@ -132,8 +136,8 @@ class NotificationAreaView @JvmOverloads constructor(
|
|||
onClick = { delegate?.onTombstoneEventClicked(state.tombstoneEvent) }
|
||||
}
|
||||
}
|
||||
roomNotificationMessage.movementMethod = BetterLinkMovementMethod.getInstance()
|
||||
roomNotificationMessage.text = message
|
||||
views.roomNotificationMessage.movementMethod = BetterLinkMovementMethod.getInstance()
|
||||
views.roomNotificationMessage.text = message
|
||||
}
|
||||
|
||||
private fun renderDefault() {
|
||||
|
|
|
@ -22,7 +22,7 @@ import android.widget.LinearLayout
|
|||
import androidx.annotation.IntRange
|
||||
import androidx.core.content.ContextCompat
|
||||
import im.vector.app.R
|
||||
|
||||
import im.vector.app.databinding.ViewPasswordStrengthBarBinding
|
||||
|
||||
/**
|
||||
* A password strength bar custom widget
|
||||
|
@ -39,6 +39,8 @@ class PasswordStrengthBar @JvmOverloads constructor(
|
|||
defStyleAttr: Int = 0)
|
||||
: LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private val views: ViewPasswordStrengthBarBinding
|
||||
|
||||
private val colorBackground = ContextCompat.getColor(context, R.color.password_strength_bar_undefined)
|
||||
private val colorWeak = ContextCompat.getColor(context, R.color.password_strength_bar_weak)
|
||||
private val colorLow = ContextCompat.getColor(context, R.color.password_strength_bar_low)
|
||||
|
@ -52,34 +54,34 @@ class PasswordStrengthBar @JvmOverloads constructor(
|
|||
|
||||
when (newValue) {
|
||||
0 -> {
|
||||
password_strength_bar_1.setBackgroundColor(colorBackground)
|
||||
password_strength_bar_2.setBackgroundColor(colorBackground)
|
||||
password_strength_bar_3.setBackgroundColor(colorBackground)
|
||||
password_strength_bar_4.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar1.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar2.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar3.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar4.setBackgroundColor(colorBackground)
|
||||
}
|
||||
1 -> {
|
||||
password_strength_bar_1.setBackgroundColor(colorWeak)
|
||||
password_strength_bar_2.setBackgroundColor(colorBackground)
|
||||
password_strength_bar_3.setBackgroundColor(colorBackground)
|
||||
password_strength_bar_4.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar1.setBackgroundColor(colorWeak)
|
||||
views.passwordStrengthBar2.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar3.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar4.setBackgroundColor(colorBackground)
|
||||
}
|
||||
2 -> {
|
||||
password_strength_bar_1.setBackgroundColor(colorLow)
|
||||
password_strength_bar_2.setBackgroundColor(colorLow)
|
||||
password_strength_bar_3.setBackgroundColor(colorBackground)
|
||||
password_strength_bar_4.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar1.setBackgroundColor(colorLow)
|
||||
views.passwordStrengthBar2.setBackgroundColor(colorLow)
|
||||
views.passwordStrengthBar3.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar4.setBackgroundColor(colorBackground)
|
||||
}
|
||||
3 -> {
|
||||
password_strength_bar_1.setBackgroundColor(colorOk)
|
||||
password_strength_bar_2.setBackgroundColor(colorOk)
|
||||
password_strength_bar_3.setBackgroundColor(colorOk)
|
||||
password_strength_bar_4.setBackgroundColor(colorBackground)
|
||||
views.passwordStrengthBar1.setBackgroundColor(colorOk)
|
||||
views.passwordStrengthBar2.setBackgroundColor(colorOk)
|
||||
views.passwordStrengthBar3.setBackgroundColor(colorOk)
|
||||
views.passwordStrengthBar4.setBackgroundColor(colorBackground)
|
||||
}
|
||||
4 -> {
|
||||
password_strength_bar_1.setBackgroundColor(colorStrong)
|
||||
password_strength_bar_2.setBackgroundColor(colorStrong)
|
||||
password_strength_bar_3.setBackgroundColor(colorStrong)
|
||||
password_strength_bar_4.setBackgroundColor(colorStrong)
|
||||
views.passwordStrengthBar1.setBackgroundColor(colorStrong)
|
||||
views.passwordStrengthBar2.setBackgroundColor(colorStrong)
|
||||
views.passwordStrengthBar3.setBackgroundColor(colorStrong)
|
||||
views.passwordStrengthBar4.setBackgroundColor(colorStrong)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +89,7 @@ class PasswordStrengthBar @JvmOverloads constructor(
|
|||
init {
|
||||
LayoutInflater.from(context)
|
||||
.inflate(R.layout.view_password_strength_bar, this, true)
|
||||
views = ViewPasswordStrengthBarBinding.bind(this)
|
||||
orientation = HORIZONTAL
|
||||
strength = 0
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.widget.ImageView
|
|||
import android.widget.LinearLayout
|
||||
import androidx.core.view.isVisible
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.ViewReadReceiptsBinding
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptData
|
||||
import im.vector.app.features.home.room.detail.timeline.item.toMatrixItem
|
||||
|
@ -37,12 +38,21 @@ class ReadReceiptsView @JvmOverloads constructor(
|
|||
defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private val receiptAvatars: List<ImageView> by lazy {
|
||||
listOf(receiptAvatar1, receiptAvatar2, receiptAvatar3, receiptAvatar4, receiptAvatar5)
|
||||
}
|
||||
private val views : ViewReadReceiptsBinding
|
||||
|
||||
init {
|
||||
setupView()
|
||||
views = ViewReadReceiptsBinding.bind(this)
|
||||
}
|
||||
|
||||
private val receiptAvatars: List<ImageView> by lazy {
|
||||
listOf(
|
||||
views.receiptAvatar1,
|
||||
views.receiptAvatar2,
|
||||
views.receiptAvatar3,
|
||||
views.receiptAvatar4,
|
||||
views.receiptAvatar5
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupView() {
|
||||
|
@ -69,12 +79,12 @@ class ReadReceiptsView @JvmOverloads constructor(
|
|||
.take(MAX_RECEIPT_DESCRIBED)
|
||||
|
||||
if (readReceipts.size > MAX_RECEIPT_DISPLAYED) {
|
||||
receiptMore.visibility = View.VISIBLE
|
||||
receiptMore.text = context.getString(
|
||||
views.receiptMore.visibility = View.VISIBLE
|
||||
views.receiptMore.text = context.getString(
|
||||
R.string.x_plus, readReceipts.size - MAX_RECEIPT_DISPLAYED
|
||||
)
|
||||
} else {
|
||||
receiptMore.visibility = View.GONE
|
||||
views.receiptMore.visibility = View.GONE
|
||||
}
|
||||
contentDescription = when (readReceipts.size) {
|
||||
1 ->
|
||||
|
|
|
@ -285,7 +285,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
|
|||
return isPermissionGranted
|
||||
}
|
||||
|
||||
fun VectorBaseActivity.onPermissionDeniedSnackbar(@StringRes rationaleMessage: Int) {
|
||||
fun VectorBaseActivity<*>.onPermissionDeniedSnackbar(@StringRes rationaleMessage: Int) {
|
||||
showSnackbar(getString(rationaleMessage), R.string.settings) {
|
||||
openAppSettingsPage(this)
|
||||
}
|
||||
|
|
|
@ -45,16 +45,16 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetC
|
|||
renderState(it)
|
||||
}
|
||||
|
||||
views.callControlsSoundDevice.clickableView.debouncedClicks {
|
||||
views.callControlsSoundDevice.views.itemVerificationClickableZone.debouncedClicks {
|
||||
callViewModel.handle(VectorCallViewActions.SwitchSoundDevice)
|
||||
}
|
||||
|
||||
views.callControlsSwitchCamera.clickableView.debouncedClicks {
|
||||
views.callControlsSwitchCamera.views.itemVerificationClickableZone.debouncedClicks {
|
||||
callViewModel.handle(VectorCallViewActions.ToggleCamera)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
views.callControlsToggleSDHD.clickableView.debouncedClicks {
|
||||
views.callControlsToggleSDHD.views.itemVerificationClickableZone.debouncedClicks {
|
||||
callViewModel.handle(VectorCallViewActions.ToggleHDSD)
|
||||
dismiss()
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity(), UserListViewModel.Fac
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
toolbar.visibility = View.GONE
|
||||
views.toolbar.visibility = View.GONE
|
||||
|
||||
sharedActionViewModel = viewModelProvider.get(UserListSharedActionViewModel::class.java)
|
||||
sharedActionViewModel
|
||||
|
|
|
@ -45,12 +45,12 @@ class KeysBackupSetupStep2Fragment @Inject constructor() : VectorBaseFragment<Fr
|
|||
private val zxcvbn = Zxcvbn()
|
||||
|
||||
private fun onPassphraseChanged() {
|
||||
viewModel.passphrase.value = keys_backup_passphrase_enter_edittext.text.toString()
|
||||
viewModel.passphrase.value = views.keysBackupPassphraseEnterEdittext.text.toString()
|
||||
viewModel.confirmPassphraseError.value = null
|
||||
}
|
||||
|
||||
private fun onConfirmPassphraseChanged() {
|
||||
viewModel.confirmPassphrase.value = mPassphraseConfirmTextEdit.text.toString()
|
||||
viewModel.confirmPassphrase.value = views.mPassphraseConfirmTextEdit.text.toString()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: KeysBackupSetupSharedViewModel
|
||||
|
@ -72,24 +72,24 @@ class KeysBackupSetupStep2Fragment @Inject constructor() : VectorBaseFragment<Fr
|
|||
private fun bindViewToViewModel() {
|
||||
viewModel.passwordStrength.observe(viewLifecycleOwner, Observer { strength ->
|
||||
if (strength == null) {
|
||||
mPassphraseProgressLevel.strength = 0
|
||||
keys_backup_passphrase_enter_til.error = null
|
||||
views.mPassphraseProgressLevel.strength = 0
|
||||
views.keysBackupPassphraseEnterTil.error = null
|
||||
} else {
|
||||
val score = strength.score
|
||||
mPassphraseProgressLevel.strength = score
|
||||
views.mPassphraseProgressLevel.strength = score
|
||||
|
||||
if (score in 1..3) {
|
||||
val warning = strength.feedback?.getWarning(VectorLocale.applicationLocale)
|
||||
if (warning != null) {
|
||||
keys_backup_passphrase_enter_til.error = warning
|
||||
views.keysBackupPassphraseEnterTil.error = warning
|
||||
}
|
||||
|
||||
val suggestions = strength.feedback?.getSuggestions(VectorLocale.applicationLocale)
|
||||
if (suggestions != null) {
|
||||
keys_backup_passphrase_enter_til.error = suggestions.firstOrNull()
|
||||
views.keysBackupPassphraseEnterTil.error = suggestions.firstOrNull()
|
||||
}
|
||||
} else {
|
||||
keys_backup_passphrase_enter_til.error = null
|
||||
views.keysBackupPassphraseEnterTil.error = null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -107,28 +107,28 @@ class KeysBackupSetupStep2Fragment @Inject constructor() : VectorBaseFragment<Fr
|
|||
}
|
||||
})
|
||||
|
||||
keys_backup_passphrase_enter_edittext.setText(viewModel.passphrase.value)
|
||||
views.keysBackupPassphraseEnterEdittext.setText(viewModel.passphrase.value)
|
||||
|
||||
viewModel.passphraseError.observe(viewLifecycleOwner, Observer {
|
||||
TransitionManager.beginDelayedTransition(keys_backup_root)
|
||||
keys_backup_passphrase_enter_til.error = it
|
||||
TransitionManager.beginDelayedTransition(views.keysBackupRoot)
|
||||
views.keysBackupPassphraseEnterTil.error = it
|
||||
})
|
||||
|
||||
mPassphraseConfirmTextEdit.setText(viewModel.confirmPassphrase.value)
|
||||
views.mPassphraseConfirmTextEdit.setText(viewModel.confirmPassphrase.value)
|
||||
|
||||
viewModel.showPasswordMode.observe(viewLifecycleOwner, Observer {
|
||||
val shouldBeVisible = it ?: false
|
||||
keys_backup_passphrase_enter_edittext.showPassword(shouldBeVisible)
|
||||
mPassphraseConfirmTextEdit.showPassword(shouldBeVisible)
|
||||
keys_backup_view_show_password.setImageResource(if (shouldBeVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
views.keysBackupPassphraseEnterEdittext.showPassword(shouldBeVisible)
|
||||
views.mPassphraseConfirmTextEdit.showPassword(shouldBeVisible)
|
||||
views.keysBackupViewShowPassword.setImageResource(if (shouldBeVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
})
|
||||
|
||||
viewModel.confirmPassphraseError.observe(viewLifecycleOwner, Observer {
|
||||
TransitionManager.beginDelayedTransition(keys_backup_root)
|
||||
mPassphraseConfirmInputLayout.error = it
|
||||
TransitionManager.beginDelayedTransition(views.keysBackupRoot)
|
||||
views.mPassphraseConfirmInputLayout.error = it
|
||||
})
|
||||
|
||||
mPassphraseConfirmTextEdit.setOnEditorActionListener { _, actionId, _ ->
|
||||
views.mPassphraseConfirmTextEdit.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
doNext()
|
||||
return@setOnEditorActionListener true
|
||||
|
@ -138,12 +138,12 @@ class KeysBackupSetupStep2Fragment @Inject constructor() : VectorBaseFragment<Fr
|
|||
}
|
||||
|
||||
private fun setupViews() {
|
||||
keys_backup_view_show_password.setOnClickListener { toggleVisibilityMode() }
|
||||
keys_backup_setup_step2_button.setOnClickListener { doNext() }
|
||||
keys_backup_setup_step2_skip_button.setOnClickListener { skipPassphrase() }
|
||||
views.keysBackupViewShowPassword.setOnClickListener { toggleVisibilityMode() }
|
||||
views.keysBackupSetupStep2Button.setOnClickListener { doNext() }
|
||||
views.keysBackupSetupStep2SkipButton.setOnClickListener { skipPassphrase() }
|
||||
|
||||
keys_backup_passphrase_enter_edittext.doOnTextChanged { _, _, _, _ -> onPassphraseChanged() }
|
||||
mPassphraseConfirmTextEdit.doOnTextChanged { _, _, _, _ -> onConfirmPassphraseChanged() }
|
||||
views.keysBackupPassphraseEnterEdittext.doOnTextChanged { _, _, _, _ -> onPassphraseChanged() }
|
||||
views.mPassphraseConfirmTextEdit.doOnTextChanged { _, _, _, _ -> onConfirmPassphraseChanged() }
|
||||
}
|
||||
|
||||
private fun toggleVisibilityMode() {
|
||||
|
|
|
@ -65,7 +65,7 @@ class SharedSecureStorageActivity :
|
|||
super.onCreate(savedInstanceState)
|
||||
supportFragmentManager.addFragmentOnAttachListener(this)
|
||||
|
||||
toolbar.visibility = View.GONE
|
||||
views.toolbar.visibility = View.GONE
|
||||
|
||||
viewModel.observeViewEvents { observeViewEvents(it) }
|
||||
|
||||
|
@ -132,7 +132,7 @@ class SharedSecureStorageActivity :
|
|||
}
|
||||
|
||||
override fun onAttachFragment(fragmentManager: FragmentManager, fragment: Fragment) {
|
||||
if (fragment is VectorBaseBottomSheetDialogFragment) {
|
||||
if (fragment is VectorBaseBottomSheetDialogFragment<*>) {
|
||||
fragment.resultListener = this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,9 +47,9 @@ class SharedSecuredStorageKeyFragment @Inject constructor() : VectorBaseFragment
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
ssss_restore_with_key_text.text = getString(R.string.enter_secret_storage_input_key)
|
||||
views.ssssRestoreWithKeyText.text = getString(R.string.enter_secret_storage_input_key)
|
||||
|
||||
ssss_key_enter_edittext.editorActionEvents()
|
||||
views.ssssKeyEnterEdittext.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
|
@ -59,35 +59,35 @@ class SharedSecuredStorageKeyFragment @Inject constructor() : VectorBaseFragment
|
|||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
ssss_key_enter_edittext.textChanges()
|
||||
views.ssssKeyEnterEdittext.textChanges()
|
||||
.skipInitialValue()
|
||||
.subscribe {
|
||||
ssss_key_enter_til.error = null
|
||||
ssss_key_submit.isEnabled = it.isNotBlank()
|
||||
views.ssssKeyEnterTil.error = null
|
||||
views.ssssKeySubmit.isEnabled = it.isNotBlank()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
ssss_key_use_file.debouncedClicks { startImportTextFromFileIntent(requireContext(), importFileStartForActivityResult) }
|
||||
views.ssssKeyUseFile.debouncedClicks { startImportTextFromFileIntent(requireContext(), importFileStartForActivityResult) }
|
||||
|
||||
ssss_key_reset.clickableView.debouncedClicks {
|
||||
views.ssssKeyReset.views.itemVerificationClickableZone.debouncedClicks {
|
||||
sharedViewModel.handle(SharedSecureStorageAction.ForgotResetAll)
|
||||
}
|
||||
|
||||
sharedViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is SharedSecureStorageViewEvent.KeyInlineError -> {
|
||||
ssss_key_enter_til.error = it.message
|
||||
views.ssssKeyEnterTil.error = it.message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssss_key_submit.debouncedClicks { submit() }
|
||||
views.ssssKeySubmit.debouncedClicks { submit() }
|
||||
}
|
||||
|
||||
fun submit() {
|
||||
val text = ssss_key_enter_edittext.text.toString()
|
||||
val text = views.ssssKeyEnterEdittext.text.toString()
|
||||
if (text.isBlank()) return // Should not reach this point as button disabled
|
||||
ssss_key_submit.isEnabled = false
|
||||
views.ssssKeySubmit.isEnabled = false
|
||||
sharedViewModel.handle(SharedSecureStorageAction.SubmitKey(text))
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ class SharedSecuredStorageKeyFragment @Inject constructor() : VectorBaseFragment
|
|||
?.bufferedReader()
|
||||
?.use { it.readText() }
|
||||
?.let {
|
||||
ssss_key_enter_edittext.setText(it)
|
||||
views.ssssKeyEnterEdittext.setText(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ class SharedSecuredStoragePassphraseFragment @Inject constructor(
|
|||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
views.ssssPassphraseReset.clickableView.debouncedClicks {
|
||||
views.ssssPassphraseReset.views.itemVerificationClickableZone.debouncedClicks {
|
||||
sharedViewModel.handle(SharedSecureStorageAction.ForgotResetAll)
|
||||
}
|
||||
|
||||
|
|
|
@ -55,13 +55,13 @@ class BootstrapAccountPasswordFragment @Inject constructor(
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val recPassPhrase = getString(R.string.account_password)
|
||||
bootstrapDescriptionText.text = getString(R.string.enter_account_password, recPassPhrase)
|
||||
views.bootstrapDescriptionText.text = getString(R.string.enter_account_password, recPassPhrase)
|
||||
.toSpannable()
|
||||
.colorizeMatchingText(recPassPhrase, colorProvider.getColorFromAttribute(android.R.attr.textColorLink))
|
||||
|
||||
bootstrapAccountPasswordEditText.hint = getString(R.string.account_password)
|
||||
views.bootstrapAccountPasswordEditText.hint = getString(R.string.account_password)
|
||||
|
||||
bootstrapAccountPasswordEditText.editorActionEvents()
|
||||
views.bootstrapAccountPasswordEditText.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
|
@ -71,21 +71,21 @@ class BootstrapAccountPasswordFragment @Inject constructor(
|
|||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
bootstrapAccountPasswordEditText.textChanges()
|
||||
views.bootstrapAccountPasswordEditText.textChanges()
|
||||
.distinctUntilChanged()
|
||||
.subscribe {
|
||||
if (!it.isNullOrBlank()) {
|
||||
bootstrapAccountPasswordTil.error = null
|
||||
views.bootstrapAccountPasswordTil.error = null
|
||||
}
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
ssss_view_show_password.debouncedClicks { sharedViewModel.handle(BootstrapActions.TogglePasswordVisibility) }
|
||||
bootstrapPasswordButton.debouncedClicks { submit() }
|
||||
views.ssssViewShowPassword.debouncedClicks { sharedViewModel.handle(BootstrapActions.TogglePasswordVisibility) }
|
||||
views.bootstrapPasswordButton.debouncedClicks { submit() }
|
||||
|
||||
withState(sharedViewModel) { state ->
|
||||
(state.step as? BootstrapStep.AccountPassword)?.failure?.let {
|
||||
bootstrapAccountPasswordTil.error = it
|
||||
views.bootstrapAccountPasswordTil.error = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,9 +94,9 @@ class BootstrapAccountPasswordFragment @Inject constructor(
|
|||
if (state.step !is BootstrapStep.AccountPassword) {
|
||||
return@withState
|
||||
}
|
||||
val accountPassword = bootstrapAccountPasswordEditText.text?.toString()
|
||||
val accountPassword = views.bootstrapAccountPasswordEditText.text?.toString()
|
||||
if (accountPassword.isNullOrBlank()) {
|
||||
bootstrapAccountPasswordTil.error = getString(R.string.error_empty_field_your_password)
|
||||
views.bootstrapAccountPasswordTil.error = getString(R.string.error_empty_field_your_password)
|
||||
} else {
|
||||
view?.hideKeyboard()
|
||||
sharedViewModel.handle(BootstrapActions.ReAuth(accountPassword))
|
||||
|
@ -106,8 +106,8 @@ class BootstrapAccountPasswordFragment @Inject constructor(
|
|||
override fun invalidate() = withState(sharedViewModel) { state ->
|
||||
if (state.step is BootstrapStep.AccountPassword) {
|
||||
val isPasswordVisible = state.step.isPasswordVisible
|
||||
bootstrapAccountPasswordEditText.showPassword(isPasswordVisible, updateCursor = false)
|
||||
ssss_view_show_password.setImageResource(if (isPasswordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
views.bootstrapAccountPasswordEditText.showPassword(isPasswordVisible, updateCursor = false)
|
||||
views.ssssViewShowPassword.setImageResource(if (isPasswordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class BootstrapConclusionFragment @Inject constructor(
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
views.bootstrapConclusionContinue.clickableView.debouncedClicks { sharedViewModel.handle(BootstrapActions.Completed) }
|
||||
views.bootstrapConclusionContinue.views.itemVerificationClickableZone.debouncedClicks { sharedViewModel.handle(BootstrapActions.Completed) }
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(sharedViewModel) { state ->
|
||||
|
|
|
@ -49,18 +49,18 @@ class BootstrapConfirmPassphraseFragment @Inject constructor()
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
ssss_passphrase_security_progress.isGone = true
|
||||
views.ssssPassphraseSecurityProgress.isGone = true
|
||||
|
||||
bootstrapDescriptionText.text = getString(R.string.set_a_security_phrase_again_notice)
|
||||
ssss_passphrase_enter_edittext.hint = getString(R.string.set_a_security_phrase_hint)
|
||||
views.bootstrapDescriptionText.text = getString(R.string.set_a_security_phrase_again_notice)
|
||||
views.ssssPassphraseEnterEdittext.hint = getString(R.string.set_a_security_phrase_hint)
|
||||
|
||||
withState(sharedViewModel) {
|
||||
// set initial value (useful when coming back)
|
||||
ssss_passphrase_enter_edittext.setText(it.passphraseRepeat ?: "")
|
||||
ssss_passphrase_enter_edittext.requestFocus()
|
||||
views.ssssPassphraseEnterEdittext.setText(it.passphraseRepeat ?: "")
|
||||
views.ssssPassphraseEnterEdittext.requestFocus()
|
||||
}
|
||||
|
||||
ssss_passphrase_enter_edittext.editorActionEvents()
|
||||
views.ssssPassphraseEnterEdittext.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
|
@ -70,9 +70,9 @@ class BootstrapConfirmPassphraseFragment @Inject constructor()
|
|||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
ssss_passphrase_enter_edittext.textChanges()
|
||||
views.ssssPassphraseEnterEdittext.textChanges()
|
||||
.subscribe {
|
||||
ssss_passphrase_enter_til.error = null
|
||||
views.ssssPassphraseEnterTil.error = null
|
||||
sharedViewModel.handle(BootstrapActions.UpdateConfirmCandidatePassphrase(it?.toString() ?: ""))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
@ -85,20 +85,20 @@ class BootstrapConfirmPassphraseFragment @Inject constructor()
|
|||
// }
|
||||
}
|
||||
|
||||
ssss_view_show_password.debouncedClicks { sharedViewModel.handle(BootstrapActions.TogglePasswordVisibility) }
|
||||
bootstrapSubmit.debouncedClicks { submit() }
|
||||
views.ssssViewShowPassword.debouncedClicks { sharedViewModel.handle(BootstrapActions.TogglePasswordVisibility) }
|
||||
views.bootstrapSubmit.debouncedClicks { submit() }
|
||||
}
|
||||
|
||||
private fun submit() = withState(sharedViewModel) { state ->
|
||||
if (state.step !is BootstrapStep.ConfirmPassphrase) {
|
||||
return@withState
|
||||
}
|
||||
val passphrase = ssss_passphrase_enter_edittext.text?.toString()
|
||||
val passphrase = views.ssssPassphraseEnterEdittext.text?.toString()
|
||||
when {
|
||||
passphrase.isNullOrBlank() ->
|
||||
ssss_passphrase_enter_til.error = getString(R.string.passphrase_empty_error_message)
|
||||
views.ssssPassphraseEnterTil.error = getString(R.string.passphrase_empty_error_message)
|
||||
passphrase != state.passphrase ->
|
||||
ssss_passphrase_enter_til.error = getString(R.string.passphrase_passphrase_does_not_match)
|
||||
views.ssssPassphraseEnterTil.error = getString(R.string.passphrase_passphrase_does_not_match)
|
||||
else -> {
|
||||
view?.hideKeyboard()
|
||||
sharedViewModel.handle(BootstrapActions.DoInitialize(passphrase))
|
||||
|
@ -109,8 +109,8 @@ class BootstrapConfirmPassphraseFragment @Inject constructor()
|
|||
override fun invalidate() = withState(sharedViewModel) { state ->
|
||||
if (state.step is BootstrapStep.ConfirmPassphrase) {
|
||||
val isPasswordVisible = state.step.isPasswordVisible
|
||||
ssss_passphrase_enter_edittext.showPassword(isPasswordVisible, updateCursor = false)
|
||||
ssss_view_show_password.setImageResource(if (isPasswordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
views.ssssPassphraseEnterEdittext.showPassword(isPasswordVisible, updateCursor = false)
|
||||
views.ssssViewShowPassword.setImageResource(if (isPasswordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,9 +64,9 @@ class BootstrapMigrateBackupFragment @Inject constructor(
|
|||
|
||||
withState(sharedViewModel) {
|
||||
// set initial value (useful when coming back)
|
||||
bootstrapMigrateEditText.setText(it.passphrase ?: "")
|
||||
views.bootstrapMigrateEditText.setText(it.passphrase ?: "")
|
||||
}
|
||||
bootstrapMigrateEditText.editorActionEvents()
|
||||
views.bootstrapMigrateEditText.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
|
@ -76,19 +76,19 @@ class BootstrapMigrateBackupFragment @Inject constructor(
|
|||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
bootstrapMigrateEditText.textChanges()
|
||||
views.bootstrapMigrateEditText.textChanges()
|
||||
.skipInitialValue()
|
||||
.subscribe {
|
||||
bootstrapRecoveryKeyEnterTil.error = null
|
||||
views.bootstrapRecoveryKeyEnterTil.error = null
|
||||
// sharedViewModel.handle(BootstrapActions.UpdateCandidatePassphrase(it?.toString() ?: ""))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
// sharedViewModel.observeViewEvents {}
|
||||
bootstrapMigrateContinueButton.debouncedClicks { submit() }
|
||||
bootstrapMigrateShowPassword.debouncedClicks { sharedViewModel.handle(BootstrapActions.TogglePasswordVisibility) }
|
||||
bootstrapMigrateForgotPassphrase.debouncedClicks { sharedViewModel.handle(BootstrapActions.HandleForgotBackupPassphrase) }
|
||||
bootstrapMigrateUseFile.debouncedClicks { startImportTextFromFileIntent(requireContext(), importFileStartForActivityResult) }
|
||||
views.bootstrapMigrateContinueButton.debouncedClicks { submit() }
|
||||
views.bootstrapMigrateShowPassword.debouncedClicks { sharedViewModel.handle(BootstrapActions.TogglePasswordVisibility) }
|
||||
views.bootstrapMigrateForgotPassphrase.debouncedClicks { sharedViewModel.handle(BootstrapActions.HandleForgotBackupPassphrase) }
|
||||
views.bootstrapMigrateUseFile.debouncedClicks { startImportTextFromFileIntent(requireContext(), importFileStartForActivityResult) }
|
||||
}
|
||||
|
||||
private fun submit() = withState(sharedViewModel) { state ->
|
||||
|
@ -96,12 +96,12 @@ class BootstrapMigrateBackupFragment @Inject constructor(
|
|||
|
||||
val isEnteringKey = getBackupSecretForMigration.useKey()
|
||||
|
||||
val secret = bootstrapMigrateEditText.text?.toString()
|
||||
val secret = views.bootstrapMigrateEditText.text?.toString()
|
||||
if (secret.isNullOrEmpty()) {
|
||||
val errRes = if (isEnteringKey) R.string.recovery_key_empty_error_message else R.string.passphrase_empty_error_message
|
||||
bootstrapRecoveryKeyEnterTil.error = getString(errRes)
|
||||
views.bootstrapRecoveryKeyEnterTil.error = getString(errRes)
|
||||
} else if (isEnteringKey && !isValidRecoveryKey(secret)) {
|
||||
bootstrapRecoveryKeyEnterTil.error = getString(R.string.bootstrap_invalid_recovery_key)
|
||||
views.bootstrapRecoveryKeyEnterTil.error = getString(R.string.bootstrap_invalid_recovery_key)
|
||||
} else {
|
||||
view?.hideKeyboard()
|
||||
if (isEnteringKey) {
|
||||
|
@ -118,38 +118,38 @@ class BootstrapMigrateBackupFragment @Inject constructor(
|
|||
val isEnteringKey = getBackupSecretForMigration.useKey()
|
||||
|
||||
if (isEnteringKey) {
|
||||
bootstrapMigrateShowPassword.isVisible = false
|
||||
bootstrapMigrateEditText.inputType = TYPE_CLASS_TEXT or TYPE_TEXT_VARIATION_VISIBLE_PASSWORD or TYPE_TEXT_FLAG_MULTI_LINE
|
||||
views.bootstrapMigrateShowPassword.isVisible = false
|
||||
views.bootstrapMigrateEditText.inputType = TYPE_CLASS_TEXT or TYPE_TEXT_VARIATION_VISIBLE_PASSWORD or TYPE_TEXT_FLAG_MULTI_LINE
|
||||
|
||||
val recKey = getString(R.string.bootstrap_migration_backup_recovery_key)
|
||||
bootstrapDescriptionText.text = getString(R.string.enter_account_password, recKey)
|
||||
views.bootstrapDescriptionText.text = getString(R.string.enter_account_password, recKey)
|
||||
|
||||
bootstrapMigrateEditText.hint = recKey
|
||||
views.bootstrapMigrateEditText.hint = recKey
|
||||
|
||||
bootstrapMigrateEditText.hint = recKey
|
||||
bootstrapMigrateForgotPassphrase.isVisible = false
|
||||
bootstrapMigrateUseFile.isVisible = true
|
||||
views.bootstrapMigrateEditText.hint = recKey
|
||||
views.bootstrapMigrateForgotPassphrase.isVisible = false
|
||||
views.bootstrapMigrateUseFile.isVisible = true
|
||||
} else {
|
||||
bootstrapMigrateShowPassword.isVisible = true
|
||||
views.bootstrapMigrateShowPassword.isVisible = true
|
||||
|
||||
if (state.step is BootstrapStep.GetBackupSecretPassForMigration) {
|
||||
val isPasswordVisible = state.step.isPasswordVisible
|
||||
bootstrapMigrateEditText.showPassword(isPasswordVisible, updateCursor = false)
|
||||
bootstrapMigrateShowPassword.setImageResource(if (isPasswordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
views.bootstrapMigrateEditText.showPassword(isPasswordVisible, updateCursor = false)
|
||||
views.bootstrapMigrateShowPassword.setImageResource(if (isPasswordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
}
|
||||
|
||||
bootstrapDescriptionText.text = getString(R.string.bootstrap_migration_enter_backup_password)
|
||||
views.bootstrapDescriptionText.text = getString(R.string.bootstrap_migration_enter_backup_password)
|
||||
|
||||
bootstrapMigrateEditText.hint = getString(R.string.passphrase_enter_passphrase)
|
||||
views.bootstrapMigrateEditText.hint = getString(R.string.passphrase_enter_passphrase)
|
||||
|
||||
bootstrapMigrateForgotPassphrase.isVisible = true
|
||||
views.bootstrapMigrateForgotPassphrase.isVisible = true
|
||||
|
||||
val recKey = getString(R.string.bootstrap_migration_use_recovery_key)
|
||||
bootstrapMigrateForgotPassphrase.text = getString(R.string.bootstrap_migration_with_passphrase_helper_with_link, recKey)
|
||||
views.bootstrapMigrateForgotPassphrase.text = getString(R.string.bootstrap_migration_with_passphrase_helper_with_link, recKey)
|
||||
.toSpannable()
|
||||
.colorizeMatchingText(recKey, colorProvider.getColorFromAttribute(android.R.attr.textColorLink))
|
||||
|
||||
bootstrapMigrateUseFile.isVisible = false
|
||||
views.bootstrapMigrateUseFile.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ class BootstrapMigrateBackupFragment @Inject constructor(
|
|||
?.bufferedReader()
|
||||
?.use { it.readText() }
|
||||
?.let {
|
||||
bootstrapMigrateEditText.setText(it)
|
||||
views.bootstrapMigrateEditText.setText(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,9 +53,9 @@ class BootstrapSaveRecoveryKeyFragment @Inject constructor(
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
views.recoverySave.clickableView.debouncedClicks { downloadRecoveryKey() }
|
||||
views.recoveryCopy.clickableView.debouncedClicks { shareRecoveryKey() }
|
||||
views.recoveryContinue.clickableView.debouncedClicks {
|
||||
views.recoverySave.views.itemVerificationClickableZone.debouncedClicks { downloadRecoveryKey() }
|
||||
views.recoveryCopy.views.itemVerificationClickableZone.debouncedClicks { shareRecoveryKey() }
|
||||
views.recoveryContinue.views.itemVerificationClickableZone.debouncedClicks {
|
||||
// We do not display the final Fragment anymore
|
||||
// TODO Do some cleanup
|
||||
// sharedViewModel.handle(BootstrapActions.GoToCompleted)
|
||||
|
|
|
@ -43,15 +43,15 @@ class BootstrapSetupRecoveryKeyFragment @Inject constructor()
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// Actions when a key backup exist
|
||||
views.bootstrapSetupSecureSubmit.clickableView.debouncedClicks {
|
||||
views.bootstrapSetupSecureSubmit.views.itemVerificationClickableZone.debouncedClicks {
|
||||
sharedViewModel.handle(BootstrapActions.StartKeyBackupMigration)
|
||||
}
|
||||
|
||||
// Actions when there is no key backup
|
||||
views.bootstrapSetupSecureUseSecurityKey.clickableView.debouncedClicks {
|
||||
views.bootstrapSetupSecureUseSecurityKey.views.itemVerificationClickableZone.debouncedClicks {
|
||||
sharedViewModel.handle(BootstrapActions.Start(userWantsToEnterPassphrase = false))
|
||||
}
|
||||
views.bootstrapSetupSecureUseSecurityPassphrase.clickableView.debouncedClicks {
|
||||
views.bootstrapSetupSecureUseSecurityPassphrase.views.itemVerificationClickableZone.debouncedClicks {
|
||||
sharedViewModel.handle(BootstrapActions.Start(userWantsToEnterPassphrase = true))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ class IncomingVerificationRequestHandler @Inject constructor(
|
|||
context.getString(R.string.sas_incoming_request_notif_content, name),
|
||||
R.drawable.ic_shield_black,
|
||||
shouldBeDisplayedIn = { activity ->
|
||||
if (activity is VectorBaseActivity) {
|
||||
if (activity is VectorBaseActivity<*>) {
|
||||
// TODO a bit too ugly :/
|
||||
activity.supportFragmentManager.findFragmentByTag(VerificationBottomSheet.WAITING_SELF_VERIF_TAG)?.let {
|
||||
false.also {
|
||||
|
@ -82,7 +82,7 @@ class IncomingVerificationRequestHandler @Inject constructor(
|
|||
)
|
||||
.apply {
|
||||
contentAction = Runnable {
|
||||
(weakCurrentActivity?.get() as? VectorBaseActivity)?.let {
|
||||
(weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let {
|
||||
it.navigator.performDeviceVerification(it, tx.otherUserId, tx.transactionId)
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ class IncomingVerificationRequestHandler @Inject constructor(
|
|||
addButton(
|
||||
context.getString(R.string.action_open),
|
||||
Runnable {
|
||||
(weakCurrentActivity?.get() as? VectorBaseActivity)?.let {
|
||||
(weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let {
|
||||
it.navigator.performDeviceVerification(it, tx.otherUserId, tx.transactionId)
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ class IncomingVerificationRequestHandler @Inject constructor(
|
|||
)
|
||||
.apply {
|
||||
contentAction = Runnable {
|
||||
(weakCurrentActivity?.get() as? VectorBaseActivity)?.let {
|
||||
(weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let {
|
||||
val roomId = pr.roomId
|
||||
if (roomId.isNullOrBlank()) {
|
||||
it.navigator.waitSessionVerification(it)
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.text.toSpannable
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
|
@ -58,11 +59,11 @@ class SetIdentityServerFragment @Inject constructor(
|
|||
override fun invalidate() = withState(viewModel) { state ->
|
||||
if (state.defaultIdentityServerUrl.isNullOrEmpty()) {
|
||||
// No default
|
||||
identityServerSetDefaultNotice.isVisible = false
|
||||
identityServerSetDefaultSubmit.isVisible = false
|
||||
identityServerSetDefaultAlternative.setText(R.string.identity_server_set_alternative_notice_no_default)
|
||||
views.identityServerSetDefaultNotice.isVisible = false
|
||||
views.identityServerSetDefaultSubmit.isVisible = false
|
||||
views.identityServerSetDefaultAlternative.setText(R.string.identity_server_set_alternative_notice_no_default)
|
||||
} else {
|
||||
identityServerSetDefaultNotice.text = getString(
|
||||
views.identityServerSetDefaultNotice.text = getString(
|
||||
R.string.identity_server_set_default_notice,
|
||||
state.homeServerUrl.toReducedUrl(),
|
||||
state.defaultIdentityServerUrl.toReducedUrl()
|
||||
|
@ -71,10 +72,10 @@ class SetIdentityServerFragment @Inject constructor(
|
|||
.colorizeMatchingText(state.defaultIdentityServerUrl.toReducedUrl(),
|
||||
colorProvider.getColorFromAttribute(R.attr.riotx_text_primary_body_contrast))
|
||||
|
||||
identityServerSetDefaultNotice.isVisible = true
|
||||
identityServerSetDefaultSubmit.isVisible = true
|
||||
identityServerSetDefaultSubmit.text = getString(R.string.identity_server_set_default_submit, state.defaultIdentityServerUrl.toReducedUrl())
|
||||
identityServerSetDefaultAlternative.setText(R.string.identity_server_set_alternative_notice)
|
||||
views.identityServerSetDefaultNotice.isVisible = true
|
||||
views.identityServerSetDefaultSubmit.isVisible = true
|
||||
views.identityServerSetDefaultSubmit.text = getString(R.string.identity_server_set_default_submit, state.defaultIdentityServerUrl.toReducedUrl())
|
||||
views.identityServerSetDefaultAlternative.setText(R.string.identity_server_set_alternative_notice)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,28 +84,28 @@ class SetIdentityServerFragment @Inject constructor(
|
|||
|
||||
sharedViewModel = activityViewModelProvider.get(DiscoverySharedViewModel::class.java)
|
||||
|
||||
identityServerSetDefaultAlternativeTextInput.setOnEditorActionListener { _, actionId, _ ->
|
||||
views.identityServerSetDefaultAlternativeTextInput.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
viewModel.handle(SetIdentityServerAction.UseCustomIdentityServer(identityServerSetDefaultAlternativeTextInput.text.toString()))
|
||||
viewModel.handle(SetIdentityServerAction.UseCustomIdentityServer(views.identityServerSetDefaultAlternativeTextInput.text.toString()))
|
||||
return@setOnEditorActionListener true
|
||||
}
|
||||
return@setOnEditorActionListener false
|
||||
}
|
||||
|
||||
identityServerSetDefaultAlternativeTextInput
|
||||
views.identityServerSetDefaultAlternativeTextInput
|
||||
.textChanges()
|
||||
.subscribe {
|
||||
identityServerSetDefaultAlternativeTil.error = null
|
||||
identityServerSetDefaultAlternativeSubmit.isEnabled = it.isNotEmpty()
|
||||
views.identityServerSetDefaultAlternativeTil.error = null
|
||||
views.identityServerSetDefaultAlternativeSubmit.isEnabled = it.isNotEmpty()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
identityServerSetDefaultSubmit.debouncedClicks {
|
||||
views.identityServerSetDefaultSubmit.debouncedClicks {
|
||||
viewModel.handle(SetIdentityServerAction.UseDefaultIdentityServer)
|
||||
}
|
||||
|
||||
identityServerSetDefaultAlternativeSubmit.debouncedClicks {
|
||||
viewModel.handle(SetIdentityServerAction.UseCustomIdentityServer(identityServerSetDefaultAlternativeTextInput.text.toString()))
|
||||
views.identityServerSetDefaultAlternativeSubmit.debouncedClicks {
|
||||
viewModel.handle(SetIdentityServerAction.UseCustomIdentityServer(views.identityServerSetDefaultAlternativeTextInput.text.toString()))
|
||||
}
|
||||
|
||||
viewModel.observeViewEvents {
|
||||
|
@ -147,7 +148,7 @@ class SetIdentityServerFragment @Inject constructor(
|
|||
.show()
|
||||
} else {
|
||||
// Display the error inlined
|
||||
identityServerSetDefaultAlternativeTil.error = message
|
||||
views.identityServerSetDefaultAlternativeTil.error = message
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import im.vector.app.core.extensions.hideKeyboard
|
|||
import im.vector.app.core.extensions.replaceFragment
|
||||
import im.vector.app.core.platform.ToolbarConfigurable
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivityRoomDetailBinding
|
||||
import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment
|
||||
import im.vector.app.features.room.RequireActiveMembershipAction
|
||||
import im.vector.app.features.room.RequireActiveMembershipViewEvents
|
||||
|
@ -42,12 +43,14 @@ import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewState
|
|||
import javax.inject.Inject
|
||||
|
||||
class RoomDetailActivity :
|
||||
VectorBaseActivity(),
|
||||
VectorBaseActivity<ActivityRoomDetailBinding>(),
|
||||
ToolbarConfigurable,
|
||||
RequireActiveMembershipViewModel.Factory,
|
||||
RoomWidgetPermissionViewModel.Factory {
|
||||
|
||||
override fun getLayoutRes() = R.layout.activity_room_detail
|
||||
override fun getBinding(): ActivityRoomDetailBinding {
|
||||
return ActivityRoomDetailBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private lateinit var sharedActionViewModel: RoomDetailSharedActionViewModel
|
||||
private val requireActiveMembershipViewModel: RequireActiveMembershipViewModel by viewModel()
|
||||
|
@ -76,7 +79,7 @@ class RoomDetailActivity :
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
waitingView = waiting_view
|
||||
waitingView = views.waitingView.waitingView
|
||||
val roomDetailArgs: RoomDetailArgs? = if (intent?.action == ACTION_ROOM_DETAILS_FROM_SHORTCUT) {
|
||||
RoomDetailArgs(roomId = intent?.extras?.getString(EXTRA_ROOM_ID)!!)
|
||||
} else {
|
||||
|
@ -106,7 +109,7 @@ class RoomDetailActivity :
|
|||
is RequireActiveMembershipViewEvents.RoomLeft -> handleRoomLeft(it)
|
||||
}
|
||||
}
|
||||
drawerLayout.addDrawerListener(drawerListener)
|
||||
views.drawerLayout.addDrawerListener(drawerListener)
|
||||
}
|
||||
|
||||
private fun handleRoomLeft(roomLeft: RequireActiveMembershipViewEvents.RoomLeft) {
|
||||
|
@ -117,7 +120,7 @@ class RoomDetailActivity :
|
|||
}
|
||||
|
||||
private fun switchToRoom(switchToRoom: RoomDetailSharedAction.SwitchToRoom) {
|
||||
drawerLayout.closeDrawer(GravityCompat.START)
|
||||
views.drawerLayout.closeDrawer(GravityCompat.START)
|
||||
// Do not replace the Fragment if it's the same roomId
|
||||
if (currentRoomId != switchToRoom.roomId) {
|
||||
currentRoomId = switchToRoom.roomId
|
||||
|
@ -127,7 +130,7 @@ class RoomDetailActivity :
|
|||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
drawerLayout.removeDrawerListener(drawerListener)
|
||||
views.drawerLayout.removeDrawerListener(drawerListener)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
@ -139,7 +142,7 @@ class RoomDetailActivity :
|
|||
override fun onDrawerStateChanged(newState: Int) {
|
||||
hideKeyboard()
|
||||
|
||||
if (!drawerLayout.isDrawerOpen(GravityCompat.START) && newState == DrawerLayout.STATE_DRAGGING) {
|
||||
if (!views.drawerLayout.isDrawerOpen(GravityCompat.START) && newState == DrawerLayout.STATE_DRAGGING) {
|
||||
// User is starting to open the drawer, scroll the list to top
|
||||
scrollBreadcrumbsToTop()
|
||||
}
|
||||
|
@ -152,8 +155,8 @@ class RoomDetailActivity :
|
|||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
|
||||
drawerLayout.closeDrawer(GravityCompat.START)
|
||||
if (views.drawerLayout.isDrawerOpen(GravityCompat.START)) {
|
||||
views.drawerLayout.closeDrawer(GravityCompat.START)
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
|
|
|
@ -77,13 +77,13 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
}
|
||||
|
||||
private fun setupViews() {
|
||||
loginGenericTextInputFormOtherButton.setOnClickListener { onOtherButtonClicked() }
|
||||
loginGenericTextInputFormSubmit.setOnClickListener { submit() }
|
||||
views.loginGenericTextInputFormOtherButton.setOnClickListener { onOtherButtonClicked() }
|
||||
views.loginGenericTextInputFormSubmit.setOnClickListener { submit() }
|
||||
}
|
||||
|
||||
private fun setupAutoFill() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
loginGenericTextInputFormTextInput.setAutofillHints(
|
||||
views.loginGenericTextInputFormTextInput.setAutofillHints(
|
||||
when (params.mode) {
|
||||
TextInputFormFragmentMode.SetEmail -> HintConstants.AUTOFILL_HINT_EMAIL_ADDRESS
|
||||
TextInputFormFragmentMode.SetMsisdn -> HintConstants.AUTOFILL_HINT_PHONE_NUMBER
|
||||
|
@ -94,9 +94,9 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
}
|
||||
|
||||
private fun setupTil() {
|
||||
loginGenericTextInputFormTextInput.textChanges()
|
||||
views.loginGenericTextInputFormTextInput.textChanges()
|
||||
.subscribe {
|
||||
loginGenericTextInputFormTil.error = null
|
||||
views.loginGenericTextInputFormTil.error = null
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
@ -104,35 +104,35 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
private fun setupUi() {
|
||||
when (params.mode) {
|
||||
TextInputFormFragmentMode.SetEmail -> {
|
||||
loginGenericTextInputFormTitle.text = getString(R.string.login_set_email_title)
|
||||
loginGenericTextInputFormNotice.text = getString(R.string.login_set_email_notice)
|
||||
loginGenericTextInputFormNotice2.setTextOrHide(null)
|
||||
loginGenericTextInputFormTil.hint =
|
||||
views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_email_title)
|
||||
views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_email_notice)
|
||||
views.loginGenericTextInputFormNotice2.setTextOrHide(null)
|
||||
views.loginGenericTextInputFormTil.hint =
|
||||
getString(if (params.mandatory) R.string.login_set_email_mandatory_hint else R.string.login_set_email_optional_hint)
|
||||
loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||
loginGenericTextInputFormOtherButton.isVisible = false
|
||||
loginGenericTextInputFormSubmit.text = getString(R.string.login_set_email_submit)
|
||||
views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||
views.loginGenericTextInputFormOtherButton.isVisible = false
|
||||
views.loginGenericTextInputFormSubmit.text = getString(R.string.login_set_email_submit)
|
||||
}
|
||||
TextInputFormFragmentMode.SetMsisdn -> {
|
||||
loginGenericTextInputFormTitle.text = getString(R.string.login_set_msisdn_title)
|
||||
loginGenericTextInputFormNotice.text = getString(R.string.login_set_msisdn_notice)
|
||||
loginGenericTextInputFormNotice2.setTextOrHide(getString(R.string.login_set_msisdn_notice2))
|
||||
loginGenericTextInputFormTil.hint =
|
||||
views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_msisdn_title)
|
||||
views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_msisdn_notice)
|
||||
views.loginGenericTextInputFormNotice2.setTextOrHide(getString(R.string.login_set_msisdn_notice2))
|
||||
views.loginGenericTextInputFormTil.hint =
|
||||
getString(if (params.mandatory) R.string.login_set_msisdn_mandatory_hint else R.string.login_set_msisdn_optional_hint)
|
||||
loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_PHONE
|
||||
loginGenericTextInputFormOtherButton.isVisible = false
|
||||
loginGenericTextInputFormSubmit.text = getString(R.string.login_set_msisdn_submit)
|
||||
views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_PHONE
|
||||
views.loginGenericTextInputFormOtherButton.isVisible = false
|
||||
views.loginGenericTextInputFormSubmit.text = getString(R.string.login_set_msisdn_submit)
|
||||
}
|
||||
TextInputFormFragmentMode.ConfirmMsisdn -> {
|
||||
loginGenericTextInputFormTitle.text = getString(R.string.login_msisdn_confirm_title)
|
||||
loginGenericTextInputFormNotice.text = getString(R.string.login_msisdn_confirm_notice, params.extra)
|
||||
loginGenericTextInputFormNotice2.setTextOrHide(null)
|
||||
loginGenericTextInputFormTil.hint =
|
||||
views.loginGenericTextInputFormTitle.text = getString(R.string.login_msisdn_confirm_title)
|
||||
views.loginGenericTextInputFormNotice.text = getString(R.string.login_msisdn_confirm_notice, params.extra)
|
||||
views.loginGenericTextInputFormNotice2.setTextOrHide(null)
|
||||
views.loginGenericTextInputFormTil.hint =
|
||||
getString(R.string.login_msisdn_confirm_hint)
|
||||
loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_NUMBER
|
||||
loginGenericTextInputFormOtherButton.isVisible = true
|
||||
loginGenericTextInputFormOtherButton.text = getString(R.string.login_msisdn_confirm_send_again)
|
||||
loginGenericTextInputFormSubmit.text = getString(R.string.login_msisdn_confirm_submit)
|
||||
views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_NUMBER
|
||||
views.loginGenericTextInputFormOtherButton.isVisible = true
|
||||
views.loginGenericTextInputFormOtherButton.text = getString(R.string.login_msisdn_confirm_send_again)
|
||||
views.loginGenericTextInputFormSubmit.text = getString(R.string.login_msisdn_confirm_submit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
|
||||
private fun submit() {
|
||||
cleanupUi()
|
||||
val text = loginGenericTextInputFormTextInput.text.toString()
|
||||
val text = views.loginGenericTextInputFormTextInput.text.toString()
|
||||
|
||||
if (text.isEmpty()) {
|
||||
// Perform dummy action
|
||||
|
@ -173,8 +173,8 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
}
|
||||
|
||||
private fun cleanupUi() {
|
||||
loginGenericTextInputFormSubmit.hideKeyboard()
|
||||
loginGenericTextInputFormSubmit.error = null
|
||||
views.loginGenericTextInputFormSubmit.hideKeyboard()
|
||||
views.loginGenericTextInputFormSubmit.error = null
|
||||
}
|
||||
|
||||
private fun getCountryCodeOrShowError(text: String): String? {
|
||||
|
@ -184,10 +184,10 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
val phoneNumber = PhoneNumberUtil.getInstance().parse(text, null)
|
||||
return PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(phoneNumber.countryCode)
|
||||
} catch (e: NumberParseException) {
|
||||
loginGenericTextInputFormTil.error = getString(R.string.login_msisdn_error_other)
|
||||
views.loginGenericTextInputFormTil.error = getString(R.string.login_msisdn_error_other)
|
||||
}
|
||||
} else {
|
||||
loginGenericTextInputFormTil.error = getString(R.string.login_msisdn_error_not_international)
|
||||
views.loginGenericTextInputFormTil.error = getString(R.string.login_msisdn_error_not_international)
|
||||
}
|
||||
|
||||
// Error
|
||||
|
@ -195,10 +195,10 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
}
|
||||
|
||||
private fun setupSubmitButton() {
|
||||
loginGenericTextInputFormSubmit.isEnabled = false
|
||||
loginGenericTextInputFormTextInput.textChanges()
|
||||
views.loginGenericTextInputFormSubmit.isEnabled = false
|
||||
views.loginGenericTextInputFormTextInput.textChanges()
|
||||
.subscribe {
|
||||
loginGenericTextInputFormSubmit.isEnabled = isInputValid(it)
|
||||
views.loginGenericTextInputFormSubmit.isEnabled = isInputValid(it)
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
// This is normal use case, we go to the mail waiting screen
|
||||
loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnSendEmailSuccess(loginViewModel.currentThreePid ?: "")))
|
||||
} else {
|
||||
loginGenericTextInputFormTil.error = errorFormatter.toHumanReadable(throwable)
|
||||
views.loginGenericTextInputFormTil.error = errorFormatter.toHumanReadable(throwable)
|
||||
}
|
||||
}
|
||||
TextInputFormFragmentMode.SetMsisdn -> {
|
||||
|
@ -236,19 +236,19 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
// This is normal use case, we go to the enter code screen
|
||||
loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnSendMsisdnSuccess(loginViewModel.currentThreePid ?: "")))
|
||||
} else {
|
||||
loginGenericTextInputFormTil.error = errorFormatter.toHumanReadable(throwable)
|
||||
views.loginGenericTextInputFormTil.error = errorFormatter.toHumanReadable(throwable)
|
||||
}
|
||||
}
|
||||
TextInputFormFragmentMode.ConfirmMsisdn -> {
|
||||
when {
|
||||
throwable is Failure.SuccessError ->
|
||||
// The entered code is not correct
|
||||
loginGenericTextInputFormTil.error = getString(R.string.login_validation_code_is_not_correct)
|
||||
views.loginGenericTextInputFormTil.error = getString(R.string.login_validation_code_is_not_correct)
|
||||
throwable.is401() ->
|
||||
// It can happen if user request again the 3pid
|
||||
Unit
|
||||
else ->
|
||||
loginGenericTextInputFormTil.error = errorFormatter.toHumanReadable(throwable)
|
||||
views.loginGenericTextInputFormTil.error = errorFormatter.toHumanReadable(throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,24 +60,24 @@ class LoginResetPasswordFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
}
|
||||
|
||||
private fun setupUi(state: LoginViewState) {
|
||||
resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.homeServerUrl.toReducedUrl())
|
||||
views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.homeServerUrl.toReducedUrl())
|
||||
}
|
||||
|
||||
private fun setupSubmitButton() {
|
||||
resetPasswordSubmit.setOnClickListener { submit() }
|
||||
views.resetPasswordSubmit.setOnClickListener { submit() }
|
||||
|
||||
Observable
|
||||
.combineLatest(
|
||||
resetPasswordEmail.textChanges().map { it.isEmail() },
|
||||
passwordField.textChanges().map { it.isNotEmpty() },
|
||||
views.resetPasswordEmail.textChanges().map { it.isEmail() },
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() },
|
||||
BiFunction<Boolean, Boolean, Boolean> { isEmail, isPasswordNotEmpty ->
|
||||
isEmail && isPasswordNotEmpty
|
||||
}
|
||||
)
|
||||
.subscribeBy {
|
||||
resetPasswordEmailTil.error = null
|
||||
passwordFieldTil.error = null
|
||||
resetPasswordSubmit.isEnabled = it
|
||||
views.resetPasswordEmailTil.error = null
|
||||
views.passwordFieldTil.error = null
|
||||
views.resetPasswordSubmit.isEnabled = it
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
@ -102,22 +102,22 @@ class LoginResetPasswordFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
}
|
||||
|
||||
private fun doSubmit() {
|
||||
val email = resetPasswordEmail.text.toString()
|
||||
val password = passwordField.text.toString()
|
||||
val email = views.resetPasswordEmail.text.toString()
|
||||
val password = views.passwordField.text.toString()
|
||||
|
||||
loginViewModel.handle(LoginAction.ResetPassword(email, password))
|
||||
}
|
||||
|
||||
private fun cleanupUi() {
|
||||
resetPasswordSubmit.hideKeyboard()
|
||||
resetPasswordEmailTil.error = null
|
||||
passwordFieldTil.error = null
|
||||
views.resetPasswordSubmit.hideKeyboard()
|
||||
views.resetPasswordEmailTil.error = null
|
||||
views.passwordFieldTil.error = null
|
||||
}
|
||||
|
||||
private fun setupPasswordReveal() {
|
||||
passwordShown = false
|
||||
|
||||
passwordReveal.setOnClickListener {
|
||||
views.passwordReveal.setOnClickListener {
|
||||
passwordShown = !passwordShown
|
||||
|
||||
renderPasswordField()
|
||||
|
@ -127,14 +127,14 @@ class LoginResetPasswordFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
}
|
||||
|
||||
private fun renderPasswordField() {
|
||||
passwordField.showPassword(passwordShown)
|
||||
views.passwordField.showPassword(passwordShown)
|
||||
|
||||
if (passwordShown) {
|
||||
passwordReveal.setImageResource(R.drawable.ic_eye_closed)
|
||||
passwordReveal.contentDescription = getString(R.string.a11y_hide_password)
|
||||
views.passwordReveal.setImageResource(R.drawable.ic_eye_closed)
|
||||
views.passwordReveal.contentDescription = getString(R.string.a11y_hide_password)
|
||||
} else {
|
||||
passwordReveal.setImageResource(R.drawable.ic_eye)
|
||||
passwordReveal.contentDescription = getString(R.string.a11y_show_password)
|
||||
views.passwordReveal.setImageResource(R.drawable.ic_eye)
|
||||
views.passwordReveal.contentDescription = getString(R.string.a11y_show_password)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ class LoginResetPasswordFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
renderPasswordField()
|
||||
}
|
||||
is Fail -> {
|
||||
resetPasswordEmailTil.error = errorFormatter.toHumanReadable(state.asyncResetPassword.error)
|
||||
views.resetPasswordEmailTil.error = errorFormatter.toHumanReadable(state.asyncResetPassword.error)
|
||||
}
|
||||
is Success -> {
|
||||
Unit
|
||||
|
|
|
@ -56,22 +56,22 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
}
|
||||
|
||||
private fun setupViews() {
|
||||
loginServerUrlFormLearnMore.setOnClickListener { learnMore() }
|
||||
loginServerUrlFormClearHistory.setOnClickListener { clearHistory() }
|
||||
loginServerUrlFormSubmit.setOnClickListener { submit() }
|
||||
views.loginServerUrlFormLearnMore.setOnClickListener { learnMore() }
|
||||
views.loginServerUrlFormClearHistory.setOnClickListener { clearHistory() }
|
||||
views.loginServerUrlFormSubmit.setOnClickListener { submit() }
|
||||
}
|
||||
|
||||
private fun setupHomeServerField() {
|
||||
loginServerUrlFormHomeServerUrl.textChanges()
|
||||
views.loginServerUrlFormHomeServerUrl.textChanges()
|
||||
.subscribe {
|
||||
loginServerUrlFormHomeServerUrlTil.error = null
|
||||
loginServerUrlFormSubmit.isEnabled = it.isNotBlank()
|
||||
views.loginServerUrlFormHomeServerUrlTil.error = null
|
||||
views.loginServerUrlFormSubmit.isEnabled = it.isNotBlank()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
loginServerUrlFormHomeServerUrl.setOnEditorActionListener { _, actionId, _ ->
|
||||
views.loginServerUrlFormHomeServerUrl.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
loginServerUrlFormHomeServerUrl.dismissDropDown()
|
||||
views.loginServerUrlFormHomeServerUrl.dismissDropDown()
|
||||
submit()
|
||||
return@setOnEditorActionListener true
|
||||
}
|
||||
|
@ -82,29 +82,29 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
private fun setupUi(state: LoginViewState) {
|
||||
when (state.serverType) {
|
||||
ServerType.EMS -> {
|
||||
loginServerUrlFormIcon.isVisible = true
|
||||
loginServerUrlFormTitle.text = getString(R.string.login_connect_to_modular)
|
||||
loginServerUrlFormText.text = getString(R.string.login_server_url_form_modular_text)
|
||||
loginServerUrlFormLearnMore.isVisible = true
|
||||
loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_modular_hint)
|
||||
loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_common_notice)
|
||||
views.loginServerUrlFormIcon.isVisible = true
|
||||
views.loginServerUrlFormTitle.text = getString(R.string.login_connect_to_modular)
|
||||
views.loginServerUrlFormText.text = getString(R.string.login_server_url_form_modular_text)
|
||||
views.loginServerUrlFormLearnMore.isVisible = true
|
||||
views.loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_modular_hint)
|
||||
views.loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_common_notice)
|
||||
}
|
||||
else -> {
|
||||
loginServerUrlFormIcon.isVisible = false
|
||||
loginServerUrlFormTitle.text = getString(R.string.login_server_other_title)
|
||||
loginServerUrlFormText.text = getString(R.string.login_connect_to_a_custom_server)
|
||||
loginServerUrlFormLearnMore.isVisible = false
|
||||
loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_other_hint)
|
||||
loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_common_notice)
|
||||
views.loginServerUrlFormIcon.isVisible = false
|
||||
views.loginServerUrlFormTitle.text = getString(R.string.login_server_other_title)
|
||||
views.loginServerUrlFormText.text = getString(R.string.login_connect_to_a_custom_server)
|
||||
views.loginServerUrlFormLearnMore.isVisible = false
|
||||
views.loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_other_hint)
|
||||
views.loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_common_notice)
|
||||
}
|
||||
}
|
||||
val completions = state.knownCustomHomeServersUrls + if (BuildConfig.DEBUG) listOf("http://10.0.2.2:8080") else emptyList()
|
||||
loginServerUrlFormHomeServerUrl.setAdapter(ArrayAdapter(
|
||||
views.loginServerUrlFormHomeServerUrl.setAdapter(ArrayAdapter(
|
||||
requireContext(),
|
||||
R.layout.item_completion_homeserver,
|
||||
completions
|
||||
))
|
||||
loginServerUrlFormHomeServerUrlTil.endIconMode = TextInputLayout.END_ICON_DROPDOWN_MENU
|
||||
views.loginServerUrlFormHomeServerUrlTil.endIconMode = TextInputLayout.END_ICON_DROPDOWN_MENU
|
||||
.takeIf { completions.isNotEmpty() }
|
||||
?: TextInputLayout.END_ICON_NONE
|
||||
}
|
||||
|
@ -126,26 +126,26 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
cleanupUi()
|
||||
|
||||
// Static check of homeserver url, empty, malformed, etc.
|
||||
val serverUrl = loginServerUrlFormHomeServerUrl.text.toString().trim().ensureProtocol()
|
||||
val serverUrl = views.loginServerUrlFormHomeServerUrl.text.toString().trim().ensureProtocol()
|
||||
|
||||
when {
|
||||
serverUrl.isBlank() -> {
|
||||
loginServerUrlFormHomeServerUrlTil.error = getString(R.string.login_error_invalid_home_server)
|
||||
views.loginServerUrlFormHomeServerUrlTil.error = getString(R.string.login_error_invalid_home_server)
|
||||
}
|
||||
else -> {
|
||||
loginServerUrlFormHomeServerUrl.setText(serverUrl, false /* to avoid completion dialog flicker*/)
|
||||
views.loginServerUrlFormHomeServerUrl.setText(serverUrl, false /* to avoid completion dialog flicker*/)
|
||||
loginViewModel.handle(LoginAction.UpdateHomeServer(serverUrl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun cleanupUi() {
|
||||
loginServerUrlFormSubmit.hideKeyboard()
|
||||
loginServerUrlFormHomeServerUrlTil.error = null
|
||||
views.loginServerUrlFormSubmit.hideKeyboard()
|
||||
views.loginServerUrlFormHomeServerUrlTil.error = null
|
||||
}
|
||||
|
||||
override fun onError(throwable: Throwable) {
|
||||
loginServerUrlFormHomeServerUrlTil.error = if (throwable is Failure.NetworkConnection
|
||||
views.loginServerUrlFormHomeServerUrlTil.error = if (throwable is Failure.NetworkConnection
|
||||
&& throwable.ioException is UnknownHostException) {
|
||||
// Invalid homeserver?
|
||||
getString(R.string.login_error_homeserver_not_found)
|
||||
|
@ -157,7 +157,7 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
override fun updateWithState(state: LoginViewState) {
|
||||
setupUi(state)
|
||||
|
||||
loginServerUrlFormClearHistory.isInvisible = state.knownCustomHomeServersUrls.isEmpty()
|
||||
views.loginServerUrlFormClearHistory.isInvisible = state.knownCustomHomeServersUrls.isEmpty()
|
||||
|
||||
if (state.loginMode != LoginMode.Unknown) {
|
||||
// The home server url is valid
|
||||
|
|
|
@ -45,37 +45,37 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOLogi
|
|||
}
|
||||
|
||||
private fun setupViews() {
|
||||
loginSignupSigninSubmit.setOnClickListener { submit() }
|
||||
loginSignupSigninSignIn.setOnClickListener { signIn() }
|
||||
views.loginSignupSigninSubmit.setOnClickListener { submit() }
|
||||
views.loginSignupSigninSignIn.setOnClickListener { signIn() }
|
||||
}
|
||||
|
||||
private fun setupUi(state: LoginViewState) {
|
||||
when (state.serverType) {
|
||||
ServerType.MatrixOrg -> {
|
||||
loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_matrix_org)
|
||||
loginSignupSigninServerIcon.isVisible = true
|
||||
loginSignupSigninTitle.text = getString(R.string.login_connect_to, state.homeServerUrl.toReducedUrl())
|
||||
loginSignupSigninText.text = getString(R.string.login_server_matrix_org_text)
|
||||
views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_matrix_org)
|
||||
views.loginSignupSigninServerIcon.isVisible = true
|
||||
views.loginSignupSigninTitle.text = getString(R.string.login_connect_to, state.homeServerUrl.toReducedUrl())
|
||||
views.loginSignupSigninText.text = getString(R.string.login_server_matrix_org_text)
|
||||
}
|
||||
ServerType.EMS -> {
|
||||
loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_element_matrix_services)
|
||||
loginSignupSigninServerIcon.isVisible = true
|
||||
loginSignupSigninTitle.text = getString(R.string.login_connect_to_modular)
|
||||
loginSignupSigninText.text = state.homeServerUrl.toReducedUrl()
|
||||
views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_element_matrix_services)
|
||||
views.loginSignupSigninServerIcon.isVisible = true
|
||||
views.loginSignupSigninTitle.text = getString(R.string.login_connect_to_modular)
|
||||
views.loginSignupSigninText.text = state.homeServerUrl.toReducedUrl()
|
||||
}
|
||||
ServerType.Other -> {
|
||||
loginSignupSigninServerIcon.isVisible = false
|
||||
loginSignupSigninTitle.text = getString(R.string.login_server_other_title)
|
||||
loginSignupSigninText.text = getString(R.string.login_connect_to, state.homeServerUrl.toReducedUrl())
|
||||
views.loginSignupSigninServerIcon.isVisible = false
|
||||
views.loginSignupSigninTitle.text = getString(R.string.login_server_other_title)
|
||||
views.loginSignupSigninText.text = getString(R.string.login_connect_to, state.homeServerUrl.toReducedUrl())
|
||||
}
|
||||
ServerType.Unknown -> Unit /* Should not happen */
|
||||
}
|
||||
|
||||
when (state.loginMode) {
|
||||
is LoginMode.SsoAndPassword -> {
|
||||
loginSignupSigninSignInSocialLoginContainer.isVisible = true
|
||||
loginSignupSigninSocialLoginButtons.ssoIdentityProviders = state.loginMode.ssoIdentityProviders()
|
||||
loginSignupSigninSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
||||
views.loginSignupSigninSignInSocialLoginContainer.isVisible = true
|
||||
views.loginSignupSigninSocialLoginButtons.ssoIdentityProviders = state.loginMode.ssoIdentityProviders()
|
||||
views.loginSignupSigninSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
||||
override fun onProviderSelected(id: String?) {
|
||||
val url = withState(loginViewModel) { it.getSsoUrl(id) }
|
||||
openInCustomTab(url)
|
||||
|
@ -84,8 +84,8 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOLogi
|
|||
}
|
||||
else -> {
|
||||
// SSO only is managed without container as well as No sso
|
||||
loginSignupSigninSignInSocialLoginContainer.isVisible = false
|
||||
loginSignupSigninSocialLoginButtons.ssoIdentityProviders = null
|
||||
views.loginSignupSigninSignInSocialLoginContainer.isVisible = false
|
||||
views.loginSignupSigninSocialLoginButtons.ssoIdentityProviders = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,12 +94,12 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOLogi
|
|||
when (state.loginMode) {
|
||||
is LoginMode.Sso -> {
|
||||
// change to only one button that is sign in with sso
|
||||
loginSignupSigninSubmit.text = getString(R.string.login_signin_sso)
|
||||
loginSignupSigninSignIn.isVisible = false
|
||||
views.loginSignupSigninSubmit.text = getString(R.string.login_signin_sso)
|
||||
views.loginSignupSigninSignIn.isVisible = false
|
||||
}
|
||||
else -> {
|
||||
loginSignupSigninSubmit.text = getString(R.string.login_signup)
|
||||
loginSignupSigninSignIn.isVisible = true
|
||||
views.loginSignupSigninSubmit.text = getString(R.string.login_signup)
|
||||
views.loginSignupSigninSignIn.isVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,9 +56,9 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupToolbar(roomPreviewNoPreviewToolbar)
|
||||
setupToolbar(views.roomPreviewNoPreviewToolbar)
|
||||
|
||||
roomPreviewNoPreviewJoin.callback = object : ButtonStateView.Callback {
|
||||
views.roomPreviewNoPreviewJoin.callback = object : ButtonStateView.Callback {
|
||||
override fun onButtonClicked() {
|
||||
roomPreviewViewModel.handle(RoomPreviewAction.Join)
|
||||
}
|
||||
|
@ -71,9 +71,9 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun invalidate() = withState(roomPreviewViewModel) { state ->
|
||||
TransitionManager.beginDelayedTransition(roomPreviewNoPreviewRoot)
|
||||
TransitionManager.beginDelayedTransition(views.roomPreviewNoPreviewRoot)
|
||||
|
||||
roomPreviewNoPreviewJoin.render(
|
||||
views.roomPreviewNoPreviewJoin.render(
|
||||
when (state.roomJoinState) {
|
||||
JoinState.NOT_JOINED -> ButtonStateView.State.Button
|
||||
JoinState.JOINING -> ButtonStateView.State.Loading
|
||||
|
@ -83,10 +83,10 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
|
|||
)
|
||||
|
||||
if (state.lastError == null) {
|
||||
roomPreviewNoPreviewError.isVisible = false
|
||||
views.roomPreviewNoPreviewError.isVisible = false
|
||||
} else {
|
||||
roomPreviewNoPreviewError.isVisible = true
|
||||
roomPreviewNoPreviewError.text = errorFormatter.toHumanReadable(state.lastError)
|
||||
views.roomPreviewNoPreviewError.isVisible = true
|
||||
views.roomPreviewNoPreviewError.text = errorFormatter.toHumanReadable(state.lastError)
|
||||
}
|
||||
|
||||
if (state.roomJoinState == JoinState.JOINED) {
|
||||
|
@ -99,37 +99,37 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
|
|||
val bestName = state.roomName ?: state.roomAlias ?: state.roomId
|
||||
when (state.peekingState) {
|
||||
is Loading -> {
|
||||
roomPreviewPeekingProgress.isVisible = true
|
||||
roomPreviewNoPreviewJoin.isVisible = false
|
||||
views.roomPreviewPeekingProgress.isVisible = true
|
||||
views.roomPreviewNoPreviewJoin.isVisible = false
|
||||
}
|
||||
is Success -> {
|
||||
roomPreviewPeekingProgress.isVisible = false
|
||||
views.roomPreviewPeekingProgress.isVisible = false
|
||||
when (state.peekingState.invoke()) {
|
||||
PeekingState.FOUND -> {
|
||||
// show join buttons
|
||||
roomPreviewNoPreviewJoin.isVisible = true
|
||||
views.roomPreviewNoPreviewJoin.isVisible = true
|
||||
renderState(bestName, state.matrixItem(), state.roomTopic)
|
||||
}
|
||||
PeekingState.NO_ACCESS -> {
|
||||
roomPreviewNoPreviewJoin.isVisible = true
|
||||
roomPreviewNoPreviewLabel.isVisible = true
|
||||
roomPreviewNoPreviewLabel.setText(R.string.room_preview_no_preview_join)
|
||||
views.roomPreviewNoPreviewJoin.isVisible = true
|
||||
views.roomPreviewNoPreviewLabel.isVisible = true
|
||||
views.roomPreviewNoPreviewLabel.setText(R.string.room_preview_no_preview_join)
|
||||
renderState(bestName, state.matrixItem().takeIf { state.roomAlias != null }, state.roomTopic)
|
||||
}
|
||||
else -> {
|
||||
roomPreviewNoPreviewJoin.isVisible = false
|
||||
roomPreviewNoPreviewLabel.isVisible = true
|
||||
roomPreviewNoPreviewLabel.setText(R.string.room_preview_not_found)
|
||||
views.roomPreviewNoPreviewJoin.isVisible = false
|
||||
views.roomPreviewNoPreviewLabel.isVisible = true
|
||||
views.roomPreviewNoPreviewLabel.setText(R.string.room_preview_not_found)
|
||||
renderState(bestName, null, state.roomTopic)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// Render with initial state, no peeking
|
||||
roomPreviewPeekingProgress.isVisible = false
|
||||
roomPreviewNoPreviewJoin.isVisible = true
|
||||
views.roomPreviewPeekingProgress.isVisible = false
|
||||
views.roomPreviewNoPreviewJoin.isVisible = true
|
||||
renderState(bestName, state.matrixItem(), state.roomTopic)
|
||||
roomPreviewNoPreviewLabel.isVisible = false
|
||||
views.roomPreviewNoPreviewLabel.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,18 +137,18 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
|
|||
private fun renderState(roomName: String, matrixItem: MatrixItem?, topic: String?) {
|
||||
// Toolbar
|
||||
if (matrixItem != null) {
|
||||
roomPreviewNoPreviewToolbarAvatar.isVisible = true
|
||||
roomPreviewNoPreviewAvatar.isVisible = true
|
||||
avatarRenderer.render(matrixItem, roomPreviewNoPreviewToolbarAvatar)
|
||||
avatarRenderer.render(matrixItem, roomPreviewNoPreviewAvatar)
|
||||
views.roomPreviewNoPreviewToolbarAvatar.isVisible = true
|
||||
views.roomPreviewNoPreviewAvatar.isVisible = true
|
||||
avatarRenderer.render(matrixItem, views.roomPreviewNoPreviewToolbarAvatar)
|
||||
avatarRenderer.render(matrixItem, views.roomPreviewNoPreviewAvatar)
|
||||
} else {
|
||||
roomPreviewNoPreviewToolbarAvatar.isVisible = false
|
||||
roomPreviewNoPreviewAvatar.isVisible = false
|
||||
views.roomPreviewNoPreviewToolbarAvatar.isVisible = false
|
||||
views.roomPreviewNoPreviewAvatar.isVisible = false
|
||||
}
|
||||
roomPreviewNoPreviewToolbarTitle.text = roomName
|
||||
views.roomPreviewNoPreviewToolbarTitle.text = roomName
|
||||
|
||||
// Screen
|
||||
roomPreviewNoPreviewName.text = roomName
|
||||
roomPreviewNoPreviewTopic.setTextOrHide(topic)
|
||||
views.roomPreviewNoPreviewName.text = roomName
|
||||
views.roomPreviewNoPreviewTopic.setTextOrHide(topic)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,13 +28,14 @@ import im.vector.app.core.di.ScreenComponent
|
|||
import im.vector.app.core.extensions.addFragment
|
||||
import im.vector.app.core.platform.ToolbarConfigurable
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivitySimpleBinding
|
||||
import im.vector.app.features.room.RequireActiveMembershipViewEvents
|
||||
import im.vector.app.features.room.RequireActiveMembershipViewModel
|
||||
import im.vector.app.features.room.RequireActiveMembershipViewState
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomMemberProfileActivity :
|
||||
VectorBaseActivity(),
|
||||
VectorBaseActivity<ActivitySimpleBinding>(),
|
||||
ToolbarConfigurable,
|
||||
RequireActiveMembershipViewModel.Factory {
|
||||
|
||||
|
@ -60,7 +61,9 @@ class RoomMemberProfileActivity :
|
|||
injector.inject(this)
|
||||
}
|
||||
|
||||
override fun getLayoutRes() = R.layout.activity_simple
|
||||
override fun getBinding(): ActivitySimpleBinding {
|
||||
return ActivitySimpleBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun initUiAndData() {
|
||||
if (isFirstCreation()) {
|
||||
|
|
|
@ -33,9 +33,9 @@ class VectorSettingsAdvancedSettingsFragment : VectorSettingsBaseFragment() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
rageshake = (activity as? VectorBaseActivity)?.rageShake
|
||||
rageshake = (activity as? VectorBaseActivity<*>)?.rageShake
|
||||
rageshake?.interceptor = {
|
||||
(activity as? VectorBaseActivity)?.showSnackbar(getString(R.string.rageshake_detected))
|
||||
(activity as? VectorBaseActivity<*>)?.showSnackbar(getString(R.string.rageshake_detected))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ class VectorSettingsAdvancedSettingsFragment : VectorSettingsBaseFragment() {
|
|||
|
||||
findPreference<SeekBarPreference>(VectorPreferences.SETTINGS_RAGE_SHAKE_DETECTION_THRESHOLD_KEY)!!
|
||||
.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
(activity as? VectorBaseActivity)?.let {
|
||||
(activity as? VectorBaseActivity<*>)?.let {
|
||||
val newValueAsInt = newValue as? Int ?: return@OnPreferenceChangeListener true
|
||||
|
||||
rageshake?.setSensitivity(newValueAsInt)
|
||||
|
|
|
@ -101,7 +101,7 @@ class SoftLogoutActivity : LoginActivity() {
|
|||
MainActivity.restartApp(this, MainActivityArgs())
|
||||
}
|
||||
|
||||
loginLoading.isVisible = softLogoutViewState.isLoading()
|
||||
views.loginLoading.isVisible = softLogoutViewState.isLoading()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
Loading…
Reference in New Issue