Hilt: finish migration of latest view models

This commit is contained in:
ganfra 2021-10-21 20:17:49 +02:00
parent ac1e4e9e9c
commit d724504662
14 changed files with 133 additions and 143 deletions

View file

@ -28,11 +28,14 @@ import im.vector.app.features.contactsbook.ContactsBookViewModel
import im.vector.app.features.createdirect.CreateDirectRoomViewModel import im.vector.app.features.createdirect.CreateDirectRoomViewModel
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel import im.vector.app.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel
import im.vector.app.features.crypto.quads.SharedSecureStorageViewModel import im.vector.app.features.crypto.quads.SharedSecureStorageViewModel
import im.vector.app.features.crypto.recover.BootstrapSharedViewModel
import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel
import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodViewModel import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodViewModel
import im.vector.app.features.crypto.verification.emoji.VerificationEmojiCodeViewModel import im.vector.app.features.crypto.verification.emoji.VerificationEmojiCodeViewModel
import im.vector.app.features.devtools.RoomDevToolViewModel import im.vector.app.features.devtools.RoomDevToolViewModel
import im.vector.app.features.discovery.DiscoverySettingsViewModel import im.vector.app.features.discovery.DiscoverySettingsViewModel
import im.vector.app.features.discovery.change.SetIdentityServerViewModel import im.vector.app.features.discovery.change.SetIdentityServerViewModel
import im.vector.app.features.home.HomeActivityViewModel
import im.vector.app.features.home.HomeDetailViewModel import im.vector.app.features.home.HomeDetailViewModel
import im.vector.app.features.home.PromoteRestrictedViewModel import im.vector.app.features.home.PromoteRestrictedViewModel
import im.vector.app.features.home.UnknownDeviceDetectorSharedViewModel import im.vector.app.features.home.UnknownDeviceDetectorSharedViewModel
@ -60,6 +63,7 @@ import im.vector.app.features.roomdirectory.createroom.CreateRoomViewModel
import im.vector.app.features.roomdirectory.picker.RoomDirectoryPickerViewModel import im.vector.app.features.roomdirectory.picker.RoomDirectoryPickerViewModel
import im.vector.app.features.roomdirectory.roompreview.RoomPreviewViewModel import im.vector.app.features.roomdirectory.roompreview.RoomPreviewViewModel
import im.vector.app.features.roommemberprofile.RoomMemberProfileViewModel import im.vector.app.features.roommemberprofile.RoomMemberProfileViewModel
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheetViewModel
import im.vector.app.features.roomprofile.RoomProfileViewModel import im.vector.app.features.roomprofile.RoomProfileViewModel
import im.vector.app.features.roomprofile.alias.RoomAliasViewModel import im.vector.app.features.roomprofile.alias.RoomAliasViewModel
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetViewModel import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetViewModel
@ -72,6 +76,7 @@ import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRul
import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel
import im.vector.app.features.settings.account.deactivation.DeactivateAccountViewModel import im.vector.app.features.settings.account.deactivation.DeactivateAccountViewModel
import im.vector.app.features.settings.crosssigning.CrossSigningSettingsViewModel import im.vector.app.features.settings.crosssigning.CrossSigningSettingsViewModel
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheetViewModel
import im.vector.app.features.settings.devices.DevicesViewModel import im.vector.app.features.settings.devices.DevicesViewModel
import im.vector.app.features.settings.devtools.AccountDataViewModel import im.vector.app.features.settings.devtools.AccountDataViewModel
import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel
@ -512,4 +517,30 @@ interface MavericksViewModelModule {
@MavericksViewModelKey(HomeDetailViewModel::class) @MavericksViewModelKey(HomeDetailViewModel::class)
fun homeDetailViewModelFactory(factory: HomeDetailViewModel.Factory): MavericksAssistedViewModelFactory<*, *> fun homeDetailViewModelFactory(factory: HomeDetailViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DeviceVerificationInfoBottomSheetViewModel::class)
fun deviceVerificationInfoBottomSheetViewModelFactory(factory: DeviceVerificationInfoBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DeviceListBottomSheetViewModel::class)
fun deviceListBottomSheetViewModelFactory(factory: DeviceListBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(HomeActivityViewModel::class)
fun homeActivityViewModelFactory(factory: HomeActivityViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(BootstrapSharedViewModel::class)
fun bootstrapSharedViewModelFactory(factory: BootstrapSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VerificationBottomSheetViewModel::class)
fun verificationBottomSheetViewModelFactory(factory: VerificationBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
} }

View file

@ -57,9 +57,6 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetBoot
override val showExpanded = true override val showExpanded = true
@Inject
lateinit var bootstrapViewModelFactory: BootstrapSharedViewModel.Factory
private val viewModel by fragmentViewModel(BootstrapSharedViewModel::class) private val viewModel by fragmentViewModel(BootstrapSharedViewModel::class)
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetBootstrapBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetBootstrapBinding {

View file

@ -16,7 +16,6 @@
package im.vector.app.features.crypto.recover package im.vector.app.features.crypto.recover
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
@ -29,6 +28,8 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
@ -59,13 +60,11 @@ import kotlin.coroutines.resumeWithException
class BootstrapSharedViewModel @AssistedInject constructor( class BootstrapSharedViewModel @AssistedInject constructor(
@Assisted initialState: BootstrapViewState, @Assisted initialState: BootstrapViewState,
@Assisted val args: BootstrapBottomSheet.Args,
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val errorFormatter: ErrorFormatter, private val errorFormatter: ErrorFormatter,
private val session: Session, private val session: Session,
private val bootstrapTask: BootstrapCrossSigningTask, private val bootstrapTask: BootstrapCrossSigningTask,
private val migrationTask: BackupToQuadSMigrationTask, private val migrationTask: BackupToQuadSMigrationTask,
private val reAuthHelper: ReAuthHelper
) : VectorViewModel<BootstrapViewState, BootstrapActions, BootstrapViewEvents>(initialState) { ) : VectorViewModel<BootstrapViewState, BootstrapActions, BootstrapViewEvents>(initialState) {
private var doesKeyBackupExist: Boolean = false private var doesKeyBackupExist: Boolean = false
@ -73,10 +72,12 @@ class BootstrapSharedViewModel @AssistedInject constructor(
private val zxcvbn = Zxcvbn() private val zxcvbn = Zxcvbn()
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<BootstrapSharedViewModel, BootstrapViewState> {
fun create(initialState: BootstrapViewState, args: BootstrapBottomSheet.Args): BootstrapSharedViewModel override fun create(initialState: BootstrapViewState): BootstrapSharedViewModel
} }
companion object : MavericksViewModelFactory<BootstrapSharedViewModel, BootstrapViewState> by hiltMavericksViewModelFactory()
// private var _pendingSession: String? = null // private var _pendingSession: String? = null
var uiaContinuation: Continuation<UIABaseAuth>? = null var uiaContinuation: Continuation<UIABaseAuth>? = null
@ -84,7 +85,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
init { init {
when (args.setUpMode) { when (initialState.setupMode) {
SetupMode.PASSPHRASE_RESET, SetupMode.PASSPHRASE_RESET,
SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET, SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET,
SetupMode.HARD_RESET -> { SetupMode.HARD_RESET -> {
@ -410,7 +411,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
progressListener = progressListener, progressListener = progressListener,
passphrase = state.passphrase, passphrase = state.passphrase,
keySpec = state.migrationRecoveryKey?.let { extractCurveKeyFromRecoveryKey(it)?.let { RawBytesKeySpec(it) } }, keySpec = state.migrationRecoveryKey?.let { extractCurveKeyFromRecoveryKey(it)?.let { RawBytesKeySpec(it) } },
setupMode = args.setUpMode setupMode = state.setupMode
) )
) { bootstrapResult -> ) { bootstrapResult ->
when (bootstrapResult) { when (bootstrapResult) {
@ -516,7 +517,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
BootstrapStep.CheckingMigration -> Unit BootstrapStep.CheckingMigration -> Unit
is BootstrapStep.FirstForm -> { is BootstrapStep.FirstForm -> {
_viewEvents.post( _viewEvents.post(
when (args.setUpMode) { when (state.setupMode) {
SetupMode.CROSS_SIGNING_ONLY, SetupMode.CROSS_SIGNING_ONLY,
SetupMode.NORMAL -> BootstrapViewEvents.SkipBootstrap() SetupMode.NORMAL -> BootstrapViewEvents.SkipBootstrap()
else -> BootstrapViewEvents.Dismiss(success = false) else -> BootstrapViewEvents.Dismiss(success = false)
@ -547,18 +548,4 @@ class BootstrapSharedViewModel @AssistedInject constructor(
else -> stringProvider.getString(R.string.unexpected_error) else -> stringProvider.getString(R.string.unexpected_error)
} }
} }
// ======================================
// Companion, view model assisted creation
// ======================================
companion object : MavericksViewModelFactory<BootstrapSharedViewModel, BootstrapViewState> {
override fun create(viewModelContext: ViewModelContext, state: BootstrapViewState): BootstrapSharedViewModel? {
val fragment: BootstrapBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
val args: BootstrapBottomSheet.Args = fragment.arguments?.getParcelable(BootstrapBottomSheet.EXTRA_ARGS)
?: BootstrapBottomSheet.Args(SetupMode.CROSS_SIGNING_ONLY)
return fragment.bootstrapViewModelFactory.create(state, args)
}
}
} }

View file

@ -24,6 +24,7 @@ import im.vector.app.core.platform.WaitingViewData
import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
data class BootstrapViewState( data class BootstrapViewState(
val setupMode: SetupMode,
val step: BootstrapStep = BootstrapStep.CheckingMigration, val step: BootstrapStep = BootstrapStep.CheckingMigration,
val passphrase: String? = null, val passphrase: String? = null,
val migrationRecoveryKey: String? = null, val migrationRecoveryKey: String? = null,
@ -34,4 +35,8 @@ data class BootstrapViewState(
val recoveryKeyCreationInfo: SsssKeyCreationInfo? = null, val recoveryKeyCreationInfo: SsssKeyCreationInfo? = null,
val initializationWaitingViewData: WaitingViewData? = null, val initializationWaitingViewData: WaitingViewData? = null,
val recoverySaveFileProcess: Async<Unit> = Uninitialized val recoverySaveFileProcess: Async<Unit> = Uninitialized
) : MavericksState ) : MavericksState {
constructor(args: BootstrapBottomSheet.Args): this(setupMode = args.setUpMode)
}

View file

@ -77,9 +77,6 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetV
override val showExpanded = true override val showExpanded = true
@Inject
lateinit var verificationViewModelFactory: VerificationBottomSheetViewModel.Factory
@Inject @Inject
lateinit var avatarRenderer: AvatarRenderer lateinit var avatarRenderer: AvatarRenderer

View file

@ -15,20 +15,19 @@
*/ */
package im.vector.app.features.crypto.verification package im.vector.app.features.crypto.verification
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.Async import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.ViewModelContext
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
@ -61,15 +60,17 @@ import org.matrix.android.sdk.internal.util.awaitCallback
import timber.log.Timber import timber.log.Timber
data class VerificationBottomSheetViewState( data class VerificationBottomSheetViewState(
val otherUserId: String,
val verificationId: String?,
val roomId: String?,
// true when we display the loading and we wait for the other (incoming request)
val selfVerificationMode: Boolean,
val otherUserMxItem: MatrixItem? = null, val otherUserMxItem: MatrixItem? = null,
val roomId: String? = null,
val pendingRequest: Async<PendingVerificationRequest> = Uninitialized, val pendingRequest: Async<PendingVerificationRequest> = Uninitialized,
val pendingLocalId: String? = null, val pendingLocalId: String? = null,
val sasTransactionState: VerificationTxState? = null, val sasTransactionState: VerificationTxState? = null,
val qrTransactionState: VerificationTxState? = null, val qrTransactionState: VerificationTxState? = null,
val transactionId: String? = null, val transactionId: String? = null,
// true when we display the loading and we wait for the other (incoming request)
val selfVerificationMode: Boolean = false,
val verifiedFromPrivateKeys: Boolean = false, val verifiedFromPrivateKeys: Boolean = false,
val verifyingFrom4S: Boolean = false, val verifyingFrom4S: Boolean = false,
val isMe: Boolean = false, val isMe: Boolean = false,
@ -79,29 +80,41 @@ data class VerificationBottomSheetViewState(
val quadSContainsSecrets: Boolean = true, val quadSContainsSecrets: Boolean = true,
val quadSHasBeenReset: Boolean = false, val quadSHasBeenReset: Boolean = false,
val hasAnyOtherSession: Boolean = false val hasAnyOtherSession: Boolean = false
) : MavericksState ) : MavericksState {
constructor(args: VerificationBottomSheet.VerificationArgs) : this(
otherUserId = args.otherUserId,
verificationId = args.verificationId,
roomId = args.roomId,
selfVerificationMode = args.selfVerificationMode
)
}
class VerificationBottomSheetViewModel @AssistedInject constructor( class VerificationBottomSheetViewModel @AssistedInject constructor(
@Assisted initialState: VerificationBottomSheetViewState, @Assisted initialState: VerificationBottomSheetViewState,
@Assisted val args: VerificationBottomSheet.VerificationArgs,
private val session: Session, private val session: Session,
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider, private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider,
private val stringProvider: StringProvider) : private val stringProvider: StringProvider) :
VectorViewModel<VerificationBottomSheetViewState, VerificationAction, VerificationBottomSheetViewEvents>(initialState), VectorViewModel<VerificationBottomSheetViewState, VerificationAction, VerificationBottomSheetViewEvents>(initialState),
VerificationService.Listener { VerificationService.Listener {
@AssistedFactory
interface Factory : MavericksAssistedViewModelFactory<VerificationBottomSheetViewModel, VerificationBottomSheetViewState> {
override fun create(initialState: VerificationBottomSheetViewState): VerificationBottomSheetViewModel
}
companion object : MavericksViewModelFactory<VerificationBottomSheetViewModel, VerificationBottomSheetViewState> by hiltMavericksViewModelFactory()
init { init {
session.cryptoService().verificationService().addListener(this) session.cryptoService().verificationService().addListener(this)
val userItem = session.getUser(args.otherUserId) val userItem = session.getUser(initialState.otherUserId)
val selfVerificationMode = args.selfVerificationMode
var autoReady = false var autoReady = false
val pr = if (selfVerificationMode) { val pr = if (initialState.selfVerificationMode) {
// See if active tx for this user and take it // See if active tx for this user and take it
session.cryptoService().verificationService().getExistingVerificationRequests(args.otherUserId) session.cryptoService().verificationService().getExistingVerificationRequests(initialState.otherUserId)
.lastOrNull { !it.isFinished } .lastOrNull { !it.isFinished }
?.also { verificationRequest -> ?.also { verificationRequest ->
if (verificationRequest.isIncoming && !verificationRequest.isReady) { if (verificationRequest.isIncoming && !verificationRequest.isReady) {
@ -110,15 +123,15 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
} }
} }
} else { } else {
session.cryptoService().verificationService().getExistingVerificationRequest(args.otherUserId, args.verificationId) session.cryptoService().verificationService().getExistingVerificationRequest(initialState.otherUserId, initialState.verificationId)
} }
val sasTx = (pr?.transactionId ?: args.verificationId)?.let { val sasTx = (pr?.transactionId ?: initialState.verificationId)?.let {
session.cryptoService().verificationService().getExistingTransaction(args.otherUserId, it) as? SasVerificationTransaction session.cryptoService().verificationService().getExistingTransaction(initialState.otherUserId, it) as? SasVerificationTransaction
} }
val qrTx = (pr?.transactionId ?: args.verificationId)?.let { val qrTx = (pr?.transactionId ?: initialState.verificationId)?.let {
session.cryptoService().verificationService().getExistingTransaction(args.otherUserId, it) as? QrCodeVerificationTransaction session.cryptoService().verificationService().getExistingTransaction(initialState.otherUserId, it) as? QrCodeVerificationTransaction
} }
val hasAnyOtherSession = session.cryptoService() val hasAnyOtherSession = session.cryptoService()
@ -132,11 +145,9 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
otherUserMxItem = userItem?.toMatrixItem(), otherUserMxItem = userItem?.toMatrixItem(),
sasTransactionState = sasTx?.state, sasTransactionState = sasTx?.state,
qrTransactionState = qrTx?.state, qrTransactionState = qrTx?.state,
transactionId = pr?.transactionId ?: args.verificationId, transactionId = pr?.transactionId ?: initialState.verificationId,
pendingRequest = if (pr != null) Success(pr) else Uninitialized, pendingRequest = if (pr != null) Success(pr) else Uninitialized,
selfVerificationMode = selfVerificationMode, isMe = initialState.otherUserId == session.myUserId,
roomId = args.roomId,
isMe = args.otherUserId == session.myUserId,
currentDeviceCanCrossSign = session.cryptoService().crossSigningService().canCrossSign(), currentDeviceCanCrossSign = session.cryptoService().crossSigningService().canCrossSign(),
quadSContainsSecrets = session.sharedSecretStorageService.isRecoverySetup(), quadSContainsSecrets = session.sharedSecretStorageService.isRecoverySetup(),
hasAnyOtherSession = hasAnyOtherSession hasAnyOtherSession = hasAnyOtherSession
@ -159,12 +170,6 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
super.onCleared() super.onCleared()
} }
@AssistedFactory
interface Factory {
fun create(initialState: VerificationBottomSheetViewState,
args: VerificationBottomSheet.VerificationArgs): VerificationBottomSheetViewModel
}
fun queryCancel() = withState { state -> fun queryCancel() = withState { state ->
if (state.userThinkItsNotHim) { if (state.userThinkItsNotHim) {
setState { setState {
@ -223,16 +228,6 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
_viewEvents.post(VerificationBottomSheetViewEvents.GoToSettings) _viewEvents.post(VerificationBottomSheetViewEvents.GoToSettings)
} }
companion object : MavericksViewModelFactory<VerificationBottomSheetViewModel, VerificationBottomSheetViewState> {
override fun create(viewModelContext: ViewModelContext, state: VerificationBottomSheetViewState): VerificationBottomSheetViewModel? {
val fragment: VerificationBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
val args: VerificationBottomSheet.VerificationArgs = viewModelContext.args()
return fragment.verificationViewModelFactory.create(state, args)
}
}
override fun handle(action: VerificationAction) = withState { state -> override fun handle(action: VerificationAction) = withState { state ->
val otherUserId = state.otherUserMxItem?.id ?: return@withState val otherUserId = state.otherUserMxItem?.id ?: return@withState
val roomId = state.roomId val roomId = state.roomId
@ -542,7 +537,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
state.pendingRequest.invoke()?.transactionId == pr.transactionId) { state.pendingRequest.invoke()?.transactionId == pr.transactionId) {
setState { setState {
copy( copy(
transactionId = args.verificationId ?: pr.transactionId, transactionId = state.verificationId ?: pr.transactionId,
pendingRequest = Success(pr) pendingRequest = Success(pr)
) )
} }

View file

@ -103,7 +103,6 @@ class HomeActivity :
private lateinit var sharedActionViewModel: HomeSharedActionViewModel private lateinit var sharedActionViewModel: HomeSharedActionViewModel
private val homeActivityViewModel: HomeActivityViewModel by viewModel() private val homeActivityViewModel: HomeActivityViewModel by viewModel()
@Inject lateinit var viewModelFactory: HomeActivityViewModel.Factory
private val serverBackupStatusViewModel: ServerBackupStatusViewModel by viewModel() private val serverBackupStatusViewModel: ServerBackupStatusViewModel by viewModel()
private val promoteRestrictedViewModel: PromoteRestrictedViewModel by viewModel() private val promoteRestrictedViewModel: PromoteRestrictedViewModel by viewModel()

View file

@ -17,14 +17,13 @@
package im.vector.app.features.home package im.vector.app.features.home
import androidx.lifecycle.asFlow import androidx.lifecycle.asFlow
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.login.ReAuthHelper import im.vector.app.features.login.ReAuthHelper
@ -58,26 +57,17 @@ import kotlin.coroutines.resumeWithException
class HomeActivityViewModel @AssistedInject constructor( class HomeActivityViewModel @AssistedInject constructor(
@Assisted initialState: HomeActivityViewState, @Assisted initialState: HomeActivityViewState,
@Assisted private val args: HomeActivityArgs,
private val activeSessionHolder: ActiveSessionHolder, private val activeSessionHolder: ActiveSessionHolder,
private val reAuthHelper: ReAuthHelper, private val reAuthHelper: ReAuthHelper,
private val vectorPreferences: VectorPreferences private val vectorPreferences: VectorPreferences
) : VectorViewModel<HomeActivityViewState, HomeActivityViewActions, HomeActivityViewEvents>(initialState) { ) : VectorViewModel<HomeActivityViewState, HomeActivityViewActions, HomeActivityViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<HomeActivityViewModel, HomeActivityViewState> {
fun create(initialState: HomeActivityViewState, args: HomeActivityArgs): HomeActivityViewModel override fun create(initialState: HomeActivityViewState): HomeActivityViewModel
} }
companion object : MavericksViewModelFactory<HomeActivityViewModel, HomeActivityViewState> { companion object : MavericksViewModelFactory<HomeActivityViewModel, HomeActivityViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: HomeActivityViewState): HomeActivityViewModel? {
val activity: HomeActivity = viewModelContext.activity()
val args: HomeActivityArgs? = activity.intent.getParcelableExtra(Mavericks.KEY_ARG)
return activity.viewModelFactory.create(state, args ?: HomeActivityArgs(clearNotification = false, accountCreation = false))
}
}
private var checkBootstrap = false private var checkBootstrap = false
private var onceTrusted = false private var onceTrusted = false

View file

@ -147,14 +147,16 @@ class RoomDetailViewModel @AssistedInject constructor(
fun create(initialState: RoomDetailViewState): RoomDetailViewModel fun create(initialState: RoomDetailViewState): RoomDetailViewModel
} }
/**
* Can't use the hiltMaverick here because some dependencies are injected here and in fragment but they don't share the graph.
*/
companion object : MavericksViewModelFactory<RoomDetailViewModel, RoomDetailViewState> { companion object : MavericksViewModelFactory<RoomDetailViewModel, RoomDetailViewState> {
const val PAGINATION_COUNT = 50 const val PAGINATION_COUNT = 50
@JvmStatic @JvmStatic
override fun create(viewModelContext: ViewModelContext, state: RoomDetailViewState): RoomDetailViewModel? { override fun create(viewModelContext: ViewModelContext, state: RoomDetailViewState): RoomDetailViewModel {
val fragment: RoomDetailFragment = (viewModelContext as FragmentViewModelContext).fragment() val fragment: RoomDetailFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.roomDetailViewModelFactory.create(state) return fragment.roomDetailViewModelFactory.create(state)
} }
} }

View file

@ -29,14 +29,12 @@ import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.commitTransaction
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetWithFragmentsBinding import im.vector.app.databinding.BottomSheetWithFragmentsBinding
import im.vector.app.features.crypto.verification.VerificationBottomSheet import im.vector.app.features.crypto.verification.VerificationBottomSheet
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import javax.inject.Inject
import kotlin.reflect.KClass import kotlin.reflect.KClass
@AndroidEntryPoint @AndroidEntryPoint
@ -49,8 +47,6 @@ class DeviceListBottomSheet :
private val viewModel: DeviceListBottomSheetViewModel by fragmentViewModel(DeviceListBottomSheetViewModel::class) private val viewModel: DeviceListBottomSheetViewModel by fragmentViewModel(DeviceListBottomSheetViewModel::class)
@Inject lateinit var viewModelFactory: DeviceListBottomSheetViewModel.Factory
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel.observeViewEvents { viewModel.observeViewEvents {

View file

@ -17,7 +17,6 @@
package im.vector.app.features.roommemberprofile.devices package im.vector.app.features.roommemberprofile.devices
import com.airbnb.mvrx.Async import com.airbnb.mvrx.Async
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
@ -26,7 +25,9 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import dagger.hilt.EntryPoints import dagger.hilt.EntryPoints
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.SingletonEntryPoint import im.vector.app.core.di.SingletonEntryPoint
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
@ -38,6 +39,8 @@ import org.matrix.android.sdk.flow.flow
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
data class DeviceListViewState( data class DeviceListViewState(
val userId: String,
val allowDeviceAction: Boolean,
val userItem: MatrixItem? = null, val userItem: MatrixItem? = null,
val isMine: Boolean = false, val isMine: Boolean = false,
val memberCrossSigningKey: MXCrossSigningInfo? = null, val memberCrossSigningKey: MXCrossSigningInfo? = null,
@ -46,24 +49,41 @@ data class DeviceListViewState(
) : MavericksState ) : MavericksState
class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted private val initialState: DeviceListViewState, class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted private val initialState: DeviceListViewState,
@Assisted private val args: DeviceListBottomSheet.Args,
private val session: Session) : private val session: Session) :
VectorViewModel<DeviceListViewState, DeviceListAction, DeviceListBottomSheetViewEvents>(initialState) { VectorViewModel<DeviceListViewState, DeviceListAction, DeviceListBottomSheetViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<DeviceListBottomSheetViewModel, DeviceListViewState> {
fun create(initialState: DeviceListViewState, args: DeviceListBottomSheet.Args): DeviceListBottomSheetViewModel override fun create(initialState: DeviceListViewState): DeviceListBottomSheetViewModel
}
companion object : MavericksViewModelFactory<DeviceListBottomSheetViewModel, DeviceListViewState> by hiltMavericksViewModelFactory() {
override fun initialState(viewModelContext: ViewModelContext): DeviceListViewState? {
val args = viewModelContext.args<DeviceListBottomSheet.Args>()
val userId = args.userId
val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession()
return session.getUser(userId)?.toMatrixItem()?.let {
DeviceListViewState(
userId = userId,
allowDeviceAction = args.allowDeviceAction,
userItem = it,
isMine = userId == session.myUserId
)
} ?: return super.initialState(viewModelContext)
}
} }
init { init {
session.flow().liveUserCryptoDevices(args.userId)
session.flow().liveUserCryptoDevices(initialState.userId)
.execute { .execute {
copy(cryptoDevices = it).also { copy(cryptoDevices = it).also {
refreshSelectedId() refreshSelectedId()
} }
} }
session.flow().liveCrossSigningInfo(args.userId) session.flow().liveCrossSigningInfo(initialState.userId)
.execute { .execute {
copy(memberCrossSigningKey = it.invoke()?.getOrNull()) copy(memberCrossSigningKey = it.invoke()?.getOrNull())
} }
@ -90,7 +110,7 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva
} }
private fun selectDevice(action: DeviceListAction.SelectDevice) { private fun selectDevice(action: DeviceListAction.SelectDevice) {
if (!args.allowDeviceAction) return if (!initialState.allowDeviceAction) return
setState { setState {
copy(selectedDevice = action.device) copy(selectedDevice = action.device)
} }
@ -103,29 +123,9 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva
} }
private fun manuallyVerify(action: DeviceListAction.ManuallyVerify) { private fun manuallyVerify(action: DeviceListAction.ManuallyVerify) {
if (!args.allowDeviceAction) return if (!initialState.allowDeviceAction) return
session.cryptoService().verificationService().beginKeyVerification(VerificationMethod.SAS, args.userId, action.deviceId, null)?.let { txID -> session.cryptoService().verificationService().beginKeyVerification(VerificationMethod.SAS, initialState.userId, action.deviceId, null)?.let { txID ->
_viewEvents.post(DeviceListBottomSheetViewEvents.Verify(args.userId, txID)) _viewEvents.post(DeviceListBottomSheetViewEvents.Verify(initialState.userId, txID))
}
}
companion object : MavericksViewModelFactory<DeviceListBottomSheetViewModel, DeviceListViewState> {
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: DeviceListViewState): DeviceListBottomSheetViewModel? {
val fragment: DeviceListBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
val args = viewModelContext.args<DeviceListBottomSheet.Args>()
return fragment.viewModelFactory.create(state, args)
}
override fun initialState(viewModelContext: ViewModelContext): DeviceListViewState? {
val userId = viewModelContext.args<DeviceListBottomSheet.Args>().userId
val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession()
return session.getUser(userId)?.toMatrixItem()?.let {
DeviceListViewState(
userItem = it,
isMine = userId == session.myUserId
)
} ?: return super.initialState(viewModelContext)
} }
} }
} }

View file

@ -49,7 +49,6 @@ class DeviceVerificationInfoBottomSheet :
private val sharedViewModel: DevicesViewModel by parentFragmentViewModel(DevicesViewModel::class) private val sharedViewModel: DevicesViewModel by parentFragmentViewModel(DevicesViewModel::class)
@Inject lateinit var deviceVerificationInfoViewModelFactory: DeviceVerificationInfoBottomSheetViewModel.Factory
@Inject lateinit var controller: DeviceVerificationInfoBottomSheetController @Inject lateinit var controller: DeviceVerificationInfoBottomSheetController
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetGenericListWithTitleBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetGenericListWithTitleBinding {

View file

@ -15,13 +15,13 @@
*/ */
package im.vector.app.features.settings.devices package im.vector.app.features.settings.devices
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
@ -31,15 +31,16 @@ import org.matrix.android.sdk.flow.flow
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@Assisted initialState: DeviceVerificationInfoBottomSheetViewState, class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@Assisted initialState: DeviceVerificationInfoBottomSheetViewState,
@Assisted val deviceId: String,
val session: Session val session: Session
) : VectorViewModel<DeviceVerificationInfoBottomSheetViewState, EmptyAction, EmptyViewEvents>(initialState) { ) : VectorViewModel<DeviceVerificationInfoBottomSheetViewState, EmptyAction, EmptyViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory: MavericksAssistedViewModelFactory<DeviceVerificationInfoBottomSheetViewModel,DeviceVerificationInfoBottomSheetViewState> {
fun create(initialState: DeviceVerificationInfoBottomSheetViewState, deviceId: String): DeviceVerificationInfoBottomSheetViewModel override fun create(initialState: DeviceVerificationInfoBottomSheetViewState): DeviceVerificationInfoBottomSheetViewModel
} }
companion object : MavericksViewModelFactory<DeviceVerificationInfoBottomSheetViewModel, DeviceVerificationInfoBottomSheetViewState> by hiltMavericksViewModelFactory()
init { init {
setState { setState {
@ -59,7 +60,7 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As
session.flow().liveUserCryptoDevices(session.myUserId) session.flow().liveUserCryptoDevices(session.myUserId)
.map { list -> .map { list ->
list.firstOrNull { it.deviceId == deviceId } list.firstOrNull { it.deviceId == initialState.deviceId }
} }
.execute { .execute {
copy( copy(
@ -82,24 +83,13 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As
session.flow().liveMyDevicesInfo() session.flow().liveMyDevicesInfo()
.map { devices -> .map { devices ->
devices.firstOrNull { it.deviceId == deviceId } ?: DeviceInfo(deviceId = deviceId) devices.firstOrNull { it.deviceId == initialState.deviceId } ?: DeviceInfo(deviceId = initialState.deviceId)
} }
.execute { .execute {
copy(deviceInfo = it) copy(deviceInfo = it)
} }
} }
companion object : MavericksViewModelFactory<DeviceVerificationInfoBottomSheetViewModel, DeviceVerificationInfoBottomSheetViewState> {
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: DeviceVerificationInfoBottomSheetViewState):
DeviceVerificationInfoBottomSheetViewModel? {
val fragment: DeviceVerificationInfoBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
val args = viewModelContext.args<DeviceVerificationInfoArgs>()
return fragment.deviceVerificationInfoViewModelFactory.create(state, args.deviceId)
}
}
override fun handle(action: EmptyAction) { override fun handle(action: EmptyAction) {
} }
} }

View file

@ -23,6 +23,7 @@ import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
data class DeviceVerificationInfoBottomSheetViewState( data class DeviceVerificationInfoBottomSheetViewState(
val deviceId: String,
val cryptoDeviceInfo: Async<CryptoDeviceInfo?> = Uninitialized, val cryptoDeviceInfo: Async<CryptoDeviceInfo?> = Uninitialized,
val deviceInfo: Async<DeviceInfo> = Uninitialized, val deviceInfo: Async<DeviceInfo> = Uninitialized,
val hasAccountCrossSigning: Boolean = false, val hasAccountCrossSigning: Boolean = false,
@ -32,6 +33,7 @@ data class DeviceVerificationInfoBottomSheetViewState(
val isRecoverySetup: Boolean = false val isRecoverySetup: Boolean = false
) : MavericksState { ) : MavericksState {
val canVerifySession: Boolean constructor(args: DeviceVerificationInfoArgs) : this(deviceId = args.deviceId)
get() = hasOtherSessions || isRecoverySetup
val canVerifySession = hasOtherSessions || isRecoverySetup
} }