extracting inline fragment view logic to a controller
This commit is contained in:
parent
92c615af31
commit
d403d16731
@ -20,8 +20,11 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.extensions.associateContentStateWith
|
||||
import im.vector.app.core.extensions.clearErrorOnChange
|
||||
import im.vector.app.core.extensions.content
|
||||
@ -30,6 +33,7 @@ import im.vector.app.core.extensions.realignPercentagesToParent
|
||||
import im.vector.app.core.extensions.setOnImeDoneListener
|
||||
import im.vector.app.core.extensions.showKeyboard
|
||||
import im.vector.app.core.extensions.toReducedUrl
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.utils.ensureProtocol
|
||||
import im.vector.app.core.utils.ensureTrailingSlash
|
||||
import im.vector.app.core.utils.openUrlInExternalBrowser
|
||||
@ -37,49 +41,82 @@ import im.vector.app.databinding.FragmentFtueServerSelectionCombinedBinding
|
||||
import im.vector.app.features.onboarding.OnboardingAction
|
||||
import im.vector.app.features.onboarding.OnboardingFlow
|
||||
import im.vector.app.features.onboarding.OnboardingViewEvents
|
||||
import im.vector.app.features.onboarding.OnboardingViewModel
|
||||
import im.vector.app.features.onboarding.OnboardingViewState
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class FtueAuthCombinedServerSelectionFragment :
|
||||
AbstractFtueAuthFragment<FragmentFtueServerSelectionCombinedBinding>() {
|
||||
class FtueAuthCombinedServerSelectionFragment : AbstractFtueAuthFragment<FragmentFtueServerSelectionCombinedBinding>() {
|
||||
|
||||
@Inject lateinit var stringProvider: StringProvider
|
||||
private lateinit var controller: Controller
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueServerSelectionCombinedBinding {
|
||||
return FragmentFtueServerSelectionCombinedBinding.inflate(inflater, container, false)
|
||||
return FragmentFtueServerSelectionCombinedBinding.inflate(inflater, container, false).also {
|
||||
controller = Controller(viewLifecycleOwner, it, stringProvider, errorFormatter)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupViews()
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
views.chooseServerRoot.realignPercentagesToParent()
|
||||
views.chooseServerToolbar.setNavigationOnClickListener {
|
||||
controller.listener = object : Controller.Listener {
|
||||
override fun onNavigationClicked() {
|
||||
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnBack))
|
||||
}
|
||||
views.chooseServerInput.associateContentStateWith(button = views.chooseServerSubmit, enabledPredicate = { canSubmit(it) })
|
||||
views.chooseServerInput.setOnImeDoneListener {
|
||||
if (canSubmit(views.chooseServerInput.content())) {
|
||||
updateServerUrl()
|
||||
}
|
||||
}
|
||||
views.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url)) }
|
||||
views.chooseServerSubmit.debouncedClicks { updateServerUrl() }
|
||||
views.chooseServerInput.clearErrorOnChange(viewLifecycleOwner)
|
||||
}
|
||||
|
||||
private fun canSubmit(url: String) = url.isNotEmpty()
|
||||
|
||||
private fun updateServerUrl() {
|
||||
override fun updateServerUrl() {
|
||||
viewModel.handle(OnboardingAction.HomeServerChange.EditHomeServer(views.chooseServerInput.content().ensureProtocol().ensureTrailingSlash()))
|
||||
}
|
||||
|
||||
override fun getInTouchClicked() {
|
||||
openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun resetViewModel() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun updateWithState(state: OnboardingViewState) {
|
||||
controller.setData(state)
|
||||
}
|
||||
|
||||
override fun onError(throwable: Throwable) {
|
||||
controller.setError(throwable)
|
||||
}
|
||||
|
||||
class Controller(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
private val views: FragmentFtueServerSelectionCombinedBinding,
|
||||
private val stringProvider: StringProvider,
|
||||
private val errorFormatter: ErrorFormatter,
|
||||
private val viewModel: OnboardingViewModel,
|
||||
) {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
init {
|
||||
views.chooseServerRoot.realignPercentagesToParent()
|
||||
views.chooseServerToolbar.setNavigationOnClickListener { listener?.onNavigationClicked() }
|
||||
views.chooseServerInput.associateContentStateWith(button = views.chooseServerSubmit, enabledPredicate = { canSubmit(it) })
|
||||
views.chooseServerInput.setOnImeDoneListener {
|
||||
if (canSubmit(views.chooseServerInput.content())) {
|
||||
listener?.updateServerUrl()
|
||||
}
|
||||
}
|
||||
views.chooseServerGetInTouch.debouncedClicks(lifecycleOwner) { listener?.getInTouchClicked() }
|
||||
views.chooseServerSubmit.debouncedClicks(lifecycleOwner) { listener?.updateServerUrl() }
|
||||
views.chooseServerInput.clearErrorOnChange(lifecycleOwner)
|
||||
}
|
||||
|
||||
private fun canSubmit(url: String) = url.isNotEmpty()
|
||||
|
||||
fun setData(state: OnboardingViewState) {
|
||||
views.chooseServerHeaderSubtitle.setText(
|
||||
when (state.onboardingFlow) {
|
||||
OnboardingFlow.SignIn -> R.string.ftue_auth_choose_server_sign_in_subtitle
|
||||
@ -97,12 +134,26 @@ class FtueAuthCombinedServerSelectionFragment :
|
||||
views.chooseServerInput.editText().showKeyboard(true)
|
||||
}
|
||||
|
||||
override fun onError(throwable: Throwable) {
|
||||
fun setError(throwable: Throwable) {
|
||||
views.chooseServerInput.error = when {
|
||||
throwable.isHomeserverUnavailable() -> getString(R.string.login_error_homeserver_not_found)
|
||||
throwable.isHomeserverUnavailable() -> stringProvider.getString(R.string.login_error_homeserver_not_found)
|
||||
else -> errorFormatter.toHumanReadable(throwable)
|
||||
}
|
||||
println(views.chooseServerInput.error)
|
||||
}
|
||||
|
||||
private fun String.toReducedUrlKeepingSchemaIfInsecure() = toReducedUrl(keepSchema = this.startsWith("http://"))
|
||||
|
||||
interface Listener {
|
||||
fun onNavigationClicked()
|
||||
fun updateServerUrl()
|
||||
fun getInTouchClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun View.debouncedClicks(lifecycleOwner: LifecycleOwner, onClicked: () -> Unit) {
|
||||
clicks()
|
||||
.onEach { onClicked() }
|
||||
.launchIn(lifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user