mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-27 03:49:04 +03:00
Login: move login code to the ViewModel
This commit is contained in:
parent
05b2092ffc
commit
a47a3ead1f
5 changed files with 154 additions and 67 deletions
|
@ -17,11 +17,8 @@
|
|||
package im.vector.riotx.core.platform
|
||||
|
||||
import com.airbnb.mvrx.*
|
||||
import im.vector.matrix.android.api.util.CancelableBag
|
||||
import im.vector.riotx.BuildConfig
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.disposables.Disposable
|
||||
|
||||
abstract class VectorViewModel<S : MvRxState>(initialState: S)
|
||||
: BaseMvRxViewModel<S>(initialState, false) {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2019 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.login
|
||||
|
||||
sealed class LoginActions {
|
||||
|
||||
data class UpdateHomeServer(val homeServerUrl: String) : LoginActions()
|
||||
data class Login(val login: String, val password: String) : LoginActions()
|
||||
|
||||
}
|
|
@ -20,26 +20,18 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isVisible
|
||||
import arrow.core.Try
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.airbnb.mvrx.*
|
||||
import com.jakewharton.rxbinding3.view.focusChanges
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.auth.Authenticator
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||
import im.vector.riotx.core.di.ScreenComponent
|
||||
import im.vector.riotx.core.error.ErrorFormatter
|
||||
import im.vector.riotx.core.extensions.configureAndStart
|
||||
import im.vector.riotx.core.extensions.setTextWithColoredPart
|
||||
import im.vector.riotx.core.extensions.showPassword
|
||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||
import im.vector.riotx.core.utils.openUrlInExternalBrowser
|
||||
import im.vector.riotx.features.home.HomeActivity
|
||||
import im.vector.riotx.features.homeserver.ServerUrlsRepository
|
||||
import im.vector.riotx.features.notifications.PushRuleTriggerListener
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.functions.Function3
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
|
@ -55,9 +47,6 @@ class LoginFragment : VectorBaseFragment() {
|
|||
|
||||
private val viewModel: LoginViewModel by activityViewModel()
|
||||
|
||||
@Inject lateinit var authenticator: Authenticator
|
||||
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||
@Inject lateinit var pushRuleTriggerListener: PushRuleTriggerListener
|
||||
private var passwordShown = false
|
||||
|
||||
@Inject lateinit var errorFormatter: ErrorFormatter
|
||||
|
@ -75,13 +64,19 @@ class LoginFragment : VectorBaseFragment() {
|
|||
setupNotice()
|
||||
setupAuthButton()
|
||||
setupPasswordReveal()
|
||||
|
||||
homeServerField.focusChanges()
|
||||
.subscribe {
|
||||
if (!it) {
|
||||
// TODO Also when clicking on button?
|
||||
viewModel.handle(LoginActions.UpdateHomeServer(homeServerField.text.toString()))
|
||||
}
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
|
||||
|
||||
homeServerField.setText(ServerUrlsRepository.getDefaultHomeServerUrl(requireContext()))
|
||||
|
||||
|
||||
// viewModel.joinRoomErrorLiveData.observeEvent(this) { throwable ->
|
||||
// Snackbar.make(publicRoomsCoordinator, errorFormatter.toHumanReadable(throwable), Snackbar.LENGTH_SHORT)
|
||||
// .show()
|
||||
// }
|
||||
viewModel.handle(LoginActions.UpdateHomeServer(homeServerField.text.toString()))
|
||||
}
|
||||
|
||||
private fun setupNotice() {
|
||||
|
@ -93,42 +88,10 @@ class LoginFragment : VectorBaseFragment() {
|
|||
}
|
||||
|
||||
private fun authenticate() {
|
||||
passwordShown = false
|
||||
renderPasswordField()
|
||||
|
||||
val login = loginField.text?.trim().toString()
|
||||
val password = passwordField.text?.trim().toString()
|
||||
buildHomeServerConnectionConfig().fold(
|
||||
{ Toast.makeText(requireActivity(), "Authenticate failure: $it", Toast.LENGTH_LONG).show() },
|
||||
{ authenticateWith(it, login, password) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun authenticateWith(homeServerConnectionConfig: HomeServerConnectionConfig, login: String, password: String) {
|
||||
progressBar.isVisible = true
|
||||
touchArea.isVisible = true
|
||||
authenticator.authenticate(homeServerConnectionConfig, login, password, object : MatrixCallback<Session> {
|
||||
override fun onSuccess(data: Session) {
|
||||
activeSessionHolder.setActiveSession(data)
|
||||
data.configureAndStart(pushRuleTriggerListener)
|
||||
goToHome()
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
progressBar.isVisible = false
|
||||
touchArea.isVisible = false
|
||||
Toast.makeText(requireActivity(), "Authenticate failure: $failure", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun buildHomeServerConnectionConfig(): Try<HomeServerConnectionConfig> {
|
||||
return Try {
|
||||
val homeServerUri = homeServerField.text?.trim().toString()
|
||||
HomeServerConnectionConfig.Builder()
|
||||
.withHomeServerUri(homeServerUri)
|
||||
.build()
|
||||
}
|
||||
viewModel.handle(LoginActions.Login(login, password))
|
||||
}
|
||||
|
||||
private fun setupAuthButton() {
|
||||
|
@ -164,14 +127,25 @@ class LoginFragment : VectorBaseFragment() {
|
|||
passwordReveal.setImageResource(if (passwordShown) R.drawable.ic_eye_closed_black else R.drawable.ic_eye_black)
|
||||
}
|
||||
|
||||
private fun goToHome() {
|
||||
val intent = HomeActivity.newIntent(requireActivity())
|
||||
startActivity(intent)
|
||||
requireActivity().finish()
|
||||
}
|
||||
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
when (state.asyncLoginAction) {
|
||||
is Loading -> {
|
||||
progressBar.isVisible = true
|
||||
touchArea.isVisible = true
|
||||
|
||||
passwordShown = false
|
||||
renderPasswordField()
|
||||
}
|
||||
is Fail -> {
|
||||
progressBar.isVisible = false
|
||||
touchArea.isVisible = false
|
||||
Toast.makeText(requireActivity(), "Authenticate failure: ${state.asyncLoginAction.error}", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
is Success -> {
|
||||
val intent = HomeActivity.newIntent(requireActivity())
|
||||
startActivity(intent)
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,14 +16,24 @@
|
|||
|
||||
package im.vector.riotx.features.login
|
||||
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import arrow.core.Try
|
||||
import com.airbnb.mvrx.*
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.auth.Authenticator
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||
import im.vector.riotx.core.extensions.configureAndStart
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.features.notifications.PushRuleTriggerListener
|
||||
|
||||
class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginViewState) : VectorViewModel<LoginViewState>(initialState) {
|
||||
class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginViewState,
|
||||
val authenticator: Authenticator,
|
||||
val activeSessionHolder: ActiveSessionHolder,
|
||||
val pushRuleTriggerListener: PushRuleTriggerListener) : VectorViewModel<LoginViewState>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
|
@ -43,5 +53,87 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
|
||||
}
|
||||
|
||||
var homeServerConnectionConfig: HomeServerConnectionConfig? = null
|
||||
private var currentTask: Cancelable? = null
|
||||
|
||||
|
||||
fun handle(action: LoginActions) {
|
||||
when (action) {
|
||||
is LoginActions.UpdateHomeServer -> handleUpdateHomeserver(action)
|
||||
is LoginActions.Login -> handleLogin(action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLogin(action: LoginActions.Login) {
|
||||
val homeServerConnectionConfigFinal = homeServerConnectionConfig
|
||||
|
||||
if (homeServerConnectionConfigFinal == null) {
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Fail(Throwable("Bad configuration"))
|
||||
)
|
||||
}
|
||||
} else {
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Loading()
|
||||
)
|
||||
}
|
||||
|
||||
authenticator.authenticate(homeServerConnectionConfigFinal, action.login, action.password, object : MatrixCallback<Session> {
|
||||
override fun onSuccess(data: Session) {
|
||||
activeSessionHolder.setActiveSession(data)
|
||||
data.configureAndStart(pushRuleTriggerListener)
|
||||
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Success(Unit)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Fail(failure)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUpdateHomeserver(action: LoginActions.UpdateHomeServer) {
|
||||
Try {
|
||||
val homeServerUri = action.homeServerUrl
|
||||
homeServerConnectionConfig = HomeServerConnectionConfig.Builder()
|
||||
.withHomeServerUri(homeServerUri)
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
// TODO Do request
|
||||
|
||||
/*
|
||||
currentTask?.cancel()
|
||||
|
||||
setState {
|
||||
copy(
|
||||
asyncHomeServerLoginFlowRequest = Loading()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// TODO currentTask =
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
currentTask?.cancel()
|
||||
}
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@ import com.airbnb.mvrx.MvRxState
|
|||
import com.airbnb.mvrx.Uninitialized
|
||||
|
||||
data class LoginViewState(
|
||||
// Current pagination request
|
||||
val asyncLoginAction: Async<Unit> = Uninitialized,
|
||||
val asyncHomeServerLoginFlowRequest: Async<LoginFlowResult> = Uninitialized
|
||||
) : MvRxState
|
||||
|
||||
|
|
Loading…
Reference in a new issue