Merge pull request #4312 from vector-im/feature/fga/hilt_app_migration

Migrate App DI framework to Hilt
This commit is contained in:
Benoit Marty 2021-10-25 12:41:02 +02:00 committed by GitHub
commit 3354cd1760
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
261 changed files with 1864 additions and 2864 deletions

View File

@ -17,6 +17,7 @@ buildscript {
// https://developer.android.com/studio/releases/gradle-plugin // https://developer.android.com/studio/releases/gradle-plugin
classpath libs.gradle.gradlePlugin classpath libs.gradle.gradlePlugin
classpath libs.gradle.kotlinPlugin classpath libs.gradle.kotlinPlugin
classpath libs.gradle.hiltPlugin
classpath 'com.google.gms:google-services:4.3.10' classpath 'com.google.gms:google-services:4.3.10'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.4' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.4'

1
changelog.d/3888.misc Normal file
View File

@ -0,0 +1 @@
Migrate app DI framework to Hilt

View File

@ -34,7 +34,9 @@ def androidxTest = "1.4.0"
ext.libs = [ ext.libs = [
gradle : [ gradle : [
'gradlePlugin' : "com.android.tools.build:gradle:$gradle", 'gradlePlugin' : "com.android.tools.build:gradle:$gradle",
'kotlinPlugin' : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin" 'kotlinPlugin' : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin",
'hiltPlugin' : "com.google.dagger:hilt-android-gradle-plugin:$dagger"
], ],
jetbrains : [ jetbrains : [
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines", 'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
@ -72,7 +74,9 @@ ext.libs = [
], ],
dagger : [ dagger : [
'dagger' : "com.google.dagger:dagger:$dagger", 'dagger' : "com.google.dagger:dagger:$dagger",
'daggerCompiler' : "com.google.dagger:dagger-compiler:$dagger" 'daggerCompiler' : "com.google.dagger:dagger-compiler:$dagger",
'hilt' : "com.google.dagger:hilt-android:$dagger",
'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger"
], ],
squareup : [ squareup : [
'moshi' : "com.squareup.moshi:moshi-adapters:$moshi", 'moshi' : "com.squareup.moshi:moshi-adapters:$moshi",

33
docs/hilt_migration.md Normal file
View File

@ -0,0 +1,33 @@
Useful links:
- https://dagger.dev/hilt/migration-guide
- https://dagger.dev/hilt/quick-start
Hilt is built on top of Dagger 2 and simplify usage by removing needs to create components manually.
When you create a new feature, you should have the following:
Annotate your Activity with @AndroidEntryPoint
If you have a BottomSheetFragment => Annotate it with @AndroidEntryPoint
Otherwise => Add your Fragment to the FragmentModule
Add your ViewModel.Factory to the MavericksViewModelModule
Makes sure your ViewModel as the following code:
```
@AssistedFactory
interface Factory: MavericksAssistedViewModelFactory<MyViewModel, MyViewState> {
override fun create(initialState: MyViewState): MyViewModel
}
companion object : MavericksViewModelFactory<MyViewModel, MyViewState> by hiltMavericksViewModelFactory()
```
## Some remarks
@MavericksViewModelScope dependencies can't be injected inside Fragments/Activities
You can only inject @Singleton, @MavericksViewModelScope or unscoped dependencies inside Maverick ViewModels
You can access some specific dependencies from Singleton component by using
```
context.singletonEntryPoint()
```
Be aware that only the app has been migrated to Hilt and not the SDK.

View File

@ -6,6 +6,7 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'placeholder-resolver' apply plugin: 'placeholder-resolver'
apply plugin: 'dagger.hilt.android.plugin'
kapt { kapt {
correctErrorTypes = true correctErrorTypes = true
@ -456,8 +457,8 @@ dependencies {
implementation 'nl.dionsegijn:konfetti:1.3.2' implementation 'nl.dionsegijn:konfetti:1.3.2'
implementation 'com.github.jetradarmobile:android-snowfall:1.2.1' implementation 'com.github.jetradarmobile:android-snowfall:1.2.1'
// DI // DI
implementation libs.dagger.dagger implementation libs.dagger.hilt
kapt libs.dagger.daggerCompiler kapt libs.dagger.hiltCompiler
// gplay flavor only // gplay flavor only
gplayImplementation('com.google.firebase:firebase-messaging:22.0.0') { gplayImplementation('com.google.firebase:firebase-messaging:22.0.0') {

View File

@ -24,9 +24,9 @@ import android.os.Build
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.Person import androidx.core.app.Person
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
@ -50,6 +50,7 @@ import org.matrix.android.sdk.internal.crypto.verification.qrcode.toQrCodeData
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint
class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() { class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() {
override fun getBinding() = ActivityDebugMenuBinding.inflate(layoutInflater) override fun getBinding() = ActivityDebugMenuBinding.inflate(layoutInflater)
@ -57,10 +58,6 @@ class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() {
@Inject @Inject
lateinit var activeSessionHolder: ActiveSessionHolder lateinit var activeSessionHolder: ActiveSessionHolder
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
private lateinit var buffer: ByteArray private lateinit var buffer: ByteArray
override fun initUiAndData() { override fun initUiAndData() {

View File

@ -18,15 +18,15 @@ package im.vector.app.fdroid.features.settings.troubleshoot
import android.content.Intent import android.content.Intent
import android.net.ConnectivityManager import android.net.ConnectivityManager
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.net.ConnectivityManagerCompat import androidx.core.net.ConnectivityManagerCompat
import androidx.fragment.app.FragmentActivity
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.features.settings.troubleshoot.TroubleshootTest import im.vector.app.features.settings.troubleshoot.TroubleshootTest
import javax.inject.Inject import javax.inject.Inject
class TestBackgroundRestrictions @Inject constructor(private val context: AppCompatActivity, class TestBackgroundRestrictions @Inject constructor(private val context: FragmentActivity,
private val stringProvider: StringProvider) : private val stringProvider: StringProvider) :
TroubleshootTest(R.string.settings_troubleshoot_test_bg_restricted_title) { TroubleshootTest(R.string.settings_troubleshoot_test_bg_restricted_title) {

View File

@ -17,7 +17,7 @@ package im.vector.app.fdroid.features.settings.troubleshoot
import android.content.Intent import android.content.Intent
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.isIgnoringBatteryOptimizations import im.vector.app.core.utils.isIgnoringBatteryOptimizations
@ -26,7 +26,7 @@ import im.vector.app.features.settings.troubleshoot.TroubleshootTest
import javax.inject.Inject import javax.inject.Inject
class TestBatteryOptimization @Inject constructor( class TestBatteryOptimization @Inject constructor(
private val context: AppCompatActivity, private val context: FragmentActivity,
private val stringProvider: StringProvider private val stringProvider: StringProvider
) : TroubleshootTest(R.string.settings_troubleshoot_test_battery_title) { ) : TroubleshootTest(R.string.settings_troubleshoot_test_battery_title) {

View File

@ -24,7 +24,7 @@ import android.content.Intent
import android.os.Build import android.os.Build
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import im.vector.app.core.di.HasVectorInjector import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.services.VectorSyncService import im.vector.app.core.services.VectorSyncService
import org.matrix.android.sdk.internal.session.sync.job.SyncService import org.matrix.android.sdk.internal.session.sync.job.SyncService
import timber.log.Timber import timber.log.Timber
@ -33,9 +33,8 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
Timber.d("## Sync: AlarmSyncBroadcastReceiver received intent") Timber.d("## Sync: AlarmSyncBroadcastReceiver received intent")
val vectorPreferences = (context.applicationContext as? HasVectorInjector) val vectorPreferences = context.singletonEntryPoint()
?.injector() .takeIf { it.activeSessionHolder().getSafeActiveSession() != null }
?.takeIf { it.activeSessionHolder().getSafeActiveSession() != null }
?.vectorPreferences() ?.vectorPreferences()
?: return Unit.also { Timber.v("No active session, so don't launch sync service.") } ?: return Unit.also { Timber.v("No active session, so don't launch sync service.") }

View File

@ -20,8 +20,7 @@ package im.vector.app.fdroid.receiver
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import im.vector.app.core.di.HasVectorInjector import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.extensions.vectorComponent
import im.vector.app.fdroid.BackgroundSyncStarter import im.vector.app.fdroid.BackgroundSyncStarter
import timber.log.Timber import timber.log.Timber
@ -29,13 +28,11 @@ class OnApplicationUpgradeOrRebootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
Timber.v("## onReceive() ${intent.action}") Timber.v("## onReceive() ${intent.action}")
val appContext = context.applicationContext val singletonEntryPoint = context.singletonEntryPoint()
if (appContext is HasVectorInjector) {
BackgroundSyncStarter.start( BackgroundSyncStarter.start(
context, context,
appContext.vectorComponent().vectorPreferences(), singletonEntryPoint.vectorPreferences(),
appContext.injector().activeSessionHolder() singletonEntryPoint.activeSessionHolder()
) )
} }
}
} }

View File

@ -17,7 +17,7 @@ package im.vector.app.gplay.features.settings.troubleshoot
import android.content.Intent import android.content.Intent
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import com.google.firebase.messaging.FirebaseMessaging import com.google.firebase.messaging.FirebaseMessaging
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
@ -30,7 +30,7 @@ import javax.inject.Inject
/* /*
* Test that app can successfully retrieve a token via firebase * Test that app can successfully retrieve a token via firebase
*/ */
class TestFirebaseToken @Inject constructor(private val context: AppCompatActivity, class TestFirebaseToken @Inject constructor(private val context: FragmentActivity,
private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) { private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) {
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) { override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {

View File

@ -17,7 +17,7 @@ package im.vector.app.gplay.features.settings.troubleshoot
import android.content.Intent import android.content.Intent
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.common.GoogleApiAvailability
import im.vector.app.R import im.vector.app.R
@ -29,7 +29,7 @@ import javax.inject.Inject
/* /*
* Check that the play services APK is available an up-to-date. If needed provide quick fix to install it. * Check that the play services APK is available an up-to-date. If needed provide quick fix to install it.
*/ */
class TestPlayServices @Inject constructor(private val context: AppCompatActivity, class TestPlayServices @Inject constructor(private val context: FragmentActivity,
private val stringProvider: StringProvider) : private val stringProvider: StringProvider) :
TroubleshootTest(R.string.settings_troubleshoot_test_play_services_title) { TroubleshootTest(R.string.settings_troubleshoot_test_play_services_title) {

View File

@ -17,7 +17,7 @@ package im.vector.app.gplay.features.settings.troubleshoot
import android.content.Intent import android.content.Intent
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
@ -36,7 +36,7 @@ import javax.inject.Inject
/** /**
* Test Push by asking the Push Gateway to send a Push back * Test Push by asking the Push Gateway to send a Push back
*/ */
class TestPushFromPushGateway @Inject constructor(private val context: AppCompatActivity, class TestPushFromPushGateway @Inject constructor(private val context: FragmentActivity,
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val errorFormatter: ErrorFormatter, private val errorFormatter: ErrorFormatter,
private val pushersManager: PushersManager, private val pushersManager: PushersManager,

View File

@ -17,7 +17,7 @@ package im.vector.app.gplay.features.settings.troubleshoot
import android.content.Intent import android.content.Intent
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.work.WorkInfo import androidx.work.WorkInfo
import androidx.work.WorkManager import androidx.work.WorkManager
@ -33,7 +33,7 @@ import javax.inject.Inject
/** /**
* Force registration of the token to HomeServer * Force registration of the token to HomeServer
*/ */
class TestTokenRegistration @Inject constructor(private val context: AppCompatActivity, class TestTokenRegistration @Inject constructor(private val context: FragmentActivity,
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val pushersManager: PushersManager, private val pushersManager: PushersManager,
private val activeSessionHolder: ActiveSessionHolder) : private val activeSessionHolder: ActiveSessionHolder) :

View File

@ -27,10 +27,10 @@ import androidx.lifecycle.ProcessLifecycleOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage import com.google.firebase.messaging.RemoteMessage
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.BuildConfig import im.vector.app.BuildConfig
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.vectorComponent
import im.vector.app.core.network.WifiDetector import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.PushersManager import im.vector.app.core.pushers.PushersManager
import im.vector.app.features.badge.BadgeProxy import im.vector.app.features.badge.BadgeProxy
@ -52,21 +52,23 @@ import org.matrix.android.sdk.api.pushrules.Action
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
private val loggerTag = LoggerTag("Push", LoggerTag.SYNC) private val loggerTag = LoggerTag("Push", LoggerTag.SYNC)
/** /**
* Class extending FirebaseMessagingService. * Class extending FirebaseMessagingService.
*/ */
@AndroidEntryPoint
class VectorFirebaseMessagingService : FirebaseMessagingService() { class VectorFirebaseMessagingService : FirebaseMessagingService() {
private lateinit var notificationDrawerManager: NotificationDrawerManager @Inject lateinit var notificationDrawerManager: NotificationDrawerManager
private lateinit var notifiableEventResolver: NotifiableEventResolver @Inject lateinit var notifiableEventResolver: NotifiableEventResolver
private lateinit var pusherManager: PushersManager @Inject lateinit var pusherManager: PushersManager
private lateinit var activeSessionHolder: ActiveSessionHolder @Inject lateinit var activeSessionHolder: ActiveSessionHolder
private lateinit var vectorPreferences: VectorPreferences @Inject lateinit var vectorPreferences: VectorPreferences
private lateinit var vectorDataStore: VectorDataStore @Inject lateinit var vectorDataStore: VectorDataStore
private lateinit var wifiDetector: WifiDetector @Inject lateinit var wifiDetector: WifiDetector
private val coroutineScope = CoroutineScope(SupervisorJob()) private val coroutineScope = CoroutineScope(SupervisorJob())
@ -75,19 +77,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
Handler(Looper.getMainLooper()) Handler(Looper.getMainLooper())
} }
override fun onCreate() {
super.onCreate()
with(vectorComponent()) {
notificationDrawerManager = notificationDrawerManager()
notifiableEventResolver = notifiableEventResolver()
pusherManager = pusherManager()
activeSessionHolder = activeSessionHolder()
vectorPreferences = vectorPreferences()
vectorDataStore = vectorDataStore()
wifiDetector = wifiDetector()
}
}
/** /**
* Called when message is received. * Called when message is received.
* *

View File

@ -39,10 +39,8 @@ import com.facebook.stetho.Stetho
import com.gabrielittner.threetenbp.LazyThreeTen import com.gabrielittner.threetenbp.LazyThreeTen
import com.vanniktech.emoji.EmojiManager import com.vanniktech.emoji.EmojiManager
import com.vanniktech.emoji.google.GoogleEmojiProvider import com.vanniktech.emoji.google.GoogleEmojiProvider
import dagger.hilt.android.HiltAndroidApp
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.DaggerVectorComponent
import im.vector.app.core.di.HasVectorInjector
import im.vector.app.core.di.VectorComponent
import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.extensions.configureAndStart
import im.vector.app.core.extensions.startSyncing import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.rx.RxConfig import im.vector.app.core.rx.RxConfig
@ -55,6 +53,7 @@ import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.pin.PinLocker import im.vector.app.features.pin.PinLocker
import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.rageshake.VectorFileLogger
import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider
import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorLocale
@ -75,9 +74,9 @@ import java.util.concurrent.Executors
import javax.inject.Inject import javax.inject.Inject
import androidx.work.Configuration as WorkConfiguration import androidx.work.Configuration as WorkConfiguration
@HiltAndroidApp
class VectorApplication : class VectorApplication :
Application(), Application(),
HasVectorInjector,
MatrixConfiguration.Provider, MatrixConfiguration.Provider,
WorkConfiguration.Provider { WorkConfiguration.Provider {
@ -99,8 +98,7 @@ class VectorApplication :
@Inject lateinit var pinLocker: PinLocker @Inject lateinit var pinLocker: PinLocker
@Inject lateinit var callManager: WebRtcCallManager @Inject lateinit var callManager: WebRtcCallManager
@Inject lateinit var invitesAcceptor: InvitesAcceptor @Inject lateinit var invitesAcceptor: InvitesAcceptor
@Inject lateinit var vectorFileLogger: VectorFileLogger
lateinit var vectorComponent: VectorComponent
// font thread handler // font thread handler
private var fontThreadHandler: Handler? = null private var fontThreadHandler: Handler? = null
@ -118,8 +116,6 @@ class VectorApplication :
enableStrictModeIfNeeded() enableStrictModeIfNeeded()
super.onCreate() super.onCreate()
appContext = this appContext = this
vectorComponent = DaggerVectorComponent.factory().create(this)
vectorComponent.inject(this)
invitesAcceptor.initialize() invitesAcceptor.initialize()
vectorUncaughtExceptionHandler.activate(this) vectorUncaughtExceptionHandler.activate(this)
rxConfig.setupRxPlugin() rxConfig.setupRxPlugin()
@ -132,7 +128,7 @@ class VectorApplication :
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree()) Timber.plant(Timber.DebugTree())
} }
Timber.plant(vectorComponent.vectorFileLogger()) Timber.plant(vectorFileLogger)
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Stetho.initializeWithDefaults(this) Stetho.initializeWithDefaults(this)
@ -236,10 +232,6 @@ class VectorApplication :
.build() .build()
} }
override fun injector(): VectorComponent {
return vectorComponent
}
private fun logInfo() { private fun logInfo() {
val appVersion = versionProvider.getVersion(longFormat = true, useBuildNumber = true) val appVersion = versionProvider.getVersion(longFormat = true, useBuildNumber = true)
val sdkVersion = Matrix.getSdkVersion() val sdkVersion = Matrix.getSdkVersion()

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019 New Vector Ltd * Copyright (c) 2021 New Vector Ltd
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,15 @@
package im.vector.app.core.di package im.vector.app.core.di
interface HasScreenInjector { import androidx.fragment.app.FragmentFactory
import androidx.lifecycle.ViewModelProvider
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
fun injector(): ScreenComponent @InstallIn(ActivityComponent::class)
@EntryPoint
interface ActivityEntryPoint {
fun fragmentFactory(): FragmentFactory
fun viewModelFactory(): ViewModelProvider.Factory
} }

View File

@ -21,6 +21,8 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory import androidx.fragment.app.FragmentFactory
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
import im.vector.app.features.attachments.preview.AttachmentsPreviewFragment import im.vector.app.features.attachments.preview.AttachmentsPreviewFragment
import im.vector.app.features.contactsbook.ContactsBookFragment import im.vector.app.features.contactsbook.ContactsBookFragment
@ -157,6 +159,7 @@ import im.vector.app.features.usercode.ShowUserCodeFragment
import im.vector.app.features.userdirectory.UserListFragment import im.vector.app.features.userdirectory.UserListFragment
import im.vector.app.features.widgets.WidgetFragment import im.vector.app.features.widgets.WidgetFragment
@InstallIn(ActivityComponent::class)
@Module @Module
interface FragmentModule { interface FragmentModule {
/** /**

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2021 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.app.core.di
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.MavericksViewModel
import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import dagger.hilt.DefineComponent
import dagger.hilt.EntryPoint
import dagger.hilt.EntryPoints
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
/**
* To connect Mavericks ViewModel creation with Hilt's dependency injection, add the following Factory and companion object to your MavericksViewModel.
*
* Example:
*
* class MyViewModel @AssistedInject constructor(...): MavericksViewModel<MyState>(...) {
*
* @AssistedFactory
* interface Factory : AssistedViewModelFactory<MyViewModel, MyState> {
* ...
* }
*
* companion object : MavericksViewModelFactory<MyViewModel, MyState> by hiltMavericksViewModelFactory()
* }
*/
inline fun <reified VM : MavericksViewModel<S>, S : MavericksState> hiltMavericksViewModelFactory() = HiltMavericksViewModelFactory<VM, S>(VM::class.java)
class HiltMavericksViewModelFactory<VM : MavericksViewModel<S>, S : MavericksState>(
private val viewModelClass: Class<out MavericksViewModel<S>>
) : MavericksViewModelFactory<VM, S> {
override fun create(viewModelContext: ViewModelContext, state: S): VM {
// We want to create the ViewModelComponent. In order to do that, we need to get its parent: ActivityComponent.
val componentBuilder = EntryPoints.get(viewModelContext.app(), CreateMavericksViewModelComponent::class.java).mavericksViewModelComponentBuilder()
val viewModelComponent = componentBuilder.build()
val viewModelFactoryMap = EntryPoints.get(viewModelComponent, HiltMavericksEntryPoint::class.java).viewModelFactories
val viewModelFactory = viewModelFactoryMap[viewModelClass]
@Suppress("UNCHECKED_CAST")
val castedViewModelFactory = viewModelFactory as? MavericksAssistedViewModelFactory<VM, S>
return castedViewModelFactory?.create(state) as VM
}
override fun initialState(viewModelContext: ViewModelContext): S? {
return super.initialState(viewModelContext)
}
}
/**
* Hilt's ViewModelComponent's parent is ActivityRetainedComponent but there is no easy way to access it. SingletonComponent should be sufficient
* because the ViewModel that gets created is the only object with a reference to the created component so the lifecycle of it will
* still be correct.
*/
@MavericksViewModelScoped
@DefineComponent(parent = SingletonComponent::class)
interface MavericksViewModelComponent
@DefineComponent.Builder
interface MavericksViewModelComponentBuilder {
fun build(): MavericksViewModelComponent
}
@EntryPoint
@InstallIn(SingletonComponent::class)
interface CreateMavericksViewModelComponent {
fun mavericksViewModelComponentBuilder(): MavericksViewModelComponentBuilder
}
@EntryPoint
@InstallIn(MavericksViewModelComponent::class)
interface HiltMavericksEntryPoint {
val viewModelFactories: Map<Class<out MavericksViewModel<*>>, MavericksAssistedViewModelFactory<*, *>>
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2021 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.app.core.di
import android.os.Handler
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import im.vector.app.features.home.room.detail.timeline.TimelineEventControllerHandler
import im.vector.app.features.home.room.detail.timeline.helper.TimelineAsyncHelper
@Module
@InstallIn(ActivityComponent::class)
object HomeModule {
@Provides
@JvmStatic
@TimelineEventControllerHandler
fun providesTimelineBackgroundHandler(): Handler {
return TimelineAsyncHelper.getBackgroundHandler()
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 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.app.core.di
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.MavericksViewModel
/**
* This factory allows Mavericks to supply the initial or restored [MavericksState] to Hilt.
*
* Add this interface inside of your [MavericksViewModel] class then create the following Hilt module:
*
* @Module
* @InstallIn(MavericksViewModelComponent::class)
* interface ViewModelsModule {
* @Binds
* @IntoMap
* @ViewModelKey(MyViewModel::class)
* fun myViewModelFactory(factory: MyViewModel.Factory): AssistedViewModelFactory<*, *>
* }
*
* If you already have a ViewModelsModule then all you have to do is add the multibinding entry for your new [MavericksViewModel].
*/
interface MavericksAssistedViewModelFactory<VM : MavericksViewModel<S>, S : MavericksState> {
fun create(initialState: S): VM
}

View File

@ -0,0 +1,543 @@
/*
* 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.app.core.di
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.multibindings.IntoMap
import im.vector.app.features.auth.ReAuthViewModel
import im.vector.app.features.call.VectorCallViewModel
import im.vector.app.features.call.conference.JitsiCallViewModel
import im.vector.app.features.call.transfer.CallTransferViewModel
import im.vector.app.features.contactsbook.ContactsBookViewModel
import im.vector.app.features.createdirect.CreateDirectRoomViewModel
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel
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.emoji.VerificationEmojiCodeViewModel
import im.vector.app.features.devtools.RoomDevToolViewModel
import im.vector.app.features.discovery.DiscoverySettingsViewModel
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.PromoteRestrictedViewModel
import im.vector.app.features.home.UnknownDeviceDetectorSharedViewModel
import im.vector.app.features.home.UnreadMessagesSharedViewModel
import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsViewModel
import im.vector.app.features.home.room.detail.composer.TextComposerViewModel
import im.vector.app.features.home.room.detail.search.SearchViewModel
import im.vector.app.features.home.room.detail.timeline.action.MessageActionsViewModel
import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryViewModel
import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsViewModel
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomViewModel
import im.vector.app.features.home.room.list.RoomListViewModel
import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel
import im.vector.app.features.invite.InviteUsersToRoomViewModel
import im.vector.app.features.login.LoginViewModel
import im.vector.app.features.login2.LoginViewModel2
import im.vector.app.features.login2.created.AccountCreatedViewModel
import im.vector.app.features.matrixto.MatrixToBottomSheetViewModel
import im.vector.app.features.rageshake.BugReportViewModel
import im.vector.app.features.reactions.EmojiSearchResultViewModel
import im.vector.app.features.room.RequireActiveMembershipViewModel
import im.vector.app.features.roomdirectory.RoomDirectoryViewModel
import im.vector.app.features.roomdirectory.createroom.CreateRoomViewModel
import im.vector.app.features.roomdirectory.picker.RoomDirectoryPickerViewModel
import im.vector.app.features.roomdirectory.roompreview.RoomPreviewViewModel
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.alias.RoomAliasViewModel
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetViewModel
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListViewModel
import im.vector.app.features.roomprofile.members.RoomMemberListViewModel
import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewModel
import im.vector.app.features.roomprofile.permissions.RoomPermissionsViewModel
import im.vector.app.features.roomprofile.settings.RoomSettingsViewModel
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel
import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel
import im.vector.app.features.settings.account.deactivation.DeactivateAccountViewModel
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.devtools.AccountDataViewModel
import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel
import im.vector.app.features.settings.devtools.KeyRequestListViewModel
import im.vector.app.features.settings.homeserver.HomeserverSettingsViewModel
import im.vector.app.features.settings.ignored.IgnoredUsersViewModel
import im.vector.app.features.settings.locale.LocalePickerViewModel
import im.vector.app.features.settings.push.PushGatewaysViewModel
import im.vector.app.features.settings.threepids.ThreePidsSettingsViewModel
import im.vector.app.features.share.IncomingShareViewModel
import im.vector.app.features.signout.soft.SoftLogoutViewModel
import im.vector.app.features.spaces.SpaceListViewModel
import im.vector.app.features.spaces.SpaceMenuViewModel
import im.vector.app.features.spaces.create.CreateSpaceViewModel
import im.vector.app.features.spaces.explore.SpaceDirectoryViewModel
import im.vector.app.features.spaces.invite.SpaceInviteBottomSheetViewModel
import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedViewModel
import im.vector.app.features.spaces.manage.SpaceAddRoomsViewModel
import im.vector.app.features.spaces.manage.SpaceManageRoomsViewModel
import im.vector.app.features.spaces.manage.SpaceManageSharedViewModel
import im.vector.app.features.spaces.people.SpacePeopleViewModel
import im.vector.app.features.spaces.preview.SpacePreviewViewModel
import im.vector.app.features.spaces.share.ShareSpaceViewModel
import im.vector.app.features.terms.ReviewTermsViewModel
import im.vector.app.features.usercode.UserCodeSharedViewModel
import im.vector.app.features.userdirectory.UserListViewModel
import im.vector.app.features.widgets.WidgetViewModel
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewModel
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import im.vector.app.features.workers.signout.SignoutCheckViewModel
@InstallIn(MavericksViewModelComponent::class)
@Module
interface MavericksViewModelModule {
@Binds
@IntoMap
@MavericksViewModelKey(RoomListViewModel::class)
fun roomListViewModelFactory(factory: RoomListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceManageRoomsViewModel::class)
fun spaceManageRoomsViewModelFactory(factory: SpaceManageRoomsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceManageSharedViewModel::class)
fun spaceManageSharedViewModelFactory(factory: SpaceManageSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceListViewModel::class)
fun spaceListViewModelFactory(factory: SpaceListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ReAuthViewModel::class)
fun reAuthViewModelFactory(factory: ReAuthViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VectorCallViewModel::class)
fun vectorCallViewModelFactory(factory: VectorCallViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(JitsiCallViewModel::class)
fun jitsiCallViewModelFactory(factory: JitsiCallViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomDirectoryViewModel::class)
fun roomDirectoryViewModelFactory(factory: RoomDirectoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ViewReactionsViewModel::class)
fun viewReactionsViewModelFactory(factory: ViewReactionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomWidgetPermissionViewModel::class)
fun roomWidgetPermissionViewModelFactory(factory: RoomWidgetPermissionViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(WidgetViewModel::class)
fun widgetViewModelFactory(factory: WidgetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ServerBackupStatusViewModel::class)
fun serverBackupStatusViewModelFactory(factory: ServerBackupStatusViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SignoutCheckViewModel::class)
fun signoutCheckViewModelFactory(factory: SignoutCheckViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomDirectoryPickerViewModel::class)
fun roomDirectoryPickerViewModelFactory(factory: RoomDirectoryPickerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomDevToolViewModel::class)
fun roomDevToolViewModelFactory(factory: RoomDevToolViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(MigrateRoomViewModel::class)
fun migrateRoomViewModelFactory(factory: MigrateRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(IgnoredUsersViewModel::class)
fun ignoredUsersViewModelFactory(factory: IgnoredUsersViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CallTransferViewModel::class)
fun callTransferViewModelFactory(factory: CallTransferViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ContactsBookViewModel::class)
fun contactsBookViewModelFactory(factory: ContactsBookViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CreateDirectRoomViewModel::class)
fun createDirectRoomViewModelFactory(factory: CreateDirectRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomNotificationSettingsViewModel::class)
fun roomNotificationSettingsViewModelFactory(factory: RoomNotificationSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(KeysBackupSettingsViewModel::class)
fun keysBackupSettingsViewModelFactory(factory: KeysBackupSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SharedSecureStorageViewModel::class)
fun sharedSecureStorageViewModelFactory(factory: SharedSecureStorageViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(PromoteRestrictedViewModel::class)
fun promoteRestrictedViewModelFactory(factory: PromoteRestrictedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(UserListViewModel::class)
fun userListViewModelFactory(factory: UserListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(UserCodeSharedViewModel::class)
fun userCodeSharedViewModelFactory(factory: UserCodeSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ReviewTermsViewModel::class)
fun reviewTermsViewModelFactory(factory: ReviewTermsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ShareSpaceViewModel::class)
fun shareSpaceViewModelFactory(factory: ShareSpaceViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpacePreviewViewModel::class)
fun spacePreviewViewModelFactory(factory: SpacePreviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpacePeopleViewModel::class)
fun spacePeopleViewModelFactory(factory: SpacePeopleViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceAddRoomsViewModel::class)
fun spaceAddRoomsViewModelFactory(factory: SpaceAddRoomsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceLeaveAdvancedViewModel::class)
fun spaceLeaveAdvancedViewModelFactory(factory: SpaceLeaveAdvancedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceInviteBottomSheetViewModel::class)
fun spaceInviteBottomSheetViewModelFactory(factory: SpaceInviteBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceDirectoryViewModel::class)
fun spaceDirectoryViewModelFactory(factory: SpaceDirectoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CreateSpaceViewModel::class)
fun createSpaceViewModelFactory(factory: CreateSpaceViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceMenuViewModel::class)
fun spaceMenuViewModelFactory(factory: SpaceMenuViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SoftLogoutViewModel::class)
fun softLogoutViewModelFactory(factory: SoftLogoutViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(IncomingShareViewModel::class)
fun incomingShareViewModelFactory(factory: IncomingShareViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ThreePidsSettingsViewModel::class)
fun threePidsSettingsViewModelFactory(factory: ThreePidsSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(PushGatewaysViewModel::class)
fun pushGatewaysViewModelFactory(factory: PushGatewaysViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(HomeserverSettingsViewModel::class)
fun homeserverSettingsViewModelFactory(factory: HomeserverSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(LocalePickerViewModel::class)
fun localePickerViewModelFactory(factory: LocalePickerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(GossipingEventsPaperTrailViewModel::class)
fun gossipingEventsPaperTrailViewModelFactory(factory: GossipingEventsPaperTrailViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(AccountDataViewModel::class)
fun accountDataViewModelFactory(factory: AccountDataViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DevicesViewModel::class)
fun devicesViewModelFactory(factory: DevicesViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(KeyRequestListViewModel::class)
fun keyRequestListViewModelFactory(factory: KeyRequestListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CrossSigningSettingsViewModel::class)
fun crossSigningSettingsViewModelFactory(factory: CrossSigningSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DeactivateAccountViewModel::class)
fun deactivateAccountViewModelFactory(factory: DeactivateAccountViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomUploadsViewModel::class)
fun roomUploadsViewModelFactory(factory: RoomUploadsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomJoinRuleChooseRestrictedViewModel::class)
fun roomJoinRuleChooseRestrictedViewModelFactory(factory: RoomJoinRuleChooseRestrictedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomSettingsViewModel::class)
fun roomSettingsViewModelFactory(factory: RoomSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomPermissionsViewModel::class)
fun roomPermissionsViewModelFactory(factory: RoomPermissionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomMemberListViewModel::class)
fun roomMemberListViewModelFactory(factory: RoomMemberListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomBannedMemberListViewModel::class)
fun roomBannedMemberListViewModelFactory(factory: RoomBannedMemberListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomAliasViewModel::class)
fun roomAliasViewModelFactory(factory: RoomAliasViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomAliasBottomSheetViewModel::class)
fun roomAliasBottomSheetViewModelFactory(factory: RoomAliasBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomProfileViewModel::class)
fun roomProfileViewModelFactory(factory: RoomProfileViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomMemberProfileViewModel::class)
fun roomMemberProfileViewModelFactory(factory: RoomMemberProfileViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomPreviewViewModel::class)
fun roomPreviewViewModelFactory(factory: RoomPreviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CreateRoomViewModel::class)
fun createRoomViewModelFactory(factory: CreateRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RequireActiveMembershipViewModel::class)
fun requireActiveMembershipViewModelFactory(factory: RequireActiveMembershipViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(EmojiSearchResultViewModel::class)
fun emojiSearchResultViewModelFactory(factory: EmojiSearchResultViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(BugReportViewModel::class)
fun bugReportViewModelFactory(factory: BugReportViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(MatrixToBottomSheetViewModel::class)
fun matrixToBottomSheetViewModelFactory(factory: MatrixToBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(AccountCreatedViewModel::class)
fun accountCreatedViewModelFactory(factory: AccountCreatedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(LoginViewModel2::class)
fun loginViewModel2Factory(factory: LoginViewModel2.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(LoginViewModel::class)
fun loginViewModelFactory(factory: LoginViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(HomeServerCapabilitiesViewModel::class)
fun homeServerCapabilitiesViewModelFactory(factory: HomeServerCapabilitiesViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(InviteUsersToRoomViewModel::class)
fun inviteUsersToRoomViewModelFactory(factory: InviteUsersToRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ViewEditHistoryViewModel::class)
fun viewEditHistoryViewModelFactory(factory: ViewEditHistoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(MessageActionsViewModel::class)
fun messageActionsViewModelFactory(factory: MessageActionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VerificationChooseMethodViewModel::class)
fun verificationChooseMethodViewModelFactory(factory: VerificationChooseMethodViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VerificationEmojiCodeViewModel::class)
fun verificationEmojiCodeViewModelFactory(factory: VerificationEmojiCodeViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SearchViewModel::class)
fun searchViewModelFactory(factory: SearchViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(UnreadMessagesSharedViewModel::class)
fun unreadMessagesSharedViewModelFactory(factory: UnreadMessagesSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(UnknownDeviceDetectorSharedViewModel::class)
fun unknownDeviceDetectorSharedViewModelFactory(factory: UnknownDeviceDetectorSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DiscoverySettingsViewModel::class)
fun discoverySettingsViewModelFactory(factory: DiscoverySettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(TextComposerViewModel::class)
fun textComposerViewModelFactory(factory: TextComposerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SetIdentityServerViewModel::class)
fun setIdentityServerViewModelFactory(factory: SetIdentityServerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(BreadcrumbsViewModel::class)
fun breadcrumbsViewModelFactory(factory: BreadcrumbsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(HomeDetailViewModel::class)
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

@ -1,5 +1,5 @@
/* /*
* Copyright 2019 New Vector Ltd * Copyright (c) 2021 New Vector Ltd
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,10 @@
package im.vector.app.core.di package im.vector.app.core.di
interface HasVectorInjector { import javax.inject.Scope
fun injector(): VectorComponent /**
} * Scope annotation for bindings that should exist for the life of an MavericksViewModel.
*/
@Scope
annotation class MavericksViewModelScoped

View File

@ -1,225 +0,0 @@
/*
* 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.app.core.di
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentFactory
import androidx.lifecycle.ViewModelProvider
import dagger.BindsInstance
import dagger.Component
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.preference.UserAvatarPreference
import im.vector.app.features.MainActivity
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.call.CallControlsBottomSheet
import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.conference.VectorJitsiActivity
import im.vector.app.features.call.transfer.CallTransferActivity
import im.vector.app.features.createdirect.CreateDirectRoomActivity
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity
import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity
import im.vector.app.features.crypto.quads.SharedSecureStorageActivity
import im.vector.app.features.crypto.recover.BootstrapBottomSheet
import im.vector.app.features.crypto.verification.VerificationBottomSheet
import im.vector.app.features.debug.DebugMenuActivity
import im.vector.app.features.devtools.RoomDevToolActivity
import im.vector.app.features.home.HomeActivity
import im.vector.app.features.home.HomeModule
import im.vector.app.features.home.room.detail.JoinReplacementRoomBottomSheet
import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
import im.vector.app.features.home.room.detail.search.SearchActivity
import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBottomSheet
import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
import im.vector.app.features.home.room.detail.widget.RoomWidgetsBottomSheet
import im.vector.app.features.home.room.filtered.FilteredRoomsActivity
import im.vector.app.features.home.room.list.RoomListModule
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.invite.InviteUsersToRoomActivity
import im.vector.app.features.invite.VectorInviteView
import im.vector.app.features.link.LinkHandlerActivity
import im.vector.app.features.login.LoginActivity
import im.vector.app.features.login2.LoginActivity2
import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.media.BigImageViewerActivity
import im.vector.app.features.media.VectorAttachmentViewerActivity
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.qrcode.QrCodeScannerActivity
import im.vector.app.features.rageshake.BugReportActivity
import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.rageshake.RageShake
import im.vector.app.features.reactions.EmojiReactionPickerActivity
import im.vector.app.features.reactions.widget.ReactionButton
import im.vector.app.features.roomdirectory.RoomDirectoryActivity
import im.vector.app.features.roomdirectory.createroom.CreateRoomActivity
import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet
import im.vector.app.features.roomprofile.RoomProfileActivity
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet
import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilityBottomSheet
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleActivity
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleBottomSheet
import im.vector.app.features.settings.VectorSettingsActivity
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet
import im.vector.app.features.share.IncomingShareActivity
import im.vector.app.features.signout.soft.SoftLogoutActivity
import im.vector.app.features.spaces.InviteRoomSpaceChooserBottomSheet
import im.vector.app.features.spaces.LeaveSpaceBottomSheet
import im.vector.app.features.spaces.SpaceCreationActivity
import im.vector.app.features.spaces.SpaceExploreActivity
import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet
import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedActivity
import im.vector.app.features.spaces.manage.SpaceManageActivity
import im.vector.app.features.spaces.share.ShareSpaceBottomSheet
import im.vector.app.features.terms.ReviewTermsActivity
import im.vector.app.features.ui.UiStateRepository
import im.vector.app.features.usercode.UserCodeActivity
import im.vector.app.features.widgets.WidgetActivity
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet
import im.vector.app.features.workers.signout.SignOutBottomSheetDialogFragment
import kotlinx.coroutines.CoroutineScope
@Component(
dependencies = [
VectorComponent::class
],
modules = [
ViewModelModule::class,
FragmentModule::class,
HomeModule::class,
RoomListModule::class,
ScreenModule::class
]
)
@ScreenScope
interface ScreenComponent {
/* ==========================================================================================
* Shortcut to VectorComponent elements
* ========================================================================================== */
fun activeSessionHolder(): ActiveSessionHolder
fun fragmentFactory(): FragmentFactory
fun viewModelFactory(): ViewModelProvider.Factory
fun bugReporter(): BugReporter
fun rageShake(): RageShake
fun navigator(): Navigator
fun pinLocker(): PinLocker
fun errorFormatter(): ErrorFormatter
fun uiStateRepository(): UiStateRepository
fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
fun autoAcceptInvites(): AutoAcceptInvites
fun appCoroutineScope(): CoroutineScope
/* ==========================================================================================
* Activities
* ========================================================================================== */
fun inject(activity: HomeActivity)
fun inject(activity: RoomDetailActivity)
fun inject(activity: RoomProfileActivity)
fun inject(activity: RoomMemberProfileActivity)
fun inject(activity: VectorSettingsActivity)
fun inject(activity: KeysBackupManageActivity)
fun inject(activity: EmojiReactionPickerActivity)
fun inject(activity: LoginActivity)
fun inject(activity: LoginActivity2)
fun inject(activity: LinkHandlerActivity)
fun inject(activity: MainActivity)
fun inject(activity: RoomDirectoryActivity)
fun inject(activity: KeysBackupSetupActivity)
fun inject(activity: BugReportActivity)
fun inject(activity: FilteredRoomsActivity)
fun inject(activity: CreateRoomActivity)
fun inject(activity: CreateDirectRoomActivity)
fun inject(activity: IncomingShareActivity)
fun inject(activity: SoftLogoutActivity)
fun inject(activity: QrCodeScannerActivity)
fun inject(activity: DebugMenuActivity)
fun inject(activity: SharedSecureStorageActivity)
fun inject(activity: BigImageViewerActivity)
fun inject(activity: InviteUsersToRoomActivity)
fun inject(activity: ReviewTermsActivity)
fun inject(activity: WidgetActivity)
fun inject(activity: VectorCallActivity)
fun inject(activity: VectorAttachmentViewerActivity)
fun inject(activity: VectorJitsiActivity)
fun inject(activity: SearchActivity)
fun inject(activity: UserCodeActivity)
fun inject(activity: CallTransferActivity)
fun inject(activity: ReAuthActivity)
fun inject(activity: RoomDevToolActivity)
fun inject(activity: SpaceCreationActivity)
fun inject(activity: SpaceExploreActivity)
fun inject(activity: SpaceManageActivity)
fun inject(activity: RoomJoinRuleActivity)
fun inject(activity: SpaceLeaveAdvancedActivity)
/* ==========================================================================================
* BottomSheets
* ========================================================================================== */
fun inject(bottomSheet: MessageActionsBottomSheet)
fun inject(bottomSheet: ViewReactionsBottomSheet)
fun inject(bottomSheet: ViewEditHistoryBottomSheet)
fun inject(bottomSheet: DisplayReadReceiptsBottomSheet)
fun inject(bottomSheet: RoomListQuickActionsBottomSheet)
fun inject(bottomSheet: RoomAliasBottomSheet)
fun inject(bottomSheet: RoomHistoryVisibilityBottomSheet)
fun inject(bottomSheet: RoomJoinRuleBottomSheet)
fun inject(bottomSheet: VerificationBottomSheet)
fun inject(bottomSheet: DeviceVerificationInfoBottomSheet)
fun inject(bottomSheet: DeviceListBottomSheet)
fun inject(bottomSheet: BootstrapBottomSheet)
fun inject(bottomSheet: RoomWidgetPermissionBottomSheet)
fun inject(bottomSheet: RoomWidgetsBottomSheet)
fun inject(bottomSheet: CallControlsBottomSheet)
fun inject(bottomSheet: SignOutBottomSheetDialogFragment)
fun inject(bottomSheet: MatrixToBottomSheet)
fun inject(bottomSheet: ShareSpaceBottomSheet)
fun inject(bottomSheet: SpaceSettingsMenuBottomSheet)
fun inject(bottomSheet: InviteRoomSpaceChooserBottomSheet)
fun inject(bottomSheet: SpaceInviteBottomSheet)
fun inject(bottomSheet: JoinReplacementRoomBottomSheet)
fun inject(bottomSheet: MigrateRoomBottomSheet)
fun inject(bottomSheet: LeaveSpaceBottomSheet)
/* ==========================================================================================
* Others
* ========================================================================================== */
fun inject(view: VectorInviteView)
fun inject(preference: UserAvatarPreference)
fun inject(button: ReactionButton)
/* ==========================================================================================
* Factory
* ========================================================================================== */
@Component.Factory
interface Factory {
fun create(vectorComponent: VectorComponent,
@BindsInstance context: AppCompatActivity
): ScreenComponent
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019 New Vector Ltd * Copyright (c) 2021 New Vector Ltd
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,9 +20,13 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.scopes.ActivityScoped
import im.vector.app.core.glide.GlideApp import im.vector.app.core.glide.GlideApp
@Module @Module
@InstallIn(ActivityComponent::class)
object ScreenModule { object ScreenModule {
@Provides @Provides
@ -31,6 +35,6 @@ object ScreenModule {
@Provides @Provides
@JvmStatic @JvmStatic
@ScreenScope @ActivityScoped
fun providesSharedViewPool() = RecyclerView.RecycledViewPool() fun providesSharedViewPool() = RecyclerView.RecycledViewPool()
} }

View File

@ -1,24 +0,0 @@
/*
* 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.app.core.di
import javax.inject.Scope
@Scope
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class ScreenScope

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2021 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.app.core.di
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.session.SessionListener
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.ui.UiStateRepository
import kotlinx.coroutines.CoroutineScope
@InstallIn(SingletonComponent::class)
@EntryPoint
interface SingletonEntryPoint {
fun sessionListener(): SessionListener
fun avatarRenderer(): AvatarRenderer
fun activeSessionHolder(): ActiveSessionHolder
fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
fun navigator(): Navigator
fun errorFormatter(): ErrorFormatter
fun bugReporter(): BugReporter
fun vectorPreferences(): VectorPreferences
fun uiStateRepository(): UiStateRepository
fun pinLocker(): PinLocker
fun webRtcCallManager(): WebRtcCallManager
fun appCoroutineScope(): CoroutineScope
}

View File

@ -16,6 +16,7 @@
package im.vector.app.core.di package im.vector.app.core.di
import android.app.Application
import android.content.Context import android.content.Context
import android.content.Context.MODE_PRIVATE import android.content.Context.MODE_PRIVATE
import android.content.SharedPreferences import android.content.SharedPreferences
@ -23,6 +24,8 @@ import android.content.res.Resources
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.error.DefaultErrorFormatter import im.vector.app.core.error.DefaultErrorFormatter
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
@ -45,11 +48,35 @@ import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import javax.inject.Singleton import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module @Module
abstract class VectorModule { abstract class VectorBindModule {
@Module @Binds
companion object { abstract fun bindNavigator(navigator: DefaultNavigator): Navigator
@Binds
abstract fun bindErrorFormatter(formatter: DefaultErrorFormatter): ErrorFormatter
@Binds
abstract fun bindUiStateRepository(repository: SharedPreferencesUiStateRepository): UiStateRepository
@Binds
abstract fun bindPinCodeStore(store: SharedPrefPinCodeStore): PinCodeStore
@Binds
abstract fun bindAutoAcceptInvites(autoAcceptInvites: CompileTimeAutoAcceptInvites): AutoAcceptInvites
}
@InstallIn(SingletonComponent::class)
@Module
object VectorStaticModule {
@Provides
@JvmStatic
fun providesContext(application: Application): Context {
return application.applicationContext
}
@Provides @Provides
@JvmStatic @JvmStatic
@ -112,20 +139,4 @@ abstract class VectorModule {
fun providesCoroutineDispatchers(): CoroutineDispatchers { fun providesCoroutineDispatchers(): CoroutineDispatchers {
return CoroutineDispatchers(io = Dispatchers.IO) return CoroutineDispatchers(io = Dispatchers.IO)
} }
}
@Binds
abstract fun bindNavigator(navigator: DefaultNavigator): Navigator
@Binds
abstract fun bindErrorFormatter(formatter: DefaultErrorFormatter): ErrorFormatter
@Binds
abstract fun bindUiStateRepository(repository: SharedPreferencesUiStateRepository): UiStateRepository
@Binds
abstract fun bindPinCodeStore(store: SharedPrefPinCodeStore): PinCodeStore
@Binds
abstract fun bindAutoAcceptInvites(autoAcceptInvites: CompileTimeAutoAcceptInvites): AutoAcceptInvites
} }

View File

@ -1,183 +0,0 @@
/*
* 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.app.core.di
import android.content.Context
import android.content.res.Resources
import dagger.BindsInstance
import dagger.Component
import im.vector.app.ActiveSessionDataSource
import im.vector.app.AppStateHandler
import im.vector.app.EmojiCompatFontProvider
import im.vector.app.EmojiCompatWrapper
import im.vector.app.VectorApplication
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.utils.AssetReader
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.call.conference.JitsiActiveConferenceHolder
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.configuration.VectorConfiguration
import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.CurrentSpaceSuggestedRoomListDataSource
import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.html.VectorHtmlCompressor
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.notifications.NotifiableEventResolver
import im.vector.app.features.notifications.NotificationBroadcastReceiver
import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.notifications.PushRuleTriggerListener
import im.vector.app.features.pin.PinCodeStore
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.rageshake.VectorFileLogger
import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.app.features.reactions.data.EmojiDataSource
import im.vector.app.features.session.SessionListener
import im.vector.app.features.settings.VectorDataStore
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.ui.UiStateRepository
import kotlinx.coroutines.CoroutineScope
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session
import javax.inject.Singleton
@Component(modules = [VectorModule::class])
@Singleton
interface VectorComponent {
fun inject(notificationBroadcastReceiver: NotificationBroadcastReceiver)
fun inject(vectorApplication: VectorApplication)
fun matrix(): Matrix
fun matrixItemColorProvider(): MatrixItemColorProvider
fun sessionListener(): SessionListener
fun currentSession(): Session
fun notificationUtils(): NotificationUtils
fun notificationDrawerManager(): NotificationDrawerManager
fun appContext(): Context
fun resources(): Resources
fun assetReader(): AssetReader
fun dimensionConverter(): DimensionConverter
fun vectorConfiguration(): VectorConfiguration
fun avatarRenderer(): AvatarRenderer
fun activeSessionHolder(): ActiveSessionHolder
fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
fun emojiCompatFontProvider(): EmojiCompatFontProvider
fun emojiCompatWrapper(): EmojiCompatWrapper
fun eventHtmlRenderer(): EventHtmlRenderer
fun vectorHtmlCompressor(): VectorHtmlCompressor
fun navigator(): Navigator
fun errorFormatter(): ErrorFormatter
fun appStateHandler(): AppStateHandler
fun currentSpaceSuggestedRoomListDataSource(): CurrentSpaceSuggestedRoomListDataSource
fun roomDetailPendingActionStore(): RoomDetailPendingActionStore
fun activeSessionObservableStore(): ActiveSessionDataSource
fun incomingVerificationRequestHandler(): IncomingVerificationRequestHandler
fun incomingKeyRequestHandler(): KeyRequestHandler
fun authenticationService(): AuthenticationService
fun rawService(): RawService
fun homeServerHistoryService(): HomeServerHistoryService
fun bugReporter(): BugReporter
fun vectorUncaughtExceptionHandler(): VectorUncaughtExceptionHandler
fun pushRuleTriggerListener(): PushRuleTriggerListener
fun pusherManager(): PushersManager
fun notifiableEventResolver(): NotifiableEventResolver
fun vectorPreferences(): VectorPreferences
fun vectorDataStore(): VectorDataStore
fun wifiDetector(): WifiDetector
fun vectorFileLogger(): VectorFileLogger
fun uiStateRepository(): UiStateRepository
fun pinCodeStore(): PinCodeStore
fun emojiDataSource(): EmojiDataSource
fun alertManager(): PopupAlertManager
fun reAuthHelper(): ReAuthHelper
fun pinLocker(): PinLocker
fun autoAcceptInvites(): AutoAcceptInvites
fun webRtcCallManager(): WebRtcCallManager
fun appCoroutineScope(): CoroutineScope
fun coroutineDispatchers(): CoroutineDispatchers
fun jitsiActiveConferenceHolder(): JitsiActiveConferenceHolder
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): VectorComponent
}
}

View File

@ -17,6 +17,7 @@
package im.vector.app.core.di package im.vector.app.core.di
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.airbnb.mvrx.MavericksViewModel
import dagger.MapKey import dagger.MapKey
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -24,3 +25,8 @@ import kotlin.reflect.KClass
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
@MapKey @MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>) annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
@MapKey
annotation class MavericksViewModelKey(val value: KClass<out MavericksViewModel<*>>)

View File

@ -20,6 +20,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
import im.vector.app.core.platform.ConfigurationViewModel import im.vector.app.core.platform.ConfigurationViewModel
import im.vector.app.features.call.SharedKnownCallsViewModel import im.vector.app.features.call.SharedKnownCallsViewModel
@ -42,6 +44,7 @@ import im.vector.app.features.spaces.SpacePreviewSharedActionViewModel
import im.vector.app.features.spaces.people.SpacePeopleSharedActionViewModel import im.vector.app.features.spaces.people.SpacePeopleSharedActionViewModel
import im.vector.app.features.userdirectory.UserListSharedActionViewModel import im.vector.app.features.userdirectory.UserListSharedActionViewModel
@InstallIn(ActivityComponent::class)
@Module @Module
interface ViewModelModule { interface ViewModelModule {

View File

@ -17,14 +17,9 @@
package im.vector.app.core.extensions package im.vector.app.core.extensions
import android.content.Context import android.content.Context
import im.vector.app.core.di.HasVectorInjector import dagger.hilt.EntryPoints
import im.vector.app.core.di.VectorComponent import im.vector.app.core.di.SingletonEntryPoint
fun Context.vectorComponent(): VectorComponent { fun Context.singletonEntryPoint(): SingletonEntryPoint {
val appContext = applicationContext return EntryPoints.get(applicationContext, SingletonEntryPoint::class.java)
if (appContext is HasVectorInjector) {
return appContext.injector()
} else {
throw IllegalStateException("Your application context doesn't implement HasVectorInjector")
}
} }

View File

@ -34,7 +34,7 @@ fun Session.configureAndStart(context: Context, startSyncing: Boolean = true) {
startSyncing(context) startSyncing(context)
} }
refreshPushers() refreshPushers()
context.vectorComponent().webRtcCallManager().checkForProtocolsSupportIfNeeded() context.singletonEntryPoint().webRtcCallManager().checkForProtocolsSupportIfNeeded()
} }
fun Session.startSyncing(context: Context) { fun Session.startSyncing(context: Context) {

View File

@ -26,7 +26,7 @@ import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey import com.bumptech.glide.signature.ObjectKey
import im.vector.app.core.extensions.vectorComponent import im.vector.app.core.extensions.singletonEntryPoint
import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.MatrixItem
data class AvatarPlaceholder(val matrixItem: MatrixItem) data class AvatarPlaceholder(val matrixItem: MatrixItem)
@ -57,7 +57,7 @@ class AvatarPlaceholderModelLoader(private val context: Context) :
class AvatarPlaceholderDataFetcher(context: Context, private val data: AvatarPlaceholder) : class AvatarPlaceholderDataFetcher(context: Context, private val data: AvatarPlaceholder) :
DataFetcher<Drawable> { DataFetcher<Drawable> {
private val avatarRenderer = context.vectorComponent().avatarRenderer() private val avatarRenderer = context.singletonEntryPoint().avatarRenderer()
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in Drawable>) { override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in Drawable>) {
val avatarPlaceholder = avatarRenderer.getPlaceholderDrawable(data.matrixItem) val avatarPlaceholder = avatarRenderer.getPlaceholderDrawable(data.matrixItem)

View File

@ -25,7 +25,7 @@ import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey import com.bumptech.glide.signature.ObjectKey
import im.vector.app.core.extensions.vectorComponent import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.files.LocalFilesHelper import im.vector.app.core.files.LocalFilesHelper
import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.session.coroutineScope import im.vector.app.features.session.coroutineScope
@ -67,7 +67,7 @@ class VectorGlideDataFetcher(context: Context,
DataFetcher<InputStream> { DataFetcher<InputStream> {
private val localFilesHelper = LocalFilesHelper(context) private val localFilesHelper = LocalFilesHelper(context)
private val activeSessionHolder = context.vectorComponent().activeSessionHolder() private val activeSessionHolder = context.singletonEntryPoint().activeSessionHolder()
private val client = activeSessionHolder.getSafeActiveSession()?.getOkHttpClient() ?: OkHttpClient() private val client = activeSessionHolder.getSafeActiveSession()?.getOkHttpClient() ?: OkHttpClient()

View File

@ -15,13 +15,10 @@
*/ */
package im.vector.app.core.platform package im.vector.app.core.platform
import androidx.annotation.CallSuper
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.databinding.ActivityBinding import im.vector.app.databinding.ActivityBinding
import org.matrix.android.sdk.api.session.Session
/** /**
* Simple activity with a toolbar, a waiting overlay, and a fragment container and a session. * Simple activity with a toolbar, a waiting overlay, and a fragment container and a session.
@ -32,13 +29,6 @@ abstract class SimpleFragmentActivity : VectorBaseActivity<ActivityBinding>() {
final override fun getCoordinatorLayout() = views.coordinatorLayout final override fun getCoordinatorLayout() = views.coordinatorLayout
lateinit var session: Session
@CallSuper
override fun injectWith(injector: ScreenComponent) {
session = injector.activeSessionHolder().getActiveSession()
}
override fun initUiAndData() { override fun initUiAndData() {
configureToolbar(views.toolbar) configureToolbar(views.toolbar)
waitingView = views.waitingView.waitingView waitingView = views.waitingView.waitingView

View File

@ -45,14 +45,11 @@ import com.bumptech.glide.util.Util
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding3.view.clicks import com.jakewharton.rxbinding3.view.clicks
import dagger.hilt.android.EntryPointAccessors
import im.vector.app.BuildConfig import im.vector.app.BuildConfig
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.DaggerScreenComponent import im.vector.app.core.di.ActivityEntryPoint
import im.vector.app.core.di.HasScreenInjector
import im.vector.app.core.di.HasVectorInjector
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.di.VectorComponent
import im.vector.app.core.dialogs.DialogLocker import im.vector.app.core.dialogs.DialogLocker
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
@ -61,7 +58,7 @@ import im.vector.app.core.extensions.observeNotNull
import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.restart import im.vector.app.core.extensions.restart
import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.extensions.vectorComponent import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.utils.toast import im.vector.app.core.utils.toast
import im.vector.app.features.MainActivity import im.vector.app.features.MainActivity
import im.vector.app.features.MainActivityArgs import im.vector.app.features.MainActivityArgs
@ -87,9 +84,9 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.GlobalError import org.matrix.android.sdk.api.failure.GlobalError
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.system.measureTimeMillis import javax.inject.Inject
abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), HasScreenInjector, MavericksView { abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), MavericksView {
/* ========================================================================================== /* ==========================================================================================
* View * View
* ========================================================================================== */ * ========================================================================================== */
@ -136,8 +133,8 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), HasSc
private lateinit var sessionListener: SessionListener private lateinit var sessionListener: SessionListener
protected lateinit var bugReporter: BugReporter protected lateinit var bugReporter: BugReporter
private lateinit var pinLocker: PinLocker private lateinit var pinLocker: PinLocker
@Inject
lateinit var rageShake: RageShake lateinit var rageShake: RageShake
lateinit var navigator: Navigator lateinit var navigator: Navigator
private set private set
private lateinit var fragmentFactory: FragmentFactory private lateinit var fragmentFactory: FragmentFactory
@ -156,8 +153,6 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), HasSc
private val uiDisposables = CompositeDisposable() private val uiDisposables = CompositeDisposable()
private val restorables = ArrayList<Restorable>() private val restorables = ArrayList<Restorable>()
private lateinit var screenComponent: ScreenComponent
override fun attachBaseContext(base: Context) { override fun attachBaseContext(base: Context) {
val vectorConfiguration = VectorConfiguration(this) val vectorConfiguration = VectorConfiguration(this)
super.attachBaseContext(vectorConfiguration.getLocalisedContext(base)) super.attachBaseContext(vectorConfiguration.getLocalisedContext(base))
@ -187,25 +182,19 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), HasSc
@CallSuper @CallSuper
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
Timber.i("onCreate Activity ${javaClass.simpleName}") Timber.i("onCreate Activity ${javaClass.simpleName}")
val vectorComponent = getVectorComponent() val singletonEntryPoint = singletonEntryPoint()
screenComponent = DaggerScreenComponent.factory().create(vectorComponent, this) val activityEntryPoint = EntryPointAccessors.fromActivity(this, ActivityEntryPoint::class.java)
val timeForInjection = measureTimeMillis {
injectWith(screenComponent)
}
Timber.v("Injecting dependencies into ${javaClass.simpleName} took $timeForInjection ms")
ThemeUtils.setActivityTheme(this, getOtherThemes()) ThemeUtils.setActivityTheme(this, getOtherThemes())
fragmentFactory = screenComponent.fragmentFactory() fragmentFactory = activityEntryPoint.fragmentFactory()
supportFragmentManager.fragmentFactory = fragmentFactory supportFragmentManager.fragmentFactory = fragmentFactory
viewModelFactory = activityEntryPoint.viewModelFactory()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
viewModelFactory = screenComponent.viewModelFactory()
configurationViewModel = viewModelProvider.get(ConfigurationViewModel::class.java) configurationViewModel = viewModelProvider.get(ConfigurationViewModel::class.java)
bugReporter = screenComponent.bugReporter() bugReporter = singletonEntryPoint.bugReporter()
pinLocker = screenComponent.pinLocker() pinLocker = singletonEntryPoint.pinLocker()
// Shake detector navigator = singletonEntryPoint.navigator()
rageShake = screenComponent.rageShake() activeSessionHolder = singletonEntryPoint.activeSessionHolder()
navigator = screenComponent.navigator() vectorPreferences = singletonEntryPoint.vectorPreferences()
activeSessionHolder = screenComponent.activeSessionHolder()
vectorPreferences = vectorComponent.vectorPreferences()
configurationViewModel.activityRestarter.observe(this) { configurationViewModel.activityRestarter.observe(this) {
if (!it.hasBeenHandled) { if (!it.hasBeenHandled) {
// Recreate the Activity because configuration has changed // Recreate the Activity because configuration has changed
@ -217,7 +206,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), HasSc
navigator.openPinCode(this, pinStartForActivityResult, PinMode.AUTH) navigator.openPinCode(this, pinStartForActivityResult, PinMode.AUTH)
} }
} }
sessionListener = vectorComponent.sessionListener() sessionListener = singletonEntryPoint.sessionListener()
sessionListener.globalErrorLiveData.observeEvent(this) { sessionListener.globalErrorLiveData.observeEvent(this) {
handleGlobalError(it) handleGlobalError(it)
} }
@ -273,7 +262,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), HasSc
} }
private fun handleCertificateError(certificateError: GlobalError.CertificateError) { private fun handleCertificateError(certificateError: GlobalError.CertificateError) {
vectorComponent() singletonEntryPoint()
.unrecognizedCertificateDialog() .unrecognizedCertificateDialog()
.show(this, .show(this,
certificateError.fingerprint, certificateError.fingerprint,
@ -403,12 +392,6 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), HasSc
bugReporter.inMultiWindowMode = isInMultiWindowMode bugReporter.inMultiWindowMode = isInMultiWindowMode
} }
override fun injector(): ScreenComponent {
return screenComponent
}
protected open fun injectWith(injector: ScreenComponent) = Unit
protected fun createFragment(fragmentClass: Class<out Fragment>, args: Bundle?): Fragment { protected fun createFragment(fragmentClass: Class<out Fragment>, args: Bundle?): Fragment {
return fragmentFactory.instantiate(classLoader, fragmentClass.name).apply { return fragmentFactory.instantiate(classLoader, fragmentClass.name).apply {
arguments = args arguments = args
@ -419,10 +402,6 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), HasSc
* PRIVATE METHODS * PRIVATE METHODS
* ========================================================================================== */ * ========================================================================================== */
internal fun getVectorComponent(): VectorComponent {
return (application as HasVectorInjector).injector()
}
/** /**
* Force to render the activity in fullscreen * Force to render the activity in fullscreen
*/ */

View File

@ -33,8 +33,8 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.jakewharton.rxbinding3.view.clicks import com.jakewharton.rxbinding3.view.clicks
import im.vector.app.core.di.DaggerScreenComponent import dagger.hilt.android.EntryPointAccessors
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ActivityEntryPoint
import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.DimensionConverter
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
@ -47,8 +47,6 @@ import java.util.concurrent.TimeUnit
*/ */
abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomSheetDialogFragment(), MavericksView { abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomSheetDialogFragment(), MavericksView {
private lateinit var screenComponent: ScreenComponent
/* ========================================================================================== /* ==========================================================================================
* View * View
* ========================================================================================== */ * ========================================================================================== */
@ -122,14 +120,11 @@ abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomShe
} }
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
screenComponent = DaggerScreenComponent.factory().create(vectorBaseActivity.getVectorComponent(), vectorBaseActivity) val activityEntryPoint = EntryPointAccessors.fromActivity(vectorBaseActivity, ActivityEntryPoint::class.java)
viewModelFactory = screenComponent.viewModelFactory() viewModelFactory = activityEntryPoint.viewModelFactory()
super.onAttach(context) super.onAttach(context)
injectWith(screenComponent)
} }
protected open fun injectWith(injector: ScreenComponent) = Unit
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
Timber.i("onResume BottomSheet ${javaClass.simpleName}") Timber.i("onResume BottomSheet ${javaClass.simpleName}")

View File

@ -35,12 +35,12 @@ import com.bumptech.glide.util.Util.assertMainThread
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jakewharton.rxbinding3.view.clicks import com.jakewharton.rxbinding3.view.clicks
import dagger.hilt.android.EntryPointAccessors
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.DaggerScreenComponent import im.vector.app.core.di.ActivityEntryPoint
import im.vector.app.core.di.HasScreenInjector
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.extensions.toMvRxBundle
import im.vector.app.features.navigation.Navigator import im.vector.app.features.navigation.Navigator
import im.vector.lib.ui.styles.dialogs.MaterialProgressDialog import im.vector.lib.ui.styles.dialogs.MaterialProgressDialog
@ -50,7 +50,7 @@ import io.reactivex.disposables.Disposable
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView, HasScreenInjector { abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView {
protected val vectorBaseActivity: VectorBaseActivity<*> by lazy { protected val vectorBaseActivity: VectorBaseActivity<*> by lazy {
activity as VectorBaseActivity<*> activity as VectorBaseActivity<*>
@ -60,8 +60,6 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView,
* Navigator and other common objects * Navigator and other common objects
* ========================================================================================== */ * ========================================================================================== */
private lateinit var screenComponent: ScreenComponent
protected lateinit var navigator: Navigator protected lateinit var navigator: Navigator
protected lateinit var errorFormatter: ErrorFormatter protected lateinit var errorFormatter: ErrorFormatter
protected lateinit var unrecognizedCertificateDialog: UnrecognizedCertificateDialog protected lateinit var unrecognizedCertificateDialog: UnrecognizedCertificateDialog
@ -95,12 +93,13 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView,
* ========================================================================================== */ * ========================================================================================== */
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
screenComponent = DaggerScreenComponent.factory().create(vectorBaseActivity.getVectorComponent(), vectorBaseActivity) val singletonEntryPoint = context.singletonEntryPoint()
navigator = screenComponent.navigator() val activityEntryPoint = EntryPointAccessors.fromActivity(vectorBaseActivity, ActivityEntryPoint::class.java)
errorFormatter = screenComponent.errorFormatter() navigator = singletonEntryPoint.navigator()
unrecognizedCertificateDialog = screenComponent.unrecognizedCertificateDialog() errorFormatter = singletonEntryPoint.errorFormatter()
viewModelFactory = screenComponent.viewModelFactory() unrecognizedCertificateDialog = singletonEntryPoint.unrecognizedCertificateDialog()
childFragmentManager.fragmentFactory = screenComponent.fragmentFactory() viewModelFactory = activityEntryPoint.viewModelFactory()
childFragmentManager.fragmentFactory = activityEntryPoint.fragmentFactory()
super.onAttach(context) super.onAttach(context)
} }
@ -161,10 +160,6 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView,
super.onDestroy() super.onDestroy()
} }
override fun injector(): ScreenComponent {
return screenComponent
}
/* ========================================================================================== /* ==========================================================================================
* Restorable * Restorable
* ========================================================================================== */ * ========================================================================================== */

View File

@ -23,7 +23,7 @@ import android.widget.ProgressBar
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder import androidx.preference.PreferenceViewHolder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.vectorComponent import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.api.session.user.model.User
import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.MatrixItem
@ -33,7 +33,7 @@ class UserAvatarPreference : Preference {
private var mAvatarView: ImageView? = null private var mAvatarView: ImageView? = null
private var mLoadingProgressBar: ProgressBar? = null private var mLoadingProgressBar: ProgressBar? = null
private var avatarRenderer: AvatarRenderer = context.vectorComponent().avatarRenderer() private var avatarRenderer: AvatarRenderer = context.singletonEntryPoint().avatarRenderer()
private var userItem: MatrixItem.UserItem? = null private var userItem: MatrixItem.UserItem? = null

View File

@ -26,7 +26,8 @@ import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.media.session.MediaButtonReceiver import androidx.media.session.MediaButtonReceiver
import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.Mavericks
import im.vector.app.core.extensions.vectorComponent import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.features.call.CallArgs import im.vector.app.features.call.CallArgs
import im.vector.app.features.call.VectorCallActivity import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.telecom.CallConnection import im.vector.app.features.call.telecom.CallConnection
@ -42,23 +43,25 @@ import org.matrix.android.sdk.api.logger.LoggerTag
import org.matrix.android.sdk.api.session.room.model.call.EndCallReason import org.matrix.android.sdk.api.session.room.model.call.EndCallReason
import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.MatrixItem
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
private val loggerTag = LoggerTag("CallService", LoggerTag.VOIP) private val loggerTag = LoggerTag("CallService", LoggerTag.VOIP)
/** /**
* Foreground service to manage calls * Foreground service to manage calls
*/ */
@AndroidEntryPoint
class CallService : VectorService() { class CallService : VectorService() {
private val connections = mutableMapOf<String, CallConnection>() private val connections = mutableMapOf<String, CallConnection>()
private val knownCalls = mutableMapOf<String, CallInformation>() private val knownCalls = mutableMapOf<String, CallInformation>()
private val connectedCallIds = mutableSetOf<String>() private val connectedCallIds = mutableSetOf<String>()
private lateinit var notificationManager: NotificationManagerCompat lateinit var notificationManager: NotificationManagerCompat
private lateinit var notificationUtils: NotificationUtils @Inject lateinit var notificationUtils: NotificationUtils
private lateinit var callManager: WebRtcCallManager @Inject lateinit var callManager: WebRtcCallManager
private lateinit var avatarRenderer: AvatarRenderer @Inject lateinit var avatarRenderer: AvatarRenderer
private lateinit var alertManager: PopupAlertManager @Inject lateinit var alertManager: PopupAlertManager
private var callRingPlayerIncoming: CallRingPlayerIncoming? = null private var callRingPlayerIncoming: CallRingPlayerIncoming? = null
private var callRingPlayerOutgoing: CallRingPlayerOutgoing? = null private var callRingPlayerOutgoing: CallRingPlayerOutgoing? = null
@ -80,10 +83,6 @@ class CallService : VectorService() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
notificationManager = NotificationManagerCompat.from(this) notificationManager = NotificationManagerCompat.from(this)
notificationUtils = vectorComponent().notificationUtils()
callManager = vectorComponent().webRtcCallManager()
avatarRenderer = vectorComponent().avatarRenderer()
alertManager = vectorComponent().alertManager()
callRingPlayerIncoming = CallRingPlayerIncoming(applicationContext, notificationUtils) callRingPlayerIncoming = CallRingPlayerIncoming(applicationContext, notificationUtils)
callRingPlayerOutgoing = CallRingPlayerOutgoing(applicationContext) callRingPlayerOutgoing = CallRingPlayerOutgoing(applicationContext)
} }
@ -298,7 +297,7 @@ class CallService : VectorService() {
callId = this.callId, callId = this.callId,
nativeRoomId = this.nativeRoomId, nativeRoomId = this.nativeRoomId,
opponentUserId = this.mxCall.opponentUserId, opponentUserId = this.mxCall.opponentUserId,
opponentMatrixItem = vectorComponent().activeSessionHolder().getSafeActiveSession()?.let { opponentMatrixItem = singletonEntryPoint().activeSessionHolder().getSafeActiveSession()?.let {
this.getOpponentAsMatrixItem(it) this.getOpponentAsMatrixItem(it)
}, },
isVideoCall = this.mxCall.isVideoCall, isVideoCall = this.mxCall.isVideoCall,

View File

@ -30,13 +30,15 @@ import androidx.work.WorkManager
import androidx.work.WorkRequest import androidx.work.WorkRequest
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.vectorComponent
import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.settings.BackgroundSyncMode import im.vector.app.features.settings.BackgroundSyncMode
import org.matrix.android.sdk.internal.session.sync.job.SyncService import org.matrix.android.sdk.internal.session.sync.job.SyncService
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
@AndroidEntryPoint
class VectorSyncService : SyncService() { class VectorSyncService : SyncService() {
companion object { companion object {
@ -71,12 +73,7 @@ class VectorSyncService : SyncService() {
} }
} }
private lateinit var notificationUtils: NotificationUtils @Inject lateinit var notificationUtils: NotificationUtils
override fun onCreate() {
super.onCreate()
notificationUtils = vectorComponent().notificationUtils()
}
override fun getDefaultSyncDelaySeconds() = BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS override fun getDefaultSyncDelaySeconds() = BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS

View File

@ -24,9 +24,9 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.extensions.startSyncing import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
@ -67,6 +67,7 @@ data class MainActivityArgs(
* This Activity, when started with argument, is also doing some cleanup when user signs out, * This Activity, when started with argument, is also doing some cleanup when user signs out,
* clears cache, is logged out, or is soft logged out * clears cache, is logged out, or is soft logged out
*/ */
@AndroidEntryPoint
class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity { class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity {
companion object { companion object {
@ -98,10 +99,6 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
@Inject lateinit var pinLocker: PinLocker @Inject lateinit var pinLocker: PinLocker
@Inject lateinit var popupAlertManager: PopupAlertManager @Inject lateinit var popupAlertManager: PopupAlertManager
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
args = parseArgs() args = parseArgs()

View File

@ -20,6 +20,7 @@ package im.vector.app.features.attachments.preview
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.addFragment import im.vector.app.core.extensions.addFragment
import im.vector.app.core.platform.ToolbarConfigurable import im.vector.app.core.platform.ToolbarConfigurable
@ -28,6 +29,7 @@ import im.vector.app.databinding.ActivitySimpleBinding
import im.vector.app.features.themes.ActivityOtherThemes import im.vector.app.features.themes.ActivityOtherThemes
import org.matrix.android.sdk.api.session.content.ContentAttachmentData import org.matrix.android.sdk.api.session.content.ContentAttachmentData
@AndroidEntryPoint
class AttachmentsPreviewActivity : VectorBaseActivity<ActivitySimpleBinding>(), ToolbarConfigurable { class AttachmentsPreviewActivity : VectorBaseActivity<ActivitySimpleBinding>(), ToolbarConfigurable {
companion object { companion object {

View File

@ -29,8 +29,8 @@ import androidx.browser.customtabs.CustomTabsSession
import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.addFragment import im.vector.app.core.extensions.addFragment
import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.platform.SimpleFragmentActivity
import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.core.utils.openUrlInChromeCustomTab
@ -42,7 +42,8 @@ import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class ReAuthActivity : SimpleFragmentActivity(), ReAuthViewModel.Factory { @AndroidEntryPoint
class ReAuthActivity : SimpleFragmentActivity() {
@Parcelize @Parcelize
data class Args( data class Args(
@ -59,14 +60,6 @@ class ReAuthActivity : SimpleFragmentActivity(), ReAuthViewModel.Factory {
private var customTabsSession: CustomTabsSession? = null private var customTabsSession: CustomTabsSession? = null
@Inject lateinit var authenticationService: AuthenticationService @Inject lateinit var authenticationService: AuthenticationService
@Inject lateinit var reAuthViewModelFactory: ReAuthViewModel.Factory
override fun create(initialState: ReAuthState) = reAuthViewModelFactory.create(initialState)
override fun injectWith(injector: ScreenComponent) {
super.injectWith(injector)
injector.inject(this)
}
private val sharedViewModel: ReAuthViewModel by viewModel() private val sharedViewModel: ReAuthViewModel by viewModel()

View File

@ -16,13 +16,12 @@
package im.vector.app.features.auth package im.vector.app.features.auth
import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.FragmentViewModelContext
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.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
@ -35,20 +34,11 @@ class ReAuthViewModel @AssistedInject constructor(
) : VectorViewModel<ReAuthState, ReAuthActions, ReAuthEvents>(initialState) { ) : VectorViewModel<ReAuthState, ReAuthActions, ReAuthEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<ReAuthViewModel, ReAuthState> {
fun create(initialState: ReAuthState): ReAuthViewModel override fun create(initialState: ReAuthState): ReAuthViewModel
} }
companion object : MavericksViewModelFactory<ReAuthViewModel, ReAuthState> { companion object : MavericksViewModelFactory<ReAuthViewModel, ReAuthState> by hiltMavericksViewModelFactory()
override fun create(viewModelContext: ViewModelContext, state: ReAuthState): ReAuthViewModel? {
val factory = when (viewModelContext) {
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
is ActivityViewModelContext -> viewModelContext.activity as? Factory
}
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
}
}
override fun handle(action: ReAuthActions) = withState { state -> override fun handle(action: ReAuthActions) = withState { state ->
when (action) { when (action) {

View File

@ -23,10 +23,12 @@ import android.view.ViewGroup
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.activityViewModel
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetCallControlsBinding import im.vector.app.databinding.BottomSheetCallControlsBinding
@AndroidEntryPoint
class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetCallControlsBinding>() { class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetCallControlsBinding>() {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetCallControlsBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetCallControlsBinding {
return BottomSheetCallControlsBinding.inflate(inflater, container, false) return BottomSheetCallControlsBinding.inflate(inflater, container, false)

View File

@ -41,8 +41,8 @@ import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL
@ -85,21 +85,16 @@ data class CallArgs(
private val loggerTag = LoggerTag("VectorCallActivity", LoggerTag.VOIP) private val loggerTag = LoggerTag("VectorCallActivity", LoggerTag.VOIP)
@AndroidEntryPoint
class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallControlsView.InteractionListener { class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallControlsView.InteractionListener {
override fun getBinding() = ActivityCallBinding.inflate(layoutInflater) override fun getBinding() = ActivityCallBinding.inflate(layoutInflater)
@Inject lateinit var callManager: WebRtcCallManager
@Inject lateinit var avatarRenderer: AvatarRenderer @Inject lateinit var avatarRenderer: AvatarRenderer
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
private val callViewModel: VectorCallViewModel by viewModel() private val callViewModel: VectorCallViewModel by viewModel()
@Inject lateinit var callManager: WebRtcCallManager
@Inject lateinit var viewModelFactory: VectorCallViewModel.Factory
private val dialPadCallback = object : DialPadFragment.Callback { private val dialPadCallback = object : DialPadFragment.Callback {
override fun onDigitAppended(digit: String) { override fun onDigitAppended(digit: String) {
callViewModel.handle(VectorCallViewActions.SendDtmfDigit(digit)) callViewModel.handle(VectorCallViewActions.SendDtmfDigit(digit))

View File

@ -21,10 +21,11 @@ import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
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.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.call.audio.CallAudioManager import im.vector.app.features.call.audio.CallAudioManager
@ -341,16 +342,9 @@ class VectorCallViewModel @AssistedInject constructor(
} }
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<VectorCallViewModel, VectorCallViewState> {
fun create(initialState: VectorCallViewState): VectorCallViewModel override fun create(initialState: VectorCallViewState): VectorCallViewModel
} }
companion object : MavericksViewModelFactory<VectorCallViewModel, VectorCallViewState> { companion object : MavericksViewModelFactory<VectorCallViewModel, VectorCallViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: VectorCallViewState): VectorCallViewModel {
val callActivity: VectorCallActivity = viewModelContext.activity()
return callActivity.viewModelFactory.create(state)
}
}
} }

View File

@ -22,10 +22,11 @@ import com.airbnb.mvrx.Fail
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.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 kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -46,8 +47,8 @@ class JitsiCallViewModel @AssistedInject constructor(
) : VectorViewModel<JitsiCallViewState, JitsiCallViewActions, JitsiCallViewEvents>(initialState) { ) : VectorViewModel<JitsiCallViewState, JitsiCallViewActions, JitsiCallViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<JitsiCallViewModel, JitsiCallViewState> {
fun create(initialState: JitsiCallViewState): JitsiCallViewModel override fun create(initialState: JitsiCallViewState): JitsiCallViewModel
} }
private var currentWidgetObserver: Job? = null private var currentWidgetObserver: Job? = null
@ -143,24 +144,7 @@ class JitsiCallViewModel @AssistedInject constructor(
} }
} }
companion object : MavericksViewModelFactory<JitsiCallViewModel, JitsiCallViewState> { companion object : MavericksViewModelFactory<JitsiCallViewModel, JitsiCallViewState> by hiltMavericksViewModelFactory() {
const val ENABLE_VIDEO_OPTION = "ENABLE_VIDEO_OPTION" const val ENABLE_VIDEO_OPTION = "ENABLE_VIDEO_OPTION"
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: JitsiCallViewState): JitsiCallViewModel? {
val callActivity: VectorJitsiActivity = viewModelContext.activity()
return callActivity.viewModelFactory.create(state)
}
override fun initialState(viewModelContext: ViewModelContext): JitsiCallViewState? {
val args: VectorJitsiActivity.Args = viewModelContext.args()
return JitsiCallViewState(
roomId = args.roomId,
widgetId = args.widgetId,
enableVideo = args.enableVideo
)
}
} }
} }

View File

@ -26,4 +26,11 @@ data class JitsiCallViewState(
val widgetId: String = "", val widgetId: String = "",
val enableVideo: Boolean = false, val enableVideo: Boolean = false,
val widget: Async<Widget> = Uninitialized val widget: Async<Widget> = Uninitialized
) : MavericksState ) : MavericksState {
constructor(args: VectorJitsiActivity.Args) : this(
roomId = args.roomId,
widgetId = args.widgetId,
enableVideo = args.enableVideo
)
}

View File

@ -33,8 +33,8 @@ import com.airbnb.mvrx.Success
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.facebook.react.modules.core.PermissionListener import com.facebook.react.modules.core.PermissionListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityJitsiBinding import im.vector.app.databinding.ActivityJitsiBinding
@ -48,8 +48,8 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.JsonDict
import timber.log.Timber import timber.log.Timber
import java.net.URL import java.net.URL
import javax.inject.Inject
@AndroidEntryPoint
class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMeetActivityInterface { class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMeetActivityInterface {
@Parcelize @Parcelize
@ -61,16 +61,10 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
override fun getBinding() = ActivityJitsiBinding.inflate(layoutInflater) override fun getBinding() = ActivityJitsiBinding.inflate(layoutInflater)
@Inject lateinit var viewModelFactory: JitsiCallViewModel.Factory
private var jitsiMeetView: JitsiMeetView? = null private var jitsiMeetView: JitsiMeetView? = null
private val jitsiViewModel: JitsiCallViewModel by viewModel() private val jitsiViewModel: JitsiCallViewModel by viewModel()
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View File

@ -19,7 +19,7 @@ package im.vector.app.features.call.service
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import im.vector.app.core.di.HasVectorInjector import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.call.webrtc.WebRtcCallManager
import timber.log.Timber import timber.log.Timber
@ -32,11 +32,7 @@ class CallHeadsUpActionReceiver : BroadcastReceiver() {
} }
override fun onReceive(context: Context, intent: Intent?) { override fun onReceive(context: Context, intent: Intent?) {
val webRtcCallManager = (context.applicationContext as? HasVectorInjector) val webRtcCallManager = context.singletonEntryPoint().webRtcCallManager()
?.injector()
?.webRtcCallManager()
?: return
when (intent?.getIntExtra(EXTRA_CALL_ACTION_KEY, 0)) { when (intent?.getIntExtra(EXTRA_CALL_ACTION_KEY, 0)) {
CALL_ACTION_REJECT -> { CALL_ACTION_REJECT -> {
val callId = intent.getStringExtra(EXTRA_CALL_ID) ?: return val callId = intent.getStringExtra(EXTRA_CALL_ID) ?: return

View File

@ -23,15 +23,11 @@ import android.os.Parcelable
import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityCallTransferBinding import im.vector.app.databinding.ActivityCallTransferBinding
import im.vector.app.features.contactsbook.ContactsBookViewModel
import im.vector.app.features.contactsbook.ContactsBookViewState
import im.vector.app.features.userdirectory.UserListViewModel
import im.vector.app.features.userdirectory.UserListViewState
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import javax.inject.Inject import javax.inject.Inject
@ -40,14 +36,9 @@ data class CallTransferArgs(val callId: String) : Parcelable
private const val USER_LIST_FRAGMENT_TAG = "USER_LIST_FRAGMENT_TAG" private const val USER_LIST_FRAGMENT_TAG = "USER_LIST_FRAGMENT_TAG"
class CallTransferActivity : VectorBaseActivity<ActivityCallTransferBinding>(), @AndroidEntryPoint
CallTransferViewModel.Factory, class CallTransferActivity : VectorBaseActivity<ActivityCallTransferBinding>() {
UserListViewModel.Factory,
ContactsBookViewModel.Factory {
@Inject lateinit var userListViewModelFactory: UserListViewModel.Factory
@Inject lateinit var callTransferViewModelFactory: CallTransferViewModel.Factory
@Inject lateinit var contactsBookViewModelFactory: ContactsBookViewModel.Factory
@Inject lateinit var errorFormatter: ErrorFormatter @Inject lateinit var errorFormatter: ErrorFormatter
private lateinit var sectionsPagerAdapter: CallTransferPagerAdapter private lateinit var sectionsPagerAdapter: CallTransferPagerAdapter
@ -58,22 +49,6 @@ class CallTransferActivity : VectorBaseActivity<ActivityCallTransferBinding>(),
override fun getCoordinatorLayout() = views.vectorCoordinatorLayout override fun getCoordinatorLayout() = views.vectorCoordinatorLayout
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun create(initialState: UserListViewState): UserListViewModel {
return userListViewModelFactory.create(initialState)
}
override fun create(initialState: CallTransferViewState): CallTransferViewModel {
return callTransferViewModelFactory.create(initialState)
}
override fun create(initialState: ContactsBookViewState): ContactsBookViewModel {
return contactsBookViewModelFactory.create(initialState)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
waitingView = views.waitingView.waitingView waitingView = views.waitingView.waitingView

View File

@ -16,13 +16,12 @@
package im.vector.app.features.call.transfer package im.vector.app.features.call.transfer
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.ActivityViewModelContext
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.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.call.dialpad.DialPadLookup import im.vector.app.features.call.dialpad.DialPadLookup
@ -41,18 +40,11 @@ class CallTransferViewModel @AssistedInject constructor(@Assisted initialState:
VectorViewModel<CallTransferViewState, CallTransferAction, CallTransferViewEvents>(initialState) { VectorViewModel<CallTransferViewState, CallTransferAction, CallTransferViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<CallTransferViewModel, CallTransferViewState> {
fun create(initialState: CallTransferViewState): CallTransferViewModel override fun create(initialState: CallTransferViewState): CallTransferViewModel
} }
companion object : MavericksViewModelFactory<CallTransferViewModel, CallTransferViewState> { companion object : MavericksViewModelFactory<CallTransferViewModel, CallTransferViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: CallTransferViewState): CallTransferViewModel? {
val activity: CallTransferActivity = (viewModelContext as ActivityViewModelContext).activity()
return activity.callTransferViewModelFactory.create(state)
}
}
private val call = callManager.getCallById(initialState.callId) private val call = callManager.getCallById(initialState.callId)
private val callListener = object : WebRtcCall.Listener { private val callListener = object : WebRtcCall.Listener {

View File

@ -43,9 +43,8 @@ import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
class ContactsBookFragment @Inject constructor( class ContactsBookFragment @Inject constructor(
private val contactsBookViewModelFactory: ContactsBookViewModel.Factory,
private val contactsBookController: ContactsBookController private val contactsBookController: ContactsBookController
) : VectorBaseFragment<FragmentContactsBookBinding>(), ContactsBookController.Callback, ContactsBookViewModel.Factory { ) : VectorBaseFragment<FragmentContactsBookBinding>(), ContactsBookController.Callback {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentContactsBookBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentContactsBookBinding {
return FragmentContactsBookBinding.inflate(inflater, container, false) return FragmentContactsBookBinding.inflate(inflater, container, false)
@ -58,10 +57,6 @@ class ContactsBookFragment @Inject constructor(
private lateinit var sharedActionViewModel: UserListSharedActionViewModel private lateinit var sharedActionViewModel: UserListSharedActionViewModel
override fun create(initialState: ContactsBookViewState): ContactsBookViewModel {
return contactsBookViewModelFactory.create(initialState)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(UserListSharedActionViewModel::class.java) sharedActionViewModel = activityViewModelProvider.get(UserListSharedActionViewModel::class.java)

View File

@ -17,17 +17,16 @@
package im.vector.app.features.contactsbook package im.vector.app.features.contactsbook
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.ActivityViewModelContext
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.Success import com.airbnb.mvrx.Success
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.contacts.ContactsDataSource import im.vector.app.core.contacts.ContactsDataSource
import im.vector.app.core.contacts.MappedContact import im.vector.app.core.contacts.MappedContact
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.EmptyViewEvents import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
@ -45,20 +44,11 @@ class ContactsBookViewModel @AssistedInject constructor(@Assisted
VectorViewModel<ContactsBookViewState, ContactsBookAction, EmptyViewEvents>(initialState) { VectorViewModel<ContactsBookViewState, ContactsBookAction, EmptyViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<ContactsBookViewModel, ContactsBookViewState> {
fun create(initialState: ContactsBookViewState): ContactsBookViewModel override fun create(initialState: ContactsBookViewState): ContactsBookViewModel
} }
companion object : MavericksViewModelFactory<ContactsBookViewModel, ContactsBookViewState> { companion object : MavericksViewModelFactory<ContactsBookViewModel, ContactsBookViewState> by hiltMavericksViewModelFactory()
override fun create(viewModelContext: ViewModelContext, state: ContactsBookViewState): ContactsBookViewModel? {
val factory = when (viewModelContext) {
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
is ActivityViewModelContext -> viewModelContext.activity as? Factory
}
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
}
}
private var allContacts: List<MappedContact> = emptyList() private var allContacts: List<MappedContact> = emptyList()
private var mappedContacts: List<MappedContact> = emptyList() private var mappedContacts: List<MappedContact> = emptyList()

View File

@ -28,8 +28,8 @@ import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.extensions.addFragment import im.vector.app.core.extensions.addFragment
import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.extensions.addFragmentToBackstack
@ -42,39 +42,22 @@ import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.onPermissionDeniedSnackbar import im.vector.app.core.utils.onPermissionDeniedSnackbar
import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.features.contactsbook.ContactsBookFragment import im.vector.app.features.contactsbook.ContactsBookFragment
import im.vector.app.features.contactsbook.ContactsBookViewModel
import im.vector.app.features.contactsbook.ContactsBookViewState
import im.vector.app.features.userdirectory.UserListFragment import im.vector.app.features.userdirectory.UserListFragment
import im.vector.app.features.userdirectory.UserListFragmentArgs import im.vector.app.features.userdirectory.UserListFragmentArgs
import im.vector.app.features.userdirectory.UserListSharedAction import im.vector.app.features.userdirectory.UserListSharedAction
import im.vector.app.features.userdirectory.UserListSharedActionViewModel import im.vector.app.features.userdirectory.UserListSharedActionViewModel
import im.vector.app.features.userdirectory.UserListViewModel
import im.vector.app.features.userdirectory.UserListViewState
import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
import java.net.HttpURLConnection import java.net.HttpURLConnection
import javax.inject.Inject import javax.inject.Inject
class CreateDirectRoomActivity : SimpleFragmentActivity(), UserListViewModel.Factory, CreateDirectRoomViewModel.Factory, ContactsBookViewModel.Factory { @AndroidEntryPoint
class CreateDirectRoomActivity : SimpleFragmentActivity() {
private val viewModel: CreateDirectRoomViewModel by viewModel() private val viewModel: CreateDirectRoomViewModel by viewModel()
private lateinit var sharedActionViewModel: UserListSharedActionViewModel private lateinit var sharedActionViewModel: UserListSharedActionViewModel
@Inject lateinit var userListViewModelFactory: UserListViewModel.Factory
@Inject lateinit var createDirectRoomViewModelFactory: CreateDirectRoomViewModel.Factory
@Inject lateinit var contactsBookViewModelFactory: ContactsBookViewModel.Factory
@Inject lateinit var errorFormatter: ErrorFormatter @Inject lateinit var errorFormatter: ErrorFormatter
override fun injectWith(injector: ScreenComponent) {
super.injectWith(injector)
injector.inject(this)
}
override fun create(initialState: UserListViewState) = userListViewModelFactory.create(initialState)
override fun create(initialState: CreateDirectRoomViewState) = createDirectRoomViewModelFactory.create(initialState)
override fun create(initialState: ContactsBookViewState) = contactsBookViewModelFactory.create(initialState)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
views.toolbar.visibility = View.GONE views.toolbar.visibility = View.GONE

View File

@ -16,16 +16,14 @@
package im.vector.app.features.createdirect package im.vector.app.features.createdirect
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.ActivityViewModelContext
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.Success import com.airbnb.mvrx.Success
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.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.mvrx.runCatchingToAsync import im.vector.app.core.mvrx.runCatchingToAsync
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
@ -45,21 +43,11 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
VectorViewModel<CreateDirectRoomViewState, CreateDirectRoomAction, CreateDirectRoomViewEvents>(initialState) { VectorViewModel<CreateDirectRoomViewState, CreateDirectRoomAction, CreateDirectRoomViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<CreateDirectRoomViewModel, CreateDirectRoomViewState> {
fun create(initialState: CreateDirectRoomViewState): CreateDirectRoomViewModel override fun create(initialState: CreateDirectRoomViewState): CreateDirectRoomViewModel
} }
companion object : MavericksViewModelFactory<CreateDirectRoomViewModel, CreateDirectRoomViewState> { companion object : MavericksViewModelFactory<CreateDirectRoomViewModel, CreateDirectRoomViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: CreateDirectRoomViewState): CreateDirectRoomViewModel? {
val factory = when (viewModelContext) {
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
is ActivityViewModelContext -> viewModelContext.activity as? Factory
}
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
}
}
override fun handle(action: CreateDirectRoomAction) { override fun handle(action: CreateDirectRoomAction) {
when (action) { when (action) {

View File

@ -19,7 +19,9 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.extensions.addFragmentToBackstack
import im.vector.app.core.extensions.observeEvent import im.vector.app.core.extensions.observeEvent
import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.registerStartForActivityResult
@ -28,7 +30,9 @@ import im.vector.app.core.platform.SimpleFragmentActivity
import im.vector.app.core.ui.views.KeysBackupBanner import im.vector.app.core.ui.views.KeysBackupBanner
import im.vector.app.features.crypto.quads.SharedSecureStorageActivity import im.vector.app.features.crypto.quads.SharedSecureStorageActivity
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
import javax.inject.Inject
@AndroidEntryPoint
class KeysBackupRestoreActivity : SimpleFragmentActivity() { class KeysBackupRestoreActivity : SimpleFragmentActivity() {
companion object { companion object {
@ -48,10 +52,12 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() {
super.onBackPressed() super.onBackPressed()
} }
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
override fun initUiAndData() { override fun initUiAndData() {
super.initUiAndData() super.initUiAndData()
viewModel = viewModelProvider.get(KeysBackupRestoreSharedViewModel::class.java) viewModel = viewModelProvider.get(KeysBackupRestoreSharedViewModel::class.java)
viewModel.initSession(session) viewModel.initSession(activeSessionHolder.getActiveSession())
viewModel.keySourceModel.observe(this) { keySource -> viewModel.keySourceModel.observe(this) { keySource ->
if (keySource != null && !keySource.isInQuadS && supportFragmentManager.fragments.isEmpty()) { if (keySource != null && !keySource.isInQuadS && supportFragmentManager.fragments.isEmpty()) {

View File

@ -21,13 +21,13 @@ import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.platform.SimpleFragmentActivity
import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.platform.WaitingViewData
import javax.inject.Inject
@AndroidEntryPoint
class KeysBackupManageActivity : SimpleFragmentActivity() { class KeysBackupManageActivity : SimpleFragmentActivity() {
companion object { companion object {
@ -40,12 +40,6 @@ class KeysBackupManageActivity : SimpleFragmentActivity() {
override fun getTitleRes() = R.string.encryption_message_recovery override fun getTitleRes() = R.string.encryption_message_recovery
private val viewModel: KeysBackupSettingsViewModel by viewModel() private val viewModel: KeysBackupSettingsViewModel by viewModel()
@Inject lateinit var keysBackupSettingsViewModelFactory: KeysBackupSettingsViewModel.Factory
override fun injectWith(injector: ScreenComponent) {
super.injectWith(injector)
injector.inject(this)
}
override fun initUiAndData() { override fun initUiAndData() {
super.initUiAndData() super.initUiAndData()

View File

@ -15,16 +15,16 @@
*/ */
package im.vector.app.features.crypto.keysbackup.settings package im.vector.app.features.crypto.keysbackup.settings
import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
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.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
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
import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCallback
@ -41,18 +41,11 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
KeysBackupStateListener { KeysBackupStateListener {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<KeysBackupSettingsViewModel, KeysBackupSettingViewState> {
fun create(initialState: KeysBackupSettingViewState): KeysBackupSettingsViewModel override fun create(initialState: KeysBackupSettingViewState): KeysBackupSettingsViewModel
} }
companion object : MavericksViewModelFactory<KeysBackupSettingsViewModel, KeysBackupSettingViewState> { companion object : MavericksViewModelFactory<KeysBackupSettingsViewModel, KeysBackupSettingViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: KeysBackupSettingViewState): KeysBackupSettingsViewModel? {
val activity: KeysBackupManageActivity = (viewModelContext as ActivityViewModelContext).activity()
return activity.keysBackupSettingsViewModelFactory.create(state)
}
}
private val keysBackupService: KeysBackupService = session.cryptoService().keysBackupService() private val keysBackupService: KeysBackupService = session.cryptoService().keysBackupService()

View File

@ -23,8 +23,9 @@ import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.dialogs.ExportKeysDialog import im.vector.app.core.dialogs.ExportKeysDialog
import im.vector.app.core.extensions.observeEvent import im.vector.app.core.extensions.observeEvent
import im.vector.app.core.extensions.queryExportKeys import im.vector.app.core.extensions.queryExportKeys
@ -36,6 +37,7 @@ import im.vector.app.features.crypto.keys.KeysExporter
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint
class KeysBackupSetupActivity : SimpleFragmentActivity() { class KeysBackupSetupActivity : SimpleFragmentActivity() {
override fun getTitleRes() = R.string.title_activity_keys_backup_setup override fun getTitleRes() = R.string.title_activity_keys_backup_setup
@ -43,10 +45,10 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
private lateinit var viewModel: KeysBackupSetupSharedViewModel private lateinit var viewModel: KeysBackupSetupSharedViewModel
@Inject lateinit var keysExporter: KeysExporter @Inject lateinit var keysExporter: KeysExporter
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
override fun injectWith(injector: ScreenComponent) { private val session by lazy {
super.injectWith(injector) activeSessionHolder.getActiveSession()
injector.inject(this)
} }
override fun initUiAndData() { override fun initUiAndData() {

View File

@ -28,8 +28,8 @@ import androidx.fragment.app.FragmentOnAttachListener
import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.commitTransaction
import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.platform.SimpleFragmentActivity
@ -39,6 +39,7 @@ import kotlinx.parcelize.Parcelize
import javax.inject.Inject import javax.inject.Inject
import kotlin.reflect.KClass import kotlin.reflect.KClass
@AndroidEntryPoint
class SharedSecureStorageActivity : class SharedSecureStorageActivity :
SimpleFragmentActivity(), SimpleFragmentActivity(),
VectorBaseBottomSheetDialogFragment.ResultListener, VectorBaseBottomSheetDialogFragment.ResultListener,
@ -52,14 +53,8 @@ class SharedSecureStorageActivity :
) : Parcelable ) : Parcelable
private val viewModel: SharedSecureStorageViewModel by viewModel() private val viewModel: SharedSecureStorageViewModel by viewModel()
@Inject lateinit var viewModelFactory: SharedSecureStorageViewModel.Factory
@Inject lateinit var errorFormatter: ErrorFormatter @Inject lateinit var errorFormatter: ErrorFormatter
override fun injectWith(injector: ScreenComponent) {
super.injectWith(injector)
injector.inject(this)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
supportFragmentManager.addFragmentOnAttachListener(this) supportFragmentManager.addFragmentOnAttachListener(this)

View File

@ -19,16 +19,16 @@ package im.vector.app.features.crypto.quads
import com.airbnb.mvrx.Async import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Mavericks
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.platform.WaitingViewData import im.vector.app.core.platform.WaitingViewData
@ -54,8 +54,18 @@ data class SharedSecureStorageViewState(
val step: Step = Step.EnterPassphrase, val step: Step = Step.EnterPassphrase,
val activeDeviceCount: Int = 0, val activeDeviceCount: Int = 0,
val showResetAllAction: Boolean = false, val showResetAllAction: Boolean = false,
val userId: String = "" val userId: String = "",
val keyId: String?,
val requestedSecrets: List<String>,
val resultKeyStoreAlias: String
) : MavericksState { ) : MavericksState {
constructor(args: SharedSecureStorageActivity.Args) : this(
keyId = args.keyId,
requestedSecrets = args.requestedSecrets,
resultKeyStoreAlias = args.resultKeyStoreAlias
)
enum class Step { enum class Step {
EnterPassphrase, EnterPassphrase,
EnterKey, EnterKey,
@ -64,23 +74,22 @@ data class SharedSecureStorageViewState(
} }
class SharedSecureStorageViewModel @AssistedInject constructor( class SharedSecureStorageViewModel @AssistedInject constructor(
@Assisted initialState: SharedSecureStorageViewState, @Assisted private val initialState: SharedSecureStorageViewState,
@Assisted val args: SharedSecureStorageActivity.Args,
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val session: Session) : private val session: Session) :
VectorViewModel<SharedSecureStorageViewState, SharedSecureStorageAction, SharedSecureStorageViewEvent>(initialState) { VectorViewModel<SharedSecureStorageViewState, SharedSecureStorageAction, SharedSecureStorageViewEvent>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<SharedSecureStorageViewModel, SharedSecureStorageViewState> {
fun create(initialState: SharedSecureStorageViewState, args: SharedSecureStorageActivity.Args): SharedSecureStorageViewModel override fun create(initialState: SharedSecureStorageViewState): SharedSecureStorageViewModel
} }
init { init {
setState { setState {
copy(userId = session.myUserId) copy(userId = session.myUserId)
} }
val isValid = session.sharedSecretStorageService.checkShouldBeAbleToAccessSecrets(args.requestedSecrets, args.keyId) is IntegrityResult.Success val integrityResult = session.sharedSecretStorageService.checkShouldBeAbleToAccessSecrets(initialState.requestedSecrets, initialState.keyId)
if (!isValid) { if (integrityResult !is IntegrityResult.Success) {
_viewEvents.post( _viewEvents.post(
SharedSecureStorageViewEvent.Error( SharedSecureStorageViewEvent.Error(
stringProvider.getString(R.string.enter_secret_storage_invalid), stringProvider.getString(R.string.enter_secret_storage_invalid),
@ -88,7 +97,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
) )
) )
} }
val keyResult = args.keyId?.let { session.sharedSecretStorageService.getKey(it) } val keyResult = initialState.keyId?.let { session.sharedSecretStorageService.getKey(it) }
?: session.sharedSecretStorageService.getDefaultKey() ?: session.sharedSecretStorageService.getDefaultKey()
if (!keyResult.isSuccess()) { if (!keyResult.isSuccess()) {
@ -218,7 +227,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
} }
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
args.requestedSecrets.forEach { initialState.requestedSecrets.forEach {
if (session.accountDataService().getUserAccountDataEvent(it) != null) { if (session.accountDataService().getUserAccountDataEvent(it) != null) {
val res = session.sharedSecretStorageService.getSecret( val res = session.sharedSecretStorageService.getSecret(
name = it, name = it,
@ -235,7 +244,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
_viewEvents.post(SharedSecureStorageViewEvent.HideModalLoading) _viewEvents.post(SharedSecureStorageViewEvent.HideModalLoading)
val safeForIntentCypher = ByteArrayOutputStream().also { val safeForIntentCypher = ByteArrayOutputStream().also {
it.use { it.use {
session.securelyStoreObject(decryptedSecretMap as Map<String, String>, args.resultKeyStoreAlias, it) session.securelyStoreObject(decryptedSecretMap as Map<String, String>, initialState.resultKeyStoreAlias, it)
} }
}.toByteArray().toBase64NoPadding() }.toByteArray().toBase64NoPadding()
_viewEvents.post(SharedSecureStorageViewEvent.FinishSuccess(safeForIntentCypher)) _viewEvents.post(SharedSecureStorageViewEvent.FinishSuccess(safeForIntentCypher))
@ -287,7 +296,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
) )
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
args.requestedSecrets.forEach { initialState.requestedSecrets.forEach {
if (session.accountDataService().getUserAccountDataEvent(it) != null) { if (session.accountDataService().getUserAccountDataEvent(it) != null) {
val res = session.sharedSecretStorageService.getSecret( val res = session.sharedSecretStorageService.getSecret(
name = it, name = it,
@ -304,7 +313,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
_viewEvents.post(SharedSecureStorageViewEvent.HideModalLoading) _viewEvents.post(SharedSecureStorageViewEvent.HideModalLoading)
val safeForIntentCypher = ByteArrayOutputStream().also { val safeForIntentCypher = ByteArrayOutputStream().also {
it.use { it.use {
session.securelyStoreObject(decryptedSecretMap as Map<String, String>, args.resultKeyStoreAlias, it) session.securelyStoreObject(decryptedSecretMap as Map<String, String>, initialState.resultKeyStoreAlias, it)
} }
}.toByteArray().toBase64NoPadding() }.toByteArray().toBase64NoPadding()
_viewEvents.post(SharedSecureStorageViewEvent.FinishSuccess(safeForIntentCypher)) _viewEvents.post(SharedSecureStorageViewEvent.FinishSuccess(safeForIntentCypher))
@ -320,13 +329,5 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
_viewEvents.post(SharedSecureStorageViewEvent.Dismiss) _viewEvents.post(SharedSecureStorageViewEvent.Dismiss)
} }
companion object : MavericksViewModelFactory<SharedSecureStorageViewModel, SharedSecureStorageViewState> { companion object : MavericksViewModelFactory<SharedSecureStorageViewModel, SharedSecureStorageViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: SharedSecureStorageViewState): SharedSecureStorageViewModel? {
val activity: SharedSecureStorageActivity = viewModelContext.activity()
val args: SharedSecureStorageActivity.Args = activity.intent.getParcelableExtra(Mavericks.KEY_ARG) ?: error("Missing args")
return activity.viewModelFactory.create(state, args)
}
}
} }

View File

@ -33,8 +33,8 @@ import androidx.fragment.app.FragmentManager
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
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.extensions.registerStartForActivityResult import im.vector.app.core.extensions.registerStartForActivityResult
@ -43,9 +43,9 @@ import im.vector.app.databinding.BottomSheetBootstrapBinding
import im.vector.app.features.auth.ReAuthActivity import im.vector.app.features.auth.ReAuthActivity
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import javax.inject.Inject
import kotlin.reflect.KClass import kotlin.reflect.KClass
@AndroidEntryPoint
class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetBootstrapBinding>() { class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetBootstrapBinding>() {
@Parcelize @Parcelize
@ -55,15 +55,8 @@ 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 injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetBootstrapBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetBootstrapBinding {
return BottomSheetBootstrapBinding.inflate(inflater, container, false) return BottomSheetBootstrapBinding.inflate(inflater, container, false)
} }

View File

@ -16,26 +16,24 @@
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.Loading import com.airbnb.mvrx.Loading
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 com.nulabinc.zxcvbn.Zxcvbn import com.nulabinc.zxcvbn.Zxcvbn
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.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
import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.platform.WaitingViewData
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.features.auth.ReAuthActivity import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.login.ReAuthHelper
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UIABaseAuth
@ -59,13 +57,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 +69,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 +82,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 +408,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 +514,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 +545,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,7 @@ 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

@ -28,8 +28,8 @@ import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
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.extensions.registerStartForActivityResult import im.vector.app.core.extensions.registerStartForActivityResult
@ -61,6 +61,7 @@ import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import kotlin.reflect.KClass import kotlin.reflect.KClass
@AndroidEntryPoint
class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetVerificationBinding>() { class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetVerificationBinding>() {
@Parcelize @Parcelize
@ -75,18 +76,11 @@ 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
private val viewModel by fragmentViewModel(VerificationBottomSheetViewModel::class) private val viewModel by fragmentViewModel(VerificationBottomSheetViewModel::class)
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationBinding {
return BottomSheetVerificationBinding.inflate(inflater, container, false) return BottomSheetVerificationBinding.inflate(inflater, container, false)
} }

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

@ -40,7 +40,6 @@ import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class VerificationChooseMethodFragment @Inject constructor( class VerificationChooseMethodFragment @Inject constructor(
val verificationChooseMethodViewModelFactory: VerificationChooseMethodViewModel.Factory,
val controller: VerificationChooseMethodController val controller: VerificationChooseMethodController
) : VectorBaseFragment<BottomSheetVerificationChildFragmentBinding>(), ) : VectorBaseFragment<BottomSheetVerificationChildFragmentBinding>(),
VerificationChooseMethodController.Listener { VerificationChooseMethodController.Listener {

View File

@ -15,14 +15,16 @@
*/ */
package im.vector.app.features.crypto.verification.choose package im.vector.app.features.crypto.verification.choose
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.ViewModelContext 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.HasScreenInjector import dagger.hilt.EntryPoints
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.SingletonEntryPoint
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
@ -50,6 +52,10 @@ class VerificationChooseMethodViewModel @AssistedInject constructor(
private val session: Session private val session: Session
) : VectorViewModel<VerificationChooseMethodViewState, EmptyAction, EmptyViewEvents>(initialState), VerificationService.Listener { ) : VectorViewModel<VerificationChooseMethodViewState, EmptyAction, EmptyViewEvents>(initialState), VerificationService.Listener {
init {
session.cryptoService().verificationService().addListener(this)
}
override fun transactionCreated(tx: VerificationTransaction) { override fun transactionCreated(tx: VerificationTransaction) {
transactionUpdated(tx) transactionUpdated(tx)
} }
@ -81,28 +87,15 @@ class VerificationChooseMethodViewModel @AssistedInject constructor(
} }
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<VerificationChooseMethodViewModel, VerificationChooseMethodViewState> {
fun create(initialState: VerificationChooseMethodViewState): VerificationChooseMethodViewModel override fun create(initialState: VerificationChooseMethodViewState): VerificationChooseMethodViewModel
} }
init { companion object : MavericksViewModelFactory<VerificationChooseMethodViewModel, VerificationChooseMethodViewState> by hiltMavericksViewModelFactory() {
session.cryptoService().verificationService().addListener(this)
}
override fun onCleared() { override fun initialState(viewModelContext: ViewModelContext): VerificationChooseMethodViewState {
session.cryptoService().verificationService().removeListener(this)
super.onCleared()
}
companion object : MavericksViewModelFactory<VerificationChooseMethodViewModel, VerificationChooseMethodViewState> {
override fun create(viewModelContext: ViewModelContext, state: VerificationChooseMethodViewState): VerificationChooseMethodViewModel? {
val fragment: VerificationChooseMethodFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.verificationChooseMethodViewModelFactory.create(state)
}
override fun initialState(viewModelContext: ViewModelContext): VerificationChooseMethodViewState? {
val args: VerificationBottomSheet.VerificationArgs = viewModelContext.args() val args: VerificationBottomSheet.VerificationArgs = viewModelContext.args()
val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession() val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession()
val verificationService = session.cryptoService().verificationService() val verificationService = session.cryptoService().verificationService()
val pvr = verificationService.getExistingVerificationRequest(args.otherUserId, args.verificationId) val pvr = verificationService.getExistingVerificationRequest(args.otherUserId, args.verificationId)
@ -121,5 +114,10 @@ class VerificationChooseMethodViewModel @AssistedInject constructor(
} }
} }
override fun onCleared() {
session.cryptoService().verificationService().removeListener(this)
super.onCleared()
}
override fun handle(action: EmptyAction) {} override fun handle(action: EmptyAction) {}
} }

View File

@ -31,7 +31,6 @@ import im.vector.app.features.crypto.verification.VerificationBottomSheetViewMod
import javax.inject.Inject import javax.inject.Inject
class VerificationEmojiCodeFragment @Inject constructor( class VerificationEmojiCodeFragment @Inject constructor(
val viewModelFactory: VerificationEmojiCodeViewModel.Factory,
val controller: VerificationEmojiCodeController val controller: VerificationEmojiCodeController
) : VectorBaseFragment<BottomSheetVerificationChildFragmentBinding>(), ) : VectorBaseFragment<BottomSheetVerificationChildFragmentBinding>(),
VerificationEmojiCodeController.Listener { VerificationEmojiCodeController.Listener {

View File

@ -17,7 +17,6 @@ package im.vector.app.features.crypto.verification.emoji
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
@ -27,7 +26,10 @@ 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.HasScreenInjector import dagger.hilt.EntryPoints
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.SingletonEntryPoint
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
@ -151,20 +153,15 @@ class VerificationEmojiCodeViewModel @AssistedInject constructor(
} }
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<VerificationEmojiCodeViewModel, VerificationEmojiCodeViewState> {
fun create(initialState: VerificationEmojiCodeViewState): VerificationEmojiCodeViewModel override fun create(initialState: VerificationEmojiCodeViewState): VerificationEmojiCodeViewModel
} }
companion object : MavericksViewModelFactory<VerificationEmojiCodeViewModel, VerificationEmojiCodeViewState> { companion object : MavericksViewModelFactory<VerificationEmojiCodeViewModel, VerificationEmojiCodeViewState> by hiltMavericksViewModelFactory() {
override fun create(viewModelContext: ViewModelContext, state: VerificationEmojiCodeViewState): VerificationEmojiCodeViewModel? {
val factory = (viewModelContext as FragmentViewModelContext).fragment<VerificationEmojiCodeFragment>().viewModelFactory
return factory.create(state)
}
override fun initialState(viewModelContext: ViewModelContext): VerificationEmojiCodeViewState? { override fun initialState(viewModelContext: ViewModelContext): VerificationEmojiCodeViewState? {
val args = viewModelContext.args<VerificationBottomSheet.VerificationArgs>() val args = viewModelContext.args<VerificationBottomSheet.VerificationArgs>()
val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession() val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession()
val matrixItem = session.getUser(args.otherUserId)?.toMatrixItem() val matrixItem = session.getUser(args.otherUserId)?.toMatrixItem()
return VerificationEmojiCodeViewState( return VerificationEmojiCodeViewState(

View File

@ -33,8 +33,8 @@ import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.extensions.toMvRxBundle
@ -45,10 +45,9 @@ import kotlinx.parcelize.Parcelize
import org.billcarsonfr.jsonviewer.JSonViewerFragment import org.billcarsonfr.jsonviewer.JSonViewerFragment
import javax.inject.Inject import javax.inject.Inject
class RoomDevToolActivity : SimpleFragmentActivity(), RoomDevToolViewModel.Factory, @AndroidEntryPoint
FragmentManager.OnBackStackChangedListener { class RoomDevToolActivity : SimpleFragmentActivity(), FragmentManager.OnBackStackChangedListener {
@Inject lateinit var viewModelFactory: RoomDevToolViewModel.Factory
@Inject lateinit var colorProvider: ColorProvider @Inject lateinit var colorProvider: ColorProvider
// private lateinit var viewModel: RoomDevToolViewModel // private lateinit var viewModel: RoomDevToolViewModel
@ -65,15 +64,6 @@ class RoomDevToolActivity : SimpleFragmentActivity(), RoomDevToolViewModel.Facto
val roomId: String val roomId: String
) : Parcelable ) : Parcelable
override fun injectWith(injector: ScreenComponent) {
super.injectWith(injector)
injector.inject(this)
}
override fun create(initialState: RoomDevToolViewState): RoomDevToolViewModel {
return viewModelFactory.create(initialState)
}
override fun initUiAndData() { override fun initUiAndData() {
super.initUiAndData() super.initUiAndData()
viewModel.subscribe(this) { viewModel.subscribe(this) {

View File

@ -16,19 +16,17 @@
package im.vector.app.features.devtools package im.vector.app.features.devtools
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.ActivityViewModelContext
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.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.ViewModelContext
import com.squareup.moshi.Types import com.squareup.moshi.Types
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.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
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
@ -51,21 +49,11 @@ class RoomDevToolViewModel @AssistedInject constructor(
) : VectorViewModel<RoomDevToolViewState, RoomDevToolAction, DevToolsViewEvents>(initialState) { ) : VectorViewModel<RoomDevToolViewState, RoomDevToolAction, DevToolsViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<RoomDevToolViewModel, RoomDevToolViewState> {
fun create(initialState: RoomDevToolViewState): RoomDevToolViewModel override fun create(initialState: RoomDevToolViewState): RoomDevToolViewModel
} }
companion object : MavericksViewModelFactory<RoomDevToolViewModel, RoomDevToolViewState> { companion object : MavericksViewModelFactory<RoomDevToolViewModel, RoomDevToolViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: RoomDevToolViewState): RoomDevToolViewModel {
val factory = when (viewModelContext) {
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
is ActivityViewModelContext -> viewModelContext.activity as? Factory
}
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
}
}
init { init {
session.getRoom(initialState.roomId) session.getRoom(initialState.roomId)

View File

@ -45,8 +45,7 @@ import org.matrix.android.sdk.api.session.terms.TermsService
import javax.inject.Inject import javax.inject.Inject
class DiscoverySettingsFragment @Inject constructor( class DiscoverySettingsFragment @Inject constructor(
private val controller: DiscoverySettingsController, private val controller: DiscoverySettingsController
val viewModelFactory: DiscoverySettingsViewModel.Factory
) : VectorBaseFragment<FragmentGenericRecyclerBinding>(), ) : VectorBaseFragment<FragmentGenericRecyclerBinding>(),
DiscoverySettingsController.Listener { DiscoverySettingsController.Listener {

View File

@ -17,16 +17,16 @@ package im.vector.app.features.discovery
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.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
@ -49,18 +49,11 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
) : VectorViewModel<DiscoverySettingsState, DiscoverySettingsAction, DiscoverySettingsViewEvents>(initialState) { ) : VectorViewModel<DiscoverySettingsState, DiscoverySettingsAction, DiscoverySettingsViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<DiscoverySettingsViewModel, DiscoverySettingsState> {
fun create(initialState: DiscoverySettingsState): DiscoverySettingsViewModel override fun create(initialState: DiscoverySettingsState): DiscoverySettingsViewModel
} }
companion object : MavericksViewModelFactory<DiscoverySettingsViewModel, DiscoverySettingsState> { companion object : MavericksViewModelFactory<DiscoverySettingsViewModel, DiscoverySettingsState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: DiscoverySettingsState): DiscoverySettingsViewModel? {
val fragment: DiscoverySettingsFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.viewModelFactory.create(state)
}
}
private val identityService = session.identityService() private val identityService = session.identityService()
private val termsService: TermsService = session private val termsService: TermsService = session

View File

@ -41,7 +41,6 @@ import org.matrix.android.sdk.api.session.terms.TermsService
import javax.inject.Inject import javax.inject.Inject
class SetIdentityServerFragment @Inject constructor( class SetIdentityServerFragment @Inject constructor(
val viewModelFactory: SetIdentityServerViewModel.Factory,
val colorProvider: ColorProvider val colorProvider: ColorProvider
) : VectorBaseFragment<FragmentSetIdentityServerBinding>() { ) : VectorBaseFragment<FragmentSetIdentityServerBinding>() {

View File

@ -15,15 +15,16 @@
*/ */
package im.vector.app.features.discovery.change package im.vector.app.features.discovery.change
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.ViewModelContext 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 dagger.hilt.EntryPoints
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.HasScreenInjector import im.vector.app.core.di.MavericksAssistedViewModelFactory
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 im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
@ -42,26 +43,19 @@ class SetIdentityServerViewModel @AssistedInject constructor(
VectorViewModel<SetIdentityServerState, SetIdentityServerAction, SetIdentityServerViewEvents>(initialState) { VectorViewModel<SetIdentityServerState, SetIdentityServerAction, SetIdentityServerViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<SetIdentityServerViewModel, SetIdentityServerState> {
fun create(initialState: SetIdentityServerState): SetIdentityServerViewModel override fun create(initialState: SetIdentityServerState): SetIdentityServerViewModel
} }
companion object : MavericksViewModelFactory<SetIdentityServerViewModel, SetIdentityServerState> { companion object : MavericksViewModelFactory<SetIdentityServerViewModel, SetIdentityServerState> by hiltMavericksViewModelFactory() {
override fun initialState(viewModelContext: ViewModelContext): SetIdentityServerState? {
val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession()
override fun initialState(viewModelContext: ViewModelContext): SetIdentityServerState {
val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession()
return SetIdentityServerState( return SetIdentityServerState(
homeServerUrl = session.sessionParams.homeServerUrl, homeServerUrl = session.sessionParams.homeServerUrl,
defaultIdentityServerUrl = session.identityService().getDefaultIdentityServer() defaultIdentityServerUrl = session.identityService().getDefaultIdentityServer()
) )
} }
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: SetIdentityServerState): SetIdentityServerViewModel? {
val fragment: SetIdentityServerFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.viewModelFactory.create(state)
}
} }
var currentWantedUrl: String? = null var currentWantedUrl: String? = null

View File

@ -34,10 +34,10 @@ import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.AppStateHandler import im.vector.app.AppStateHandler
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.registerStartForActivityResult
@ -72,7 +72,6 @@ import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet
import im.vector.app.features.spaces.share.ShareSpaceBottomSheet import im.vector.app.features.spaces.share.ShareSpaceBottomSheet
import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import im.vector.app.features.workers.signout.ServerBackupStatusViewState
import im.vector.app.push.fcm.FcmHelper import im.vector.app.push.fcm.FcmHelper
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -91,13 +90,10 @@ data class HomeActivityArgs(
val inviteNotificationRoomId: String? = null val inviteNotificationRoomId: String? = null
) : Parcelable ) : Parcelable
@AndroidEntryPoint
class HomeActivity : class HomeActivity :
VectorBaseActivity<ActivityHomeBinding>(), VectorBaseActivity<ActivityHomeBinding>(),
ToolbarConfigurable, ToolbarConfigurable,
UnknownDeviceDetectorSharedViewModel.Factory,
ServerBackupStatusViewModel.Factory,
UnreadMessagesSharedViewModel.Factory,
PromoteRestrictedViewModel.Factory,
NavigationInterceptor, NavigationInterceptor,
SpaceInviteBottomSheet.InteractionListener, SpaceInviteBottomSheet.InteractionListener,
MatrixToBottomSheet.InteractionListener { MatrixToBottomSheet.InteractionListener {
@ -105,11 +101,8 @@ 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()
@Inject lateinit var serverBackupviewModelFactory: ServerBackupStatusViewModel.Factory
@Inject lateinit var promoteRestrictedViewModelFactory: PromoteRestrictedViewModel.Factory
private val promoteRestrictedViewModel: PromoteRestrictedViewModel by viewModel() private val promoteRestrictedViewModel: PromoteRestrictedViewModel by viewModel()
@Inject lateinit var activeSessionHolder: ActiveSessionHolder @Inject lateinit var activeSessionHolder: ActiveSessionHolder
@ -119,8 +112,6 @@ class HomeActivity :
@Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var popupAlertManager: PopupAlertManager @Inject lateinit var popupAlertManager: PopupAlertManager
@Inject lateinit var shortcutsHandler: ShortcutsHandler @Inject lateinit var shortcutsHandler: ShortcutsHandler
@Inject lateinit var unknownDeviceViewModelFactory: UnknownDeviceDetectorSharedViewModel.Factory
@Inject lateinit var unreadMessagesSharedViewModelFactory: UnreadMessagesSharedViewModel.Factory
@Inject lateinit var permalinkHandler: PermalinkHandler @Inject lateinit var permalinkHandler: PermalinkHandler
@Inject lateinit var avatarRenderer: AvatarRenderer @Inject lateinit var avatarRenderer: AvatarRenderer
@Inject lateinit var initSyncStepFormatter: InitSyncStepFormatter @Inject lateinit var initSyncStepFormatter: InitSyncStepFormatter
@ -175,22 +166,6 @@ class HomeActivity :
override fun getBinding() = ActivityHomeBinding.inflate(layoutInflater) override fun getBinding() = ActivityHomeBinding.inflate(layoutInflater)
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun create(initialState: UnknownDevicesState): UnknownDeviceDetectorSharedViewModel {
return unknownDeviceViewModelFactory.create(initialState)
}
override fun create(initialState: ServerBackupStatusViewState): ServerBackupStatusViewModel {
return serverBackupviewModelFactory.create(initialState)
}
override fun create(initialState: UnreadMessagesState): UnreadMessagesSharedViewModel {
return unreadMessagesSharedViewModelFactory.create(initialState)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false) supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false)
@ -590,8 +565,6 @@ class HomeActivity :
} }
} }
override fun create(initialState: ActiveSpaceViewState) = promoteRestrictedViewModelFactory.create(initialState)
override fun mxToBottomSheetNavigateToRoom(roomId: String) { override fun mxToBottomSheetNavigateToRoom(roomId: String) {
navigator.openRoom(this, roomId) navigator.openRoom(this, roomId)
} }

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

@ -57,15 +57,12 @@ import im.vector.app.features.settings.VectorSettingsActivity.Companion.EXTRA_DI
import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.workers.signout.BannerState import im.vector.app.features.workers.signout.BannerState
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import im.vector.app.features.workers.signout.ServerBackupStatusViewState
import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.group.model.GroupSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
import javax.inject.Inject import javax.inject.Inject
class HomeDetailFragment @Inject constructor( class HomeDetailFragment @Inject constructor(
val homeDetailViewModelFactory: HomeDetailViewModel.Factory,
private val serverBackupStatusViewModelFactory: ServerBackupStatusViewModel.Factory,
private val avatarRenderer: AvatarRenderer, private val avatarRenderer: AvatarRenderer,
private val colorProvider: ColorProvider, private val colorProvider: ColorProvider,
private val alertManager: PopupAlertManager, private val alertManager: PopupAlertManager,
@ -74,8 +71,7 @@ class HomeDetailFragment @Inject constructor(
private val appStateHandler: AppStateHandler private val appStateHandler: AppStateHandler
) : VectorBaseFragment<FragmentHomeDetailBinding>(), ) : VectorBaseFragment<FragmentHomeDetailBinding>(),
KeysBackupBanner.Delegate, KeysBackupBanner.Delegate,
CurrentCallsView.Callback, CurrentCallsView.Callback {
ServerBackupStatusViewModel.Factory {
private val viewModel: HomeDetailViewModel by fragmentViewModel() private val viewModel: HomeDetailViewModel by fragmentViewModel()
private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel() private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel()
@ -503,8 +499,4 @@ class HomeDetailFragment @Inject constructor(
} }
return this return this
} }
override fun create(initialState: ServerBackupStatusViewState): ServerBackupStatusViewModel {
return serverBackupStatusViewModelFactory.create(initialState)
}
} }

View File

@ -17,7 +17,6 @@
package im.vector.app.features.home package im.vector.app.features.home
import androidx.lifecycle.asFlow import androidx.lifecycle.asFlow
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.ViewModelContext import com.airbnb.mvrx.ViewModelContext
import dagger.assisted.Assisted import dagger.assisted.Assisted
@ -25,7 +24,9 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import im.vector.app.AppStateHandler import im.vector.app.AppStateHandler
import im.vector.app.RoomGroupingMethod import im.vector.app.RoomGroupingMethod
import im.vector.app.core.di.HasScreenInjector import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.call.dialpad.DialPadLookup import im.vector.app.features.call.dialpad.DialPadLookup
import im.vector.app.features.call.lookup.CallProtocolsChecker import im.vector.app.features.call.lookup.CallProtocolsChecker
@ -69,24 +70,18 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
CallProtocolsChecker.Listener { CallProtocolsChecker.Listener {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<HomeDetailViewModel, HomeDetailViewState> {
fun create(initialState: HomeDetailViewState): HomeDetailViewModel override fun create(initialState: HomeDetailViewState): HomeDetailViewModel
} }
companion object : MavericksViewModelFactory<HomeDetailViewModel, HomeDetailViewState> { companion object : MavericksViewModelFactory<HomeDetailViewModel, HomeDetailViewState> by hiltMavericksViewModelFactory() {
override fun initialState(viewModelContext: ViewModelContext): HomeDetailViewState? { override fun initialState(viewModelContext: ViewModelContext): HomeDetailViewState {
val uiStateRepository = (viewModelContext.activity as HasScreenInjector).injector().uiStateRepository() val uiStateRepository = viewModelContext.activity.singletonEntryPoint().uiStateRepository()
return HomeDetailViewState( return HomeDetailViewState(
currentTab = HomeTab.RoomList(uiStateRepository.getDisplayMode()) currentTab = HomeTab.RoomList(uiStateRepository.getDisplayMode())
) )
} }
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: HomeDetailViewState): HomeDetailViewModel? {
val fragment: HomeDetailFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.homeDetailViewModelFactory.create(state)
}
} }
init { init {

View File

@ -19,9 +19,11 @@ package im.vector.app.features.home
import android.os.Handler import android.os.Handler
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.migration.DisableInstallInCheck
import im.vector.app.features.home.room.detail.timeline.TimelineEventControllerHandler import im.vector.app.features.home.room.detail.timeline.TimelineEventControllerHandler
import im.vector.app.features.home.room.detail.timeline.helper.TimelineAsyncHelper import im.vector.app.features.home.room.detail.timeline.helper.TimelineAsyncHelper
@DisableInstallInCheck
@Module @Module
object HomeModule { object HomeModule {

View File

@ -16,17 +16,16 @@
package im.vector.app.features.home package im.vector.app.features.home
import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.MavericksState
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.AppStateHandler import im.vector.app.AppStateHandler
import im.vector.app.RoomGroupingMethod import im.vector.app.RoomGroupingMethod
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.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
@ -72,21 +71,11 @@ class PromoteRestrictedViewModel @AssistedInject constructor(
} }
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<PromoteRestrictedViewModel, ActiveSpaceViewState> {
fun create(initialState: ActiveSpaceViewState): PromoteRestrictedViewModel override fun create(initialState: ActiveSpaceViewState): PromoteRestrictedViewModel
} }
companion object : MavericksViewModelFactory<PromoteRestrictedViewModel, ActiveSpaceViewState> { companion object : MavericksViewModelFactory<PromoteRestrictedViewModel, ActiveSpaceViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: ActiveSpaceViewState): PromoteRestrictedViewModel? {
val factory = when (viewModelContext) {
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
is ActivityViewModelContext -> viewModelContext.activity as? Factory
}
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
}
}
override fun handle(action: EmptyAction) {} override fun handle(action: EmptyAction) {}
} }

View File

@ -16,17 +16,16 @@
package im.vector.app.features.home package im.vector.app.features.home
import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.Async import com.airbnb.mvrx.Async
import com.airbnb.mvrx.FragmentViewModelContext
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.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
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
import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.core.platform.VectorViewModelAction
@ -66,21 +65,11 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(@Assisted
} }
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<UnknownDeviceDetectorSharedViewModel, UnknownDevicesState> {
fun create(initialState: UnknownDevicesState): UnknownDeviceDetectorSharedViewModel override fun create(initialState: UnknownDevicesState): UnknownDeviceDetectorSharedViewModel
} }
companion object : MavericksViewModelFactory<UnknownDeviceDetectorSharedViewModel, UnknownDevicesState> { companion object : MavericksViewModelFactory<UnknownDeviceDetectorSharedViewModel, UnknownDevicesState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: UnknownDevicesState): UnknownDeviceDetectorSharedViewModel? {
val factory = when (viewModelContext) {
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
is ActivityViewModelContext -> viewModelContext.activity as? Factory
}
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
}
}
private val ignoredDeviceList = ArrayList<String>() private val ignoredDeviceList = ArrayList<String>()

View File

@ -16,16 +16,15 @@
package im.vector.app.features.home package im.vector.app.features.home
import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.MavericksState
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.AppStateHandler import im.vector.app.AppStateHandler
import im.vector.app.RoomGroupingMethod import im.vector.app.RoomGroupingMethod
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
@ -61,21 +60,11 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initia
VectorViewModel<UnreadMessagesState, EmptyAction, EmptyViewEvents>(initialState) { VectorViewModel<UnreadMessagesState, EmptyAction, EmptyViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<UnreadMessagesSharedViewModel, UnreadMessagesState> {
fun create(initialState: UnreadMessagesState): UnreadMessagesSharedViewModel override fun create(initialState: UnreadMessagesState): UnreadMessagesSharedViewModel
} }
companion object : MavericksViewModelFactory<UnreadMessagesSharedViewModel, UnreadMessagesState> { companion object : MavericksViewModelFactory<UnreadMessagesSharedViewModel, UnreadMessagesState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: UnreadMessagesState): UnreadMessagesSharedViewModel? {
val factory = when (viewModelContext) {
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
is ActivityViewModelContext -> viewModelContext.activity as? Factory
}
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
}
}
override fun handle(action: EmptyAction) {} override fun handle(action: EmptyAction) {}

View File

@ -31,8 +31,7 @@ import im.vector.app.features.home.room.detail.RoomDetailSharedActionViewModel
import javax.inject.Inject import javax.inject.Inject
class BreadcrumbsFragment @Inject constructor( class BreadcrumbsFragment @Inject constructor(
private val breadcrumbsController: BreadcrumbsController, private val breadcrumbsController: BreadcrumbsController
val breadcrumbsViewModelFactory: BreadcrumbsViewModel.Factory
) : VectorBaseFragment<FragmentBreadcrumbsBinding>(), ) : VectorBaseFragment<FragmentBreadcrumbsBinding>(),
BreadcrumbsController.Listener { BreadcrumbsController.Listener {

View File

@ -16,12 +16,12 @@
package im.vector.app.features.home.room.breadcrumbs package im.vector.app.features.home.room.breadcrumbs
import com.airbnb.mvrx.FragmentViewModelContext
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
@ -36,18 +36,11 @@ class BreadcrumbsViewModel @AssistedInject constructor(@Assisted initialState: B
VectorViewModel<BreadcrumbsViewState, EmptyAction, EmptyViewEvents>(initialState) { VectorViewModel<BreadcrumbsViewState, EmptyAction, EmptyViewEvents>(initialState) {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<BreadcrumbsViewModel, BreadcrumbsViewState> {
fun create(initialState: BreadcrumbsViewState): BreadcrumbsViewModel override fun create(initialState: BreadcrumbsViewState): BreadcrumbsViewModel
} }
companion object : MavericksViewModelFactory<BreadcrumbsViewModel, BreadcrumbsViewState> { companion object : MavericksViewModelFactory<BreadcrumbsViewModel, BreadcrumbsViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: BreadcrumbsViewState): BreadcrumbsViewModel? {
val fragment: BreadcrumbsFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.breadcrumbsViewModelFactory.create(state)
}
}
init { init {
observeBreadcrumbs() observeBreadcrumbs()

View File

@ -25,8 +25,8 @@ import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.parentFragmentViewModel
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.platform.ButtonStateView import im.vector.app.core.platform.ButtonStateView
@ -34,6 +34,7 @@ import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetTombstoneJoinBinding import im.vector.app.databinding.BottomSheetTombstoneJoinBinding
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint
class JoinReplacementRoomBottomSheet : class JoinReplacementRoomBottomSheet :
VectorBaseBottomSheetDialogFragment<BottomSheetTombstoneJoinBinding>() { VectorBaseBottomSheetDialogFragment<BottomSheetTombstoneJoinBinding>() {
@ -43,10 +44,6 @@ class JoinReplacementRoomBottomSheet :
@Inject @Inject
lateinit var errorFormatter: ErrorFormatter lateinit var errorFormatter: ErrorFormatter
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
private val viewModel: RoomDetailViewModel by parentFragmentViewModel() private val viewModel: RoomDetailViewModel by parentFragmentViewModel()
override val showExpanded: Boolean override val showExpanded: Boolean

View File

@ -24,10 +24,11 @@ import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.ToolbarConfigurable import im.vector.app.core.platform.ToolbarConfigurable
@ -39,16 +40,11 @@ import im.vector.app.features.navigation.Navigator
import im.vector.app.features.room.RequireActiveMembershipAction import im.vector.app.features.room.RequireActiveMembershipAction
import im.vector.app.features.room.RequireActiveMembershipViewEvents import im.vector.app.features.room.RequireActiveMembershipViewEvents
import im.vector.app.features.room.RequireActiveMembershipViewModel import im.vector.app.features.room.RequireActiveMembershipViewModel
import im.vector.app.features.room.RequireActiveMembershipViewState
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewModel
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewState
import javax.inject.Inject
@AndroidEntryPoint
class RoomDetailActivity : class RoomDetailActivity :
VectorBaseActivity<ActivityRoomDetailBinding>(), VectorBaseActivity<ActivityRoomDetailBinding>(),
ToolbarConfigurable, ToolbarConfigurable,
RequireActiveMembershipViewModel.Factory,
RoomWidgetPermissionViewModel.Factory,
MatrixToBottomSheet.InteractionListener { MatrixToBottomSheet.InteractionListener {
override fun getBinding(): ActivityRoomDetailBinding { override fun getBinding(): ActivityRoomDetailBinding {
@ -77,24 +73,6 @@ class RoomDetailActivity :
private lateinit var sharedActionViewModel: RoomDetailSharedActionViewModel private lateinit var sharedActionViewModel: RoomDetailSharedActionViewModel
private val requireActiveMembershipViewModel: RequireActiveMembershipViewModel by viewModel() private val requireActiveMembershipViewModel: RequireActiveMembershipViewModel by viewModel()
@Inject
lateinit var requireActiveMembershipViewModelFactory: RequireActiveMembershipViewModel.Factory
override fun create(initialState: RequireActiveMembershipViewState): RequireActiveMembershipViewModel {
// Due to shortcut, we cannot use MvRx args. Pass the first roomId here
return requireActiveMembershipViewModelFactory.create(initialState.copy(roomId = currentRoomId ?: ""))
}
@Inject
lateinit var permissionsViewModelFactory: RoomWidgetPermissionViewModel.Factory
override fun create(initialState: RoomWidgetPermissionViewState): RoomWidgetPermissionViewModel {
return permissionsViewModelFactory.create(initialState)
}
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
// Simple filter // Simple filter
var currentRoomId: String? = null var currentRoomId: String? = null
@ -108,6 +86,7 @@ class RoomDetailActivity :
intent?.extras?.getParcelable(EXTRA_ROOM_DETAIL_ARGS) intent?.extras?.getParcelable(EXTRA_ROOM_DETAIL_ARGS)
} }
if (roomDetailArgs == null) return if (roomDetailArgs == null) return
intent.putExtra(Mavericks.KEY_ARG, roomDetailArgs)
currentRoomId = roomDetailArgs.roomId currentRoomId = roomDetailArgs.roomId
if (isFirstCreation()) { if (isFirstCreation()) {

View File

@ -237,7 +237,6 @@ class RoomDetailFragment @Inject constructor(
private val permalinkHandler: PermalinkHandler, private val permalinkHandler: PermalinkHandler,
private val notificationDrawerManager: NotificationDrawerManager, private val notificationDrawerManager: NotificationDrawerManager,
val roomDetailViewModelFactory: RoomDetailViewModel.Factory, val roomDetailViewModelFactory: RoomDetailViewModel.Factory,
val textComposerViewModelFactory: TextComposerViewModel.Factory,
private val eventHtmlRenderer: EventHtmlRenderer, private val eventHtmlRenderer: EventHtmlRenderer,
private val vectorPreferences: VectorPreferences, private val vectorPreferences: VectorPreferences,
private val colorProvider: ColorProvider, private val colorProvider: ColorProvider,

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

@ -16,20 +16,19 @@
package im.vector.app.features.home.room.detail.composer package im.vector.app.features.home.room.detail.composer
import com.airbnb.mvrx.FragmentViewModelContext
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.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
import im.vector.app.features.command.CommandParser import im.vector.app.features.command.CommandParser
import im.vector.app.features.command.ParsedCommand import im.vector.app.features.command.ParsedCommand
import im.vector.app.features.home.room.detail.ChatEffect import im.vector.app.features.home.room.detail.ChatEffect
import im.vector.app.features.home.room.detail.RoomDetailFragment
import im.vector.app.features.home.room.detail.composer.rainbow.RainbowGenerator import im.vector.app.features.home.room.detail.composer.rainbow.RainbowGenerator
import im.vector.app.features.home.room.detail.toMessageType import im.vector.app.features.home.room.detail.toMessageType
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
@ -710,16 +709,9 @@ class TextComposerViewModel @AssistedInject constructor(
} }
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<TextComposerViewModel, TextComposerViewState> {
fun create(initialState: TextComposerViewState): TextComposerViewModel override fun create(initialState: TextComposerViewState): TextComposerViewModel
} }
companion object : MavericksViewModelFactory<TextComposerViewModel, TextComposerViewState> { companion object : MavericksViewModelFactory<TextComposerViewModel, TextComposerViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: TextComposerViewState): TextComposerViewModel {
val fragment: RoomDetailFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.textComposerViewModelFactory.create(state)
}
}
} }

View File

@ -23,8 +23,8 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.args import com.airbnb.mvrx.args
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.configureWith
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
@ -43,6 +43,7 @@ data class DisplayReadReceiptArgs(
/** /**
* Bottom sheet displaying list of read receipts for a given event ordered by descending timestamp * Bottom sheet displaying list of read receipts for a given event ordered by descending timestamp
*/ */
@AndroidEntryPoint
class DisplayReadReceiptsBottomSheet : class DisplayReadReceiptsBottomSheet :
VectorBaseBottomSheetDialogFragment<BottomSheetGenericListWithTitleBinding>(), VectorBaseBottomSheetDialogFragment<BottomSheetGenericListWithTitleBinding>(),
DisplayReadReceiptsController.Listener { DisplayReadReceiptsController.Listener {
@ -53,10 +54,6 @@ class DisplayReadReceiptsBottomSheet :
private lateinit var sharedActionViewModel: MessageSharedActionViewModel private lateinit var sharedActionViewModel: MessageSharedActionViewModel
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetGenericListWithTitleBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetGenericListWithTitleBinding {
return BottomSheetGenericListWithTitleBinding.inflate(inflater, container, false) return BottomSheetGenericListWithTitleBinding.inflate(inflater, container, false)
} }

View File

@ -21,12 +21,13 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.Mavericks
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.addFragment import im.vector.app.core.extensions.addFragment
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySearchBinding import im.vector.app.databinding.ActivitySearchBinding
@AndroidEntryPoint
class SearchActivity : VectorBaseActivity<ActivitySearchBinding>() { class SearchActivity : VectorBaseActivity<ActivitySearchBinding>() {
private val searchFragment: SearchFragment? private val searchFragment: SearchFragment?
@ -38,10 +39,6 @@ class SearchActivity : VectorBaseActivity<ActivitySearchBinding>() {
override fun getCoordinatorLayout() = views.coordinatorLayout override fun getCoordinatorLayout() = views.coordinatorLayout
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
configureToolbar(views.searchToolbar) configureToolbar(views.searchToolbar)

View File

@ -47,7 +47,6 @@ data class SearchArgs(
) : Parcelable ) : Parcelable
class SearchFragment @Inject constructor( class SearchFragment @Inject constructor(
val viewModelFactory: SearchViewModel.Factory,
private val controller: SearchResultController private val controller: SearchResultController
) : VectorBaseFragment<FragmentSearchBinding>(), ) : VectorBaseFragment<FragmentSearchBinding>(),
StateView.EventCallback, StateView.EventCallback,

View File

@ -16,16 +16,15 @@
package im.vector.app.features.home.room.detail.search package im.vector.app.features.home.room.detail.search
import androidx.lifecycle.viewModelScope
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.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
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.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
@ -46,18 +45,11 @@ class SearchViewModel @AssistedInject constructor(
private var nextBatch: String? = null private var nextBatch: String? = null
@AssistedFactory @AssistedFactory
interface Factory { interface Factory : MavericksAssistedViewModelFactory<SearchViewModel, SearchViewState> {
fun create(initialState: SearchViewState): SearchViewModel override fun create(initialState: SearchViewState): SearchViewModel
} }
companion object : MavericksViewModelFactory<SearchViewModel, SearchViewState> { companion object : MavericksViewModelFactory<SearchViewModel, SearchViewState> by hiltMavericksViewModelFactory()
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: SearchViewState): SearchViewModel? {
val fragment: SearchFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.viewModelFactory.create(state)
}
}
override fun handle(action: SearchAction) { override fun handle(action: SearchAction) {
when (action) { when (action) {

View File

@ -21,7 +21,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import im.vector.app.core.di.ScreenComponent import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.configureWith
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
@ -32,11 +32,11 @@ import javax.inject.Inject
/** /**
* Bottom sheet fragment that shows a message preview with list of contextual actions * Bottom sheet fragment that shows a message preview with list of contextual actions
*/ */
@AndroidEntryPoint
class MessageActionsBottomSheet : class MessageActionsBottomSheet :
VectorBaseBottomSheetDialogFragment<BottomSheetGenericListBinding>(), VectorBaseBottomSheetDialogFragment<BottomSheetGenericListBinding>(),
MessageActionsEpoxyController.MessageActionsEpoxyControllerListener { MessageActionsEpoxyController.MessageActionsEpoxyControllerListener {
@Inject lateinit var messageActionViewModelFactory: MessageActionsViewModel.Factory
@Inject lateinit var messageActionsEpoxyController: MessageActionsEpoxyController @Inject lateinit var messageActionsEpoxyController: MessageActionsEpoxyController
private val viewModel: MessageActionsViewModel by fragmentViewModel(MessageActionsViewModel::class) private val viewModel: MessageActionsViewModel by fragmentViewModel(MessageActionsViewModel::class)
@ -45,10 +45,6 @@ class MessageActionsBottomSheet :
private lateinit var sharedActionViewModel: MessageSharedActionViewModel private lateinit var sharedActionViewModel: MessageSharedActionViewModel
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetGenericListBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetGenericListBinding {
return BottomSheetGenericListBinding.inflate(inflater, container, false) return BottomSheetGenericListBinding.inflate(inflater, container, false)
} }

Some files were not shown because too many files have changed in this diff Show More