mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 18:35:40 +03:00
Create a ViewState for HomeActivity
And disable the popup - WIP
This commit is contained in:
parent
1365240f69
commit
48a30a7b82
6 changed files with 164 additions and 54 deletions
|
@ -20,10 +20,13 @@ import androidx.lifecycle.LiveData
|
|||
|
||||
interface InitialSyncProgressService {
|
||||
|
||||
fun getInitialSyncProgressStatus() : LiveData<Status?>
|
||||
fun getInitialSyncProgressStatus(): LiveData<Status>
|
||||
|
||||
data class Status(
|
||||
@StringRes val statusText: Int,
|
||||
val percentProgress: Int = 0
|
||||
)
|
||||
sealed class Status {
|
||||
object Idle : Status()
|
||||
data class Progressing(
|
||||
@StringRes val statusText: Int,
|
||||
val percentProgress: Int = 0
|
||||
) : Status()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,11 +25,11 @@ import javax.inject.Inject
|
|||
@SessionScope
|
||||
class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgressService {
|
||||
|
||||
private var status = MutableLiveData<InitialSyncProgressService.Status>()
|
||||
private val status = MutableLiveData<InitialSyncProgressService.Status>()
|
||||
|
||||
private var rootTask: TaskInfo? = null
|
||||
|
||||
override fun getInitialSyncProgressStatus(): LiveData<InitialSyncProgressService.Status?> {
|
||||
override fun getInitialSyncProgressStatus(): LiveData<InitialSyncProgressService.Status> {
|
||||
return status
|
||||
}
|
||||
|
||||
|
@ -63,13 +63,13 @@ class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgr
|
|||
parent?.setProgress(endedTask.offset + (endedTask.totalProgress * endedTask.parentWeight).toInt())
|
||||
}
|
||||
if (endedTask?.parent == null) {
|
||||
status.postValue(null)
|
||||
status.postValue(InitialSyncProgressService.Status.Idle)
|
||||
}
|
||||
}
|
||||
|
||||
fun endAll() {
|
||||
rootTask = null
|
||||
status.postValue(null)
|
||||
status.postValue(InitialSyncProgressService.Status.Idle)
|
||||
}
|
||||
|
||||
private inner class TaskInfo(@StringRes var nameRes: Int,
|
||||
|
@ -102,9 +102,7 @@ class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgr
|
|||
it.setProgress(offset + parentProgress)
|
||||
} ?: run {
|
||||
Timber.v("--- ${leaf().nameRes}: $currentProgress")
|
||||
status.postValue(
|
||||
InitialSyncProgressService.Status(leaf().nameRes, currentProgress)
|
||||
)
|
||||
status.postValue(InitialSyncProgressService.Status.Progressing(leaf().nameRes, currentProgress))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,20 +19,16 @@ package im.vector.riotx.features.home
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.lifecycle.Observer
|
||||
import com.airbnb.mvrx.MvRx
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||
import im.vector.riotx.core.di.ScreenComponent
|
||||
|
@ -46,21 +42,28 @@ import im.vector.riotx.features.crypto.recover.BootstrapBottomSheet
|
|||
import im.vector.riotx.features.disclaimer.showDisclaimerDialog
|
||||
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
||||
import im.vector.riotx.features.popup.PopupAlertManager
|
||||
import im.vector.riotx.features.popup.VerificationVectorAlert
|
||||
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
|
||||
import im.vector.riotx.features.settings.VectorPreferences
|
||||
import im.vector.riotx.features.workers.signout.SignOutViewModel
|
||||
import im.vector.riotx.push.fcm.FcmHelper
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.activity_home.*
|
||||
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Parcelize
|
||||
data class HomeActivityArgs(
|
||||
val clearNotification: Boolean,
|
||||
val accountCreation: Boolean
|
||||
) : Parcelable
|
||||
|
||||
class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDetectorSharedViewModel.Factory {
|
||||
|
||||
private lateinit var sharedActionViewModel: HomeSharedActionViewModel
|
||||
|
||||
private val homeActivityViewModel: HomeActivityViewModel by viewModel()
|
||||
@Inject lateinit var viewModelFactory: HomeActivityViewModel.Factory
|
||||
|
||||
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||
@Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler
|
||||
|
@ -114,21 +117,33 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
|||
}
|
||||
.disposeOnDestroy()
|
||||
|
||||
if (intent.getBooleanExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION, false)) {
|
||||
val args = intent.getParcelableExtra<HomeActivityArgs>(MvRx.KEY_ARG)
|
||||
|
||||
if (args?.clearNotification == true) {
|
||||
notificationDrawerManager.clearAllEvents()
|
||||
intent.removeExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION)
|
||||
}
|
||||
if (intent.getBooleanExtra(EXTRA_ACCOUNT_CREATION, false)) {
|
||||
sharedActionViewModel.post(HomeActivitySharedAction.PromptForSecurityBootstrap)
|
||||
homeActivityViewModel.isAccountCreation = true
|
||||
intent.removeExtra(EXTRA_ACCOUNT_CREATION)
|
||||
}
|
||||
|
||||
activeSessionHolder.getSafeActiveSession()?.getInitialSyncProgressStatus()?.observe(this, Observer { status ->
|
||||
if (status == null) {
|
||||
homeActivityViewModel.subscribe(this) { renderState(it) }
|
||||
|
||||
/*
|
||||
// TODO Remove
|
||||
// Ask again if the app is relaunched
|
||||
if (!homeActivityViewModel.hasDisplayedCompleteSecurityPrompt
|
||||
&& activeSessionHolder.getSafeActiveSession()?.hasAlreadySynced() == true) {
|
||||
promptCompleteSecurityIfNeeded()
|
||||
}
|
||||
*/
|
||||
|
||||
shortcutsHandler.observeRoomsAndBuildShortcuts()
|
||||
.disposeOnDestroy()
|
||||
}
|
||||
|
||||
private fun renderState(state: HomeActivityViewState) {
|
||||
when (val status = state.initialSyncProgressServiceStatus) {
|
||||
is InitialSyncProgressService.Status.Idle -> {
|
||||
waiting_view.isVisible = false
|
||||
promptCompleteSecurityIfNeeded()
|
||||
} else {
|
||||
}
|
||||
is InitialSyncProgressService.Status.Progressing -> {
|
||||
homeActivityViewModel.hasDisplayedCompleteSecurityPrompt = false
|
||||
Timber.v("${getString(status.statusText)} ${status.percentProgress}")
|
||||
waiting_view.setOnClickListener {
|
||||
|
@ -146,18 +161,11 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
|||
}
|
||||
waiting_view.isVisible = true
|
||||
}
|
||||
})
|
||||
|
||||
// Ask again if the app is relaunched
|
||||
if (!homeActivityViewModel.hasDisplayedCompleteSecurityPrompt
|
||||
&& activeSessionHolder.getSafeActiveSession()?.hasAlreadySynced() == true) {
|
||||
promptCompleteSecurityIfNeeded()
|
||||
}
|
||||
|
||||
shortcutsHandler.observeRoomsAndBuildShortcuts()
|
||||
.disposeOnDestroy()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO Remove
|
||||
private fun promptCompleteSecurityIfNeeded() {
|
||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||
if (!session.hasAlreadySynced()) return
|
||||
|
@ -172,7 +180,10 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
|||
}
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO Remove
|
||||
/*
|
||||
private fun alertCompleteSecurity(session: Session) {
|
||||
val myCrossSigningKeys = session.cryptoService().crossSigningService()
|
||||
.getMyCrossSigningKeys()
|
||||
|
@ -204,7 +215,10 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// TODO Remove
|
||||
private fun promptSecurityEvent(session: Session, titleRes: Int, descRes: Int, action: ((VectorBaseActivity) -> Unit)) {
|
||||
homeActivityViewModel.hasDisplayedCompleteSecurityPrompt = true
|
||||
popupAlertManager.postVectorAlert(
|
||||
|
@ -225,12 +239,12 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
|||
}
|
||||
)
|
||||
}
|
||||
*/
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
if (intent?.hasExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION) == true) {
|
||||
if (intent?.getParcelableExtra<HomeActivityArgs>(MvRx.KEY_ARG)?.clearNotification == true) {
|
||||
notificationDrawerManager.clearAllEvents()
|
||||
intent.removeExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,14 +307,15 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val EXTRA_CLEAR_EXISTING_NOTIFICATION = "EXTRA_CLEAR_EXISTING_NOTIFICATION"
|
||||
private const val EXTRA_ACCOUNT_CREATION = "EXTRA_ACCOUNT_CREATION"
|
||||
|
||||
fun newIntent(context: Context, clearNotification: Boolean = false, accountCreation: Boolean = false): Intent {
|
||||
val args = HomeActivityArgs(
|
||||
clearNotification = clearNotification,
|
||||
accountCreation = accountCreation
|
||||
)
|
||||
|
||||
return Intent(context, HomeActivity::class.java)
|
||||
.apply {
|
||||
putExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION, clearNotification)
|
||||
putExtra(EXTRA_ACCOUNT_CREATION, accountCreation)
|
||||
putExtra(MvRx.KEY_ARG, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,5 +25,6 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
|
|||
object OpenDrawer : HomeActivitySharedAction()
|
||||
object CloseDrawer : HomeActivitySharedAction()
|
||||
object OpenGroup : HomeActivitySharedAction()
|
||||
// TODO Remove?
|
||||
object PromptForSecurityBootstrap : HomeActivitySharedAction()
|
||||
}
|
||||
|
|
|
@ -16,18 +16,87 @@
|
|||
|
||||
package im.vector.riotx.features.home
|
||||
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.MvRx
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
||||
import im.vector.matrix.rx.asObservable
|
||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||
import im.vector.riotx.core.platform.EmptyAction
|
||||
import im.vector.riotx.core.platform.EmptyViewEvents
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.features.login.ReAuthHelper
|
||||
import timber.log.Timber
|
||||
|
||||
data class EmptyState(
|
||||
val dummy: Boolean = false
|
||||
) : MvRxState
|
||||
class HomeActivityViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: HomeActivityViewState,
|
||||
@Assisted private val args: HomeActivityArgs,
|
||||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val reAuthHelper: ReAuthHelper
|
||||
) : VectorViewModel<HomeActivityViewState, EmptyAction, EmptyViewEvents>(initialState) {
|
||||
|
||||
class HomeActivityViewModel : VectorViewModel<EmptyState, EmptyAction, EmptyViewEvents>(EmptyState()) {
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: HomeActivityViewState, args: HomeActivityArgs): HomeActivityViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<HomeActivityViewModel, HomeActivityViewState> {
|
||||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: HomeActivityViewState): HomeActivityViewModel? {
|
||||
val activity: HomeActivity = viewModelContext.activity()
|
||||
val args: HomeActivityArgs? = activity.intent.getParcelableExtra(MvRx.KEY_ARG)
|
||||
return args?.let { activity.viewModelFactory.create(state, it) }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Remove?
|
||||
var hasDisplayedCompleteSecurityPrompt: Boolean = false
|
||||
var isAccountCreation: Boolean = false
|
||||
|
||||
init {
|
||||
observeInitialSync()
|
||||
mayBeInitializeCrossSigning()
|
||||
}
|
||||
|
||||
private fun observeInitialSync() {
|
||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||
|
||||
session.getInitialSyncProgressStatus()
|
||||
.asObservable()
|
||||
.subscribe { status ->
|
||||
setState {
|
||||
copy(
|
||||
initialSyncProgressServiceStatus = status
|
||||
)
|
||||
}
|
||||
}
|
||||
.disposeOnClear()
|
||||
}
|
||||
|
||||
private fun mayBeInitializeCrossSigning() {
|
||||
if (args.accountCreation) {
|
||||
val password = reAuthHelper.data ?: return Unit.also {
|
||||
Timber.w("No password to init cross signing")
|
||||
}
|
||||
|
||||
val session = activeSessionHolder.getSafeActiveSession() ?: return Unit.also {
|
||||
Timber.w("No session to init cross signing")
|
||||
}
|
||||
|
||||
// We do not use the viewModel context because we do not want to cancel this action
|
||||
Timber.d("Initialize cross signing")
|
||||
session.cryptoService().crossSigningService().initializeCrossSigning(
|
||||
authParams = UserPasswordAuth(
|
||||
session = null,
|
||||
user = session.myUserId,
|
||||
password = password
|
||||
)
|
||||
)
|
||||
// TODO Download keys?
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: EmptyAction) {
|
||||
// NA
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.home
|
||||
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
||||
|
||||
data class HomeActivityViewState(
|
||||
val initialSyncProgressServiceStatus: InitialSyncProgressService.Status = InitialSyncProgressService.Status.Idle
|
||||
) : MvRxState
|
Loading…
Reference in a new issue