From 3d465f6fdf27fd57ae52997be8084b60ddb011a6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 14 Jun 2019 16:32:23 +0200 Subject: [PATCH 01/11] Start to introduce Dagger into SDK [WIP] --- matrix-sdk-android/build.gradle | 7 +- .../timeline/FakeGetContextOfEventTask.kt | 2 +- .../room/timeline/FakePaginationTask.kt | 2 +- .../session/room/timeline/TimelineTest.kt | 4 +- .../interceptors/CurlLoggingInterceptor.kt | 5 +- .../im/vector/matrix/android/api/Matrix.kt | 19 +- .../android/internal/auth/AuthModule.kt | 43 +-- .../internal/auth/DefaultAuthenticator.kt | 21 +- .../auth/db/RealmSessionParamsStore.kt | 7 +- .../android/internal/crypto/CryptoManager.kt | 5 +- .../android/internal/crypto/CryptoModule.kt | 340 +++--------------- .../internal/crypto/DeviceListManager.kt | 20 +- .../crypto/IncomingRoomKeyRequestManager.kt | 5 +- .../android/internal/crypto/MXOlmDevice.kt | 16 +- .../internal/crypto/MyDeviceInfoHolder.kt | 5 +- .../android/internal/crypto/ObjectSigner.kt | 5 +- .../internal/crypto/OneTimeKeysUploader.kt | 5 +- .../crypto/OutgoingRoomKeyRequestManager.kt | 5 +- .../internal/crypto/RoomDecryptorProvider.kt | 5 +- .../EnsureOlmSessionsForDevicesAction.kt | 7 +- .../EnsureOlmSessionsForUsersAction.kt | 5 +- .../actions/MegolmSessionDataImporter.kt | 11 +- .../crypto/actions/MessageEncrypter.kt | 7 +- .../actions/SetDeviceVerificationAction.kt | 5 +- .../megolm/MXMegolmDecryptionFactory.kt | 5 +- .../megolm/MXMegolmEncryptionFactory.kt | 5 +- .../algorithms/olm/MXOlmDecryptionFactory.kt | 7 +- .../algorithms/olm/MXOlmEncryptionFactory.kt | 15 +- .../internal/crypto/keysbackup/KeysBackup.kt | 6 +- .../tasks/CreateKeysBackupVersionTask.kt | 6 +- .../keysbackup/tasks/DeleteBackupTask.kt | 6 +- .../tasks/DeleteRoomSessionDataTask.kt | 6 +- .../tasks/DeleteRoomSessionsDataTask.kt | 6 +- .../tasks/DeleteSessionsDataTask.kt | 6 +- .../tasks/GetKeysBackupLastVersionTask.kt | 6 +- .../tasks/GetKeysBackupVersionTask.kt | 6 +- .../tasks/GetRoomSessionDataTask.kt | 6 +- .../tasks/GetRoomSessionsDataTask.kt | 6 +- .../keysbackup/tasks/GetSessionsDataTask.kt | 6 +- .../tasks/StoreRoomSessionDataTask.kt | 6 +- .../tasks/StoreRoomSessionsDataTask.kt | 6 +- .../keysbackup/tasks/StoreSessionsDataTask.kt | 6 +- .../tasks/UpdateKeysBackupVersionTask.kt | 6 +- .../WarnOnUnknownDeviceRepository.kt | 6 +- .../ClaimOneTimeKeysForUsersDeviceTask.kt | 5 +- .../internal/crypto/tasks/DeleteDeviceTask.kt | 5 +- .../crypto/tasks/DownloadKeysForUsersTask.kt | 5 +- .../internal/crypto/tasks/GetDevicesTask.kt | 5 +- .../crypto/tasks/GetKeyChangesTask.kt | 5 +- .../internal/crypto/tasks/SendToDeviceTask.kt | 5 +- .../crypto/tasks/SetDeviceNameTask.kt | 5 +- .../internal/crypto/tasks/UploadKeysTask.kt | 5 +- .../DefaultSasVerificationService.kt | 20 +- ...rixKoinHolder.kt => ChildWorkerFactory.kt} | 20 +- .../android/internal/di/MatrixComponent.kt | 25 ++ .../android/internal/di/MatrixModule.kt | 36 +- .../UserModule.kt => di/MatrixScope.java} | 20 +- .../android/internal/di/NetworkModule.kt | 137 ++++--- .../network/AccessTokenInterceptor.kt | 5 +- .../network/NetworkConnectivityChecker.kt | 5 +- .../internal/network/UserAgentHolder.kt | 5 +- .../internal/network/UserAgentInterceptor.kt | 5 +- .../internal/session/DefaultSession.kt | 318 ++-------------- .../internal/session/SessionComponent.kt | 31 ++ .../internal/session/SessionFactory.kt | 75 ++++ .../internal/session/SessionListeners.kt | 3 +- .../android/internal/session/SessionModule.kt | 179 +++------ .../internal/session/SessionScope.java | 29 ++ .../session/cache/RealmCacheService.kt | 7 +- .../session/cache/RealmClearCacheTask.kt | 5 +- .../internal/session/content/ContentModule.kt | 28 +- .../DefaultContentUploadStateTracker.kt | 5 +- .../content/DefaultContentUrlResolver.kt | 5 +- .../internal/session/content/FileUploader.kt | 5 +- .../session/content/UploadContentWorker.kt | 30 +- .../session/filter/DefaultFilterRepository.kt | 5 +- .../session/filter/DefaultFilterService.kt | 13 +- .../session/filter/DefaultSaveFilterTask.kt | 9 +- .../session/group/DefaultGetGroupDataTask.kt | 6 +- .../session/group/DefaultGroupService.kt | 3 +- .../session/group/GetGroupDataWorker.kt | 19 +- .../internal/session/group/GroupModule.kt | 21 +- .../session/group/GroupSummaryUpdater.kt | 6 +- .../room/DefaultRoomDirectoryService.kt | 9 +- .../session/room/DefaultRoomService.kt | 11 +- .../session/room/EventRelationExtractor.kt | 6 +- .../room/EventRelationsAggregationTask.kt | 5 +- .../room/EventRelationsAggregationUpdater.kt | 12 +- .../session/room/RoomAvatarResolver.kt | 7 +- .../internal/session/room/RoomFactory.kt | 31 +- .../internal/session/room/RoomModule.kt | 95 +---- .../session/room/RoomSummaryUpdater.kt | 9 +- .../session/room/create/CreateRoomTask.kt | 6 +- .../room/directory/GetPublicRoomTask.kt | 5 +- .../directory/GetThirdPartyProtocolsTask.kt | 5 +- .../membership/DefaultMembershipService.kt | 17 +- .../room/membership/LoadRoomMembersTask.kt | 5 +- .../membership/RoomDisplayNameResolver.kt | 9 +- .../RoomMemberDisplayNameResolver.kt | 3 +- .../room/membership/joining/InviteTask.kt | 5 +- .../room/membership/joining/JoinRoomTask.kt | 5 +- .../room/membership/leaving/LeaveRoomTask.kt | 5 +- .../session/room/prune/EventsPruner.kt | 11 +- .../session/room/prune/PruneEventTask.kt | 6 +- .../session/room/read/DefaultReadService.kt | 5 +- .../session/room/read/SetReadMarkersTask.kt | 5 +- .../room/relation/DefaultRelationService.kt | 21 +- .../relation/FindReactionEventForUndoTask.kt | 5 +- .../room/relation/SendRelationWorker.kt | 41 ++- .../room/relation/UpdateQuickReactionTask.kt | 5 +- .../room/send/LocalEchoEventFactory.kt | 6 +- .../session/room/send/LocalEchoUpdater.kt | 5 +- .../session/room/send/SendEventWorker.kt | 40 ++- .../session/room/state/DefaultStateService.kt | 5 +- .../session/room/state/SendStateTask.kt | 5 +- .../timeline/DefaultGetContextOfEventTask.kt | 5 +- .../room/timeline/DefaultPaginationTask.kt | 9 +- .../session/room/timeline/DefaultTimeline.kt | 6 +- .../session/room/timeline/GetEventTask.kt | 2 +- .../room/timeline/TimelineEventFactory.kt | 3 +- .../room/timeline/TokenChunkEventPersistor.kt | 5 +- .../session/signout/DefaultSignOutService.kt | 7 +- .../internal/session/signout/SignOutModule.kt | 22 +- .../internal/session/signout/SignOutTask.kt | 8 +- .../session/sync/CryptoSyncHandler.kt | 9 +- .../internal/session/sync/GroupSyncHandler.kt | 6 +- .../session/sync/ReadReceiptHandler.kt | 4 +- .../internal/session/sync/RoomSyncHandler.kt | 23 +- .../internal/session/sync/RoomTagHandler.kt | 7 +- .../internal/session/sync/SyncModule.kt | 58 +-- .../session/sync/SyncResponseHandler.kt | 13 +- .../android/internal/session/sync/SyncTask.kt | 13 +- .../internal/session/sync/SyncTokenStore.kt | 5 +- .../sync/UserAccountDataSyncHandler.kt | 5 +- .../internal/session/sync/job/SyncThread.kt | 19 +- .../session/user/DefaultUserService.kt | 5 +- .../internal/session/user/UpdateUserTask.kt | 5 +- .../session/user/UserEntityUpdater.kt | 9 +- .../android/internal/task/ConfigurableTask.kt | 2 +- .../android/internal/task/TaskExecutor.kt | 5 +- .../android/internal/util/StringProvider.kt | 6 +- .../VectorSettingsPreferencesFragment.kt | 2 +- 142 files changed, 1093 insertions(+), 1384 deletions(-) rename matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/{MatrixKoinHolder.kt => ChildWorkerFactory.kt} (64%) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt rename matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/{session/user/UserModule.kt => di/MatrixScope.java} (63%) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionFactory.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionScope.java diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index ba29aad2..4119c03c 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -91,6 +91,7 @@ dependencies { def lifecycle_version = '2.0.0' def coroutines_version = "1.0.1" def markwon_version = '3.0.0' + def daggerVersion = '2.23.1' implementation fileTree(dir: 'libs', include: ['*.aar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" @@ -132,8 +133,10 @@ dependencies { implementation 'org.matrix.gitlab.matrix-org:olm:3.1.2' // DI - implementation "org.koin:koin-core:$koin_version" - implementation "org.koin:koin-core-ext:$koin_version" + implementation "com.google.dagger:dagger:$daggerVersion" + kapt "com.google.dagger:dagger-compiler:$daggerVersion" + compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0' + kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0' // Logging implementation 'com.jakewharton.timber:timber:4.7.1' diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakeGetContextOfEventTask.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakeGetContextOfEventTask.kt index c2d32549..afcb846f 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakeGetContextOfEventTask.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakeGetContextOfEventTask.kt @@ -23,7 +23,7 @@ import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEvent import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor import kotlin.random.Random -internal class FakeGetContextOfEventTask(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : GetContextOfEventTask { +internal class FakeGetContextOfEventTask @Inject constructor(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : GetContextOfEventTask { override suspend fun execute(params: GetContextOfEventTask.Params): Try { val fakeEvents = RoomDataHelper.createFakeListOfEvents(30) diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakePaginationTask.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakePaginationTask.kt index a0bc1f74..e4082b35 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakePaginationTask.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakePaginationTask.kt @@ -21,7 +21,7 @@ import im.vector.matrix.android.internal.session.room.timeline.PaginationTask import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor import kotlin.random.Random -internal class FakePaginationTask(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : PaginationTask { +internal class FakePaginationTask @Inject constructor(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : PaginationTask { override suspend fun execute(params: PaginationTask.Params): Try { val fakeEvents = RoomDataHelper.createFakeListOfEvents(30) diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/TimelineTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/TimelineTest.kt index 221887c7..5a470ce7 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/TimelineTest.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/TimelineTest.kt @@ -59,8 +59,8 @@ internal class TimelineTest : InstrumentedTest { private fun createTimeline(initialEventId: String? = null): Timeline { val taskExecutor = TaskExecutor(testCoroutineDispatchers) val tokenChunkEventPersistor = TokenChunkEventPersistor(monarchy) - val paginationTask = FakePaginationTask(tokenChunkEventPersistor) - val getContextOfEventTask = FakeGetContextOfEventTask(tokenChunkEventPersistor) + val paginationTask = FakePaginationTask @Inject constructor(tokenChunkEventPersistor) + val getContextOfEventTask = FakeGetContextOfEventTask @Inject constructor(tokenChunkEventPersistor) val roomMemberExtractor = SenderRoomMemberExtractor(ROOM_ID) val timelineEventFactory = TimelineEventFactory(roomMemberExtractor, EventRelationExtractor()) return DefaultTimeline( diff --git a/matrix-sdk-android/src/debug/java/im/vector/matrix/android/internal/network/interceptors/CurlLoggingInterceptor.kt b/matrix-sdk-android/src/debug/java/im/vector/matrix/android/internal/network/interceptors/CurlLoggingInterceptor.kt index edca0156..33f460bd 100644 --- a/matrix-sdk-android/src/debug/java/im/vector/matrix/android/internal/network/interceptors/CurlLoggingInterceptor.kt +++ b/matrix-sdk-android/src/debug/java/im/vector/matrix/android/internal/network/interceptors/CurlLoggingInterceptor.kt @@ -17,12 +17,14 @@ package im.vector.matrix.android.internal.network.interceptors +import im.vector.matrix.android.internal.di.MatrixScope import okhttp3.Interceptor import okhttp3.Response import okhttp3.logging.HttpLoggingInterceptor import okio.Buffer import java.io.IOException import java.nio.charset.Charset +import javax.inject.Inject /** * An OkHttp interceptor that logs requests as curl shell commands. They can then @@ -33,7 +35,8 @@ import java.nio.charset.Charset * information. It should only be used in a controlled manner or in a * non-production environment. */ -internal class CurlLoggingInterceptor(private val logger: HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger.DEFAULT) +@MatrixScope +internal class CurlLoggingInterceptor @Inject constructor(private val logger: HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger.DEFAULT) : Interceptor { /** diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt index b3b98847..9f990889 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt @@ -22,34 +22,25 @@ import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.auth.Authenticator import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.sync.FilterService -import im.vector.matrix.android.internal.auth.AuthModule -import im.vector.matrix.android.internal.di.MatrixKoinComponent -import im.vector.matrix.android.internal.di.MatrixKoinHolder -import im.vector.matrix.android.internal.di.MatrixModule -import im.vector.matrix.android.internal.di.NetworkModule import im.vector.matrix.android.internal.network.UserAgentHolder import im.vector.matrix.android.internal.util.BackgroundDetectionObserver -import org.koin.standalone.inject import java.util.concurrent.atomic.AtomicBoolean +import javax.inject.Inject /** * This is the main entry point to the matrix sdk. * This class is automatically init by a provider. * To get the singleton instance, use getInstance static method. */ -class Matrix private constructor(context: Context) : MatrixKoinComponent { +class Matrix private constructor(context: Context) { - private val authenticator by inject() - private val userAgentHolder by inject() - private val backgroundDetectionObserver by inject() + @Inject internal lateinit var authenticator: Authenticator + @Inject internal lateinit var userAgentHolder: UserAgentHolder + @Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver var currentSession: Session? = null init { Monarchy.init(context) - val matrixModule = MatrixModule(context).definition - val networkModule = NetworkModule().definition - val authModule = AuthModule().definition - MatrixKoinHolder.instance.loadModules(listOf(matrixModule, networkModule, authModule)) ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver) authenticator.getLastActiveSession()?.also { currentSession = it diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt index 5a49c512..3653f7df 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt @@ -17,38 +17,27 @@ package im.vector.matrix.android.internal.auth import android.content.Context -import im.vector.matrix.android.api.auth.Authenticator +import dagger.Module +import dagger.Provides import im.vector.matrix.android.internal.auth.db.AuthRealmModule -import im.vector.matrix.android.internal.auth.db.RealmSessionParamsStore -import im.vector.matrix.android.internal.auth.db.SessionParamsMapper +import im.vector.matrix.android.internal.di.MatrixScope import io.realm.RealmConfiguration -import org.koin.dsl.module.module import java.io.File -class AuthModule { +@Module +internal class AuthModule { - val definition = module { - - single { - DefaultAuthenticator(get(), get(), get()) as Authenticator + @Provides + @MatrixScope + fun providesRealmConfiguration(context: Context): RealmConfiguration { + val old = File(context.filesDir, "matrix-sdk-auth") + if (old.exists()) { + old.renameTo(File(context.filesDir, "matrix-sdk-auth.realm")) } - - single { - val context: Context = get() - val old = File(context.filesDir, "matrix-sdk-auth") - - if (old.exists()) { - old.renameTo(File(context.filesDir, "matrix-sdk-auth.realm")) - } - - val mapper = SessionParamsMapper((get())) - val realmConfiguration = RealmConfiguration.Builder() - .name("matrix-sdk-auth.realm") - .modules(AuthRealmModule()) - .deleteRealmIfMigrationNeeded() - .build() - RealmSessionParamsStore(mapper, realmConfiguration) as SessionParamsStore - } - + return RealmConfiguration.Builder() + .name("matrix-sdk-auth.realm") + .modules(AuthRealmModule()) + .deleteRealmIfMigrationNeeded() + .build() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt index d2474f37..8d6f8d29 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt @@ -19,25 +19,32 @@ package im.vector.matrix.android.internal.auth import android.util.Patterns import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.Authenticator +import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig +import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.util.Cancelable -import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.auth.data.PasswordLoginParams -import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.internal.auth.data.ThreePidMedium +import im.vector.matrix.android.internal.di.MatrixScope import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.session.DefaultSession +import im.vector.matrix.android.internal.session.SessionFactory import im.vector.matrix.android.internal.util.CancelableCoroutine import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import retrofit2.Retrofit +import javax.inject.Inject +import kotlin.random.Random -internal class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val sessionParamsStore: SessionParamsStore) : Authenticator { +@MatrixScope +internal class DefaultAuthenticator @Inject constructor(private val retrofitBuilder: Retrofit.Builder, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val sessionParamsStore: SessionParamsStore, + private val sessionFactory: DefaultSession.Factory +) : Authenticator { override fun hasActiveSessions(): Boolean { return sessionParamsStore.get() != null @@ -46,7 +53,7 @@ internal class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builde override fun getLastActiveSession(): Session? { val sessionParams = sessionParamsStore.get() return sessionParams?.let { - DefaultSession(it) + sessionFactory.create(it) } } @@ -80,7 +87,7 @@ internal class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builde sessionParamsStore.save(sessionParams) sessionParams }.map { - DefaultSession(it) + sessionFactory.create(it) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt index 08449586..ecb442ca 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt @@ -19,11 +19,14 @@ package im.vector.matrix.android.internal.auth.db import arrow.core.Try import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.internal.auth.SessionParamsStore +import im.vector.matrix.android.internal.di.MatrixScope import io.realm.Realm import io.realm.RealmConfiguration +import javax.inject.Inject -internal class RealmSessionParamsStore(private val mapper: SessionParamsMapper, - private val realmConfiguration: RealmConfiguration) : SessionParamsStore { +@MatrixScope +internal class RealmSessionParamsStore @Inject constructor(private val mapper: SessionParamsMapper, + private val realmConfiguration: RealmConfiguration) : SessionParamsStore { override fun save(sessionParams: SessionParams): Try { return Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt index 8b29287d..8b60b5c0 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt @@ -63,6 +63,7 @@ import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificat import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.MoshiProvider +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.cache.ClearCacheTask import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask import im.vector.matrix.android.internal.session.room.membership.RoomMembers @@ -76,6 +77,7 @@ import org.matrix.olm.OlmManager import timber.log.Timber import java.util.* import java.util.concurrent.atomic.AtomicBoolean +import javax.inject.Inject import kotlin.coroutines.EmptyCoroutineContext /** @@ -88,7 +90,8 @@ import kotlin.coroutines.EmptyCoroutineContext * CryptoService maintains all necessary keys and their sharing with other devices required for the crypto. * Specially, it tracks all room membership changes events in order to do keys updates. */ -internal class CryptoManager( +@SessionScope +internal class CryptoManager @Inject constructor( // The credentials, private val credentials: Credentials, private val myDeviceInfoHolder: MyDeviceInfoHolder, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt index 84029ba6..775eaad4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt @@ -17,316 +17,62 @@ package im.vector.matrix.android.internal.crypto import android.content.Context +import dagger.Module +import dagger.Provides import im.vector.matrix.android.api.auth.data.Credentials -import im.vector.matrix.android.api.session.crypto.CryptoService -import im.vector.matrix.android.internal.crypto.actions.* -import im.vector.matrix.android.internal.crypto.algorithms.megolm.MXMegolmDecryptionFactory -import im.vector.matrix.android.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory -import im.vector.matrix.android.internal.crypto.algorithms.olm.MXOlmDecryptionFactory -import im.vector.matrix.android.internal.crypto.algorithms.olm.MXOlmEncryptionFactory import im.vector.matrix.android.internal.crypto.api.CryptoApi -import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi -import im.vector.matrix.android.internal.crypto.keysbackup.tasks.* -import im.vector.matrix.android.internal.crypto.repository.WarnOnUnknownDeviceRepository import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreMigration import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule import im.vector.matrix.android.internal.crypto.store.db.hash -import im.vector.matrix.android.internal.crypto.tasks.* -import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService -import im.vector.matrix.android.internal.session.DefaultSession -import im.vector.matrix.android.internal.session.cache.ClearCacheTask -import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask +import im.vector.matrix.android.internal.session.SessionScope import io.realm.RealmConfiguration -import org.koin.dsl.module.module -import org.matrix.olm.OlmManager import retrofit2.Retrofit import java.io.File +@Module internal class CryptoModule { - val definition = module(override = true) { - - /* ========================================================================================== - * Crypto Main - * ========================================================================================== */ - - // Realm configuration, named to avoid clash with main cache realm configuration - scope(DefaultSession.SCOPE, name = "CryptoRealmConfiguration") { - val context: Context = get() - - val credentials: Credentials = get() - - RealmConfiguration.Builder() - .directory(File(context.filesDir, credentials.userId.hash())) - .name("crypto_store.realm") - .modules(RealmCryptoStoreModule()) - .schemaVersion(RealmCryptoStoreMigration.CRYPTO_STORE_SCHEMA_VERSION) - .migration(RealmCryptoStoreMigration) - .build() - } - - // CryptoStore - scope(DefaultSession.SCOPE) { - RealmCryptoStore(false /* TODO*/, - get("CryptoRealmConfiguration"), - get()) as IMXCryptoStore - } - - scope(DefaultSession.SCOPE) { - val retrofit: Retrofit = get() - retrofit.create(CryptoApi::class.java) - } - - // CryptoService - scope(DefaultSession.SCOPE) { - get() as CryptoService - } - - // - scope(DefaultSession.SCOPE) { - OutgoingRoomKeyRequestManager(get(), get(), get()) - } - - scope(DefaultSession.SCOPE) { - IncomingRoomKeyRequestManager(get(), get(), get()) - } - - scope(DefaultSession.SCOPE) { - RoomDecryptorProvider(get(), get()) - } - - scope(DefaultSession.SCOPE) { - // Ensure OlmManager is loaded first - get() - MXOlmDevice(get()) - } - - // ObjectSigner - scope(DefaultSession.SCOPE) { - ObjectSigner(get(), get()) - } - - // OneTimeKeysUploader - scope(DefaultSession.SCOPE) { - OneTimeKeysUploader(get(), get(), get(), get()) - } - - // Actions - scope(DefaultSession.SCOPE) { - SetDeviceVerificationAction(get(), get(), get()) - } - - // Device info - scope(DefaultSession.SCOPE) { - MyDeviceInfoHolder(get(), get(), get()) - } - - scope(DefaultSession.SCOPE) { - EnsureOlmSessionsForDevicesAction(get(), get()) - } - - scope(DefaultSession.SCOPE) { - EnsureOlmSessionsForUsersAction(get(), get(), get()) - } - - scope(DefaultSession.SCOPE) { - MegolmSessionDataImporter(get(), get(), get(), get()) - } - - scope(DefaultSession.SCOPE) { - MessageEncrypter(get(), get()) - } - - - scope(DefaultSession.SCOPE) { - WarnOnUnknownDeviceRepository() - } - - // Factories - scope(DefaultSession.SCOPE) { - MXMegolmDecryptionFactory( - get(), get(), get(), get(), get(), get(), get(), get(), get() - ) - } - - scope(DefaultSession.SCOPE) { - MXMegolmEncryptionFactory( - get(), get(), get(), get(), get(), get(), get(), get(), get(), get() - ) - } - - scope(DefaultSession.SCOPE) { - MXOlmDecryptionFactory( - get(), get() - ) - } - - scope(DefaultSession.SCOPE) { - MXOlmEncryptionFactory( - get(), get(), get(), get(), get(), get() - ) - } - - // CryptoManager - scope(DefaultSession.SCOPE) { - CryptoManager( - credentials = get(), - myDeviceInfoHolder = get(), - cryptoStore = get(), - olmDevice = get(), - cryptoConfig = get(), - deviceListManager = get(), - keysBackup = get(), - objectSigner = get(), - oneTimeKeysUploader = get(), - roomDecryptorProvider = get(), - sasVerificationService = get(), - incomingRoomKeyRequestManager = get(), - outgoingRoomKeyRequestManager = get(), - olmManager = get(), - setDeviceVerificationAction = get(), - megolmSessionDataImporter = get(), - warnOnUnknownDevicesRepository = get(), - megolmEncryptionFactory = get(), - olmEncryptionFactory = get(), - deleteDeviceTask = get(), - // Tasks - getDevicesTask = get(), - setDeviceNameTask = get(), - uploadKeysTask = get(), - loadRoomMembersTask = get(), - clearCryptoDataTask = get("ClearTaskCryptoCache"), - monarchy = get(), - coroutineDispatchers = get(), - taskExecutor = get() - ) - } - - // Olm manager - single { - // load the crypto libs. - OlmManager() - } - - - // Crypto config - scope(DefaultSession.SCOPE) { - MXCryptoConfig() - } - - // Device list - scope(DefaultSession.SCOPE) { - DeviceListManager(get(), get(), get(), get(), get()) - } - - // Crypto tasks - scope(DefaultSession.SCOPE) { - DefaultClaimOneTimeKeysForUsersDevice(get()) as ClaimOneTimeKeysForUsersDeviceTask - } - scope(DefaultSession.SCOPE) { - DefaultDeleteDeviceTask(get()) as DeleteDeviceTask - } - scope(DefaultSession.SCOPE) { - DefaultDownloadKeysForUsers(get()) as DownloadKeysForUsersTask - } - scope(DefaultSession.SCOPE) { - DefaultGetDevicesTask(get()) as GetDevicesTask - } - scope(DefaultSession.SCOPE) { - DefaultGetKeyChangesTask(get()) as GetKeyChangesTask - } - scope(DefaultSession.SCOPE) { - DefaultSendToDeviceTask(get()) as SendToDeviceTask - } - scope(DefaultSession.SCOPE) { - DefaultSetDeviceNameTask(get()) as SetDeviceNameTask - } - scope(DefaultSession.SCOPE) { - DefaultUploadKeysTask(get()) as UploadKeysTask - } - - scope(DefaultSession.SCOPE, name = "ClearTaskCryptoCache") { - RealmClearCacheTask(get("CryptoRealmConfiguration")) as ClearCacheTask - } - - /* ========================================================================================== - * Keys backup - * ========================================================================================== */ - - scope(DefaultSession.SCOPE) { - val retrofit: Retrofit = get() - retrofit.create(RoomKeysApi::class.java) - } - - scope(DefaultSession.SCOPE) { - KeysBackup( - // Credentials - get(), - // CryptoStore - get(), - get(), - get(), - get(), - // Task - get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), - // Task executor - get()) - } - - // Key backup tasks - scope(DefaultSession.SCOPE) { - DefaultCreateKeysBackupVersionTask(get()) as CreateKeysBackupVersionTask - } - scope(DefaultSession.SCOPE) { - DefaultDeleteBackupTask(get()) as DeleteBackupTask - } - scope(DefaultSession.SCOPE) { - DefaultDeleteRoomSessionDataTask(get()) as DeleteRoomSessionDataTask - } - scope(DefaultSession.SCOPE) { - DefaultDeleteRoomSessionsDataTask(get()) as DeleteRoomSessionsDataTask - } - scope(DefaultSession.SCOPE) { - DefaultDeleteSessionsDataTask(get()) as DeleteSessionsDataTask - } - scope(DefaultSession.SCOPE) { - DefaultGetKeysBackupLastVersionTask(get()) as GetKeysBackupLastVersionTask - } - scope(DefaultSession.SCOPE) { - DefaultGetKeysBackupVersionTask(get()) as GetKeysBackupVersionTask - } - scope(DefaultSession.SCOPE) { - DefaultGetRoomSessionDataTask(get()) as GetRoomSessionDataTask - } - scope(DefaultSession.SCOPE) { - DefaultGetRoomSessionsDataTask(get()) as GetRoomSessionsDataTask - } - scope(DefaultSession.SCOPE) { - DefaultGetSessionsDataTask(get()) as GetSessionsDataTask - } - scope(DefaultSession.SCOPE) { - DefaultStoreRoomSessionDataTask(get()) as StoreRoomSessionDataTask - } - scope(DefaultSession.SCOPE) { - DefaultStoreRoomSessionsDataTask(get()) as StoreRoomSessionsDataTask - } - scope(DefaultSession.SCOPE) { - DefaultStoreSessionsDataTask(get()) as StoreSessionsDataTask - } - scope(DefaultSession.SCOPE) { - DefaultUpdateKeysBackupVersionTask(get()) as UpdateKeysBackupVersionTask - } - - /* ========================================================================================== - * SAS Verification - * ========================================================================================== */ - - scope(DefaultSession.SCOPE) { - DefaultSasVerificationService(get(), get(), get(), get(), get(), get(), get(), get()) - } - + // Realm configuration, named to avoid clash with main cache realm configuration + @Provides + @SessionScope + fun providesRealmConfiguration(context: Context, credentials: Credentials): RealmConfiguration { + return RealmConfiguration.Builder() + .directory(File(context.filesDir, credentials.userId.hash())) + .name("crypto_store.realm") + .modules(RealmCryptoStoreModule()) + .schemaVersion(RealmCryptoStoreMigration.CRYPTO_STORE_SCHEMA_VERSION) + .migration(RealmCryptoStoreMigration) + .build() } + + @Provides + @SessionScope + fun providesCryptoStore(realmConfiguration: RealmConfiguration, credentials: Credentials): IMXCryptoStore { + return RealmCryptoStore(false /* TODO*/, + realmConfiguration, + credentials) + } + + @Provides + @SessionScope + fun providesCryptoAPI(retrofit: Retrofit): CryptoApi { + return retrofit.create(CryptoApi::class.java) + } + + @Provides + @SessionScope + fun providesRoomKeysAPI(retrofit: Retrofit): RoomKeysApi { + return retrofit.create(RoomKeysApi::class.java) + } + + @Provides + @SessionScope + fun providesCryptoConfig(): MXCryptoConfig { + return MXCryptoConfig() + } + + } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt index 2217a796..f58901d1 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt @@ -26,16 +26,20 @@ import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.DownloadKeysForUsersTask +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.sync.SyncTokenStore import timber.log.Timber import java.util.* +import javax.inject.Inject // Legacy name: MXDeviceList -internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, - private val olmDevice: MXOlmDevice, - private val syncTokenStore: SyncTokenStore, - private val credentials: Credentials, - private val downloadKeysForUsersTask: DownloadKeysForUsersTask) { + +@SessionScope +internal class DeviceListManager @Inject constructor(private val cryptoStore: IMXCryptoStore, + private val olmDevice: MXOlmDevice, + private val syncTokenStore: SyncTokenStore, + private val credentials: Credentials, + private val downloadKeysForUsersTask: DownloadKeysForUsersTask) { // HS not ready for retry private val notReadyToRetryHS = HashSet() @@ -410,7 +414,7 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, if (!isVerified) { Timber.e("## validateDeviceKeys() : Unable to verify signature on device " + userId + ":" - + deviceKeys.deviceId + " with error " + errorMessage) + + deviceKeys.deviceId + " with error " + errorMessage) return false } @@ -421,8 +425,8 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, // // Should we warn the user about it somehow? Timber.e("## validateDeviceKeys() : WARNING:Ed25519 key for device " + userId + ":" - + deviceKeys.deviceId + " has changed : " - + previouslyStoredDeviceKeys.fingerprint() + " -> " + signKey) + + deviceKeys.deviceId + " has changed : " + + previouslyStoredDeviceKeys.fingerprint() + " -> " + signKey) Timber.e("## validateDeviceKeys() : $previouslyStoredDeviceKeys -> $deviceKeys") Timber.e("## validateDeviceKeys() : " + previouslyStoredDeviceKeys.keys + " -> " + deviceKeys.keys) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt index 37d76340..7901ca1a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt @@ -23,11 +23,14 @@ import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShare import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore +import im.vector.matrix.android.internal.session.SessionScope import timber.log.Timber import java.util.* +import javax.inject.Inject import kotlin.collections.ArrayList -internal class IncomingRoomKeyRequestManager( +@SessionScope +internal class IncomingRoomKeyRequestManager @Inject constructor( private val credentials: Credentials, private val cryptoStore: IMXCryptoStore, private val roomDecryptorProvider: RoomDecryptorProvider) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt index 12381a5b..243ddea6 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt @@ -26,15 +26,23 @@ import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrap import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.di.MoshiProvider +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.util.convertFromUTF8 import im.vector.matrix.android.internal.util.convertToUTF8 -import org.matrix.olm.* +import org.matrix.olm.OlmAccount +import org.matrix.olm.OlmInboundGroupSession +import org.matrix.olm.OlmMessage +import org.matrix.olm.OlmOutboundGroupSession +import org.matrix.olm.OlmSession +import org.matrix.olm.OlmUtility import timber.log.Timber import java.net.URLEncoder import java.util.* +import javax.inject.Inject // The libolm wrapper. -internal class MXOlmDevice( +@SessionScope +internal class MXOlmDevice @Inject constructor( /** * The store where crypto data is saved. */ @@ -670,7 +678,7 @@ internal class MXOlmDevice( val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex) Timber.e("## decryptGroupMessage() : $reason") throw MXDecryptionException(MXCryptoError(MXCryptoError.DUPLICATED_MESSAGE_INDEX_ERROR_CODE, - MXCryptoError.UNABLE_TO_DECRYPT, reason)) + MXCryptoError.UNABLE_TO_DECRYPT, reason)) } inboundGroupSessionMessageIndexes[timeline]!!.put(messageIndexKey, true) @@ -703,7 +711,7 @@ internal class MXOlmDevice( val reason = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, session.roomId) Timber.e("## decryptGroupMessage() : $reason") throw MXDecryptionException(MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, - MXCryptoError.UNABLE_TO_DECRYPT, reason)) + MXCryptoError.UNABLE_TO_DECRYPT, reason)) } } else { Timber.e("## decryptGroupMessage() : Cannot retrieve inbound group session $sessionId") diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MyDeviceInfoHolder.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MyDeviceInfoHolder.kt index 80e03f5d..42239832 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MyDeviceInfoHolder.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MyDeviceInfoHolder.kt @@ -20,9 +20,12 @@ import android.text.TextUtils import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore +import im.vector.matrix.android.internal.session.SessionScope import java.util.* +import javax.inject.Inject -internal class MyDeviceInfoHolder( +@SessionScope +internal class MyDeviceInfoHolder @Inject constructor( // The credentials, credentials: Credentials, // the crypto store diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/ObjectSigner.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/ObjectSigner.kt index 78359abc..2e91cb7a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/ObjectSigner.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/ObjectSigner.kt @@ -17,9 +17,12 @@ package im.vector.matrix.android.internal.crypto import im.vector.matrix.android.api.auth.data.Credentials +import im.vector.matrix.android.internal.session.SessionScope import java.util.* +import javax.inject.Inject -internal class ObjectSigner(private val credentials: Credentials, +@SessionScope +internal class ObjectSigner @Inject constructor(private val credentials: Credentials, private val olmDevice: MXOlmDevice) { /** diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt index 20c6800e..27bd7e2a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt @@ -23,11 +23,14 @@ import im.vector.matrix.android.internal.crypto.model.MXKey import im.vector.matrix.android.internal.crypto.model.rest.KeysUploadResponse import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask import im.vector.matrix.android.internal.di.MoshiProvider +import im.vector.matrix.android.internal.session.SessionScope import org.matrix.olm.OlmAccount import timber.log.Timber import java.util.* +import javax.inject.Inject -internal class OneTimeKeysUploader( +@SessionScope +internal class OneTimeKeysUploader @Inject constructor( private val credentials: Credentials, private val olmDevice: MXOlmDevice, private val objectSigner: ObjectSigner, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt index 4c68e905..a07b136c 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt @@ -26,12 +26,15 @@ import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShareCancellat import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShareRequest import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import timber.log.Timber import java.util.* +import javax.inject.Inject -internal class OutgoingRoomKeyRequestManager( +@SessionScope +internal class OutgoingRoomKeyRequestManager @Inject constructor( private val cryptoStore: IMXCryptoStore, private val sendToDeviceTask: SendToDeviceTask, private val taskExecutor: TaskExecutor) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/RoomDecryptorProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/RoomDecryptorProvider.kt index e75885a3..6e30484d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/RoomDecryptorProvider.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/RoomDecryptorProvider.kt @@ -20,10 +20,13 @@ import android.text.TextUtils import im.vector.matrix.android.internal.crypto.algorithms.IMXDecrypting import im.vector.matrix.android.internal.crypto.algorithms.megolm.MXMegolmDecryptionFactory import im.vector.matrix.android.internal.crypto.algorithms.olm.MXOlmDecryptionFactory +import im.vector.matrix.android.internal.session.SessionScope import timber.log.Timber import java.util.* +import javax.inject.Inject -internal class RoomDecryptorProvider( +@SessionScope +internal class RoomDecryptorProvider @Inject constructor( private val olmDecryptionFactory: MXOlmDecryptionFactory, private val megolmDecryptionFactory: MXMegolmDecryptionFactory ) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt index da357c6a..6ea04594 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt @@ -24,11 +24,14 @@ import im.vector.matrix.android.internal.crypto.model.MXKey import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask +import im.vector.matrix.android.internal.session.SessionScope import timber.log.Timber import java.util.* +import javax.inject.Inject -internal class EnsureOlmSessionsForDevicesAction(private val olmDevice: MXOlmDevice, - private val oneTimeKeysForUsersDeviceTask: ClaimOneTimeKeysForUsersDeviceTask) { +@SessionScope +internal class EnsureOlmSessionsForDevicesAction @Inject constructor(private val olmDevice: MXOlmDevice, + private val oneTimeKeysForUsersDeviceTask: ClaimOneTimeKeysForUsersDeviceTask) { suspend fun handle(devicesByUser: Map>): Try> { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt index 6b7e28be..0f784b69 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt @@ -24,10 +24,13 @@ import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore +import im.vector.matrix.android.internal.session.SessionScope import timber.log.Timber import java.util.* +import javax.inject.Inject -internal class EnsureOlmSessionsForUsersAction(private val olmDevice: MXOlmDevice, +@SessionScope +internal class EnsureOlmSessionsForUsersAction @Inject constructor(private val olmDevice: MXOlmDevice, private val cryptoStore: IMXCryptoStore, private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt index 07c8b465..a311ee0a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt @@ -26,12 +26,15 @@ import im.vector.matrix.android.internal.crypto.RoomDecryptorProvider import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore +import im.vector.matrix.android.internal.session.SessionScope import timber.log.Timber +import javax.inject.Inject -internal class MegolmSessionDataImporter(private val olmDevice: MXOlmDevice, - private val roomDecryptorProvider: RoomDecryptorProvider, - private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager, - private val cryptoStore: IMXCryptoStore) { +@SessionScope +internal class MegolmSessionDataImporter @Inject constructor(private val olmDevice: MXOlmDevice, + private val roomDecryptorProvider: RoomDecryptorProvider, + private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager, + private val cryptoStore: IMXCryptoStore) { /** * Import a list of megolm session keys. diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt index bbd23dad..fd063df9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt @@ -23,12 +23,15 @@ import im.vector.matrix.android.internal.crypto.MXOlmDevice import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.EncryptedMessage import im.vector.matrix.android.internal.di.MoshiProvider +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.util.convertToUTF8 import timber.log.Timber import java.util.* +import javax.inject.Inject -internal class MessageEncrypter(private val credentials: Credentials, - private val olmDevice: MXOlmDevice) { +@SessionScope +internal class MessageEncrypter @Inject constructor(private val credentials: Credentials, + private val olmDevice: MXOlmDevice) { /** * Encrypt an event payload for a list of devices. diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt index b76f905b..d5450077 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt @@ -19,9 +19,12 @@ package im.vector.matrix.android.internal.crypto.actions import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore +import im.vector.matrix.android.internal.session.SessionScope import timber.log.Timber +import javax.inject.Inject -internal class SetDeviceVerificationAction(private val cryptoStore: IMXCryptoStore, +@SessionScope +internal class SetDeviceVerificationAction @Inject constructor(private val cryptoStore: IMXCryptoStore, private val credentials: Credentials, private val keysBackup: KeysBackup) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt index 1f2a3758..2f9a61cf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt @@ -24,9 +24,12 @@ import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForDevi import im.vector.matrix.android.internal.crypto.actions.MessageEncrypter import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import javax.inject.Inject -internal class MXMegolmDecryptionFactory(private val credentials: Credentials, +@SessionScope +internal class MXMegolmDecryptionFactory @Inject constructor(private val credentials: Credentials, private val olmDevice: MXOlmDevice, private val deviceListManager: DeviceListManager, private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt index e7daf9ad..0fad79a6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt @@ -25,9 +25,12 @@ import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup import im.vector.matrix.android.internal.crypto.repository.WarnOnUnknownDeviceRepository import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor +import javax.inject.Inject -internal class MXMegolmEncryptionFactory( +@SessionScope +internal class MXMegolmEncryptionFactory @Inject constructor( private val olmDevice: MXOlmDevice, private val keysBackup: KeysBackup, private val cryptoStore: IMXCryptoStore, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt index 5f18fe3e..4fbf88bf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt @@ -18,9 +18,12 @@ package im.vector.matrix.android.internal.crypto.algorithms.olm import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.crypto.MXOlmDevice +import im.vector.matrix.android.internal.session.SessionScope +import javax.inject.Inject -internal class MXOlmDecryptionFactory(private val olmDevice: MXOlmDevice, - private val credentials: Credentials) { +@SessionScope +internal class MXOlmDecryptionFactory @Inject constructor(private val olmDevice: MXOlmDevice, + private val credentials: Credentials) { fun create(): MXOlmDecryption { return MXOlmDecryption( diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt index 30c66a3e..ef047d6c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt @@ -21,14 +21,17 @@ import im.vector.matrix.android.internal.crypto.MXOlmDevice import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForUsersAction import im.vector.matrix.android.internal.crypto.actions.MessageEncrypter import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import javax.inject.Inject -internal class MXOlmEncryptionFactory(private val olmDevice: MXOlmDevice, - private val cryptoStore: IMXCryptoStore, - private val messageEncrypter: MessageEncrypter, - private val deviceListManager: DeviceListManager, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val ensureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction) { +@SessionScope +internal class MXOlmEncryptionFactory @Inject constructor(private val olmDevice: MXOlmDevice, + private val cryptoStore: IMXCryptoStore, + private val messageEncrypter: MessageEncrypter, + private val deviceListManager: DeviceListManager, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val ensureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction) { fun create(roomId: String): MXOlmEncryption { return MXOlmEncryption( diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt index b80b063f..673fd6db 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt @@ -47,6 +47,7 @@ import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrap import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEntity import im.vector.matrix.android.internal.di.MoshiProvider +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskThread @@ -58,13 +59,16 @@ import org.matrix.olm.OlmPkMessage import timber.log.Timber import java.security.InvalidParameterException import java.util.* +import javax.inject.Inject import kotlin.collections.HashMap /** * A KeysBackup class instance manage incremental backup of e2e keys (megolm keys) * to the user's homeserver. */ -internal class KeysBackup( + +@SessionScope +internal class KeysBackup @Inject constructor( private val credentials: Credentials, private val cryptoStore: IMXCryptoStore, private val olmDevice: MXOlmDevice, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt index e63201bd..feb4a189 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt @@ -21,12 +21,14 @@ import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersion import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface CreateKeysBackupVersionTask : Task - -internal class DefaultCreateKeysBackupVersionTask(private val roomKeysApi: RoomKeysApi) +@SessionScope +internal class DefaultCreateKeysBackupVersionTask @Inject constructor(private val roomKeysApi: RoomKeysApi) : CreateKeysBackupVersionTask { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt index 34d183a1..6d857636 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt @@ -19,7 +19,9 @@ package im.vector.matrix.android.internal.crypto.keysbackup.tasks import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface DeleteBackupTask : Task { @@ -28,8 +30,8 @@ internal interface DeleteBackupTask : Task { ) } - -internal class DefaultDeleteBackupTask(private val roomKeysApi: RoomKeysApi) +@SessionScope +internal class DefaultDeleteBackupTask @Inject constructor(private val roomKeysApi: RoomKeysApi) : DeleteBackupTask { override suspend fun execute(params: DeleteBackupTask.Params): Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt index e80e160b..3edd90a8 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt @@ -19,7 +19,9 @@ package im.vector.matrix.android.internal.crypto.keysbackup.tasks import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface DeleteRoomSessionDataTask : Task { data class Params( @@ -29,8 +31,8 @@ internal interface DeleteRoomSessionDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt index 25e930f4..71dd7801 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt @@ -19,7 +19,9 @@ package im.vector.matrix.android.internal.crypto.keysbackup.tasks import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface DeleteRoomSessionsDataTask : Task { data class Params( @@ -28,8 +30,8 @@ internal interface DeleteRoomSessionsDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteSessionsDataTask.kt index 1580849a..dfdf3afa 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteSessionsDataTask.kt @@ -19,7 +19,9 @@ package im.vector.matrix.android.internal.crypto.keysbackup.tasks import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface DeleteSessionsDataTask : Task { data class Params( @@ -27,8 +29,8 @@ internal interface DeleteSessionsDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt index eb5d8899..ec6029bc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt @@ -20,12 +20,14 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersionResult import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetKeysBackupLastVersionTask : Task - -internal class DefaultGetKeysBackupLastVersionTask(private val roomKeysApi: RoomKeysApi) +@SessionScope +internal class DefaultGetKeysBackupLastVersionTask @Inject constructor(private val roomKeysApi: RoomKeysApi) : GetKeysBackupLastVersionTask { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt index 209c8136..0016a01b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt @@ -20,12 +20,14 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersionResult import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetKeysBackupVersionTask : Task - -internal class DefaultGetKeysBackupVersionTask(private val roomKeysApi: RoomKeysApi) +@SessionScope +internal class DefaultGetKeysBackupVersionTask @Inject constructor(private val roomKeysApi: RoomKeysApi) : GetKeysBackupVersionTask { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt index 849e37eb..05aee672 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt @@ -20,7 +20,9 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeyBackupData import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetRoomSessionDataTask : Task { data class Params( @@ -30,8 +32,8 @@ internal interface GetRoomSessionDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt index e67e2bc3..fa466815 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt @@ -20,7 +20,9 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.RoomKeysBackupData import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetRoomSessionsDataTask : Task { @@ -30,8 +32,8 @@ internal interface GetRoomSessionsDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetSessionsDataTask.kt index b2f3005b..f541df78 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetSessionsDataTask.kt @@ -20,7 +20,9 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysBackupData import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetSessionsDataTask : Task { data class Params( @@ -28,8 +30,8 @@ internal interface GetSessionsDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt index e7452b0e..c1005801 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt @@ -21,7 +21,9 @@ import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeyBackupData import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.BackupKeysResult import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface StoreRoomSessionDataTask : Task { data class Params( @@ -32,8 +34,8 @@ internal interface StoreRoomSessionDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt index 29ab818d..edaa666c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt @@ -21,7 +21,9 @@ import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.RoomKeysBackupData import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.BackupKeysResult import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface StoreRoomSessionsDataTask : Task { data class Params( @@ -31,8 +33,8 @@ internal interface StoreRoomSessionsDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt index c5b39d2d..252dc906 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt @@ -21,7 +21,9 @@ import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysBackupData import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.BackupKeysResult import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface StoreSessionsDataTask : Task { data class Params( @@ -30,8 +32,8 @@ internal interface StoreSessionsDataTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt index e2605bfb..7f060e68 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt @@ -20,7 +20,9 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.UpdateKeysBackupVersionBody import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface UpdateKeysBackupVersionTask : Task { data class Params( @@ -29,8 +31,8 @@ internal interface UpdateKeysBackupVersionTask : Task> { data class Params( @@ -34,7 +36,8 @@ internal interface ClaimOneTimeKeysForUsersDeviceTask : Task> { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DeleteDeviceTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DeleteDeviceTask.kt index 0fb9ad0f..acd84b41 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DeleteDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DeleteDeviceTask.kt @@ -20,7 +20,9 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.model.rest.DeleteDeviceParams import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface DeleteDeviceTask : Task { data class Params( @@ -29,7 +31,8 @@ internal interface DeleteDeviceTask : Task { ) } -internal class DefaultDeleteDeviceTask(private val cryptoApi: CryptoApi) +@SessionScope +internal class DefaultDeleteDeviceTask @Inject constructor(private val cryptoApi: CryptoApi) : DeleteDeviceTask { override suspend fun execute(params: DeleteDeviceTask.Params): Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt index a8da9eab..09539ade 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt @@ -22,8 +22,10 @@ import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.model.rest.KeysQueryBody import im.vector.matrix.android.internal.crypto.model.rest.KeysQueryResponse import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import java.util.* +import javax.inject.Inject internal interface DownloadKeysForUsersTask : Task { data class Params( @@ -33,7 +35,8 @@ internal interface DownloadKeysForUsersTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetDevicesTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetDevicesTask.kt index 7d634ab5..d0296a39 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetDevicesTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetDevicesTask.kt @@ -20,11 +20,14 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetDevicesTask : Task -internal class DefaultGetDevicesTask(private val cryptoApi: CryptoApi) +@SessionScope +internal class DefaultGetDevicesTask @Inject constructor(private val cryptoApi: CryptoApi) : GetDevicesTask { override suspend fun execute(params: Unit): Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt index 937607d9..a89dabea 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt @@ -20,7 +20,9 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.model.rest.KeyChangesResponse import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetKeyChangesTask : Task { data class Params( @@ -31,7 +33,8 @@ internal interface GetKeyChangesTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SendToDeviceTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SendToDeviceTask.kt index 89417b08..6e6fcff3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SendToDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SendToDeviceTask.kt @@ -21,8 +21,10 @@ import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.model.rest.SendToDeviceBody import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import java.util.* +import javax.inject.Inject internal interface SendToDeviceTask : Task { data class Params( @@ -35,7 +37,8 @@ internal interface SendToDeviceTask : Task { ) } -internal class DefaultSendToDeviceTask(private val cryptoApi: CryptoApi) +@SessionScope +internal class DefaultSendToDeviceTask @Inject constructor(private val cryptoApi: CryptoApi) : SendToDeviceTask { override suspend fun execute(params: SendToDeviceTask.Params): Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt index 22daf517..0997a4b2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt @@ -21,7 +21,9 @@ import arrow.core.Try import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.model.rest.UpdateDeviceInfoBody import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface SetDeviceNameTask : Task { data class Params( @@ -32,7 +34,8 @@ internal interface SetDeviceNameTask : Task { ) } -internal class DefaultSetDeviceNameTask(private val cryptoApi: CryptoApi) +@SessionScope +internal class DefaultSetDeviceNameTask @Inject constructor(private val cryptoApi: CryptoApi) : SetDeviceNameTask { override suspend fun execute(params: SetDeviceNameTask.Params): Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt index 067f8ff7..434803c2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt @@ -23,8 +23,10 @@ import im.vector.matrix.android.internal.crypto.model.rest.KeysUploadResponse import im.vector.matrix.android.internal.crypto.model.rest.DeviceKeys import im.vector.matrix.android.internal.crypto.model.rest.KeysUploadBody import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.util.convertToUTF8 +import javax.inject.Inject internal interface UploadKeysTask : Task { data class Params( @@ -36,7 +38,8 @@ internal interface UploadKeysTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt index 81556052..803bcb98 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt @@ -40,6 +40,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers @@ -47,6 +48,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import timber.log.Timber import java.util.* +import javax.inject.Inject import kotlin.collections.HashMap /** @@ -54,14 +56,16 @@ import kotlin.collections.HashMap * Short codes interactive verification is a more user friendly way of verifying devices * that is still maintaining a good level of security (alternative to the 43-character strings compare method). */ -internal class DefaultSasVerificationService(private val credentials: Credentials, - private val cryptoStore: IMXCryptoStore, - private val myDeviceInfoHolder: MyDeviceInfoHolder, - private val deviceListManager: DeviceListManager, - private val setDeviceVerificationAction: SetDeviceVerificationAction, - private val sendToDeviceTask: SendToDeviceTask, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val taskExecutor: TaskExecutor) + +@SessionScope +internal class DefaultSasVerificationService @Inject constructor(private val credentials: Credentials, + private val cryptoStore: IMXCryptoStore, + private val myDeviceInfoHolder: MyDeviceInfoHolder, + private val deviceListManager: DeviceListManager, + private val setDeviceVerificationAction: SetDeviceVerificationAction, + private val sendToDeviceTask: SendToDeviceTask, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val taskExecutor: TaskExecutor) : VerificationTransaction.Listener, SasVerificationService { private val uiHandler = Handler(Looper.getMainLooper()) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixKoinHolder.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/ChildWorkerFactory.kt similarity index 64% rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixKoinHolder.kt rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/ChildWorkerFactory.kt index e3d2047f..169bcb6f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixKoinHolder.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/ChildWorkerFactory.kt @@ -16,22 +16,12 @@ package im.vector.matrix.android.internal.di -import org.koin.core.Koin -import org.koin.core.KoinContext -import org.koin.standalone.KoinComponent +import android.content.Context +import androidx.work.ListenableWorker +import androidx.work.WorkerParameters -internal object MatrixKoinHolder { +interface ChildWorkerFactory { - val instance: Koin by lazy { - Koin.create() - } - -} - -internal interface MatrixKoinComponent : KoinComponent { - - override fun getKoin(): KoinContext { - return MatrixKoinHolder.instance.koinContext - } + fun create(appContext: Context, params: WorkerParameters): ListenableWorker } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt new file mode 100644 index 00000000..444475d5 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt @@ -0,0 +1,25 @@ +/* + * 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.matrix.android.internal.di + +import dagger.Component + +@Component +@MatrixScope +interface MatrixComponent { + +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt index 8f9447c6..795ec83c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt @@ -17,43 +17,31 @@ package im.vector.matrix.android.internal.di import android.content.Context +import dagger.Module +import dagger.Provides import im.vector.matrix.android.internal.crypto.CryptoAsyncHelper -import im.vector.matrix.android.internal.task.TaskExecutor -import im.vector.matrix.android.internal.util.BackgroundDetectionObserver import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers -import im.vector.matrix.android.internal.util.StringProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.android.asCoroutineDispatcher -import org.koin.dsl.module.module +@Module +internal class MatrixModule(private val context: Context) { -class MatrixModule(private val context: Context) { - - val definition = module { - - single { - context + @Provides + @MatrixScope + fun providesContext(): Context { + return context } - single { + @Provides + @MatrixScope + fun providesMatrixCoroutineDispatchers(): MatrixCoroutineDispatchers { val cryptoHandler = CryptoAsyncHelper.getDecryptBackgroundHandler() - MatrixCoroutineDispatchers(io = Dispatchers.IO, + return MatrixCoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.IO, main = Dispatchers.Main, crypto = cryptoHandler.asCoroutineDispatcher("crypto") ) } - single { - TaskExecutor(get()) - } - single { - StringProvider(context.resources) - } - - single { - BackgroundDetectionObserver() - } - - } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixScope.java similarity index 63% rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixScope.java index a82fddc8..30c9138e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixScope.java @@ -14,18 +14,16 @@ * limitations under the License. */ -package im.vector.matrix.android.internal.session.user +package im.vector.matrix.android.internal.di; -import im.vector.matrix.android.internal.session.DefaultSession -import org.koin.dsl.module.module +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; -internal class UserModule { +import javax.inject.Scope; - val definition = module(override = true) { +import static java.lang.annotation.RetentionPolicy.RUNTIME; - scope(DefaultSession.SCOPE) { - DefaultUpdateUserTask(get()) as UpdateUserTask - } - - } -} +@Scope +@Documented +@Retention(RUNTIME) +public @interface MatrixScope {} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt index d41f2cf8..b11e5a1e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt @@ -17,85 +17,84 @@ package im.vector.matrix.android.internal.di import com.facebook.stetho.okhttp3.StethoInterceptor +import com.squareup.moshi.Moshi +import dagger.Module +import dagger.Provides import im.vector.matrix.android.BuildConfig -import im.vector.matrix.android.internal.network.* +import im.vector.matrix.android.internal.network.AccessTokenInterceptor +import im.vector.matrix.android.internal.network.UnitConverterFactory +import im.vector.matrix.android.internal.network.UserAgentInterceptor import im.vector.matrix.android.internal.network.interceptors.CurlLoggingInterceptor import im.vector.matrix.android.internal.network.interceptors.FormattedJsonHttpLogger import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import okreplay.OkReplayInterceptor -import org.koin.dsl.module.module import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory import java.util.concurrent.TimeUnit -class NetworkModule { - - val definition = module { - - single { - UserAgentHolder(get()) - } - - single { - UserAgentInterceptor(get()) - } - - single { - AccessTokenInterceptor(get()) - } - - single { - val logger = FormattedJsonHttpLogger() - val interceptor = HttpLoggingInterceptor(logger) - interceptor.level = BuildConfig.OKHTTP_LOGGING_LEVEL - interceptor - } - - single { - CurlLoggingInterceptor() - } - - single { - OkReplayInterceptor() - } - - single { - StethoInterceptor() - } - - single { - OkHttpClient.Builder() - .connectTimeout(1, TimeUnit.MINUTES) - .readTimeout(30, TimeUnit.SECONDS) - .writeTimeout(30, TimeUnit.SECONDS) - .addNetworkInterceptor(get()) - .addInterceptor(get()) - .addInterceptor(get()) - .addInterceptor(get()) - .apply { - if (BuildConfig.LOG_PRIVATE_DATA) { - addInterceptor(get()) - } - } - .addInterceptor(get()) - .build() - } - - single { - MoshiProvider.providesMoshi() - } - - single { - NetworkConnectivityChecker(get()) - } - - factory { - Retrofit.Builder() - .client(get()) - .addConverterFactory(UnitConverterFactory) - .addConverterFactory(MoshiConverterFactory.create(get())) - } +@Module +internal class NetworkModule { + @MatrixScope + @Provides + fun providesHttpLogingInterceptor(): HttpLoggingInterceptor { + val logger = FormattedJsonHttpLogger() + val interceptor = HttpLoggingInterceptor(logger) + interceptor.level = BuildConfig.OKHTTP_LOGGING_LEVEL + return interceptor } + + @MatrixScope + @Provides + fun providesOkReplayInterceptor(): OkReplayInterceptor { + return OkReplayInterceptor() + } + + @MatrixScope + @Provides + fun providesStethoInterceptor(): StethoInterceptor { + return StethoInterceptor() + } + + @MatrixScope + @Provides + fun providesOkHttpClient(stethoInterceptor: StethoInterceptor, + userAgentInterceptor: UserAgentInterceptor, + accessTokenInterceptor: AccessTokenInterceptor, + httpLoggingInterceptor: HttpLoggingInterceptor, + curlLoggingInterceptor: CurlLoggingInterceptor, + okReplayInterceptor: OkReplayInterceptor): OkHttpClient { + return OkHttpClient.Builder() + .connectTimeout(1, TimeUnit.MINUTES) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .addNetworkInterceptor(stethoInterceptor) + .addInterceptor(userAgentInterceptor) + .addInterceptor(accessTokenInterceptor) + .addInterceptor(httpLoggingInterceptor) + .apply { + if (BuildConfig.LOG_PRIVATE_DATA) { + addInterceptor(curlLoggingInterceptor) + } + } + .addInterceptor(okReplayInterceptor) + .build() + } + + @MatrixScope + @Provides + fun providesMoshi(): Moshi { + return MoshiProvider.providesMoshi() + } + + @Provides + fun providesRetrofitBuilder(okHttpClient: OkHttpClient, + moshi: Moshi): Retrofit.Builder { + return Retrofit.Builder() + .client(okHttpClient) + .addConverterFactory(UnitConverterFactory) + .addConverterFactory(MoshiConverterFactory.create(moshi)) + } + } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/AccessTokenInterceptor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/AccessTokenInterceptor.kt index 77d2ec92..62030490 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/AccessTokenInterceptor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/AccessTokenInterceptor.kt @@ -17,10 +17,13 @@ package im.vector.matrix.android.internal.network import im.vector.matrix.android.internal.auth.SessionParamsStore +import im.vector.matrix.android.internal.di.MatrixScope import okhttp3.Interceptor import okhttp3.Response +import javax.inject.Inject -internal class AccessTokenInterceptor(private val sessionParamsStore: SessionParamsStore) : Interceptor { +@MatrixScope +internal class AccessTokenInterceptor @Inject constructor(private val sessionParamsStore: SessionParamsStore) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { var request = chain.request() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConnectivityChecker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConnectivityChecker.kt index ef83e47e..9502cb28 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConnectivityChecker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConnectivityChecker.kt @@ -20,8 +20,11 @@ import android.content.Context import com.novoda.merlin.Merlin import com.novoda.merlin.MerlinsBeard import com.novoda.merlin.registerable.connection.Connectable +import im.vector.matrix.android.internal.di.MatrixScope +import javax.inject.Inject -internal class NetworkConnectivityChecker(context: Context) { +@MatrixScope +internal class NetworkConnectivityChecker @Inject constructor(context: Context) { private val merlin = Merlin.Builder().withConnectableCallbacks().build(context) private val merlinsBeard = MerlinsBeard.from(context) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/UserAgentHolder.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/UserAgentHolder.kt index 7917f960..306b8a91 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/UserAgentHolder.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/UserAgentHolder.kt @@ -19,9 +19,12 @@ package im.vector.matrix.android.internal.network import android.content.Context import android.text.TextUtils import im.vector.matrix.android.BuildConfig +import im.vector.matrix.android.internal.di.MatrixScope import timber.log.Timber +import javax.inject.Inject -internal class UserAgentHolder(val context: Context) { +@MatrixScope +internal class UserAgentHolder @Inject constructor(val context: Context) { var userAgent: String = "" private set diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/UserAgentInterceptor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/UserAgentInterceptor.kt index 151ba0c3..30759923 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/UserAgentInterceptor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/UserAgentInterceptor.kt @@ -16,10 +16,13 @@ package im.vector.matrix.android.internal.network +import im.vector.matrix.android.internal.di.MatrixScope import okhttp3.Interceptor import okhttp3.Response +import javax.inject.Inject -internal class UserAgentInterceptor(private val userAgentHolder: UserAgentHolder) : Interceptor { +@MatrixScope +internal class UserAgentInterceptor @Inject constructor(private val userAgentHolder: UserAgentHolder) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { var request = chain.request() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index 747ee9e4..80f60b8c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -16,86 +16,63 @@ package im.vector.matrix.android.internal.session -import android.content.Context import android.os.Looper import androidx.annotation.MainThread import androidx.lifecycle.LiveData +import com.squareup.inject.assisted.Assisted +import com.squareup.inject.assisted.AssistedInject import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.SessionParams -import im.vector.matrix.android.api.listeners.ProgressListener import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.cache.CacheService import im.vector.matrix.android.api.session.content.ContentUploadStateTracker import im.vector.matrix.android.api.session.content.ContentUrlResolver -import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupService -import im.vector.matrix.android.api.session.crypto.keyshare.RoomKeysRequestListener -import im.vector.matrix.android.api.session.crypto.sas.SasVerificationService -import im.vector.matrix.android.api.session.events.model.Content -import im.vector.matrix.android.api.session.events.model.Event -import im.vector.matrix.android.api.session.group.Group +import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.group.GroupService -import im.vector.matrix.android.api.session.group.model.GroupSummary -import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.RoomDirectoryService import im.vector.matrix.android.api.session.room.RoomService -import im.vector.matrix.android.api.session.room.model.RoomSummary -import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams -import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsParams -import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsResponse -import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol import im.vector.matrix.android.api.session.signout.SignOutService import im.vector.matrix.android.api.session.sync.FilterService import im.vector.matrix.android.api.session.sync.SyncState import im.vector.matrix.android.api.session.user.UserService -import im.vector.matrix.android.api.session.user.model.User -import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.api.util.MatrixCallbackDelegate import im.vector.matrix.android.internal.crypto.CryptoManager -import im.vector.matrix.android.internal.crypto.CryptoModule -import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult -import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult -import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo -import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult -import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap -import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse -import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody import im.vector.matrix.android.internal.database.LiveEntityObserver -import im.vector.matrix.android.internal.di.MatrixKoinComponent -import im.vector.matrix.android.internal.di.MatrixKoinHolder -import im.vector.matrix.android.internal.session.content.ContentModule -import im.vector.matrix.android.internal.session.group.GroupModule -import im.vector.matrix.android.internal.session.room.RoomModule -import im.vector.matrix.android.internal.session.signout.SignOutModule -import im.vector.matrix.android.internal.session.sync.SyncModule import im.vector.matrix.android.internal.session.sync.job.SyncThread -import im.vector.matrix.android.internal.session.user.UserModule -import org.koin.core.scope.Scope -import org.koin.standalone.inject import timber.log.Timber -internal class DefaultSession(override val sessionParams: SessionParams) : Session, MatrixKoinComponent { - companion object { - const val SCOPE: String = "session" +internal class DefaultSession @AssistedInject constructor(@Assisted override val sessionParams: SessionParams, + private val monarchy: Monarchy, + private val liveEntityUpdaters: List, + private val sessionListeners: SessionListeners, + private val roomService: RoomService, + private val roomDirectoryService: RoomDirectoryService, + private val groupService: GroupService, + private val userService: UserService, + private val filterService: FilterService, + private val cacheService: CacheService, + private val signOutService: SignOutService, + private val cryptoService: CryptoManager, + private val syncThread: SyncThread, + private val contentUrlResolver: ContentUrlResolver, + private val contentUploadProgressTracker: ContentUploadStateTracker) + : Session, + RoomService by roomService, + RoomDirectoryService by roomDirectoryService, + GroupService by groupService, + UserService by userService, + CryptoService by cryptoService, + CacheService by cacheService, + SignOutService by signOutService, + FilterService by filterService { + + @AssistedInject.Factory + interface Factory { + fun create(sessionParams: SessionParams): DefaultSession } - private lateinit var scope: Scope - - private val monarchy by inject() - private val liveEntityUpdaters by inject>() - private val sessionListeners by inject() - private val roomService by inject() - private val roomDirectoryService by inject() - private val groupService by inject() - private val userService by inject() - private val filterService by inject() - private val cacheService by inject() - private val signOutService by inject() - private val cryptoService by inject() - private val syncThread by inject() - private val contentUrlResolver by inject() - private val contentUploadProgressTracker by inject() private var isOpen = false @MainThread @@ -103,23 +80,6 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi assertMainThread() assert(!isOpen) isOpen = true - val sessionModule = SessionModule(sessionParams).definition - val syncModule = SyncModule().definition - val roomModule = RoomModule().definition - val groupModule = GroupModule().definition - val signOutModule = SignOutModule().definition - val userModule = UserModule().definition - val contentModule = ContentModule().definition - val cryptoModule = CryptoModule().definition - MatrixKoinHolder.instance.loadModules(listOf(sessionModule, - syncModule, - roomModule, - groupModule, - userModule, - signOutModule, - contentModule, - cryptoModule)) - scope = getKoin().getOrCreateScope(SCOPE) if (!monarchy.isMonarchyThreadOpen) { monarchy.openManually() } @@ -147,7 +107,6 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi if (monarchy.isMonarchyThreadOpen) { monarchy.closeManually() } - scope.close() isOpen = false } @@ -207,221 +166,6 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi sessionListeners.removeListener(listener) } - // ROOM SERVICE - - override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback) { - assert(isOpen) - return roomService.createRoom(createRoomParams, callback) - } - - override fun getRoom(roomId: String): Room? { - assert(isOpen) - return roomService.getRoom(roomId) - } - - - override fun liveRoomSummaries(): LiveData> { - assert(isOpen) - return roomService.liveRoomSummaries() - } - - // ROOM DIRECTORY SERVICE - - override fun getPublicRooms(server: String?, publicRoomsParams: PublicRoomsParams, callback: MatrixCallback): Cancelable { - assert(isOpen) - return roomDirectoryService.getPublicRooms(server, publicRoomsParams, callback) - } - - override fun joinRoom(roomId: String, callback: MatrixCallback) { - assert(isOpen) - return roomDirectoryService.joinRoom(roomId, callback) - } - - override fun getThirdPartyProtocol(callback: MatrixCallback>) { - assert(isOpen) - return roomDirectoryService.getThirdPartyProtocol(callback) - } - - // GROUP SERVICE - - override fun getGroup(groupId: String): Group? { - assert(isOpen) - return groupService.getGroup(groupId) - } - - override fun liveGroupSummaries(): LiveData> { - assert(isOpen) - return groupService.liveGroupSummaries() - } - - override fun setFilter(filterPreset: FilterService.FilterPreset) { - assert(isOpen) - return filterService.setFilter(filterPreset) - } - - override fun clearCache(callback: MatrixCallback) { - assert(isOpen) - syncThread.pause() - cacheService.clearCache(object : MatrixCallbackDelegate(callback) { - override fun onSuccess(data: Unit) { - // Restart the sync - syncThread.restart() - - super.onSuccess(data) - } - }) - } - - // USER SERVICE - - override fun getUser(userId: String): User? { - assert(isOpen) - return userService.getUser(userId) - } - - override fun observeUser(userId: String): LiveData { - assert(isOpen) - return userService.observeUser(userId) - } - - // CRYPTO SERVICE - - override fun setDeviceName(deviceId: String, deviceName: String, callback: MatrixCallback) { - cryptoService.setDeviceName(deviceId, deviceName, callback) - } - - override fun deleteDevice(deviceId: String, accountPassword: String, callback: MatrixCallback) { - cryptoService.deleteDevice(deviceId, accountPassword, callback) - } - - override fun getCryptoVersion(context: Context, longFormat: Boolean): String { - return cryptoService.getCryptoVersion(context, longFormat) - } - - override fun isCryptoEnabled(): Boolean { - return cryptoService.isCryptoEnabled() - } - - override fun getSasVerificationService(): SasVerificationService { - return cryptoService.getSasVerificationService() - } - - override fun getKeysBackupService(): KeysBackupService { - return cryptoService.getKeysBackupService() - } - - override fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean { - return cryptoService.isRoomBlacklistUnverifiedDevices(roomId) - } - - override fun setWarnOnUnknownDevices(warn: Boolean) { - cryptoService.setWarnOnUnknownDevices(warn) - } - - override fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String) { - cryptoService.setDeviceVerification(verificationStatus, deviceId, userId) - } - - override fun getUserDevices(userId: String): MutableList { - return cryptoService.getUserDevices(userId) - } - - override fun setDevicesKnown(devices: List, callback: MatrixCallback?) { - cryptoService.setDevicesKnown(devices, callback) - } - - override fun deviceWithIdentityKey(senderKey: String, algorithm: String): MXDeviceInfo? { - return cryptoService.deviceWithIdentityKey(senderKey, algorithm) - } - - override fun getMyDevice(): MXDeviceInfo { - return cryptoService.getMyDevice() - } - - override fun getDevicesList(callback: MatrixCallback) { - cryptoService.getDevicesList(callback) - } - - override fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int { - return cryptoService.inboundGroupSessionsCount(onlyBackedUp) - } - - override fun getGlobalBlacklistUnverifiedDevices(): Boolean { - return cryptoService.getGlobalBlacklistUnverifiedDevices() - } - - override fun setGlobalBlacklistUnverifiedDevices(block: Boolean) { - cryptoService.setGlobalBlacklistUnverifiedDevices(block) - } - - override fun setRoomUnBlacklistUnverifiedDevices(roomId: String) { - cryptoService.setRoomUnBlacklistUnverifiedDevices(roomId) - } - - override fun getDeviceTrackingStatus(userId: String): Int { - return cryptoService.getDeviceTrackingStatus(userId) - } - - override fun importRoomKeys(roomKeysAsArray: ByteArray, password: String, progressListener: ProgressListener?, callback: MatrixCallback) { - cryptoService.importRoomKeys(roomKeysAsArray, password, progressListener, callback) - } - - override fun exportRoomKeys(password: String, callback: MatrixCallback) { - cryptoService.exportRoomKeys(password, callback) - } - - override fun setRoomBlacklistUnverifiedDevices(roomId: String) { - cryptoService.setRoomBlacklistUnverifiedDevices(roomId) - } - - override fun isRoomEncrypted(roomId: String): Boolean { - return cryptoService.isRoomEncrypted(roomId) - } - - override fun encryptEventContent(eventContent: Content, eventType: String, roomId: String, callback: MatrixCallback) { - cryptoService.encryptEventContent(eventContent, eventType, roomId, callback) - } - - override fun getDeviceInfo(userId: String, deviceId: String?): MXDeviceInfo? { - return cryptoService.getDeviceInfo(userId, deviceId) - } - - override fun reRequestRoomKeyForEvent(event: Event) { - cryptoService.reRequestRoomKeyForEvent(event) - } - - override fun cancelRoomKeyRequest(requestBody: RoomKeyRequestBody) { - cryptoService.cancelRoomKeyRequest(requestBody) - } - - override fun addRoomKeysRequestListener(listener: RoomKeysRequestListener) { - cryptoService.addRoomKeysRequestListener(listener) - } - - override fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult? { - return cryptoService.decryptEvent(event, timeline) - } - - override fun decryptEventAsync(event: Event, timeline: String, callback: MatrixCallback) { - return cryptoService.decryptEventAsync(event, timeline, callback) - } - - override fun getEncryptionAlgorithm(roomId: String): String? { - return cryptoService.getEncryptionAlgorithm(roomId) - } - - override fun shouldEncryptForInvitedMembers(roomId: String): Boolean { - return cryptoService.shouldEncryptForInvitedMembers(roomId) - } - - override fun downloadKeys(userIds: List, forceDownload: Boolean, callback: MatrixCallback>) { - cryptoService.downloadKeys(userIds, forceDownload, callback) - } - - override fun clearCryptoCache(callback: MatrixCallback) { - cryptoService.clearCryptoCache(callback) - } - // Private methods ***************************************************************************** private fun assertMainThread() { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt new file mode 100644 index 00000000..74eb73b4 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt @@ -0,0 +1,31 @@ +/* + * 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.matrix.android.internal.session + +import dagger.Component +import im.vector.matrix.android.internal.di.MatrixComponent + +@Component(dependencies = [MatrixComponent::class]) +@SessionScope +interface SessionComponent { + + @Component.Builder + interface Builder { + fun matrixComponent(matrixComponent: MatrixComponent): Builder + } + +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionFactory.kt new file mode 100644 index 00000000..ef5a0e4c --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionFactory.kt @@ -0,0 +1,75 @@ +/* + * 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.matrix.android.internal.session + +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.auth.data.SessionParams +import im.vector.matrix.android.api.session.Session +import im.vector.matrix.android.api.session.cache.CacheService +import im.vector.matrix.android.api.session.content.ContentUploadStateTracker +import im.vector.matrix.android.api.session.content.ContentUrlResolver +import im.vector.matrix.android.api.session.group.GroupService +import im.vector.matrix.android.api.session.room.RoomDirectoryService +import im.vector.matrix.android.api.session.room.RoomService +import im.vector.matrix.android.api.session.signout.SignOutService +import im.vector.matrix.android.api.session.sync.FilterService +import im.vector.matrix.android.api.session.user.UserService +import im.vector.matrix.android.internal.crypto.CryptoManager +import im.vector.matrix.android.internal.database.LiveEntityObserver +import im.vector.matrix.android.internal.di.MatrixScope +import im.vector.matrix.android.internal.session.sync.job.SyncThread +import javax.inject.Inject + +@MatrixScope +internal class SessionFactory @Inject constructor( + private val monarchy: Monarchy, + private val liveEntityUpdaters: List, + private val sessionListeners: SessionListeners, + private val roomService: RoomService, + private val roomDirectoryService: RoomDirectoryService, + private val groupService: GroupService, + private val userService: UserService, + private val filterService: FilterService, + private val cacheService: CacheService, + private val signOutService: SignOutService, + private val cryptoService: CryptoManager, + private val syncThread: SyncThread, + private val contentUrlResolver: ContentUrlResolver, + private val contentUploadProgressTracker: ContentUploadStateTracker) { + + + fun create(sessionParams: SessionParams): Session { + return DefaultSession( + sessionParams, + monarchy, + liveEntityUpdaters, + sessionListeners, + roomService, + roomDirectoryService, + groupService, + userService, + filterService, + cacheService, + signOutService, + cryptoService, + syncThread, + contentUrlResolver, + contentUploadProgressTracker + ) + } + +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionListeners.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionListeners.kt index 4fcb16e8..51b73547 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionListeners.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionListeners.kt @@ -17,8 +17,9 @@ package im.vector.matrix.android.internal.session import im.vector.matrix.android.api.session.Session +import javax.inject.Inject -internal class SessionListeners { +internal class SessionListeners @Inject constructor(){ private val listeners = ArrayList() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt index 4a5d3b4e..aea08a69 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt @@ -18,161 +18,68 @@ package im.vector.matrix.android.internal.session import android.content.Context import com.zhuinden.monarchy.Monarchy +import dagger.Module +import dagger.Provides +import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.SessionParams -import im.vector.matrix.android.api.session.cache.CacheService -import im.vector.matrix.android.api.session.group.GroupService -import im.vector.matrix.android.api.session.room.RoomDirectoryService -import im.vector.matrix.android.api.session.room.RoomService -import im.vector.matrix.android.api.session.signout.SignOutService -import im.vector.matrix.android.api.session.sync.FilterService -import im.vector.matrix.android.api.session.user.UserService import im.vector.matrix.android.internal.database.LiveEntityObserver import im.vector.matrix.android.internal.database.model.SessionRealmModule -import im.vector.matrix.android.internal.session.cache.ClearCacheTask -import im.vector.matrix.android.internal.session.cache.RealmCacheService -import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask -import im.vector.matrix.android.internal.session.filter.* -import im.vector.matrix.android.internal.session.group.DefaultGroupService +import im.vector.matrix.android.internal.session.filter.FilterApi import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater -import im.vector.matrix.android.internal.session.room.* -import im.vector.matrix.android.internal.session.room.directory.DefaultGetPublicRoomTask -import im.vector.matrix.android.internal.session.room.directory.DefaultGetThirdPartyProtocolsTask -import im.vector.matrix.android.internal.session.room.directory.GetPublicRoomTask -import im.vector.matrix.android.internal.session.room.directory.GetThirdPartyProtocolsTask -import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver -import im.vector.matrix.android.internal.session.room.membership.RoomMemberDisplayNameResolver +import im.vector.matrix.android.internal.session.room.EventRelationsAggregationUpdater import im.vector.matrix.android.internal.session.room.prune.EventsPruner -import im.vector.matrix.android.internal.session.signout.DefaultSignOutService -import im.vector.matrix.android.internal.session.user.DefaultUserService import im.vector.matrix.android.internal.session.user.UserEntityUpdater import im.vector.matrix.android.internal.util.md5 import io.realm.RealmConfiguration -import org.koin.dsl.module.module import retrofit2.Retrofit import java.io.File +@Module internal class SessionModule(private val sessionParams: SessionParams) { - val definition = module(override = true) { + @Provides + fun providesCredentials(): Credentials { + return sessionParams.credentials + } - scope(DefaultSession.SCOPE) { - sessionParams - } + @Provides + fun providesRealmConfiguration(context: Context): RealmConfiguration { + val childPath = sessionParams.credentials.userId.md5() + val directory = File(context.filesDir, childPath) - scope(DefaultSession.SCOPE) { - sessionParams.credentials - } + return RealmConfiguration.Builder() + .directory(directory) + .name("disk_store.realm") + .modules(SessionRealmModule()) + .deleteRealmIfMigrationNeeded() + .build() + } - scope(DefaultSession.SCOPE, name = "SessionRealmConfiguration") { - val context = get() - val childPath = sessionParams.credentials.userId.md5() - val directory = File(context.filesDir, childPath) + @Provides + fun providesMonarchy(realmConfiguration: RealmConfiguration): Monarchy { + return Monarchy.Builder() + .setRealmConfiguration(realmConfiguration) + .build() + } - RealmConfiguration.Builder() - .directory(directory) - .name("disk_store.realm") - .modules(SessionRealmModule()) - .deleteRealmIfMigrationNeeded() - .build() - } - - scope(DefaultSession.SCOPE) { - Monarchy.Builder() - .setRealmConfiguration(get("SessionRealmConfiguration")) - .build() - } - - scope(DefaultSession.SCOPE) { - val retrofitBuilder = get() - retrofitBuilder - .baseUrl(sessionParams.homeServerConnectionConfig.homeServerUri.toString()) - .build() - } - - scope(DefaultSession.SCOPE) { - RoomMemberDisplayNameResolver() - } - - scope(DefaultSession.SCOPE) { - RoomDisplayNameResolver(get(), get(), get(), sessionParams.credentials) - } - - scope(DefaultSession.SCOPE) { - RoomAvatarResolver(get(), get()) - } - - scope(DefaultSession.SCOPE) { - RoomSummaryUpdater(get(), get(), get()) - } - - scope(DefaultSession.SCOPE) { - DefaultRoomService(get(), get(), get(), get()) as RoomService - } - - scope(DefaultSession.SCOPE) { - DefaultGetPublicRoomTask(get()) as GetPublicRoomTask - } - - scope(DefaultSession.SCOPE) { - DefaultGetThirdPartyProtocolsTask(get()) as GetThirdPartyProtocolsTask - } - - scope(DefaultSession.SCOPE) { - DefaultRoomDirectoryService(get(), get(), get(), get()) as RoomDirectoryService - } - - scope(DefaultSession.SCOPE) { - DefaultGroupService(get()) as GroupService - } - - scope(DefaultSession.SCOPE) { - DefaultSignOutService(get(), get()) as SignOutService - } - - scope(DefaultSession.SCOPE) { - RealmCacheService(get("ClearTaskMainCache"), get()) as CacheService - } - - // Give a name, because we have a clear task for crypto store as well - scope(DefaultSession.SCOPE, name = "ClearTaskMainCache") { - RealmClearCacheTask(get("SessionRealmConfiguration")) as ClearCacheTask - } - - scope(DefaultSession.SCOPE) { - DefaultUserService(get()) as UserService - } - - scope(DefaultSession.SCOPE) { - SessionListeners() - } - - scope(DefaultSession.SCOPE) { - DefaultFilterRepository(get("SessionRealmConfiguration")) as FilterRepository - } - - scope(DefaultSession.SCOPE) { - DefaultSaveFilterTask(get(), get(), get()) as SaveFilterTask - } - - scope(DefaultSession.SCOPE) { - DefaultFilterService(get(), get(), get()) as FilterService - } - - scope(DefaultSession.SCOPE) { - val retrofit: Retrofit = get() - retrofit.create(FilterApi::class.java) - } - - scope(DefaultSession.SCOPE) { - val groupSummaryUpdater = GroupSummaryUpdater(get()) - val userEntityUpdater = UserEntityUpdater(get(), get(), get()) - val aggregationUpdater = EventRelationsAggregationUpdater(get(), get(), get(), get()) - //Event pruner must be the last one, because it will clear contents - val eventsPruner = EventsPruner(get(), get(), get(), get()) - listOf(groupSummaryUpdater, userEntityUpdater, aggregationUpdater, eventsPruner) - } + @Provides + fun providesRetrofit(retrofitBuilder: Retrofit.Builder): Retrofit { + return retrofitBuilder + .baseUrl(sessionParams.homeServerConnectionConfig.homeServerUri.toString()) + .build() + } + @Provides + fun providesFilterAPI(retrofit: Retrofit): FilterApi { + return retrofit.create(FilterApi::class.java) + } + @Provides + fun providesLiveEntityObservers(groupSummaryUpdater: GroupSummaryUpdater, + userEntityUpdater: UserEntityUpdater, + aggregationUpdater: EventRelationsAggregationUpdater, + eventsPruner: EventsPruner): List { + return listOf(groupSummaryUpdater, userEntityUpdater, aggregationUpdater, eventsPruner) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionScope.java b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionScope.java new file mode 100644 index 00000000..52842641 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionScope.java @@ -0,0 +1,29 @@ +/* + * 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.matrix.android.internal.session; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Scope; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Scope +@Documented +@Retention(RUNTIME) +public @interface SessionScope {} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmCacheService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmCacheService.kt index 7af01b7e..588ec63a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmCacheService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmCacheService.kt @@ -18,11 +18,14 @@ package im.vector.matrix.android.internal.session.cache import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.cache.CacheService +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import javax.inject.Inject -internal class RealmCacheService(private val clearCacheTask: ClearCacheTask, - private val taskExecutor: TaskExecutor) : CacheService { +@SessionScope +internal class RealmCacheService @Inject constructor(private val clearCacheTask: ClearCacheTask, + private val taskExecutor: TaskExecutor) : CacheService { override fun clearCache(callback: MatrixCallback) { clearCacheTask diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt index f1e927f0..67ed54dc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt @@ -17,13 +17,16 @@ package im.vector.matrix.android.internal.session.cache import arrow.core.Try +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import io.realm.Realm import io.realm.RealmConfiguration +import javax.inject.Inject internal interface ClearCacheTask : Task -internal class RealmClearCacheTask(val realmConfiguration: RealmConfiguration) : ClearCacheTask { +@SessionScope +internal class RealmClearCacheTask @Inject constructor(val realmConfiguration: RealmConfiguration) : ClearCacheTask { override suspend fun execute(params: Unit): Try { return Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt index 7fb9b757..9f431862 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt @@ -16,34 +16,10 @@ package im.vector.matrix.android.internal.session.content -import im.vector.matrix.android.api.auth.data.SessionParams -import im.vector.matrix.android.api.session.content.ContentUploadStateTracker -import im.vector.matrix.android.api.session.content.ContentUrlResolver -import im.vector.matrix.android.internal.session.DefaultSession -import org.koin.dsl.module.module +import dagger.Module +@Module internal class ContentModule { - val definition = module(override = true) { - - scope(DefaultSession.SCOPE) { - DefaultContentUploadStateTracker() - } - - scope(DefaultSession.SCOPE) { - get() as ContentUploadStateTracker - } - - scope(DefaultSession.SCOPE) { - FileUploader(get(), get()) - } - - scope(DefaultSession.SCOPE) { - val sessionParams = get() - DefaultContentUrlResolver(sessionParams.homeServerConnectionConfig) as ContentUrlResolver - } - - } - } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt index a5dd16fb..fbd7983d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt @@ -19,8 +19,11 @@ package im.vector.matrix.android.internal.session.content import android.os.Handler import android.os.Looper import im.vector.matrix.android.api.session.content.ContentUploadStateTracker +import im.vector.matrix.android.internal.session.SessionScope +import javax.inject.Inject -internal class DefaultContentUploadStateTracker : ContentUploadStateTracker { +@SessionScope +internal class DefaultContentUploadStateTracker @Inject constructor() : ContentUploadStateTracker { private val mainHandler = Handler(Looper.getMainLooper()) private val states = mutableMapOf() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUrlResolver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUrlResolver.kt index 0fad40d0..bfba5bb7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUrlResolver.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUrlResolver.kt @@ -18,12 +18,15 @@ package im.vector.matrix.android.internal.session.content import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig import im.vector.matrix.android.api.session.content.ContentUrlResolver +import im.vector.matrix.android.internal.session.SessionScope +import javax.inject.Inject private const val MATRIX_CONTENT_URI_SCHEME = "mxc://" private const val URI_PREFIX_CONTENT_API = "_matrix/media/v1/" -internal class DefaultContentUrlResolver(private val homeServerConnectionConfig: HomeServerConnectionConfig) : ContentUrlResolver { +@SessionScope +internal class DefaultContentUrlResolver @Inject constructor(private val homeServerConnectionConfig: HomeServerConnectionConfig) : ContentUrlResolver { companion object { fun getUploadUrl(homeServerConnectionConfig: HomeServerConnectionConfig): String { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt index e8133070..67d79305 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt @@ -21,12 +21,15 @@ import arrow.core.Try.Companion.raise import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.network.ProgressRequestBody +import im.vector.matrix.android.internal.session.SessionScope import okhttp3.* import java.io.File import java.io.IOException +import javax.inject.Inject -internal class FileUploader(private val okHttpClient: OkHttpClient, +@SessionScope +internal class FileUploader @Inject constructor(private val okHttpClient: OkHttpClient, sessionParams: SessionParams) { private val uploadUrl = DefaultContentUrlResolver.getUploadUrl(sessionParams.homeServerConnectionConfig) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt index bdfd9395..58516088 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt @@ -19,26 +19,32 @@ package im.vector.matrix.android.internal.session.content import android.content.Context import androidx.work.CoroutineWorker import androidx.work.WorkerParameters +import com.squareup.inject.assisted.Assisted +import com.squareup.inject.assisted.AssistedInject import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.events.model.toModel -import im.vector.matrix.android.api.session.room.model.message.* -import im.vector.matrix.android.internal.di.MatrixKoinComponent +import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent +import im.vector.matrix.android.api.session.room.model.message.MessageContent +import im.vector.matrix.android.api.session.room.model.message.MessageFileContent +import im.vector.matrix.android.api.session.room.model.message.MessageImageContent +import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent +import im.vector.matrix.android.internal.di.ChildWorkerFactory import im.vector.matrix.android.internal.network.ProgressRequestBody import im.vector.matrix.android.internal.session.room.send.SendEventWorker import im.vector.matrix.android.internal.util.WorkerParamsFactory -import org.koin.standalone.inject import timber.log.Timber import java.io.File -internal class UploadContentWorker(context: Context, params: WorkerParameters) - : CoroutineWorker(context, params), MatrixKoinComponent { - - private val fileUploader by inject() - private val contentUploadProgressTracker by inject() +internal class UploadContentWorker @AssistedInject constructor( + @Assisted context: Context, + @Assisted params: WorkerParameters, + private val fileUploader: FileUploader, + private val contentUploadStateTracker: DefaultContentUploadStateTracker) + : CoroutineWorker(context, params) { @JsonClass(generateAdapter = true) internal data class Params( @@ -69,7 +75,7 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) val progressListener = object : ProgressRequestBody.Listener { override fun onProgress(current: Long, total: Long) { - contentUploadProgressTracker.setProgress(eventId, current, total) + contentUploadStateTracker.setProgress(eventId, current, total) } } return fileUploader @@ -90,14 +96,14 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) } private fun handleFailure(params: Params): Result { - contentUploadProgressTracker.setFailure(params.event.eventId!!) + contentUploadStateTracker.setFailure(params.event.eventId!!) return Result.success() } private fun handleSuccess(params: Params, attachmentUrl: String, thumbnailUrl: String?): Result { - contentUploadProgressTracker.setFailure(params.event.eventId!!) + contentUploadStateTracker.setSuccess(params.event.eventId!!) val event = updateEvent(params.event, attachmentUrl, thumbnailUrl) val sendParams = SendEventWorker.Params(params.roomId, event) return Result.success(WorkerParamsFactory.toData(sendParams)) @@ -131,6 +137,8 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) return copy(url = url) } + @AssistedInject.Factory + interface Factory : ChildWorkerFactory } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt index 32d9541a..690db907 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt @@ -19,11 +19,14 @@ package im.vector.matrix.android.internal.session.filter import im.vector.matrix.android.internal.database.model.FilterEntity import im.vector.matrix.android.internal.database.model.FilterEntityFields import im.vector.matrix.android.internal.database.query.getFilter +import im.vector.matrix.android.internal.session.SessionScope import io.realm.Realm import io.realm.RealmConfiguration import io.realm.kotlin.where +import javax.inject.Inject -internal class DefaultFilterRepository(val realmConfiguration: RealmConfiguration) : FilterRepository { +@SessionScope +internal class DefaultFilterRepository @Inject constructor(val realmConfiguration: RealmConfiguration) : FilterRepository { override fun storeFilter(filterBody: FilterBody, roomEventFilter: RoomEventFilter): Boolean { val result: Boolean diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt index 94c3f1cf..033838ee 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt @@ -17,12 +17,15 @@ package im.vector.matrix.android.internal.session.filter import im.vector.matrix.android.api.session.sync.FilterService +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import javax.inject.Inject -internal class DefaultFilterService(private val filterRepository: FilterRepository, - private val saveFilterTask: SaveFilterTask, - private val taskExecutor: TaskExecutor) : FilterService { +@SessionScope +internal class DefaultFilterService @Inject constructor(private val filterRepository: FilterRepository, + private val saveFilterTask: SaveFilterTask, + private val taskExecutor: TaskExecutor) : FilterService { // TODO Pass a list of support events instead override fun setFilter(filterPreset: FilterService.FilterPreset) { @@ -30,7 +33,7 @@ internal class DefaultFilterService(private val filterRepository: FilterReposito FilterService.FilterPreset.RiotFilter -> { FilterFactory.createRiotFilterBody() } - FilterService.FilterPreset.NoFilter -> { + FilterService.FilterPreset.NoFilter -> { FilterFactory.createDefaultFilterBody() } } @@ -39,7 +42,7 @@ internal class DefaultFilterService(private val filterRepository: FilterReposito FilterService.FilterPreset.RiotFilter -> { FilterFactory.createRiotRoomFilter() } - FilterService.FilterPreset.NoFilter -> { + FilterService.FilterPreset.NoFilter -> { FilterFactory.createDefaultRoomFilter() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt index ab826805..a3c7fea8 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt @@ -19,7 +19,9 @@ package im.vector.matrix.android.internal.session.filter import arrow.core.Try import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject /** @@ -33,9 +35,10 @@ internal interface SaveFilterTask : Task { } -internal class DefaultSaveFilterTask(private val sessionParams: SessionParams, - private val filterAPI: FilterApi, - private val filterRepository: FilterRepository +@SessionScope +internal class DefaultSaveFilterTask @Inject constructor(private val sessionParams: SessionParams, + private val filterAPI: FilterApi, + private val filterRepository: FilterRepository ) : SaveFilterTask { override suspend fun execute(params: SaveFilterTask.Params): Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt index 0785c334..15d4d55f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt @@ -25,11 +25,13 @@ import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.database.model.GroupSummaryEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.group.model.GroupRooms import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse import im.vector.matrix.android.internal.session.group.model.GroupUsers import im.vector.matrix.android.internal.util.tryTransactionSync import io.realm.kotlin.createObject +import javax.inject.Inject internal interface GetGroupDataTask : Task { @@ -37,8 +39,8 @@ internal interface GetGroupDataTask : Task { } - -internal class DefaultGetGroupDataTask( +@SessionScope +internal class DefaultGetGroupDataTask @Inject constructor( private val groupAPI: GroupAPI, private val monarchy: Monarchy ) : GetGroupDataTask { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt index 5c0f88de..a574df7c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt @@ -25,8 +25,9 @@ import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.GroupSummaryEntity import im.vector.matrix.android.internal.database.model.GroupSummaryEntityFields import im.vector.matrix.android.internal.database.query.where +import javax.inject.Inject -internal class DefaultGroupService(private val monarchy: Monarchy) : GroupService { +internal class DefaultGroupService @Inject constructor(private val monarchy: Monarchy) : GroupService { override fun getGroup(groupId: String): Group? { return null diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt index 34960493..7e979c72 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt @@ -18,25 +18,25 @@ package im.vector.matrix.android.internal.session.group import android.content.Context import androidx.work.CoroutineWorker -import androidx.work.Worker import androidx.work.WorkerParameters import arrow.core.Try +import com.squareup.inject.assisted.Assisted +import com.squareup.inject.assisted.AssistedInject import com.squareup.moshi.JsonClass -import im.vector.matrix.android.internal.di.MatrixKoinComponent +import im.vector.matrix.android.internal.di.ChildWorkerFactory import im.vector.matrix.android.internal.util.WorkerParamsFactory -import org.koin.standalone.inject -internal class GetGroupDataWorker(context: Context, - workerParameters: WorkerParameters -) : CoroutineWorker(context, workerParameters), MatrixKoinComponent { +internal class GetGroupDataWorker @AssistedInject constructor( + @Assisted context: Context, + @Assisted workerParameters: WorkerParameters, + private val getGroupDataTask: GetGroupDataTask +) : CoroutineWorker(context, workerParameters) { @JsonClass(generateAdapter = true) internal data class Params( val groupIds: List ) - private val getGroupDataTask by inject() - override suspend fun doWork(): Result { val params = WorkerParamsFactory.fromData(inputData) ?: return Result.failure() @@ -52,4 +52,7 @@ internal class GetGroupDataWorker(context: Context, return getGroupDataTask.execute(GetGroupDataTask.Params(groupId)) } + @AssistedInject.Factory + interface Factory : ChildWorkerFactory + } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt index fe63ef90..5d7ac1f2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt @@ -16,22 +16,15 @@ package im.vector.matrix.android.internal.session.group -import im.vector.matrix.android.internal.session.DefaultSession -import org.koin.dsl.module.module +import dagger.Module +import im.vector.matrix.android.internal.session.SessionScope import retrofit2.Retrofit -class GroupModule { - - val definition = module(override = true) { - - scope(DefaultSession.SCOPE) { - val retrofit: Retrofit = get() - retrofit.create(GroupAPI::class.java) - } - - scope(DefaultSession.SCOPE) { - DefaultGetGroupDataTask(get(), get()) as GetGroupDataTask - } +@Module +internal class GroupModule { + @SessionScope + fun providesGroupAPI(retrofit: Retrofit): GroupAPI { + return retrofit.create(GroupAPI::class.java) } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt index 826c53fc..f1306b76 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt @@ -25,12 +25,14 @@ import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.model.GroupEntity import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.util.WorkerParamsFactory +import javax.inject.Inject private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER" -internal class GroupSummaryUpdater(monarchy: Monarchy -) : RealmLiveEntityObserver(monarchy) { +@SessionScope +internal class GroupSummaryUpdater @Inject constructor(monarchy: Monarchy) : RealmLiveEntityObserver(monarchy) { override val query = Monarchy.Query { GroupEntity.where(it) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomDirectoryService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomDirectoryService.kt index 1a434dd6..764d4816 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomDirectoryService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomDirectoryService.kt @@ -27,11 +27,12 @@ import im.vector.matrix.android.internal.session.room.directory.GetThirdPartyPro import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import javax.inject.Inject -internal class DefaultRoomDirectoryService(private val getPublicRoomTask: GetPublicRoomTask, - private val joinRoomTask: JoinRoomTask, - private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask, - private val taskExecutor: TaskExecutor) : RoomDirectoryService { +internal class DefaultRoomDirectoryService @Inject constructor(private val getPublicRoomTask: GetPublicRoomTask, + private val joinRoomTask: JoinRoomTask, + private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask, + private val taskExecutor: TaskExecutor) : RoomDirectoryService { override fun getPublicRooms(server: String?, publicRoomsParams: PublicRoomsParams, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt index 18de69c4..448d316c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt @@ -28,15 +28,18 @@ import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.create.CreateRoomTask import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.fetchManaged +import javax.inject.Inject -internal class DefaultRoomService(private val monarchy: Monarchy, - private val createRoomTask: CreateRoomTask, - private val roomFactory: RoomFactory, - private val taskExecutor: TaskExecutor) : RoomService { +@SessionScope +internal class DefaultRoomService @Inject constructor(private val monarchy: Monarchy, + private val createRoomTask: CreateRoomTask, + private val roomFactory: RoomFactory, + private val taskExecutor: TaskExecutor) : RoomService { override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback) { createRoomTask diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationExtractor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationExtractor.kt index e52f5e09..78e24b2d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationExtractor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationExtractor.kt @@ -20,12 +20,16 @@ import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import io.realm.Realm +import javax.inject.Inject /** * Fetches annotations (reactions, edits...) associated to a given eventEntity from the data layer. */ -internal class EventRelationExtractor { + +@SessionScope +internal class EventRelationExtractor @Inject constructor() { fun extractFrom(event: EventEntity, realm: Realm = event.realm): EventAnnotationsSummary? { return EventAnnotationsSummaryEntity.where(realm, event.eventId).findFirst()?.asDomain() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt index e12d60ca..18d0896e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt @@ -26,10 +26,12 @@ import im.vector.matrix.android.internal.database.mapper.EventMapper import im.vector.matrix.android.internal.database.model.* import im.vector.matrix.android.internal.database.query.create import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.util.tryTransactionSync import io.realm.Realm import timber.log.Timber +import javax.inject.Inject internal interface EventRelationsAggregationTask : Task { @@ -42,7 +44,8 @@ internal interface EventRelationsAggregationTask : Task(monarchy) { override val query = Monarchy.Query { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAvatarResolver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAvatarResolver.kt index c26f0596..68373428 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAvatarResolver.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAvatarResolver.kt @@ -27,10 +27,13 @@ import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.query.prev import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.membership.RoomMembers +import javax.inject.Inject -internal class RoomAvatarResolver(private val monarchy: Monarchy, - private val credentials: Credentials) { +@SessionScope +internal class RoomAvatarResolver @Inject constructor(private val monarchy: Monarchy, + private val credentials: Credentials) { /** * Compute the room avatar url diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt index 4f4b7e73..c3c58e5a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt @@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.session.room import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.room.Room +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask import im.vector.matrix.android.internal.session.room.membership.SenderRoomMemberExtractor @@ -39,21 +40,23 @@ import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEvent import im.vector.matrix.android.internal.session.room.timeline.PaginationTask import im.vector.matrix.android.internal.session.room.timeline.TimelineEventFactory import im.vector.matrix.android.internal.task.TaskExecutor +import javax.inject.Inject -internal class RoomFactory(private val monarchy: Monarchy, - private val eventFactory: LocalEchoEventFactory, - private val taskExecutor: TaskExecutor, - private val loadRoomMembersTask: LoadRoomMembersTask, - private val inviteTask: InviteTask, - private val sendStateTask: SendStateTask, - private val paginationTask: PaginationTask, - private val contextOfEventTask: GetContextOfEventTask, - private val setReadMarkersTask: SetReadMarkersTask, - private val cryptoService: CryptoService, - private val findReactionEventForUndoTask: FindReactionEventForUndoTask, - private val updateQuickReactionTask: UpdateQuickReactionTask, - private val joinRoomTask: JoinRoomTask, - private val leaveRoomTask: LeaveRoomTask) { +@SessionScope +internal class RoomFactory @Inject constructor(private val monarchy: Monarchy, + private val eventFactory: LocalEchoEventFactory, + private val taskExecutor: TaskExecutor, + private val loadRoomMembersTask: LoadRoomMembersTask, + private val inviteTask: InviteTask, + private val sendStateTask: SendStateTask, + private val paginationTask: PaginationTask, + private val contextOfEventTask: GetContextOfEventTask, + private val setReadMarkersTask: SetReadMarkersTask, + private val cryptoService: CryptoService, + private val findReactionEventForUndoTask: FindReactionEventForUndoTask, + private val updateQuickReactionTask: UpdateQuickReactionTask, + private val joinRoomTask: JoinRoomTask, + private val leaveRoomTask: LeaveRoomTask) { fun instantiate(roomId: String): Room { val roomMemberExtractor = SenderRoomMemberExtractor(roomId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt index 671a947f..64ac991c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt @@ -16,7 +16,9 @@ package im.vector.matrix.android.internal.session.room -import im.vector.matrix.android.internal.session.DefaultSession +import dagger.Module +import dagger.Provides +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.create.CreateRoomTask import im.vector.matrix.android.internal.session.room.create.DefaultCreateRoomTask import im.vector.matrix.android.internal.session.room.membership.DefaultLoadRoomMembersTask @@ -39,87 +41,20 @@ import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory import im.vector.matrix.android.internal.session.room.send.LocalEchoUpdater import im.vector.matrix.android.internal.session.room.state.DefaultSendStateTask import im.vector.matrix.android.internal.session.room.state.SendStateTask -import im.vector.matrix.android.internal.session.room.timeline.* -import org.koin.dsl.module.module +import im.vector.matrix.android.internal.session.room.timeline.DefaultGetContextOfEventTask +import im.vector.matrix.android.internal.session.room.timeline.DefaultPaginationTask +import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask +import im.vector.matrix.android.internal.session.room.timeline.PaginationTask +import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor import retrofit2.Retrofit +@Module +internal class RoomModule { -class RoomModule { - - val definition = module(override = true) { - - scope(DefaultSession.SCOPE) { - val retrofit: Retrofit = get() - retrofit.create(RoomAPI::class.java) - } - - scope(DefaultSession.SCOPE) { - DefaultLoadRoomMembersTask(get(), get(), get(), get()) as LoadRoomMembersTask - } - - scope(DefaultSession.SCOPE) { - TokenChunkEventPersistor(get()) - } - - scope(DefaultSession.SCOPE) { - DefaultPaginationTask(get(), get(), get()) as PaginationTask - } - - scope(DefaultSession.SCOPE) { - DefaultGetContextOfEventTask(get(), get(), get()) as GetContextOfEventTask - } - - scope(DefaultSession.SCOPE) { - DefaultSetReadMarkersTask(get(), get(), get()) as SetReadMarkersTask - } - - scope(DefaultSession.SCOPE) { - LocalEchoEventFactory(get(), get()) - } - - scope(DefaultSession.SCOPE) { - LocalEchoUpdater(get()) - } - - scope(DefaultSession.SCOPE) { - RoomFactory(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) - } - - scope(DefaultSession.SCOPE) { - DefaultCreateRoomTask(get(), get("SessionRealmConfiguration")) as CreateRoomTask - } - - scope(DefaultSession.SCOPE) { - DefaultInviteTask(get()) as InviteTask - } - - scope(DefaultSession.SCOPE) { - DefaultJoinRoomTask(get()) as JoinRoomTask - } - - scope(DefaultSession.SCOPE) { - DefaultLeaveRoomTask(get()) as LeaveRoomTask - } - - scope(DefaultSession.SCOPE) { - DefaultSendStateTask(get()) as SendStateTask - } - - scope(DefaultSession.SCOPE) { - DefaultFindReactionEventForUndoTask(get()) as FindReactionEventForUndoTask - } - - scope(DefaultSession.SCOPE) { - DefaultUpdateQuickReactionTask(get()) as UpdateQuickReactionTask - } - - scope(DefaultSession.SCOPE) { - DefaultPruneEventTask(get()) as PruneEventTask - } - - scope(DefaultSession.SCOPE) { - DefaultEventRelationsAggregationTask(get()) as EventRelationsAggregationTask - } - + @SessionScope + @Provides + fun providesRoomAPI(retrofit: Retrofit): RoomAPI { + return retrofit.create(RoomAPI::class.java) } + } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt index 7bf08b70..609e55f1 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt @@ -29,16 +29,19 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.query.latestEvent import im.vector.matrix.android.internal.database.query.prev import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver import im.vector.matrix.android.internal.session.room.membership.RoomMembers import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications import io.realm.Realm import io.realm.kotlin.createObject +import javax.inject.Inject -internal class RoomSummaryUpdater(private val credentials: Credentials, - private val roomDisplayNameResolver: RoomDisplayNameResolver, - private val roomAvatarResolver: RoomAvatarResolver) { +@SessionScope +internal class RoomSummaryUpdater @Inject constructor(private val credentials: Credentials, + private val roomDisplayNameResolver: RoomDisplayNameResolver, + private val roomAvatarResolver: RoomAvatarResolver) { fun update(realm: Realm, roomId: String, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt index 9ff5f511..37088f74 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt @@ -23,14 +23,16 @@ import im.vector.matrix.android.internal.database.RealmQueryLatch import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomEntityFields import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task import io.realm.RealmConfiguration +import javax.inject.Inject internal interface CreateRoomTask : Task - -internal class DefaultCreateRoomTask(private val roomAPI: RoomAPI, +@SessionScope +internal class DefaultCreateRoomTask @Inject constructor(private val roomAPI: RoomAPI, private val realmConfiguration: RealmConfiguration) : CreateRoomTask { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetPublicRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetPublicRoomTask.kt index 4b71b871..e3fbed1e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetPublicRoomTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetPublicRoomTask.kt @@ -20,8 +20,10 @@ import arrow.core.Try import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsParams import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsResponse import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetPublicRoomTask : Task { data class Params( @@ -30,7 +32,8 @@ internal interface GetPublicRoomTask : Task { return executeRequest { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetThirdPartyProtocolsTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetThirdPartyProtocolsTask.kt index a50ec367..d72c3b5a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetThirdPartyProtocolsTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetThirdPartyProtocolsTask.kt @@ -19,12 +19,15 @@ package im.vector.matrix.android.internal.session.room.directory import arrow.core.Try import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetThirdPartyProtocolsTask : Task> -internal class DefaultGetThirdPartyProtocolsTask(private val roomAPI: RoomAPI) : GetThirdPartyProtocolsTask { +@SessionScope +internal class DefaultGetThirdPartyProtocolsTask @Inject constructor (private val roomAPI: RoomAPI) : GetThirdPartyProtocolsTask { override suspend fun execute(params: Unit): Try> { return executeRequest { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt index a9b48ea6..9f51ade0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt @@ -27,20 +27,23 @@ import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.RoomMember import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.database.mapper.asDomain +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.fetchCopied +import javax.inject.Inject -internal class DefaultMembershipService(private val roomId: String, - private val monarchy: Monarchy, - private val taskExecutor: TaskExecutor, - private val loadRoomMembersTask: LoadRoomMembersTask, - private val inviteTask: InviteTask, - private val joinTask: JoinRoomTask, - private val leaveRoomTask: LeaveRoomTask +@SessionScope +internal class DefaultMembershipService @Inject constructor(private val roomId: String, + private val monarchy: Monarchy, + private val taskExecutor: TaskExecutor, + private val loadRoomMembersTask: LoadRoomMembersTask, + private val inviteTask: InviteTask, + private val joinTask: JoinRoomTask, + private val leaveRoomTask: LeaveRoomTask ) : MembershipService { override fun loadRoomMembersIfNeeded(): Cancelable { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt index 44a050db..d49448a0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt @@ -23,12 +23,14 @@ import im.vector.matrix.android.internal.database.helper.addStateEvents import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater import im.vector.matrix.android.internal.session.sync.SyncTokenStore import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.util.tryTransactionSync import io.realm.kotlin.createObject +import javax.inject.Inject internal interface LoadRoomMembersTask : Task { @@ -38,7 +40,8 @@ internal interface LoadRoomMembersTask : Task): String? { val currentMember = members[userId] diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/InviteTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/InviteTask.kt index 3610cbe0..ec35b443 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/InviteTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/InviteTask.kt @@ -18,8 +18,10 @@ package im.vector.matrix.android.internal.session.room.membership.joining import arrow.core.Try import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface InviteTask : Task { @@ -29,7 +31,8 @@ internal interface InviteTask : Task { ) } -internal class DefaultInviteTask(private val roomAPI: RoomAPI) : InviteTask { +@SessionScope +internal class DefaultInviteTask @Inject constructor(private val roomAPI: RoomAPI) : InviteTask { override suspend fun execute(params: InviteTask.Params): Try { return executeRequest { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/JoinRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/JoinRoomTask.kt index 3fe2d139..37f4a2fa 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/JoinRoomTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/JoinRoomTask.kt @@ -18,8 +18,10 @@ package im.vector.matrix.android.internal.session.room.membership.joining import arrow.core.Try import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface JoinRoomTask : Task { data class Params( @@ -27,7 +29,8 @@ internal interface JoinRoomTask : Task { ) } -internal class DefaultJoinRoomTask(private val roomAPI: RoomAPI) : JoinRoomTask { +@SessionScope +internal class DefaultJoinRoomTask @Inject constructor(private val roomAPI: RoomAPI) : JoinRoomTask { override suspend fun execute(params: JoinRoomTask.Params): Try { return executeRequest { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/leaving/LeaveRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/leaving/LeaveRoomTask.kt index 9eb1728f..30c73035 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/leaving/LeaveRoomTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/leaving/LeaveRoomTask.kt @@ -18,8 +18,10 @@ package im.vector.matrix.android.internal.session.room.membership.leaving import arrow.core.Try import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface LeaveRoomTask : Task { data class Params( @@ -27,7 +29,8 @@ internal interface LeaveRoomTask : Task { ) } -internal class DefaultLeaveRoomTask(private val roomAPI: RoomAPI) : LeaveRoomTask { +@SessionScope +internal class DefaultLeaveRoomTask @Inject constructor(private val roomAPI: RoomAPI) : LeaveRoomTask { override suspend fun execute(params: LeaveRoomTask.Params): Try { return executeRequest { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt index 4d3bc6fd..4b663d5a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt @@ -23,18 +23,21 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import timber.log.Timber +import javax.inject.Inject /** * Listens to the database for the insertion of any redaction event. * As it will actually delete the content, it should be called last in the list of listener. */ -internal class EventsPruner(monarchy: Monarchy, - private val credentials: Credentials, - private val pruneEventTask: PruneEventTask, - private val taskExecutor: TaskExecutor) : +@SessionScope +internal class EventsPruner @Inject constructor(monarchy: Monarchy, + private val credentials: Credentials, + private val pruneEventTask: PruneEventTask, + private val taskExecutor: TaskExecutor) : RealmLiveEntityObserver(monarchy) { override val query = Monarchy.Query { EventEntity.where(it, type = EventType.REDACTION) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt index ef8557ae..08d52e24 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt @@ -26,10 +26,12 @@ import im.vector.matrix.android.internal.database.mapper.EventMapper import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.MoshiProvider +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.util.tryTransactionSync import io.realm.Realm import timber.log.Timber +import javax.inject.Inject internal interface PruneEventTask : Task { @@ -41,8 +43,8 @@ internal interface PruneEventTask : Task { } -internal class DefaultPruneEventTask( - private val monarchy: Monarchy) : PruneEventTask { +@SessionScope +internal class DefaultPruneEventTask @Inject constructor(private val monarchy: Monarchy) : PruneEventTask { override suspend fun execute(params: PruneEventTask.Params): Try { return monarchy.tryTransactionSync { realm -> diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/DefaultReadService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/DefaultReadService.kt index 30bbe30c..ad3ad3b6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/DefaultReadService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/DefaultReadService.kt @@ -21,11 +21,14 @@ import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.room.read.ReadService import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.latestEvent +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.fetchCopied +import javax.inject.Inject -internal class DefaultReadService(private val roomId: String, +@SessionScope +internal class DefaultReadService @Inject constructor(private val roomId: String, private val monarchy: Monarchy, private val taskExecutor: TaskExecutor, private val setReadMarkersTask: SetReadMarkersTask) : ReadService { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt index 0592077e..aef52f5f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt @@ -29,9 +29,11 @@ import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoo import im.vector.matrix.android.internal.database.query.latestEvent import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.util.tryTransactionAsync +import javax.inject.Inject internal interface SetReadMarkersTask : Task { @@ -45,7 +47,8 @@ internal interface SetReadMarkersTask : Task { private const val READ_MARKER = "m.fully_read" private const val READ_RECEIPT = "m.read" -internal class DefaultSetReadMarkersTask(private val roomAPI: RoomAPI, +@SessionScope +internal class DefaultSetReadMarkersTask @Inject constructor(private val roomAPI: RoomAPI, private val credentials: Credentials, private val monarchy: Monarchy ) : SetReadMarkersTask { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt index 264909e9..a48a0ad6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt @@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryE import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory import im.vector.matrix.android.internal.session.room.send.RedactEventWorker import im.vector.matrix.android.internal.session.room.send.SendEventWorker @@ -41,14 +42,14 @@ import im.vector.matrix.android.internal.util.CancelableWork import im.vector.matrix.android.internal.util.WorkerParamsFactory import im.vector.matrix.android.internal.util.tryTransactionAsync import timber.log.Timber +import javax.inject.Inject - -internal class DefaultRelationService(private val roomId: String, - private val eventFactory: LocalEchoEventFactory, - private val findReactionEventForUndoTask: FindReactionEventForUndoTask, - private val updateQuickReactionTask: UpdateQuickReactionTask, - private val monarchy: Monarchy, - private val taskExecutor: TaskExecutor) +internal class DefaultRelationService constructor(private val roomId: String, + private val eventFactory: LocalEchoEventFactory, + private val findReactionEventForUndoTask: FindReactionEventForUndoTask, + private val updateQuickReactionTask: UpdateQuickReactionTask, + private val monarchy: Monarchy, + private val taskExecutor: TaskExecutor) : RelationService { @@ -139,7 +140,7 @@ internal class DefaultRelationService(private val roomId: String, private fun createRedactEventWork(localEvent: Event, eventId: String, reason: String?): OneTimeWorkRequest { val sendContentWorkerParams = RedactEventWorker.Params(localEvent.eventId!!, - roomId, eventId, reason) + roomId, eventId, reason) val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) return TimelineSendEventWorkCommon.createWork(redactWorkData) } @@ -194,9 +195,9 @@ internal class DefaultRelationService(private val roomId: String, private fun saveLocalEcho(event: Event) { monarchy.tryTransactionAsync { realm -> val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() - ?: return@tryTransactionAsync + ?: return@tryTransactionAsync val liveChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId = roomId) - ?: return@tryTransactionAsync + ?: return@tryTransactionAsync roomEntity.addSendingEvent(event, liveChunk.forwardsStateIndex ?: 0) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FindReactionEventForUndoTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FindReactionEventForUndoTask.kt index 07b48bd0..7a7abdbe 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FindReactionEventForUndoTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FindReactionEventForUndoTask.kt @@ -21,8 +21,10 @@ import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryE import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.ReactionAggregatedSummaryEntityFields import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import io.realm.Realm +import javax.inject.Inject internal interface FindReactionEventForUndoTask : Task { @@ -40,7 +42,8 @@ internal interface FindReactionEventForUndoTask : Task { return Try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt index 41184aaf..c41ac5df 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt @@ -18,21 +18,25 @@ package im.vector.matrix.android.internal.session.room.relation import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters +import com.squareup.inject.assisted.Assisted +import com.squareup.inject.assisted.AssistedInject import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.relation.ReactionContent import im.vector.matrix.android.api.session.room.model.relation.ReactionInfo -import im.vector.matrix.android.internal.di.MatrixKoinComponent +import im.vector.matrix.android.internal.di.ChildWorkerFactory import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.session.room.send.SendResponse import im.vector.matrix.android.internal.util.WorkerParamsFactory -import org.koin.standalone.inject -class SendRelationWorker(context: Context, params: WorkerParameters) - : Worker(context, params), MatrixKoinComponent { +internal class SendRelationWorker @AssistedInject constructor( + @Assisted context: Context, + @Assisted params: WorkerParameters, + private val roomAPI: RoomAPI) + : Worker(context, params) { @JsonClass(generateAdapter = true) @@ -42,21 +46,19 @@ class SendRelationWorker(context: Context, params: WorkerParameters) val relationType: String? = null ) - private val roomAPI by inject() - override fun doWork(): Result { val params = WorkerParamsFactory.fromData(inputData) - ?: return Result.failure() + ?: return Result.failure() val localEvent = params.event if (localEvent.eventId == null) { return Result.failure() } val relationContent = localEvent.content.toModel() - ?: return Result.failure() + ?: return Result.failure() val relatedEventId = relationContent.relatesTo?.eventId ?: return Result.failure() val relationType = (relationContent.relatesTo as? ReactionInfo)?.type ?: params.relationType - ?: return Result.failure() + ?: return Result.failure() val result = executeRequest { apiCall = roomAPI.sendRelation( @@ -68,14 +70,17 @@ class SendRelationWorker(context: Context, params: WorkerParameters) ) } return result.fold({ - when (it) { - is Failure.NetworkConnection -> Result.retry() - else -> { - //TODO mark as failed to send? - //always return success, or the chain will be stuck for ever! - Result.success() - } - } - }, { Result.success() }) + when (it) { + is Failure.NetworkConnection -> Result.retry() + else -> { + //TODO mark as failed to send? + //always return success, or the chain will be stuck for ever! + Result.success() + } + } + }, { Result.success() }) } + + @AssistedInject.Factory + interface Factory : ChildWorkerFactory } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/UpdateQuickReactionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/UpdateQuickReactionTask.kt index bc54464f..2169adeb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/UpdateQuickReactionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/UpdateQuickReactionTask.kt @@ -21,8 +21,10 @@ import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryE import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.ReactionAggregatedSummaryEntityFields import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import io.realm.Realm +import javax.inject.Inject internal interface UpdateQuickReactionTask : Task { @@ -41,7 +43,8 @@ internal interface UpdateQuickReactionTask : Task { return Try { var res: Pair?>? = null diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt index e54af1ca..585b925a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt @@ -33,12 +33,14 @@ import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.content.ThumbnailExtractor import im.vector.matrix.android.internal.util.StringProvider import im.vector.matrix.android.internal.util.tryTransactionAsync import org.commonmark.parser.Parser import org.commonmark.renderer.html.HtmlRenderer import java.util.* +import javax.inject.Inject /** * Creates local echo of events for room events. @@ -49,7 +51,9 @@ import java.util.* * * The transactionID is used as loc */ -internal class LocalEchoEventFactory(private val credentials: Credentials, private val stringProvider: StringProvider) { + +@SessionScope +internal class LocalEchoEventFactory @Inject constructor(private val credentials: Credentials, private val stringProvider: StringProvider) { fun createTextEvent(roomId: String, msgType: String, text: String, autoMarkdown: Boolean): Event { if (autoMarkdown && msgType == MessageType.MSGTYPE_TEXT) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoUpdater.kt index 7dc69536..689d2b48 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoUpdater.kt @@ -22,9 +22,12 @@ import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.room.send.SendState import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.util.tryTransactionAsync +import javax.inject.Inject -internal class LocalEchoUpdater(private val monarchy: Monarchy) { +@SessionScope +internal class LocalEchoUpdater @Inject constructor(private val monarchy: Monarchy) { fun updateSendState(eventId: String, sendState: SendState) { monarchy.tryTransactionAsync { realm -> diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt index 32239b53..598352c5 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt @@ -19,18 +19,23 @@ package im.vector.matrix.android.internal.session.room.send import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters +import com.squareup.inject.assisted.Assisted +import com.squareup.inject.assisted.AssistedInject import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.send.SendState -import im.vector.matrix.android.internal.di.MatrixKoinComponent +import im.vector.matrix.android.internal.di.ChildWorkerFactory import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.util.WorkerParamsFactory -import org.koin.standalone.inject -internal class SendEventWorker(context: Context, params: WorkerParameters) - : Worker(context, params), MatrixKoinComponent { +internal class SendEventWorker @AssistedInject constructor( + @Assisted context: Context, + @Assisted params: WorkerParameters, + private val roomAPI: RoomAPI, + private val localEchoUpdater: LocalEchoUpdater) + : Worker(context, params) { @JsonClass(generateAdapter = true) @@ -39,13 +44,10 @@ internal class SendEventWorker(context: Context, params: WorkerParameters) val event: Event ) - private val roomAPI by inject() - private val localEchoUpdater by inject() - override fun doWork(): Result { val params = WorkerParamsFactory.fromData(inputData) - ?: return Result.success() + ?: return Result.success() val event = params.event if (event.eventId == null) { @@ -62,14 +64,18 @@ internal class SendEventWorker(context: Context, params: WorkerParameters) ) } return result.fold({ - when (it) { - is Failure.NetworkConnection -> Result.retry() - else -> { - localEchoUpdater.updateSendState(event.eventId, SendState.UNDELIVERED) - //always return success, or the chain will be stuck for ever! - Result.success() - } - } - }, { Result.success() }) + when (it) { + is Failure.NetworkConnection -> Result.retry() + else -> { + localEchoUpdater.updateSendState(event.eventId, SendState.UNDELIVERED) + //always return success, or the chain will be stuck for ever! + Result.success() + } + } + }, { Result.success() }) } + + @AssistedInject.Factory + interface Factory : ChildWorkerFactory + } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt index f1ad712e..6988b6f8 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt @@ -19,10 +19,13 @@ package im.vector.matrix.android.internal.session.room.state import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.state.StateService +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import javax.inject.Inject -internal class DefaultStateService(private val roomId: String, +@SessionScope +internal class DefaultStateService @Inject constructor(private val roomId: String, private val taskExecutor: TaskExecutor, private val sendStateTask: SendStateTask) : StateService { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt index b6d3a748..45e714e1 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt @@ -18,8 +18,10 @@ package im.vector.matrix.android.internal.session.room.state import arrow.core.Try import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface SendStateTask : Task { data class Params( @@ -29,7 +31,8 @@ internal interface SendStateTask : Task { ) } -internal class DefaultSendStateTask(private val roomAPI: RoomAPI) : SendStateTask { +@SessionScope +internal class DefaultSendStateTask @Inject constructor(private val roomAPI: RoomAPI) : SendStateTask { override suspend fun execute(params: SendStateTask.Params): Try { return executeRequest { apiCall = roomAPI.sendStateEvent(params.roomId, params.eventType, params.body) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt index 5d72ac33..49c69a00 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt @@ -18,9 +18,11 @@ package im.vector.matrix.android.internal.session.room.timeline import arrow.core.Try import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.filter.FilterRepository import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject internal interface GetContextOfEventTask : Task { @@ -31,7 +33,8 @@ internal interface GetContextOfEventTask : Task { @@ -34,9 +36,10 @@ internal interface PaginationTask : Task { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt index 6743d1cb..c276c26f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt @@ -274,7 +274,7 @@ internal class DefaultTimeline( val newRequestedCount = count - builtCount updatePaginationState(direction) { it.copy(requestedCount = newRequestedCount) } val fetchingCount = Math.max(MIN_FETCHING_COUNT, newRequestedCount) - executePaginationTask(direction, fetchingCount) + executePaginationTask @Inject constructor(direction, fetchingCount) } else { updatePaginationState(direction) { it.copy(isPaginating = false, requestedCount = 0) } } @@ -350,7 +350,7 @@ internal class DefaultTimeline( /** * This has to be called on TimelineThread as it access realm live results */ - private fun executePaginationTask(direction: Timeline.Direction, limit: Int) { + private fun executePaginationTask @Inject constructor(direction: Timeline.Direction, limit: Int) { val token = getTokenLive(direction) ?: return val params = PaginationTask.Params(roomId = roomId, from = token, @@ -367,7 +367,7 @@ internal class DefaultTimeline( } else { // Database won't be updated, so we force pagination request backgroundHandler.get()?.post { - executePaginationTask(direction, limit) + executePaginationTask @Inject constructor(direction, limit) } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt index ae575d68..9ac5fce3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt @@ -22,7 +22,7 @@ import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.session.room.RoomAPI -internal class GetEventTask(private val roomAPI: RoomAPI +internal class GetEventTask @Inject constructor(private val roomAPI: RoomAPI ) : Task { internal data class Params( diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventFactory.kt index 7c4cfff9..fa602500 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventFactory.kt @@ -30,12 +30,13 @@ import im.vector.matrix.android.internal.session.room.membership.SenderRoomMembe import io.realm.Realm import timber.log.Timber import java.util.* +import javax.inject.Inject /** * This class is responsible for building [TimelineEvent] returned by a [Timeline] through [TimelineService] * It handles decryption, extracting additional data around an event as sender data and relation. */ -internal class TimelineEventFactory( +internal class TimelineEventFactory @Inject constructor( private val roomMemberExtractor: SenderRoomMemberExtractor, private val relationExtractor: EventRelationExtractor, private val cryptoService: CryptoService) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt index 9c40b4aa..3aa07b00 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt @@ -25,14 +25,17 @@ import im.vector.matrix.android.internal.database.query.create import im.vector.matrix.android.internal.database.query.find import im.vector.matrix.android.internal.database.query.findAllIncludingEvents import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.util.tryTransactionSync import io.realm.kotlin.createObject import timber.log.Timber +import javax.inject.Inject /** * Insert Chunk in DB, and eventually merge with existing chunk event */ -internal class TokenChunkEventPersistor(private val monarchy: Monarchy) { +@SessionScope +internal class TokenChunkEventPersistor @Inject constructor(private val monarchy: Monarchy) { /** *
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
index ff399900..3589df3d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
@@ -18,11 +18,14 @@ package im.vector.matrix.android.internal.session.signout
 
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.signout.SignOutService
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
+import javax.inject.Inject
 
-internal class DefaultSignOutService(private val signOutTask: SignOutTask,
-                                     private val taskExecutor: TaskExecutor) : SignOutService {
+@SessionScope
+internal class DefaultSignOutService @Inject constructor(private val signOutTask: SignOutTask,
+                                                         private val taskExecutor: TaskExecutor) : SignOutService {
 
     override fun signOut(callback: MatrixCallback) {
         signOutTask
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
index 98098b1a..7e2fbc85 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
@@ -16,22 +16,16 @@
 
 package im.vector.matrix.android.internal.session.signout
 
-import im.vector.matrix.android.internal.session.DefaultSession
-import org.koin.dsl.module.module
+import dagger.Module
+import im.vector.matrix.android.internal.session.SessionScope
 import retrofit2.Retrofit
 
-class SignOutModule {
-
-    val definition = module(override = true) {
-
-        scope(DefaultSession.SCOPE) {
-            val retrofit: Retrofit = get()
-            retrofit.create(SignOutAPI::class.java)
-        }
-
-        scope(DefaultSession.SCOPE) {
-            DefaultSignOutTask(get(), get()) as SignOutTask
-        }
+@Module
+internal class SignOutModule {
 
+    @SessionScope
+    fun providesSignOutAPI(retrofit: Retrofit): SignOutAPI {
+        return retrofit.create(SignOutAPI::class.java)
     }
+
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
index 5fa09b9a..ab34e0f8 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
@@ -19,13 +19,15 @@ package im.vector.matrix.android.internal.session.signout
 import arrow.core.Try
 import im.vector.matrix.android.internal.auth.SessionParamsStore
 import im.vector.matrix.android.internal.network.executeRequest
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.task.Task
+import javax.inject.Inject
 
 internal interface SignOutTask : Task
 
-
-internal class DefaultSignOutTask(private val signOutAPI: SignOutAPI,
-                                  private val sessionParamsStore: SessionParamsStore) : SignOutTask {
+@SessionScope
+internal class DefaultSignOutTask @Inject constructor(private val signOutAPI: SignOutAPI,
+                                                      private val sessionParamsStore: SessionParamsStore) : SignOutTask {
 
     override suspend fun execute(params: Unit): Try {
         return executeRequest {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt
index 6dd2763f..5930d861 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt
@@ -25,20 +25,23 @@ import im.vector.matrix.android.internal.crypto.CryptoManager
 import im.vector.matrix.android.internal.crypto.MXDecryptionException
 import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
 import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.sync.model.SyncResponse
 import im.vector.matrix.android.internal.session.sync.model.ToDeviceSyncResponse
 import timber.log.Timber
+import javax.inject.Inject
 
 
-internal class CryptoSyncHandler(private val cryptoManager: CryptoManager,
-                                 private val sasVerificationService: DefaultSasVerificationService) {
+@SessionScope
+internal class CryptoSyncHandler @Inject constructor(private val cryptoManager: CryptoManager,
+                                                     private val sasVerificationService: DefaultSasVerificationService) {
 
     fun handleToDevice(toDevice: ToDeviceSyncResponse) {
         toDevice.events?.forEach { event ->
             // Decrypt event if necessary
             decryptEvent(event, null)
             if (TextUtils.equals(event.getClearType(), EventType.MESSAGE)
-                    && event.mClearEvent?.content?.toModel()?.type == "m.bad.encrypted") {
+                && event.mClearEvent?.content?.toModel()?.type == "m.bad.encrypted") {
                 Timber.e("## handleToDeviceEvent() : Warning: Unable to decrypt to-device event : " + event.content)
             } else {
                 sasVerificationService.onToDeviceEvent(event)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt
index 25bea096..7c9248c9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt
@@ -20,12 +20,14 @@ import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.api.session.room.model.Membership
 import im.vector.matrix.android.internal.database.model.GroupEntity
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.sync.model.GroupsSyncResponse
 import im.vector.matrix.android.internal.session.sync.model.InvitedGroupSync
 import io.realm.Realm
+import javax.inject.Inject
 
-
-internal class GroupSyncHandler(private val monarchy: Monarchy) {
+@SessionScope
+internal class GroupSyncHandler @Inject constructor(private val monarchy: Monarchy) {
 
     sealed class HandlingStrategy {
         data class JOINED(val data: Map) : HandlingStrategy()
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
index 7557f71a..a7af1e34 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
@@ -17,6 +17,7 @@
 package im.vector.matrix.android.internal.session.sync
 
 import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
+import im.vector.matrix.android.internal.session.SessionScope
 import io.realm.Realm
 import timber.log.Timber
 
@@ -28,7 +29,8 @@ import timber.log.Timber
 //                    dict value ts value
 typealias ReadReceiptContent = Map>>>
 
-internal class ReadReceiptHandler {
+@SessionScope
+internal class ReadReceiptHandler internal constructor() {
 
     fun handle(realm: Realm, roomId: String, content: ReadReceiptContent?) {
         if (content == null) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
index e6d77775..f8fb285d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
@@ -32,18 +32,21 @@ import im.vector.matrix.android.internal.database.model.RoomEntity
 import im.vector.matrix.android.internal.database.query.find
 import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
 import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
 import im.vector.matrix.android.internal.session.sync.model.*
 import io.realm.Realm
 import io.realm.kotlin.createObject
 import timber.log.Timber
+import javax.inject.Inject
 
-internal class RoomSyncHandler(private val monarchy: Monarchy,
-                               private val readReceiptHandler: ReadReceiptHandler,
-                               private val roomSummaryUpdater: RoomSummaryUpdater,
-                               private val roomTagHandler: RoomTagHandler,
-                               private val cryptoManager: CryptoManager) {
+@SessionScope
+internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarchy,
+                                                   private val readReceiptHandler: ReadReceiptHandler,
+                                                   private val roomSummaryUpdater: RoomSummaryUpdater,
+                                                   private val roomTagHandler: RoomTagHandler,
+                                                   private val cryptoManager: CryptoManager) {
 
     sealed class HandlingStrategy {
         data class JOINED(val data: Map) : HandlingStrategy()
@@ -63,9 +66,9 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
 
     private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy) {
         val rooms = when (handlingStrategy) {
-            is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
+            is HandlingStrategy.JOINED  -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
             is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) }
-            is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(realm, it.key, it.value) }
+            is HandlingStrategy.LEFT    -> handlingStrategy.data.map { handleLeftRoom(realm, it.key, it.value) }
         }
         realm.insertOrUpdate(rooms)
     }
@@ -77,7 +80,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
         Timber.v("Handle join sync for room $roomId")
 
         val roomEntity = RoomEntity.where(realm, roomId).findFirst()
-                ?: realm.createObject(roomId)
+                         ?: realm.createObject(roomId)
 
         if (roomEntity.membership == Membership.INVITE) {
             roomEntity.chunks.deleteAllFromRealm()
@@ -148,7 +151,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
                                   InvitedRoomSync): RoomEntity {
         Timber.v("Handle invited sync for room $roomId")
         val roomEntity = RoomEntity.where(realm, roomId).findFirst()
-                ?: realm.createObject(roomId)
+                         ?: realm.createObject(roomId)
         roomEntity.membership = Membership.INVITE
         if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
             val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.inviteState.events)
@@ -162,7 +165,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
                                roomId: String,
                                roomSync: RoomSync): RoomEntity {
         val roomEntity = RoomEntity.where(realm, roomId).findFirst()
-                ?: realm.createObject(roomId)
+                         ?: realm.createObject(roomId)
 
         roomEntity.membership = Membership.LEAVE
         roomEntity.chunks.deleteAllFromRealm()
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomTagHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomTagHandler.kt
index 90915b42..9bec48dd 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomTagHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomTagHandler.kt
@@ -20,10 +20,13 @@ import im.vector.matrix.android.api.session.room.model.tag.RoomTagContent
 import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
 import im.vector.matrix.android.internal.database.model.RoomTagEntity
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import io.realm.Realm
 import java.util.*
+import javax.inject.Inject
 
-internal class RoomTagHandler {
+@SessionScope
+internal class RoomTagHandler @Inject constructor() {
 
     fun handle(realm: Realm, roomId: String, content: RoomTagContent?) {
         if (content == null) {
@@ -41,7 +44,7 @@ internal class RoomTagHandler {
             tags.add(tag)
         }
         val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
-                ?: RoomSummaryEntity(roomId)
+                                ?: RoomSummaryEntity(roomId)
 
         roomSummaryEntity.tags.clear()
         roomSummaryEntity.tags.addAll(tags)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
index 5fd7f610..4e12ccd8 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
@@ -16,60 +16,16 @@
 
 package im.vector.matrix.android.internal.session.sync
 
-import im.vector.matrix.android.internal.session.DefaultSession
-import im.vector.matrix.android.internal.session.sync.job.SyncThread
-import org.koin.dsl.module.module
+import dagger.Module
+import im.vector.matrix.android.internal.session.SessionScope
 import retrofit2.Retrofit
 
-
+@Module
 internal class SyncModule {
 
-    val definition = module(override = true) {
-
-        scope(DefaultSession.SCOPE) {
-            val retrofit: Retrofit = get()
-            retrofit.create(SyncAPI::class.java)
-        }
-
-        scope(DefaultSession.SCOPE) {
-            ReadReceiptHandler()
-        }
-
-        scope(DefaultSession.SCOPE) {
-            RoomTagHandler()
-        }
-
-        scope(DefaultSession.SCOPE) {
-            RoomSyncHandler(get(), get(), get(), get(), get())
-        }
-
-        scope(DefaultSession.SCOPE) {
-            GroupSyncHandler(get())
-        }
-
-        scope(DefaultSession.SCOPE) {
-            CryptoSyncHandler(get(), get())
-        }
-
-        scope(DefaultSession.SCOPE) {
-            UserAccountDataSyncHandler(get())
-        }
-
-        scope(DefaultSession.SCOPE) {
-            SyncResponseHandler(get(), get(), get(), get(), get())
-        }
-
-        scope(DefaultSession.SCOPE) {
-            DefaultSyncTask(get(), get(), get(), get()) as SyncTask
-        }
-
-        scope(DefaultSession.SCOPE) {
-            SyncTokenStore(get("SessionRealmConfiguration"))
-        }
-
-        scope(DefaultSession.SCOPE) {
-            SyncThread(get(), get(), get(), get(), get())
-        }
-
+    @SessionScope
+    fun providesSyncAPI(retrofit: Retrofit): SyncAPI {
+        return retrofit.create(SyncAPI::class.java)
     }
+
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt
index c6305bd9..174f2de9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt
@@ -18,15 +18,18 @@ package im.vector.matrix.android.internal.session.sync
 
 import arrow.core.Try
 import im.vector.matrix.android.internal.crypto.CryptoManager
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.sync.model.SyncResponse
 import timber.log.Timber
+import javax.inject.Inject
 import kotlin.system.measureTimeMillis
 
-internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler,
-                                   private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
-                                   private val groupSyncHandler: GroupSyncHandler,
-                                   private val cryptoSyncHandler: CryptoSyncHandler,
-                                   private val cryptoManager: CryptoManager) {
+@SessionScope
+internal class SyncResponseHandler @Inject constructor(private val roomSyncHandler: RoomSyncHandler,
+                                                       private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
+                                                       private val groupSyncHandler: GroupSyncHandler,
+                                                       private val cryptoSyncHandler: CryptoSyncHandler,
+                                                       private val cryptoManager: CryptoManager) {
 
     fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean): Try {
         return Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
index 1f09f4c6..920fb389 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
@@ -23,9 +23,11 @@ import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.api.failure.MatrixError
 import im.vector.matrix.android.internal.auth.SessionParamsStore
 import im.vector.matrix.android.internal.network.executeRequest
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.filter.FilterRepository
 import im.vector.matrix.android.internal.session.sync.model.SyncResponse
 import im.vector.matrix.android.internal.task.Task
+import javax.inject.Inject
 
 internal interface SyncTask : Task {
 
@@ -33,10 +35,11 @@ internal interface SyncTask : Task {
 
 }
 
-internal class DefaultSyncTask(private val syncAPI: SyncAPI,
-                               private val filterRepository: FilterRepository,
-                               private val syncResponseHandler: SyncResponseHandler,
-                               private val sessionParamsStore: SessionParamsStore
+@SessionScope
+internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
+                                                   private val filterRepository: FilterRepository,
+                                                   private val syncResponseHandler: SyncResponseHandler,
+                                                   private val sessionParamsStore: SessionParamsStore
 ) : SyncTask {
 
 
@@ -55,7 +58,7 @@ internal class DefaultSyncTask(private val syncAPI: SyncAPI,
         }.recoverWith { throwable ->
             // Intercept 401
             if (throwable is Failure.ServerError
-                    && throwable.error.code == MatrixError.UNKNOWN_TOKEN) {
+                && throwable.error.code == MatrixError.UNKNOWN_TOKEN) {
                 sessionParamsStore.delete()
             }
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
index d4874178..d9a00636 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
@@ -17,10 +17,13 @@
 package im.vector.matrix.android.internal.session.sync
 
 import im.vector.matrix.android.internal.database.model.SyncEntity
+import im.vector.matrix.android.internal.session.SessionScope
 import io.realm.Realm
 import io.realm.RealmConfiguration
+import javax.inject.Inject
 
-internal class SyncTokenStore(private val realmConfiguration: RealmConfiguration) {
+@SessionScope
+internal class SyncTokenStore @Inject constructor(private val realmConfiguration: RealmConfiguration) {
 
     fun getLastToken(): String? {
         val realm = Realm.getInstance(realmConfiguration)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt
index 65a19afc..db377599 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt
@@ -20,10 +20,13 @@ import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
 import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages
 import im.vector.matrix.android.internal.session.sync.model.UserAccountDataSync
+import javax.inject.Inject
 
-internal class UserAccountDataSyncHandler(private val monarchy: Monarchy) {
+@SessionScope
+internal class UserAccountDataSyncHandler @Inject constructor(private val monarchy: Monarchy) {
 
     fun handle(accountData: UserAccountDataSync) {
         accountData.list.forEach {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt
index 7bad5e64..db79d392 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt
@@ -25,6 +25,7 @@ import im.vector.matrix.android.api.failure.MatrixError
 import im.vector.matrix.android.api.session.sync.SyncState
 import im.vector.matrix.android.api.util.Cancelable
 import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.sync.SyncTask
 import im.vector.matrix.android.internal.session.sync.SyncTokenStore
 import im.vector.matrix.android.internal.session.sync.model.SyncResponse
@@ -35,14 +36,16 @@ import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
 import timber.log.Timber
 import java.net.SocketTimeoutException
 import java.util.concurrent.CountDownLatch
+import javax.inject.Inject
 
 private const val RETRY_WAIT_TIME_MS = 10_000L
 
-internal class SyncThread(private val syncTask: SyncTask,
-                          private val networkConnectivityChecker: NetworkConnectivityChecker,
-                          private val syncTokenStore: SyncTokenStore,
-                          private val backgroundDetectionObserver: BackgroundDetectionObserver,
-                          private val taskExecutor: TaskExecutor
+@SessionScope
+internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
+                                              private val networkConnectivityChecker: NetworkConnectivityChecker,
+                                              private val syncTokenStore: SyncTokenStore,
+                                              private val backgroundDetectionObserver: BackgroundDetectionObserver,
+                                              private val taskExecutor: TaskExecutor
 ) : Thread(), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
 
     private var state: SyncState = SyncState.IDLE
@@ -111,7 +114,7 @@ internal class SyncThread(private val syncTask: SyncTask,
 
                             override fun onFailure(failure: Throwable) {
                                 if (failure is Failure.NetworkConnection
-                                        && failure.cause is SocketTimeoutException) {
+                                    && failure.cause is SocketTimeoutException) {
                                     // Timeout are not critical
                                     Timber.v("Timeout")
                                 } else {
@@ -119,13 +122,13 @@ internal class SyncThread(private val syncTask: SyncTask,
                                 }
 
                                 if (failure !is Failure.NetworkConnection
-                                        || failure.cause is JsonEncodingException) {
+                                    || failure.cause is JsonEncodingException) {
                                     // Wait 10s before retrying
                                     sleep(RETRY_WAIT_TIME_MS)
                                 }
 
                                 if (failure is Failure.ServerError
-                                        && (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
+                                    && (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
                                     // No token or invalid token, stop the thread
                                     updateStateTo(SyncState.KILLING)
                                 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt
index e3f68f06..4f79a9f1 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt
@@ -27,9 +27,12 @@ import im.vector.matrix.android.internal.database.RealmLiveData
 import im.vector.matrix.android.internal.database.mapper.asDomain
 import im.vector.matrix.android.internal.database.model.UserEntity
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.util.fetchCopied
+import javax.inject.Inject
 
-internal class DefaultUserService(private val monarchy: Monarchy) : UserService {
+@SessionScope
+internal class DefaultUserService @Inject constructor(private val monarchy: Monarchy) : UserService {
 
     override fun getUser(userId: String): User? {
         val userEntity = monarchy.fetchCopied { UserEntity.where(it, userId).findFirst() }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt
index 3230ecf0..b653e48f 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt
@@ -23,9 +23,11 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
 import im.vector.matrix.android.internal.database.model.EventEntity
 import im.vector.matrix.android.internal.database.model.UserEntity
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.room.membership.RoomMembers
 import im.vector.matrix.android.internal.task.Task
 import im.vector.matrix.android.internal.util.tryTransactionSync
+import javax.inject.Inject
 
 internal interface UpdateUserTask : Task {
 
@@ -33,7 +35,8 @@ internal interface UpdateUserTask : Task {
 
 }
 
-internal class DefaultUpdateUserTask(private val monarchy: Monarchy) : UpdateUserTask {
+@SessionScope
+internal class DefaultUpdateUserTask @Inject constructor(private val monarchy: Monarchy) : UpdateUserTask {
 
     override suspend fun execute(params: UpdateUserTask.Params): Try {
         return monarchy.tryTransactionSync { realm ->
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt
index b09fa911..40998d04 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt
@@ -24,14 +24,17 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
 import im.vector.matrix.android.internal.database.model.EventEntity
 import im.vector.matrix.android.internal.database.model.EventEntityFields
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.TaskThread
 import im.vector.matrix.android.internal.task.configureWith
 import io.realm.Sort
+import javax.inject.Inject
 
-internal class UserEntityUpdater(monarchy: Monarchy,
-                                 private val updateUserTask: UpdateUserTask,
-                                 private val taskExecutor: TaskExecutor)
+@SessionScope
+internal class UserEntityUpdater @Inject constructor(monarchy: Monarchy,
+                                                     private val updateUserTask: UpdateUserTask,
+                                                     private val taskExecutor: TaskExecutor)
     : RealmLiveEntityObserver(monarchy) {
 
     override val query = Monarchy.Query {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt
index 153bd97c..02ce07b0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt
@@ -21,7 +21,7 @@ import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.util.Cancelable
 
 internal fun  Task.configureWith(params: PARAMS): ConfigurableTask {
-    return ConfigurableTask(this, params)
+    return ConfigurableTask (this, params)
 }
 
 internal data class ConfigurableTask(
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
index 986fe81b..228e83ba 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
@@ -25,9 +25,12 @@ import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import timber.log.Timber
+import javax.inject.Inject
+import javax.inject.Singleton
 import kotlin.coroutines.EmptyCoroutineContext
 
-internal class TaskExecutor(private val coroutineDispatchers: MatrixCoroutineDispatchers) {
+@Singleton
+internal class TaskExecutor @Inject constructor(private val coroutineDispatchers: MatrixCoroutineDispatchers) {
 
     fun  execute(task: ConfigurableTask): Cancelable {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringProvider.kt
index 02d90c2f..14f2a825 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringProvider.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringProvider.kt
@@ -19,8 +19,12 @@ package im.vector.matrix.android.internal.util
 import android.content.res.Resources
 import androidx.annotation.NonNull
 import androidx.annotation.StringRes
+import im.vector.matrix.android.internal.di.MatrixScope
+import javax.inject.Inject
+import javax.inject.Singleton
 
-internal class StringProvider(private val resources: Resources) {
+@MatrixScope
+internal class StringProvider @Inject constructor(private val resources: Resources) {
 
     /**
      * Returns a localized string from the application's package's
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
index 69bc82fc..e30f9bb7 100755
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
@@ -710,7 +710,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
                 /* TODO
                 displayLoadingView()
 
-                val task = ClearMediaCacheAsyncTask(
+                val task = ClearMediaCacheAsyncTask @Inject constructor(
                         backgroundTask = {
                             session.mediaCache.clear()
                             activity?.let { it -> Glide.get(it).clearDiskCache() }

From 4be0ab87fc91d2f7c18b7eaea45482552f1cfa0c Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Sun, 16 Jun 2019 17:00:47 +0200
Subject: [PATCH 02/11] Dagger: continue adding it to SDK [WIP]

---
 .../interceptors/CurlLoggingInterceptor.kt    |   2 +-
 .../matrix/android/internal/SessionManager.kt |  43 ++++++
 .../android/internal/auth/AuthModule.kt       |  40 ++++--
 .../internal/auth/DefaultAuthenticator.kt     |  10 +-
 .../auth/db/RealmSessionParamsStore.kt        |   2 +
 .../internal/auth/db/SessionParamsMapper.kt   |   7 +-
 .../android/internal/crypto/CryptoModule.kt   |   9 +-
 .../android/internal/di/ChildWorkerFactory.kt |  27 ----
 .../internal/di/MatrixAssistedInjectModule.kt |  26 ++++
 .../android/internal/di/MatrixComponent.kt    |  26 +++-
 .../android/internal/di/MatrixModule.kt       |  23 ++-
 .../internal/session/DefaultSession.kt        |   2 +-
 .../internal/session/SessionComponent.kt      |  40 +++++-
 .../internal/session/SessionFactory.kt        |  75 ----------
 .../android/internal/session/SessionModule.kt |  20 ++-
 .../internal/session/cache/CacheModule.kt     |  38 +++++
 ...CacheService.kt => DefaultCacheService.kt} |   4 +-
 .../internal/session/content/ContentModule.kt |  12 +-
 .../internal/session/content/FileUploader.kt  |   6 +-
 .../session/content/UploadContentWorker.kt    |   4 +-
 .../internal/session/filter/FilterModule.kt   |  54 +++++++
 .../session/group/DefaultGroupService.kt      |   2 +
 .../session/group/GetGroupDataWorker.kt       |   4 +-
 .../internal/session/group/GroupModule.kt     |  24 +++-
 .../internal/session/room/DefaultRoom.kt      |   5 +-
 .../session/room/DefaultRoomService.kt        |   2 +-
 .../internal/session/room/RoomFactory.kt      |   2 +-
 .../internal/session/room/RoomModule.kt       | 135 +++++++++++++++---
 .../session/room/create/CreateRoomTask.kt     |   2 +-
 .../room/relation/SendRelationWorker.kt       |   4 +-
 .../session/room/send/EncryptEventWorker.kt   |  20 ++-
 .../session/room/send/EventFactory.kt         |   5 +-
 .../session/room/send/RedactEventWorker.kt    |  17 ++-
 .../session/room/send/SendEventWorker.kt      |   4 +-
 .../session/room/timeline/DefaultTimeline.kt  |   6 +-
 .../session/room/timeline/GetEventTask.kt     |   3 +
 .../internal/session/signout/SignOutModule.kt |  26 +++-
 .../internal/session/sync/SyncModule.kt       |  20 ++-
 .../internal/session/user/UserModule.kt       |  37 +++++
 .../matrix/android/internal/worker/DI.kt      |  71 +++++++++
 .../internal/worker/DelegateWorkerFactory.kt  |  29 ++++
 .../internal/worker/MatrixWorkerFactory.kt    |  45 ++++++
 42 files changed, 713 insertions(+), 220 deletions(-)
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
 delete mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/ChildWorkerFactory.kt
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedInjectModule.kt
 delete mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionFactory.kt
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/CacheModule.kt
 rename matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/{RealmCacheService.kt => DefaultCacheService.kt} (85%)
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterModule.kt
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DI.kt
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DelegateWorkerFactory.kt
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/MatrixWorkerFactory.kt

diff --git a/matrix-sdk-android/src/debug/java/im/vector/matrix/android/internal/network/interceptors/CurlLoggingInterceptor.kt b/matrix-sdk-android/src/debug/java/im/vector/matrix/android/internal/network/interceptors/CurlLoggingInterceptor.kt
index 33f460bd..3d499be3 100644
--- a/matrix-sdk-android/src/debug/java/im/vector/matrix/android/internal/network/interceptors/CurlLoggingInterceptor.kt
+++ b/matrix-sdk-android/src/debug/java/im/vector/matrix/android/internal/network/interceptors/CurlLoggingInterceptor.kt
@@ -36,7 +36,7 @@ import javax.inject.Inject
  * non-production environment.
  */
 @MatrixScope
-internal class CurlLoggingInterceptor @Inject constructor(private val logger: HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger.DEFAULT)
+internal class CurlLoggingInterceptor @Inject constructor(private val logger: HttpLoggingInterceptor.Logger)
     : Interceptor {
 
     /**
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
new file mode 100644
index 00000000..b46e4b78
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
@@ -0,0 +1,43 @@
+/*
+ *
+ *  * 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.matrix.android.internal
+
+import im.vector.matrix.android.api.session.Session
+import im.vector.matrix.android.internal.di.MatrixScope
+import im.vector.matrix.android.internal.session.SessionComponent
+import javax.inject.Inject
+
+@MatrixScope
+internal class SessionManager @Inject constructor() {
+
+    private val sessionComponents = HashMap()
+    private val sessions = HashMap()
+
+    fun createSession(userId: String): Session? {
+        if (sessionComponents.containsKey(userId)) {
+            throw RuntimeException("You already have a session for the user $userId")
+        }
+        return null
+    }
+
+    fun releaseSession(userId: String) {
+    }
+
+
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
index 3653f7df..1e11a3c3 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
@@ -17,27 +17,43 @@
 package im.vector.matrix.android.internal.auth
 
 import android.content.Context
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
 import im.vector.matrix.android.internal.auth.db.AuthRealmModule
+import im.vector.matrix.android.internal.auth.db.RealmSessionParamsStore
 import im.vector.matrix.android.internal.di.MatrixScope
+import im.vector.matrix.android.internal.session.SessionScope
+import im.vector.matrix.android.internal.session.cache.ClearCacheTask
+import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask
 import io.realm.RealmConfiguration
 import java.io.File
+import javax.inject.Named
 
 @Module
-internal class AuthModule {
+internal abstract class AuthModule {
 
-    @Provides
-    @MatrixScope
-    fun providesRealmConfiguration(context: Context): RealmConfiguration {
-        val old = File(context.filesDir, "matrix-sdk-auth")
-        if (old.exists()) {
-            old.renameTo(File(context.filesDir, "matrix-sdk-auth.realm"))
+    @Module
+    companion object {
+        @Provides
+        @MatrixScope
+        @Named("AuthRealmConfiguration")
+        fun providesRealmConfiguration(context: Context): RealmConfiguration {
+            val old = File(context.filesDir, "matrix-sdk-auth")
+            if (old.exists()) {
+                old.renameTo(File(context.filesDir, "matrix-sdk-auth.realm"))
+            }
+            return RealmConfiguration.Builder()
+                    .name("matrix-sdk-auth.realm")
+                    .modules(AuthRealmModule())
+                    .deleteRealmIfMigrationNeeded()
+                    .build()
         }
-        return RealmConfiguration.Builder()
-                .name("matrix-sdk-auth.realm")
-                .modules(AuthRealmModule())
-                .deleteRealmIfMigrationNeeded()
-                .build()
     }
+
+    @Binds
+    @MatrixScope
+    abstract fun bindSessionParamsStore(sessionParamsStore: RealmSessionParamsStore): SessionParamsStore
+
+
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
index 8d6f8d29..4acd9800 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
@@ -24,12 +24,11 @@ import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
 import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.util.Cancelable
+import im.vector.matrix.android.internal.SessionManager
 import im.vector.matrix.android.internal.auth.data.PasswordLoginParams
 import im.vector.matrix.android.internal.auth.data.ThreePidMedium
 import im.vector.matrix.android.internal.di.MatrixScope
 import im.vector.matrix.android.internal.network.executeRequest
-import im.vector.matrix.android.internal.session.DefaultSession
-import im.vector.matrix.android.internal.session.SessionFactory
 import im.vector.matrix.android.internal.util.CancelableCoroutine
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
 import kotlinx.coroutines.GlobalScope
@@ -37,13 +36,12 @@ import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import retrofit2.Retrofit
 import javax.inject.Inject
-import kotlin.random.Random
 
 @MatrixScope
 internal class DefaultAuthenticator @Inject constructor(private val retrofitBuilder: Retrofit.Builder,
                                                         private val coroutineDispatchers: MatrixCoroutineDispatchers,
                                                         private val sessionParamsStore: SessionParamsStore,
-                                                        private val sessionFactory: DefaultSession.Factory
+                                                        private val sessionManager: SessionManager
 ) : Authenticator {
 
     override fun hasActiveSessions(): Boolean {
@@ -53,7 +51,7 @@ internal class DefaultAuthenticator @Inject constructor(private val retrofitBuil
     override fun getLastActiveSession(): Session? {
         val sessionParams = sessionParamsStore.get()
         return sessionParams?.let {
-            sessionFactory.create(it)
+            sessionManager.createSession(it.credentials.userId)
         }
     }
 
@@ -87,7 +85,7 @@ internal class DefaultAuthenticator @Inject constructor(private val retrofitBuil
             sessionParamsStore.save(sessionParams)
             sessionParams
         }.map {
-            sessionFactory.create(it)
+            sessionManager.createSession(it.credentials.userId)!!
         }
 
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
index ecb442ca..94b86a18 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
@@ -23,9 +23,11 @@ import im.vector.matrix.android.internal.di.MatrixScope
 import io.realm.Realm
 import io.realm.RealmConfiguration
 import javax.inject.Inject
+import javax.inject.Named
 
 @MatrixScope
 internal class RealmSessionParamsStore @Inject constructor(private val mapper: SessionParamsMapper,
+                                                           @Named("AuthRealmConfiguration")
                                                            private val realmConfiguration: RealmConfiguration) : SessionParamsStore {
 
     override fun save(sessionParams: SessionParams): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
index 7fc0a334..53e3a98a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
@@ -17,11 +17,14 @@
 package im.vector.matrix.android.internal.auth.db
 
 import com.squareup.moshi.Moshi
-import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
 import im.vector.matrix.android.api.auth.data.Credentials
+import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
 import im.vector.matrix.android.api.auth.data.SessionParams
+import im.vector.matrix.android.internal.di.MatrixScope
+import javax.inject.Inject
 
-internal class SessionParamsMapper(moshi: Moshi) {
+@MatrixScope
+internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
 
     private val credentialsAdapter = moshi.adapter(Credentials::class.java)
     private val homeServerConnectionConfigAdapter = moshi.adapter(HomeServerConnectionConfig::class.java)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
index 775eaad4..acb8045d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
@@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.session.SessionScope
 import io.realm.RealmConfiguration
 import retrofit2.Retrofit
 import java.io.File
+import javax.inject.Named
 
 @Module
 internal class CryptoModule {
@@ -38,6 +39,7 @@ internal class CryptoModule {
     // Realm configuration, named to avoid clash with main cache realm configuration
     @Provides
     @SessionScope
+    @Named("CryptonRealmConfiguration")
     fun providesRealmConfiguration(context: Context, credentials: Credentials): RealmConfiguration {
         return RealmConfiguration.Builder()
                 .directory(File(context.filesDir, credentials.userId.hash()))
@@ -50,10 +52,11 @@ internal class CryptoModule {
 
     @Provides
     @SessionScope
-    fun providesCryptoStore(realmConfiguration: RealmConfiguration, credentials: Credentials): IMXCryptoStore {
+    fun providesCryptoStore(@Named("CryptonRealmConfiguration")
+                            realmConfiguration: RealmConfiguration, credentials: Credentials): IMXCryptoStore {
         return RealmCryptoStore(false /* TODO*/,
-                                realmConfiguration,
-                                credentials)
+                realmConfiguration,
+                credentials)
     }
 
     @Provides
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/ChildWorkerFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/ChildWorkerFactory.kt
deleted file mode 100644
index 169bcb6f..00000000
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/ChildWorkerFactory.kt
+++ /dev/null
@@ -1,27 +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.matrix.android.internal.di
-
-import android.content.Context
-import androidx.work.ListenableWorker
-import androidx.work.WorkerParameters
-
-interface ChildWorkerFactory {
-
-    fun create(appContext: Context, params: WorkerParameters): ListenableWorker
-
-}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedInjectModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedInjectModule.kt
new file mode 100644
index 00000000..8f5723d0
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedInjectModule.kt
@@ -0,0 +1,26 @@
+/*
+ *
+ *  * 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.matrix.android.internal.di
+
+import com.squareup.inject.assisted.dagger2.AssistedModule
+import dagger.Module
+
+@Module(includes = [AssistedInject_MatrixAssistedInjectModule::class])
+@AssistedModule
+internal interface MatrixAssistedInjectModule
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
index 444475d5..aa91eadc 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
@@ -16,10 +16,32 @@
 
 package im.vector.matrix.android.internal.di
 
+import android.content.Context
+import com.squareup.moshi.Moshi
+import dagger.BindsInstance
 import dagger.Component
+import im.vector.matrix.android.internal.auth.AuthModule
+import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
+import im.vector.matrix.android.internal.worker.WorkerBindingModule
+import retrofit2.Retrofit
+import java.net.Authenticator
 
-@Component
+
+@Component(modules = [MatrixModule::class, NetworkModule::class, AuthModule::class])
 @MatrixScope
-interface MatrixComponent {
+internal interface MatrixComponent {
+
+    fun matrixCoroutineDispatchers(): MatrixCoroutineDispatchers
+
+    fun moshi(): Moshi
+
+    fun retrofitBuilder(): Retrofit.Builder
+
+    fun authenticator(): Authenticator
+
+    @Component.Factory
+    interface Factory {
+        fun create(@BindsInstance context: Context): MatrixComponent
+    }
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt
index 795ec83c..b2bbefd5 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt
@@ -16,7 +16,6 @@
 
 package im.vector.matrix.android.internal.di
 
-import android.content.Context
 import dagger.Module
 import dagger.Provides
 import im.vector.matrix.android.internal.crypto.CryptoAsyncHelper
@@ -25,23 +24,17 @@ import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.android.asCoroutineDispatcher
 
 @Module
-internal class MatrixModule(private val context: Context) {
-
-    @Provides
-    @MatrixScope
-    fun providesContext(): Context {
-            return context
-        }
+internal class MatrixModule {
 
     @Provides
     @MatrixScope
     fun providesMatrixCoroutineDispatchers(): MatrixCoroutineDispatchers {
-            val cryptoHandler = CryptoAsyncHelper.getDecryptBackgroundHandler()
-            return MatrixCoroutineDispatchers(io = Dispatchers.IO,
-                    computation = Dispatchers.IO,
-                    main = Dispatchers.Main,
-                    crypto = cryptoHandler.asCoroutineDispatcher("crypto")
-            )
-        }
+        val cryptoHandler = CryptoAsyncHelper.getDecryptBackgroundHandler()
+        return MatrixCoroutineDispatchers(io = Dispatchers.IO,
+                computation = Dispatchers.IO,
+                main = Dispatchers.Main,
+                crypto = cryptoHandler.asCoroutineDispatcher("crypto")
+        )
+    }
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
index 80f60b8c..ec272083 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
@@ -42,7 +42,7 @@ import im.vector.matrix.android.internal.database.LiveEntityObserver
 import im.vector.matrix.android.internal.session.sync.job.SyncThread
 import timber.log.Timber
 
-
+@SessionScope
 internal class DefaultSession @AssistedInject constructor(@Assisted override val sessionParams: SessionParams,
                                                           private val monarchy: Monarchy,
                                                           private val liveEntityUpdaters: List,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
index 74eb73b4..1283f3b0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
@@ -16,16 +16,46 @@
 
 package im.vector.matrix.android.internal.session
 
+import dagger.BindsInstance
 import dagger.Component
+import im.vector.matrix.android.api.auth.data.SessionParams
+import im.vector.matrix.android.internal.crypto.CryptoModule
+import im.vector.matrix.android.internal.di.MatrixAssistedInjectModule
 import im.vector.matrix.android.internal.di.MatrixComponent
+import im.vector.matrix.android.internal.session.content.ContentModule
+import im.vector.matrix.android.internal.session.cache.CacheModule
+import im.vector.matrix.android.internal.session.filter.FilterModule
+import im.vector.matrix.android.internal.session.group.GroupModule
+import im.vector.matrix.android.internal.session.room.RoomModule
+import im.vector.matrix.android.internal.session.signout.SignOutModule
+import im.vector.matrix.android.internal.session.sync.SyncModule
+import im.vector.matrix.android.internal.worker.WorkerBindingModule
 
-@Component(dependencies = [MatrixComponent::class])
+@Component(dependencies = [MatrixComponent::class],
+        modules = [
+            SessionModule::class,
+            RoomModule::class,
+            SyncModule::class,
+            SignOutModule::class,
+            GroupModule::class,
+            FilterModule::class,
+            GroupModule::class,
+            ContentModule::class,
+            CacheModule::class,
+            CryptoModule::class,
+            MatrixAssistedInjectModule::class,
+            WorkerBindingModule::class
+        ]
+)
 @SessionScope
-interface SessionComponent {
+internal interface SessionComponent {
 
-    @Component.Builder
-    interface Builder {
-        fun matrixComponent(matrixComponent: MatrixComponent): Builder
+    @Component.Factory
+    interface Factory {
+        fun create(
+                matrixComponent: MatrixComponent,
+                @BindsInstance sessionParams: SessionParams): SessionComponent
     }
 
+
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionFactory.kt
deleted file mode 100644
index ef5a0e4c..00000000
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionFactory.kt
+++ /dev/null
@@ -1,75 +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.matrix.android.internal.session
-
-import com.zhuinden.monarchy.Monarchy
-import im.vector.matrix.android.api.auth.data.SessionParams
-import im.vector.matrix.android.api.session.Session
-import im.vector.matrix.android.api.session.cache.CacheService
-import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
-import im.vector.matrix.android.api.session.content.ContentUrlResolver
-import im.vector.matrix.android.api.session.group.GroupService
-import im.vector.matrix.android.api.session.room.RoomDirectoryService
-import im.vector.matrix.android.api.session.room.RoomService
-import im.vector.matrix.android.api.session.signout.SignOutService
-import im.vector.matrix.android.api.session.sync.FilterService
-import im.vector.matrix.android.api.session.user.UserService
-import im.vector.matrix.android.internal.crypto.CryptoManager
-import im.vector.matrix.android.internal.database.LiveEntityObserver
-import im.vector.matrix.android.internal.di.MatrixScope
-import im.vector.matrix.android.internal.session.sync.job.SyncThread
-import javax.inject.Inject
-
-@MatrixScope
-internal class SessionFactory @Inject constructor(
-        private val monarchy: Monarchy,
-        private val liveEntityUpdaters: List,
-        private val sessionListeners: SessionListeners,
-        private val roomService: RoomService,
-        private val roomDirectoryService: RoomDirectoryService,
-        private val groupService: GroupService,
-        private val userService: UserService,
-        private val filterService: FilterService,
-        private val cacheService: CacheService,
-        private val signOutService: SignOutService,
-        private val cryptoService: CryptoManager,
-        private val syncThread: SyncThread,
-        private val contentUrlResolver: ContentUrlResolver,
-        private val contentUploadProgressTracker: ContentUploadStateTracker) {
-
-
-    fun create(sessionParams: SessionParams): Session {
-        return DefaultSession(
-                sessionParams,
-                monarchy,
-                liveEntityUpdaters,
-                sessionListeners,
-                roomService,
-                roomDirectoryService,
-                groupService,
-                userService,
-                filterService,
-                cacheService,
-                signOutService,
-                cryptoService,
-                syncThread,
-                contentUrlResolver,
-                contentUploadProgressTracker
-        )
-    }
-
-}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
index aea08a69..e68cd809 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
@@ -33,17 +33,21 @@ import im.vector.matrix.android.internal.util.md5
 import io.realm.RealmConfiguration
 import retrofit2.Retrofit
 import java.io.File
+import javax.inject.Named
 
 @Module
-internal class SessionModule(private val sessionParams: SessionParams) {
+internal object SessionModule {
 
     @Provides
-    fun providesCredentials(): Credentials {
+    @SessionScope
+    fun providesCredentials(sessionParams: SessionParams): Credentials {
         return sessionParams.credentials
     }
 
     @Provides
-    fun providesRealmConfiguration(context: Context): RealmConfiguration {
+    @SessionScope
+    @Named("SessionRealmConfiguration")
+    fun providesRealmConfiguration(sessionParams: SessionParams, context: Context): RealmConfiguration {
         val childPath = sessionParams.credentials.userId.md5()
         val directory = File(context.filesDir, childPath)
 
@@ -56,25 +60,30 @@ internal class SessionModule(private val sessionParams: SessionParams) {
     }
 
     @Provides
-    fun providesMonarchy(realmConfiguration: RealmConfiguration): Monarchy {
+    @SessionScope
+    fun providesMonarchy(@Named("SessionRealmConfiguration")
+                         realmConfiguration: RealmConfiguration): Monarchy {
         return Monarchy.Builder()
                 .setRealmConfiguration(realmConfiguration)
                 .build()
     }
 
     @Provides
-    fun providesRetrofit(retrofitBuilder: Retrofit.Builder): Retrofit {
+    @SessionScope
+    fun providesRetrofit(sessionParams: SessionParams, retrofitBuilder: Retrofit.Builder): Retrofit {
         return retrofitBuilder
                 .baseUrl(sessionParams.homeServerConnectionConfig.homeServerUri.toString())
                 .build()
     }
 
     @Provides
+    @SessionScope
     fun providesFilterAPI(retrofit: Retrofit): FilterApi {
         return retrofit.create(FilterApi::class.java)
     }
 
     @Provides
+    @SessionScope
     fun providesLiveEntityObservers(groupSummaryUpdater: GroupSummaryUpdater,
                                     userEntityUpdater: UserEntityUpdater,
                                     aggregationUpdater: EventRelationsAggregationUpdater,
@@ -82,5 +91,4 @@ internal class SessionModule(private val sessionParams: SessionParams) {
         return listOf(groupSummaryUpdater, userEntityUpdater, aggregationUpdater, eventsPruner)
     }
 
-
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/CacheModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/CacheModule.kt
new file mode 100644
index 00000000..349dc246
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/CacheModule.kt
@@ -0,0 +1,38 @@
+/*
+ *
+ *  * 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.matrix.android.internal.session.cache
+
+import dagger.Binds
+import dagger.Module
+import im.vector.matrix.android.api.session.cache.CacheService
+import im.vector.matrix.android.internal.session.SessionScope
+
+@Module
+internal abstract class CacheModule {
+
+    @Binds
+    @SessionScope
+    abstract fun bindCacheService(cacheService: DefaultCacheService): CacheService
+
+    @Binds
+    @SessionScope
+    abstract fun bindClearCacheTask(clearCacheTask: RealmClearCacheTask): ClearCacheTask
+
+
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmCacheService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
similarity index 85%
rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmCacheService.kt
rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
index 588ec63a..7dcb24e9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmCacheService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
@@ -24,8 +24,8 @@ import im.vector.matrix.android.internal.task.configureWith
 import javax.inject.Inject
 
 @SessionScope
-internal class RealmCacheService @Inject constructor(private val clearCacheTask: ClearCacheTask,
-                                                     private val taskExecutor: TaskExecutor) : CacheService {
+internal class DefaultCacheService @Inject constructor(private val clearCacheTask: ClearCacheTask,
+                                                       private val taskExecutor: TaskExecutor) : CacheService {
 
     override fun clearCache(callback: MatrixCallback) {
         clearCacheTask
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt
index 9f431862..66b75a54 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt
@@ -16,10 +16,20 @@
 
 package im.vector.matrix.android.internal.session.content
 
+import dagger.Binds
 import dagger.Module
+import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
+import im.vector.matrix.android.api.session.content.ContentUrlResolver
+import im.vector.matrix.android.internal.session.SessionScope
 
 @Module
-internal class ContentModule {
+internal abstract class ContentModule {
 
+    @Binds
+    @SessionScope
+    abstract fun bindContentUploadStateTracker(contentUploadStateTracker: DefaultContentUploadStateTracker): ContentUploadStateTracker
 
+    @Binds
+    @SessionScope
+    abstract fun bindContentUrlResolver(contentUrlResolver: DefaultContentUrlResolver): ContentUrlResolver
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
index 67d79305..71906b11 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
@@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.content
 
 import arrow.core.Try
 import arrow.core.Try.Companion.raise
+import com.squareup.moshi.Moshi
 import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.internal.di.MoshiProvider
 import im.vector.matrix.android.internal.network.ProgressRequestBody
@@ -30,11 +31,10 @@ import javax.inject.Inject
 
 @SessionScope
 internal class FileUploader @Inject constructor(private val okHttpClient: OkHttpClient,
-                            sessionParams: SessionParams) {
+                                                private val sessionParams: SessionParams,
+                                                private val moshi: Moshi) {
 
     private val uploadUrl = DefaultContentUrlResolver.getUploadUrl(sessionParams.homeServerConnectionConfig)
-
-    private val moshi = MoshiProvider.providesMoshi()
     private val responseAdapter = moshi.adapter(ContentUploadResponse::class.java)
 
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
index 58516088..ce5c8e58 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
@@ -31,7 +31,7 @@ import im.vector.matrix.android.api.session.room.model.message.MessageContent
 import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
 import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
 import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
-import im.vector.matrix.android.internal.di.ChildWorkerFactory
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.ProgressRequestBody
 import im.vector.matrix.android.internal.session.room.send.SendEventWorker
 import im.vector.matrix.android.internal.util.WorkerParamsFactory
@@ -138,7 +138,7 @@ internal class UploadContentWorker @AssistedInject constructor(
     }
 
     @AssistedInject.Factory
-    interface Factory : ChildWorkerFactory
+    interface Factory : DelegateWorkerFactory
 
 }
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterModule.kt
new file mode 100644
index 00000000..fed83d87
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterModule.kt
@@ -0,0 +1,54 @@
+/*
+ *
+ *  * 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.matrix.android.internal.session.filter
+
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import im.vector.matrix.android.api.session.sync.FilterService
+import im.vector.matrix.android.internal.session.SessionScope
+import retrofit2.Retrofit
+
+@Module
+internal abstract class FilterModule {
+
+    @Module
+    companion object {
+        @SessionScope
+        @Provides
+        @JvmStatic
+        fun providesFilterApi(retrofit: Retrofit): FilterApi {
+            return retrofit.create(FilterApi::class.java)
+        }
+    }
+
+    @Binds
+    @SessionScope
+    abstract fun bindFilterRepository(filterRepository: DefaultFilterRepository): FilterRepository
+
+    @Binds
+    @SessionScope
+    abstract fun bindFilterService(filterService: DefaultFilterService): FilterService
+
+    @Binds
+    @SessionScope
+    abstract fun bindSaveFilterTask(saveFilterTask_Factory: DefaultSaveFilterTask): SaveFilterTask
+
+
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt
index a574df7c..90ee7d58 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt
@@ -25,8 +25,10 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
 import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
 import im.vector.matrix.android.internal.database.model.GroupSummaryEntityFields
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import javax.inject.Inject
 
+@SessionScope
 internal class DefaultGroupService @Inject constructor(private val monarchy: Monarchy) : GroupService {
 
     override fun getGroup(groupId: String): Group? {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
index 7e979c72..4d35d0c7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
@@ -23,7 +23,7 @@ import arrow.core.Try
 import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
-import im.vector.matrix.android.internal.di.ChildWorkerFactory
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.util.WorkerParamsFactory
 
 internal class GetGroupDataWorker @AssistedInject constructor(
@@ -53,6 +53,6 @@ internal class GetGroupDataWorker @AssistedInject constructor(
     }
 
     @AssistedInject.Factory
-    interface Factory  : ChildWorkerFactory
+    interface Factory  : DelegateWorkerFactory
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt
index 5d7ac1f2..518585d3 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt
@@ -16,15 +16,31 @@
 
 package im.vector.matrix.android.internal.session.group
 
+import dagger.Binds
 import dagger.Module
+import dagger.Provides
+import im.vector.matrix.android.api.session.group.GroupService
 import im.vector.matrix.android.internal.session.SessionScope
 import retrofit2.Retrofit
 
 @Module
-internal class GroupModule {
+internal abstract class GroupModule {
 
-    @SessionScope
-    fun providesGroupAPI(retrofit: Retrofit): GroupAPI {
-        return retrofit.create(GroupAPI::class.java)
+    @Module
+    companion object {
+        @SessionScope
+        @Provides
+        @JvmStatic
+        fun providesGroupAPI(retrofit: Retrofit): GroupAPI {
+            return retrofit.create(GroupAPI::class.java)
+        }
     }
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetGroupDataTask(getGroupDataTask: DefaultGetGroupDataTask): GetGroupDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindGroupService(groupService: DefaultGroupService): GroupService
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt
index 5c37fa7d..51f93873 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt
@@ -33,8 +33,11 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
 import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
 import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
+import javax.inject.Inject
 
-internal class DefaultRoom(
+@SessionScope
+internal class DefaultRoom @Inject constructor(
         override val roomId: String,
         private val monarchy: Monarchy,
         private val timelineService: TimelineService,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt
index 448d316c..571a50d2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt
@@ -50,7 +50,7 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona
 
     override fun getRoom(roomId: String): Room? {
         monarchy.fetchManaged { RoomEntity.where(it, roomId).findFirst() } ?: return null
-        return roomFactory.instantiate(roomId)
+        return roomFactory.create(roomId)
     }
 
     override fun liveRoomSummaries(): LiveData> {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt
index c3c58e5a..75d35e81 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt
@@ -58,7 +58,7 @@ internal class RoomFactory @Inject constructor(private val monarchy: Monarchy,
                                                private val joinRoomTask: JoinRoomTask,
                                                private val leaveRoomTask: LeaveRoomTask) {
 
-    fun instantiate(roomId: String): Room {
+    fun create(roomId: String): Room {
         val roomMemberExtractor = SenderRoomMemberExtractor(roomId)
         val relationExtractor = EventRelationExtractor()
         val timelineEventFactory = TimelineEventFactory(roomMemberExtractor, relationExtractor, cryptoService)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
index 64ac991c..cc5e7aa8 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
@@ -16,12 +16,26 @@
 
 package im.vector.matrix.android.internal.session.room
 
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
+import im.vector.matrix.android.api.session.room.RoomDirectoryService
+import im.vector.matrix.android.api.session.room.RoomService
+import im.vector.matrix.android.api.session.room.members.MembershipService
+import im.vector.matrix.android.api.session.room.model.relation.RelationService
+import im.vector.matrix.android.api.session.room.read.ReadService
+import im.vector.matrix.android.api.session.room.send.SendService
+import im.vector.matrix.android.api.session.room.state.StateService
+import im.vector.matrix.android.api.session.room.timeline.TimelineService
 import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.room.create.CreateRoomTask
 import im.vector.matrix.android.internal.session.room.create.DefaultCreateRoomTask
+import im.vector.matrix.android.internal.session.room.directory.DefaultGetPublicRoomTask
+import im.vector.matrix.android.internal.session.room.directory.DefaultGetThirdPartyProtocolsTask
+import im.vector.matrix.android.internal.session.room.directory.GetPublicRoomTask
+import im.vector.matrix.android.internal.session.room.directory.GetThirdPartyProtocolsTask
 import im.vector.matrix.android.internal.session.room.membership.DefaultLoadRoomMembersTask
+import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService
 import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
 import im.vector.matrix.android.internal.session.room.membership.joining.DefaultInviteTask
 import im.vector.matrix.android.internal.session.room.membership.joining.DefaultJoinRoomTask
@@ -31,30 +45,115 @@ import im.vector.matrix.android.internal.session.room.membership.leaving.Default
 import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
 import im.vector.matrix.android.internal.session.room.prune.DefaultPruneEventTask
 import im.vector.matrix.android.internal.session.room.prune.PruneEventTask
+import im.vector.matrix.android.internal.session.room.read.DefaultReadService
 import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask
 import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
-import im.vector.matrix.android.internal.session.room.relation.DefaultFindReactionEventForUndoTask
-import im.vector.matrix.android.internal.session.room.relation.DefaultUpdateQuickReactionTask
-import im.vector.matrix.android.internal.session.room.relation.FindReactionEventForUndoTask
-import im.vector.matrix.android.internal.session.room.relation.UpdateQuickReactionTask
-import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
-import im.vector.matrix.android.internal.session.room.send.LocalEchoUpdater
-import im.vector.matrix.android.internal.session.room.state.DefaultSendStateTask
-import im.vector.matrix.android.internal.session.room.state.SendStateTask
-import im.vector.matrix.android.internal.session.room.timeline.DefaultGetContextOfEventTask
-import im.vector.matrix.android.internal.session.room.timeline.DefaultPaginationTask
-import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask
-import im.vector.matrix.android.internal.session.room.timeline.PaginationTask
-import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor
+import im.vector.matrix.android.internal.session.room.relation.*
+import im.vector.matrix.android.internal.session.room.send.DefaultSendService
+import im.vector.matrix.android.internal.session.room.state.DefaultStateService
+import im.vector.matrix.android.internal.session.room.timeline.*
 import retrofit2.Retrofit
 
 @Module
-internal class RoomModule {
+internal abstract class RoomModule {
 
-    @SessionScope
-    @Provides
-    fun providesRoomAPI(retrofit: Retrofit): RoomAPI {
-        return retrofit.create(RoomAPI::class.java)
+    @Module
+    companion object {
+        @SessionScope
+        @Provides
+        @JvmStatic
+        fun providesRoomAPI(retrofit: Retrofit): RoomAPI {
+            return retrofit.create(RoomAPI::class.java)
+        }
     }
 
+    @Binds
+    @SessionScope
+    abstract fun bindRoomService(roomService: DefaultRoomService): RoomService
+
+    @Binds
+    @SessionScope
+    abstract fun bindRoomDirectoryService(roomDirectoryService: DefaultRoomDirectoryService): RoomDirectoryService
+
+    @Binds
+    @SessionScope
+    abstract fun bindEventRelationsAggregationTask(eventRelationsAggregationTask: DefaultEventRelationsAggregationTask): EventRelationsAggregationTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindCreateRoomTask(createRoomTask: DefaultCreateRoomTask): CreateRoomTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetPublicRoomTask(getPublicRoomTask: DefaultGetPublicRoomTask): GetPublicRoomTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetThirdPartyProtocolsTask(getThirdPartyProtocolsTask: DefaultGetThirdPartyProtocolsTask): GetThirdPartyProtocolsTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindInviteTask(inviteTask: DefaultInviteTask): InviteTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindJoinRoomTask(joinRoomTask: DefaultJoinRoomTask): JoinRoomTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindLeaveRoomTask(leaveRoomTask: DefaultLeaveRoomTask): LeaveRoomTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindMembershipService(membershipService: DefaultMembershipService): MembershipService
+
+    @Binds
+    @SessionScope
+    abstract fun bindLoadRoomMembersTask(loadRoomMembersTask: DefaultLoadRoomMembersTask): LoadRoomMembersTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindPruneEventTask(pruneEventTask: DefaultPruneEventTask): PruneEventTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindReadService(readService: DefaultReadService): ReadService
+
+    @Binds
+    @SessionScope
+    abstract fun bindSetReadMarkersTask(setReadMarkersTask: DefaultSetReadMarkersTask): SetReadMarkersTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindRelationService(relationService: DefaultRelationService): RelationService
+
+    @Binds
+    @SessionScope
+    abstract fun bindFindReactionEventForUndoTask(findReactionEventForUndoTask: DefaultFindReactionEventForUndoTask): FindReactionEventForUndoTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindUpdateQuickReactionTask(updateQuickReactionTask: DefaultUpdateQuickReactionTask): UpdateQuickReactionTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindSendService(sendService: DefaultSendService): SendService
+
+    @Binds
+    @SessionScope
+    abstract fun bindStateService(stateService: DefaultStateService): StateService
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetContextOfEventTask(getContextOfEventTask: DefaultGetContextOfEventTask): GetContextOfEventTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindPaginationTask(paginationTask: DefaultPaginationTask): PaginationTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindTimelineService(timelineService: DefaultTimelineService): TimelineService
+
+
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt
index 37088f74..a1f10c62 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt
@@ -33,7 +33,7 @@ internal interface CreateRoomTask : Task
 
 @SessionScope
 internal class DefaultCreateRoomTask @Inject constructor(private val roomAPI: RoomAPI,
-                                     private val realmConfiguration: RealmConfiguration) : CreateRoomTask {
+                                                         private val realmConfiguration: RealmConfiguration) : CreateRoomTask {
 
 
     override suspend fun execute(params: CreateRoomParams): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
index c41ac5df..de32c6f8 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
@@ -26,7 +26,7 @@ import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.model.relation.ReactionContent
 import im.vector.matrix.android.api.session.room.model.relation.ReactionInfo
-import im.vector.matrix.android.internal.di.ChildWorkerFactory
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
 import im.vector.matrix.android.internal.session.room.send.SendResponse
@@ -82,5 +82,5 @@ internal class SendRelationWorker @AssistedInject constructor(
     }
 
     @AssistedInject.Factory
-    interface Factory : ChildWorkerFactory
+    interface Factory : DelegateWorkerFactory
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
index 8dcae0cc..70a9ddf0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
@@ -19,6 +19,8 @@ package im.vector.matrix.android.internal.session.room.send
 import android.content.Context
 import androidx.work.Worker
 import androidx.work.WorkerParameters
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.failure.Failure
@@ -26,13 +28,16 @@ import im.vector.matrix.android.api.session.crypto.CryptoService
 import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.room.send.SendState
 import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
-import im.vector.matrix.android.internal.di.MatrixKoinComponent
 import im.vector.matrix.android.internal.util.WorkerParamsFactory
-import org.koin.standalone.inject
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import java.util.concurrent.CountDownLatch
 
-internal class EncryptEventWorker(context: Context, params: WorkerParameters)
-    : Worker(context, params), MatrixKoinComponent {
+internal class EncryptEventWorker @AssistedInject constructor(
+        @Assisted context: Context,
+        @Assisted params: WorkerParameters,
+        private val crypto: CryptoService,
+        private val localEchoUpdater: LocalEchoUpdater)
+    : Worker(context, params) {
 
 
     @JsonClass(generateAdapter = true)
@@ -41,9 +46,6 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
             val event: Event
     )
 
-    private val crypto by inject()
-    private val localEchoUpdater by inject()
-
     override fun doWork(): Result {
 
         val params = WorkerParamsFactory.fromData(inputData)
@@ -97,4 +99,8 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
         //always return success, or the chain will be stuck for ever!
         return Result.success()
     }
+
+    @AssistedInject.Factory
+    interface Factory : DelegateWorkerFactory
+
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt
index d42c7222..7ebab9d6 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt
@@ -22,8 +22,11 @@ import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
 import im.vector.matrix.android.internal.di.MoshiProvider
+import im.vector.matrix.android.internal.session.SessionScope
+import javax.inject.Inject
 
-internal class EventFactory(private val credentials: Credentials) {
+@SessionScope
+internal class EventFactory @Inject constructor(private val credentials: Credentials) {
 
     private val moshi = MoshiProvider.providesMoshi()
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
index 5056a93b..0054329f 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
@@ -18,16 +18,20 @@ package im.vector.matrix.android.internal.session.room.send
 import android.content.Context
 import androidx.work.Worker
 import androidx.work.WorkerParameters
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.api.failure.Failure
-import im.vector.matrix.android.internal.di.MatrixKoinComponent
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
 import im.vector.matrix.android.internal.util.WorkerParamsFactory
-import org.koin.standalone.inject
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 
-internal class RedactEventWorker(context: Context, params: WorkerParameters)
-    : Worker(context, params), MatrixKoinComponent {
+internal class RedactEventWorker @AssistedInject constructor(
+        @Assisted context: Context,
+        @Assisted params: WorkerParameters,
+        private val roomAPI: RoomAPI)
+    : Worker(context, params) {
 
     @JsonClass(generateAdapter = true)
     internal data class Params(
@@ -37,8 +41,6 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters)
             val reason: String?
     )
 
-    private val roomAPI by inject()
-
     override fun doWork(): Result {
         val params = WorkerParamsFactory.fromData(inputData)
                 ?: return Result.failure()
@@ -66,4 +68,7 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters)
         })
     }
 
+    @AssistedInject.Factory
+    interface Factory : DelegateWorkerFactory
+
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
index 598352c5..790db2ce 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
@@ -25,7 +25,7 @@ import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.room.send.SendState
-import im.vector.matrix.android.internal.di.ChildWorkerFactory
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
 import im.vector.matrix.android.internal.util.WorkerParamsFactory
@@ -76,6 +76,6 @@ internal class SendEventWorker @AssistedInject constructor(
     }
 
     @AssistedInject.Factory
-    interface Factory : ChildWorkerFactory
+    interface Factory : DelegateWorkerFactory
 
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt
index c276c26f..6743d1cb 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt
@@ -274,7 +274,7 @@ internal class DefaultTimeline(
             val newRequestedCount = count - builtCount
             updatePaginationState(direction) { it.copy(requestedCount = newRequestedCount) }
             val fetchingCount = Math.max(MIN_FETCHING_COUNT, newRequestedCount)
-            executePaginationTask @Inject constructor(direction, fetchingCount)
+            executePaginationTask(direction, fetchingCount)
         } else {
             updatePaginationState(direction) { it.copy(isPaginating = false, requestedCount = 0) }
         }
@@ -350,7 +350,7 @@ internal class DefaultTimeline(
     /**
      * This has to be called on TimelineThread as it access realm live results
      */
-    private fun executePaginationTask @Inject constructor(direction: Timeline.Direction, limit: Int) {
+    private fun executePaginationTask(direction: Timeline.Direction, limit: Int) {
         val token = getTokenLive(direction) ?: return
         val params = PaginationTask.Params(roomId = roomId,
                 from = token,
@@ -367,7 +367,7 @@ internal class DefaultTimeline(
                         } else {
                             // Database won't be updated, so we force pagination request
                             backgroundHandler.get()?.post {
-                                executePaginationTask @Inject constructor(direction, limit)
+                                executePaginationTask(direction, limit)
                             }
                         }
                     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt
index 9ac5fce3..e791ba76 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt
@@ -20,8 +20,11 @@ import arrow.core.Try
 import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.internal.task.Task
 import im.vector.matrix.android.internal.network.executeRequest
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.room.RoomAPI
+import javax.inject.Inject
 
+@SessionScope
 internal class GetEventTask @Inject constructor(private val roomAPI: RoomAPI
 ) : Task {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
index 7e2fbc85..63df5a03 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
@@ -16,16 +16,34 @@
 
 package im.vector.matrix.android.internal.session.signout
 
+import dagger.Binds
 import dagger.Module
+import dagger.Provides
+import im.vector.matrix.android.api.session.signout.SignOutService
 import im.vector.matrix.android.internal.session.SessionScope
+import im.vector.matrix.android.internal.session.user.DefaultUpdateUserTask
+import im.vector.matrix.android.internal.session.user.UpdateUserTask
 import retrofit2.Retrofit
 
 @Module
-internal class SignOutModule {
+internal abstract class SignOutModule {
 
-    @SessionScope
-    fun providesSignOutAPI(retrofit: Retrofit): SignOutAPI {
-        return retrofit.create(SignOutAPI::class.java)
+    @Module
+    companion object {
+        @SessionScope
+        @Provides
+        @JvmStatic
+        fun providesSignOutAPI(retrofit: Retrofit): SignOutAPI {
+            return retrofit.create(SignOutAPI::class.java)
+        }
     }
 
+    @Binds
+    @SessionScope
+    abstract fun bindSignOutTask(signOutTask: DefaultSignOutTask): SignOutTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindSignOutService(signOutService: DefaultSignOutService): SignOutService
+
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
index 4e12ccd8..cd8b7605 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
@@ -16,16 +16,28 @@
 
 package im.vector.matrix.android.internal.session.sync
 
+import dagger.Binds
 import dagger.Module
+import dagger.Provides
 import im.vector.matrix.android.internal.session.SessionScope
+import im.vector.matrix.android.internal.session.user.DefaultUpdateUserTask
+import im.vector.matrix.android.internal.session.user.UpdateUserTask
 import retrofit2.Retrofit
 
 @Module
-internal class SyncModule {
+internal abstract class SyncModule {
 
-    @SessionScope
-    fun providesSyncAPI(retrofit: Retrofit): SyncAPI {
-        return retrofit.create(SyncAPI::class.java)
+    @Module
+    companion object {
+        @SessionScope
+        @Provides
+        @JvmStatic
+        fun providesSyncAPI(retrofit: Retrofit): SyncAPI {
+            return retrofit.create(SyncAPI::class.java)
+        }
     }
 
+    @Binds
+    abstract fun bindSyncTask(syncTask: DefaultSyncTask): SyncTask
+
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt
new file mode 100644
index 00000000..00714c77
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt
@@ -0,0 +1,37 @@
+/*
+ *
+ *  * 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.matrix.android.internal.session.user
+
+import dagger.Binds
+import dagger.Module
+import im.vector.matrix.android.api.session.user.UserService
+import im.vector.matrix.android.internal.session.SessionScope
+
+@Module
+internal abstract class UserModule {
+
+    @Binds
+    @SessionScope
+    abstract fun bindUserService(userService: DefaultUserService): UserService
+
+    @Binds
+    @SessionScope
+    abstract fun bindUpdateUserTask(updateUserTask: DefaultUpdateUserTask): UpdateUserTask
+
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DI.kt
new file mode 100644
index 00000000..ec0d0866
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DI.kt
@@ -0,0 +1,71 @@
+/*
+ *
+ *  * 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.matrix.android.internal.worker
+
+import androidx.work.ListenableWorker
+import dagger.Binds
+import dagger.MapKey
+import dagger.Module
+import dagger.multibindings.IntoMap
+import im.vector.matrix.android.internal.session.content.UploadContentWorker
+import im.vector.matrix.android.internal.session.group.GetGroupDataWorker
+import im.vector.matrix.android.internal.session.room.relation.SendRelationWorker
+import im.vector.matrix.android.internal.session.room.send.EncryptEventWorker
+import im.vector.matrix.android.internal.session.room.send.RedactEventWorker
+import im.vector.matrix.android.internal.session.room.send.SendEventWorker
+import kotlin.reflect.KClass
+
+@MapKey
+@Target(AnnotationTarget.FUNCTION)
+@Retention(AnnotationRetention.RUNTIME)
+internal annotation class WorkerKey(val value: KClass)
+
+@Module
+internal interface WorkerBindingModule {
+
+    @Binds
+    @IntoMap
+    @WorkerKey(SendEventWorker::class)
+    fun bindSendEventWorker(factory: SendEventWorker.Factory): DelegateWorkerFactory
+
+    @Binds
+    @IntoMap
+    @WorkerKey(SendRelationWorker::class)
+    fun bindSendRelationWorker(factory: SendRelationWorker.Factory): DelegateWorkerFactory
+
+    @Binds
+    @IntoMap
+    @WorkerKey(EncryptEventWorker::class)
+    fun bindEncryptEventWorker(factory: EncryptEventWorker.Factory): DelegateWorkerFactory
+
+    @Binds
+    @IntoMap
+    @WorkerKey(RedactEventWorker::class)
+    fun bindRedactEventWorker(factory: RedactEventWorker.Factory): DelegateWorkerFactory
+
+    @Binds
+    @IntoMap
+    @WorkerKey(GetGroupDataWorker::class)
+    fun bindGetGroupDataWorker(factory: GetGroupDataWorker.Factory): DelegateWorkerFactory
+
+    @Binds
+    @IntoMap
+    @WorkerKey(UploadContentWorker::class)
+    fun bindUploadContentWorker(factory: UploadContentWorker.Factory): DelegateWorkerFactory
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DelegateWorkerFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DelegateWorkerFactory.kt
new file mode 100644
index 00000000..cb0c7580
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DelegateWorkerFactory.kt
@@ -0,0 +1,29 @@
+/*
+ *
+ *  * 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.matrix.android.internal.worker
+
+import android.content.Context
+import androidx.work.ListenableWorker
+import androidx.work.WorkerParameters
+
+interface DelegateWorkerFactory {
+
+    fun create(appContext: Context, workerParameters: WorkerParameters): ListenableWorker
+
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/MatrixWorkerFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/MatrixWorkerFactory.kt
new file mode 100644
index 00000000..63d5836b
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/MatrixWorkerFactory.kt
@@ -0,0 +1,45 @@
+/*
+ *
+ *  * 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.matrix.android.internal.worker
+
+import android.content.Context
+import androidx.work.ListenableWorker
+import androidx.work.WorkerFactory
+import androidx.work.WorkerParameters
+import im.vector.matrix.android.internal.di.MatrixScope
+import javax.inject.Inject
+import javax.inject.Provider
+
+@MatrixScope
+class MatrixWorkerFactory @Inject constructor(
+        private val workerFactories: Map, @JvmSuppressWildcards Provider>
+) : WorkerFactory() {
+
+    override fun createWorker(
+            appContext: Context,
+            workerClassName: String,
+            workerParameters: WorkerParameters
+    ): ListenableWorker? {
+        val foundEntry =
+                workerFactories.entries.find { Class.forName(workerClassName).isAssignableFrom(it.key) }
+        val factoryProvider = foundEntry?.value
+                ?: throw IllegalArgumentException("unknown worker class name: $workerClassName")
+        return factoryProvider.get().create(appContext, workerParameters)
+    }
+}

From c2c2d0b21e12b73a2a8444f53fdfbf9843190c92 Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Mon, 17 Jun 2019 18:17:37 +0200
Subject: [PATCH 03/11] Dagger: make SDK DI working

---
 .../im/vector/matrix/android/api/Matrix.kt    |   4 +
 .../matrix/android/internal/SessionManager.kt |  24 +-
 .../android/internal/auth/AuthModule.kt       |  12 +-
 .../internal/auth/DefaultAuthenticator.kt     |   4 +-
 .../auth/db/RealmSessionParamsStore.kt        |   6 +-
 .../android/internal/crypto/CryptoManager.kt  |   3 +-
 .../android/internal/crypto/CryptoModule.kt   | 220 +++++++++++++++---
 .../android/internal/di/DbQualifiers.kt       |  31 +++
 .../internal/di/MatrixAssistedInjectModule.kt |  26 ---
 .../internal/di/MatrixAssistedModule.kt       |  24 ++
 .../android/internal/di/MatrixComponent.kt    |  27 ++-
 .../android/internal/di/MatrixModule.kt       |  26 ++-
 .../android/internal/di/NetworkModule.kt      |  16 +-
 .../internal/session/DefaultSession.kt        |  41 ++--
 .../internal/session/SessionComponent.kt      |  37 +--
 .../android/internal/session/SessionModule.kt | 116 +++++----
 .../internal/session/cache/CacheModule.kt     |  19 +-
 ...almClearCacheTask.kt => ClearCacheTask.kt} |   3 +-
 .../session/cache/DefaultCacheService.kt      |   3 +-
 .../session/content/UploadContentWorker.kt    |   2 +-
 .../session/filter/DefaultFilterRepository.kt |   5 +-
 .../session/group/GetGroupDataWorker.kt       |  12 +-
 .../session/group/GroupSummaryUpdater.kt      |   2 +-
 .../internal/session/room/RoomModule.kt       |   6 +
 .../session/room/create/CreateRoomTask.kt     |   3 +-
 .../session/room/prune/EventsPruner.kt        |   3 +-
 .../room/relation/DefaultRelationService.kt   |   4 +-
 .../room/relation/SendRelationWorker.kt       |   2 +-
 .../session/room/send/DefaultSendService.kt   |   2 +-
 .../session/room/send/EncryptEventWorker.kt   |   4 +-
 .../session/room/send/RedactEventWorker.kt    |   4 +-
 .../session/room/send/SendEventWorker.kt      |   2 +-
 .../session/sync/ReadReceiptHandler.kt        |   3 +-
 .../internal/session/sync/SyncTokenStore.kt   |   3 +-
 .../android/internal/task/TaskExecutor.kt     |  15 +-
 .../util/BackgroundDetectionObserver.kt       |   5 +-
 .../android/internal/util/StringProvider.kt   |   3 +-
 .../internal/worker/DelegateWorkerFactory.kt  |   2 +-
 .../internal/worker/MatrixWorkerFactory.kt    |   1 -
 .../worker/{DI.kt => WorkerBindingModule.kt}  |   7 -
 .../android/internal/worker/WorkerKey.kt      |  26 +++
 .../{util => worker}/WorkerParamsFactory.kt   |   2 +-
 42 files changed, 544 insertions(+), 216 deletions(-)
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/DbQualifiers.kt
 delete mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedInjectModule.kt
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedModule.kt
 rename matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/{RealmClearCacheTask.kt => ClearCacheTask.kt} (88%)
 rename matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/{DI.kt => WorkerBindingModule.kt} (89%)
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerKey.kt
 rename matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/{util => worker}/WorkerParamsFactory.kt (96%)

diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
index 9f990889..c4d128ea 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
@@ -22,8 +22,10 @@ import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.api.auth.Authenticator
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.sync.FilterService
+import im.vector.matrix.android.internal.di.DaggerMatrixComponent
 import im.vector.matrix.android.internal.network.UserAgentHolder
 import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
+import org.matrix.olm.OlmManager
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
 
@@ -34,6 +36,7 @@ import javax.inject.Inject
  */
 class Matrix private constructor(context: Context) {
 
+    @Inject internal lateinit var olmManager: OlmManager
     @Inject internal lateinit var authenticator: Authenticator
     @Inject internal lateinit var userAgentHolder: UserAgentHolder
     @Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
@@ -41,6 +44,7 @@ class Matrix private constructor(context: Context) {
 
     init {
         Monarchy.init(context)
+        DaggerMatrixComponent.factory().create(context).inject(this)
         ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
         authenticator.getLastActiveSession()?.also {
             currentSession = it
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
index b46e4b78..74124bba 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
@@ -18,25 +18,41 @@
 
 package im.vector.matrix.android.internal
 
+import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.api.session.Session
+import im.vector.matrix.android.internal.di.MatrixComponent
 import im.vector.matrix.android.internal.di.MatrixScope
+import im.vector.matrix.android.internal.session.DaggerSessionComponent
 import im.vector.matrix.android.internal.session.SessionComponent
 import javax.inject.Inject
 
 @MatrixScope
-internal class SessionManager @Inject constructor() {
+internal class SessionManager @Inject constructor(private val matrixComponent: MatrixComponent) {
 
     private val sessionComponents = HashMap()
-    private val sessions = HashMap()
 
-    fun createSession(userId: String): Session? {
+    fun createSession(sessionParams: SessionParams): Session {
+        val userId = sessionParams.credentials.userId
         if (sessionComponents.containsKey(userId)) {
             throw RuntimeException("You already have a session for the user $userId")
         }
-        return null
+        return DaggerSessionComponent
+                .factory()
+                .create(matrixComponent, sessionParams)
+                .also {
+                    sessionComponents[userId] = it
+                }.let {
+                    it.session()
+                }
     }
 
     fun releaseSession(userId: String) {
+        if (sessionComponents.containsKey(userId).not()) {
+            throw RuntimeException("You don't have a session for the user $userId")
+        }
+        sessionComponents.remove(userId)?.also {
+            it.session().close()
+        }
     }
 
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
index 1e11a3c3..2f774647 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
@@ -20,24 +20,23 @@ import android.content.Context
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
+import im.vector.matrix.android.api.auth.Authenticator
 import im.vector.matrix.android.internal.auth.db.AuthRealmModule
 import im.vector.matrix.android.internal.auth.db.RealmSessionParamsStore
+import im.vector.matrix.android.internal.di.AuthDatabase
 import im.vector.matrix.android.internal.di.MatrixScope
-import im.vector.matrix.android.internal.session.SessionScope
-import im.vector.matrix.android.internal.session.cache.ClearCacheTask
-import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask
 import io.realm.RealmConfiguration
 import java.io.File
-import javax.inject.Named
 
 @Module
 internal abstract class AuthModule {
 
     @Module
     companion object {
+        @JvmStatic
         @Provides
         @MatrixScope
-        @Named("AuthRealmConfiguration")
+        @AuthDatabase
         fun providesRealmConfiguration(context: Context): RealmConfiguration {
             val old = File(context.filesDir, "matrix-sdk-auth")
             if (old.exists()) {
@@ -55,5 +54,8 @@ internal abstract class AuthModule {
     @MatrixScope
     abstract fun bindSessionParamsStore(sessionParamsStore: RealmSessionParamsStore): SessionParamsStore
 
+    @Binds
+    @MatrixScope
+    abstract fun bindAuthenticator(authenticator: DefaultAuthenticator): Authenticator
 
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
index 4acd9800..56571fa8 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
@@ -51,7 +51,7 @@ internal class DefaultAuthenticator @Inject constructor(private val retrofitBuil
     override fun getLastActiveSession(): Session? {
         val sessionParams = sessionParamsStore.get()
         return sessionParams?.let {
-            sessionManager.createSession(it.credentials.userId)
+            sessionManager.createSession(it)
         }
     }
 
@@ -85,7 +85,7 @@ internal class DefaultAuthenticator @Inject constructor(private val retrofitBuil
             sessionParamsStore.save(sessionParams)
             sessionParams
         }.map {
-            sessionManager.createSession(it.credentials.userId)!!
+            sessionManager.createSession(it)
         }
 
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
index 94b86a18..3b742e65 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
@@ -19,16 +19,16 @@ package im.vector.matrix.android.internal.auth.db
 import arrow.core.Try
 import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.internal.auth.SessionParamsStore
+import im.vector.matrix.android.internal.di.AuthDatabase
 import im.vector.matrix.android.internal.di.MatrixScope
 import io.realm.Realm
 import io.realm.RealmConfiguration
 import javax.inject.Inject
-import javax.inject.Named
 
 @MatrixScope
 internal class RealmSessionParamsStore @Inject constructor(private val mapper: SessionParamsMapper,
-                                                           @Named("AuthRealmConfiguration")
-                                                           private val realmConfiguration: RealmConfiguration) : SessionParamsStore {
+                                                           @AuthDatabase private val realmConfiguration: RealmConfiguration
+) : SessionParamsStore {
 
     override fun save(sessionParams: SessionParams): Try {
         return Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt
index 8b60b5c0..4c011bfd 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt
@@ -60,6 +60,7 @@ import im.vector.matrix.android.internal.crypto.tasks.GetDevicesTask
 import im.vector.matrix.android.internal.crypto.tasks.SetDeviceNameTask
 import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask
 import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
+import im.vector.matrix.android.internal.di.CryptoDatabase
 import im.vector.matrix.android.internal.database.model.EventEntity
 import im.vector.matrix.android.internal.database.query.where
 import im.vector.matrix.android.internal.di.MoshiProvider
@@ -132,7 +133,7 @@ internal class CryptoManager @Inject constructor(
         private val setDeviceNameTask: SetDeviceNameTask,
         private val uploadKeysTask: UploadKeysTask,
         private val loadRoomMembersTask: LoadRoomMembersTask,
-        private val clearCryptoDataTask: ClearCacheTask,
+        @CryptoDatabase private val clearCryptoDataTask: ClearCacheTask,
         private val monarchy: Monarchy,
         private val coroutineDispatchers: MatrixCoroutineDispatchers,
         private val taskExecutor: TaskExecutor
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
index acb8045d..ccaa6c56 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
@@ -17,65 +17,219 @@
 package im.vector.matrix.android.internal.crypto
 
 import android.content.Context
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
 import im.vector.matrix.android.api.auth.data.Credentials
+import im.vector.matrix.android.api.session.crypto.CryptoService
 import im.vector.matrix.android.internal.crypto.api.CryptoApi
 import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultCreateKeysBackupVersionTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteBackupTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteRoomSessionDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteRoomSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetKeysBackupLastVersionTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetKeysBackupVersionTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetRoomSessionDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetRoomSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreRoomSessionDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreRoomSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultUpdateKeysBackupVersionTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteBackupTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteRoomSessionDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteRoomSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetKeysBackupLastVersionTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetKeysBackupVersionTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetRoomSessionDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetRoomSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreRoomSessionDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreSessionsDataTask
+import im.vector.matrix.android.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask
 import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
 import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore
 import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreMigration
 import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
 import im.vector.matrix.android.internal.crypto.store.db.hash
+import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
+import im.vector.matrix.android.internal.crypto.tasks.DefaultClaimOneTimeKeysForUsersDevice
+import im.vector.matrix.android.internal.crypto.tasks.DefaultDeleteDeviceTask
+import im.vector.matrix.android.internal.crypto.tasks.DefaultDownloadKeysForUsers
+import im.vector.matrix.android.internal.crypto.tasks.DefaultGetDevicesTask
+import im.vector.matrix.android.internal.crypto.tasks.DefaultSendToDeviceTask
+import im.vector.matrix.android.internal.crypto.tasks.DefaultSetDeviceNameTask
+import im.vector.matrix.android.internal.crypto.tasks.DefaultUploadKeysTask
+import im.vector.matrix.android.internal.crypto.tasks.DeleteDeviceTask
+import im.vector.matrix.android.internal.crypto.tasks.DownloadKeysForUsersTask
+import im.vector.matrix.android.internal.crypto.tasks.GetDevicesTask
+import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
+import im.vector.matrix.android.internal.crypto.tasks.SetDeviceNameTask
+import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask
+import im.vector.matrix.android.internal.di.CryptoDatabase
 import im.vector.matrix.android.internal.session.SessionScope
+import im.vector.matrix.android.internal.session.cache.ClearCacheTask
+import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask
 import io.realm.RealmConfiguration
 import retrofit2.Retrofit
 import java.io.File
-import javax.inject.Named
 
 @Module
-internal class CryptoModule {
+internal abstract class CryptoModule {
+
+    @Module
+    companion object {
+
+        // Realm configuration, named to avoid clash with main cache realm configuration
+        @JvmStatic
+        @Provides
+        @SessionScope
+        @CryptoDatabase
+        fun providesRealmConfiguration(context: Context, credentials: Credentials): RealmConfiguration {
+            return RealmConfiguration.Builder()
+                    .directory(File(context.filesDir, credentials.userId.hash()))
+                    .name("crypto_store.realm")
+                    .modules(RealmCryptoStoreModule())
+                    .schemaVersion(RealmCryptoStoreMigration.CRYPTO_STORE_SCHEMA_VERSION)
+                    .migration(RealmCryptoStoreMigration)
+                    .build()
+        }
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        @CryptoDatabase
+        fun providesClearCacheTask(@CryptoDatabase realmConfiguration: RealmConfiguration): ClearCacheTask {
+            return RealmClearCacheTask(realmConfiguration)
+        }
+
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesCryptoStore(@CryptoDatabase realmConfiguration: RealmConfiguration, credentials: Credentials): IMXCryptoStore {
+            return RealmCryptoStore(false /* TODO*/,
+                                    realmConfiguration,
+                                    credentials)
+        }
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesCryptoAPI(retrofit: Retrofit): CryptoApi {
+            return retrofit.create(CryptoApi::class.java)
+        }
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesRoomKeysAPI(retrofit: Retrofit): RoomKeysApi {
+            return retrofit.create(RoomKeysApi::class.java)
+        }
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesCryptoConfig(): MXCryptoConfig {
+            return MXCryptoConfig()
+        }
 
-    // Realm configuration, named to avoid clash with main cache realm configuration
-    @Provides
-    @SessionScope
-    @Named("CryptonRealmConfiguration")
-    fun providesRealmConfiguration(context: Context, credentials: Credentials): RealmConfiguration {
-        return RealmConfiguration.Builder()
-                .directory(File(context.filesDir, credentials.userId.hash()))
-                .name("crypto_store.realm")
-                .modules(RealmCryptoStoreModule())
-                .schemaVersion(RealmCryptoStoreMigration.CRYPTO_STORE_SCHEMA_VERSION)
-                .migration(RealmCryptoStoreMigration)
-                .build()
     }
 
-    @Provides
+    @Binds
     @SessionScope
-    fun providesCryptoStore(@Named("CryptonRealmConfiguration")
-                            realmConfiguration: RealmConfiguration, credentials: Credentials): IMXCryptoStore {
-        return RealmCryptoStore(false /* TODO*/,
-                realmConfiguration,
-                credentials)
-    }
+    abstract fun bindCryptoService(cryptoManager: CryptoManager): CryptoService
 
-    @Provides
+    @Binds
     @SessionScope
-    fun providesCryptoAPI(retrofit: Retrofit): CryptoApi {
-        return retrofit.create(CryptoApi::class.java)
-    }
+    abstract fun bindDeleteDeviceTask(deleteDeviceTask: DefaultDeleteDeviceTask): DeleteDeviceTask
 
-    @Provides
+    @Binds
     @SessionScope
-    fun providesRoomKeysAPI(retrofit: Retrofit): RoomKeysApi {
-        return retrofit.create(RoomKeysApi::class.java)
-    }
+    abstract fun bindGetDevicesTask(getDevicesTask: DefaultGetDevicesTask): GetDevicesTask
 
-    @Provides
+    @Binds
     @SessionScope
-    fun providesCryptoConfig(): MXCryptoConfig {
-        return MXCryptoConfig()
-    }
+    abstract fun bindSetDeviceNameTask(getDevicesTask: DefaultSetDeviceNameTask): SetDeviceNameTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindUploadKeysTask(getDevicesTask: DefaultUploadKeysTask): UploadKeysTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindDownloadKeysForUsersTask(downloadKeysForUsers: DefaultDownloadKeysForUsers): DownloadKeysForUsersTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindCreateKeysBackupVersionTask(createKeysBackupVersionTask: DefaultCreateKeysBackupVersionTask): CreateKeysBackupVersionTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindDeleteBackupTask(deleteBackupTask: DefaultDeleteBackupTask): DeleteBackupTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindDeleteRoomSessionDataTask(deleteRoomSessionDataTask: DefaultDeleteRoomSessionDataTask): DeleteRoomSessionDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindDeleteRoomSessionsDataTask(deleteRoomSessionDataTask: DefaultDeleteRoomSessionsDataTask): DeleteRoomSessionsDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindDeleteSessionsDataTask(deleteRoomSessionDataTask: DefaultDeleteSessionsDataTask): DeleteSessionsDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetKeysBackupLastVersionTask(getKeysBackupLastVersionTask: DefaultGetKeysBackupLastVersionTask): GetKeysBackupLastVersionTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetKeysBackupVersionTask(getKeysBackupVersionTask: DefaultGetKeysBackupVersionTask) : GetKeysBackupVersionTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetRoomSessionDataTask(getRoomSessionDataTask: DefaultGetRoomSessionDataTask) : GetRoomSessionDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetRoomSessionsDataTask(getRoomSessionDataTask: DefaultGetRoomSessionsDataTask) : GetRoomSessionsDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindGetSessionsDataTask(getRoomSessionDataTask: DefaultGetSessionsDataTask) : GetSessionsDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindStoreRoomSessionDataTask(storeRoomSessionDataTask: DefaultStoreRoomSessionDataTask) : StoreRoomSessionDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindStoreRoomSessionsDataTask(storeRoomSessionDataTask: DefaultStoreRoomSessionsDataTask) : StoreRoomSessionsDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindStoreSessionsDataTask(storeRoomSessionDataTask: DefaultStoreSessionsDataTask) : StoreSessionsDataTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindUpdateKeysBackupVersionTask(updateKeysBackupVersionTask: DefaultUpdateKeysBackupVersionTask) : UpdateKeysBackupVersionTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindSendToDeviceTask(sendToDeviceTask: DefaultSendToDeviceTask) : SendToDeviceTask
+
+    @Binds
+    @SessionScope
+    abstract fun bindClaimOneTimeKeysForUsersDeviceTask(claimOneTimeKeysForUsersDevice: DefaultClaimOneTimeKeysForUsersDevice) : ClaimOneTimeKeysForUsersDeviceTask
+
+
 
 
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/DbQualifiers.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/DbQualifiers.kt
new file mode 100644
index 00000000..ac9a30a3
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/DbQualifiers.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.matrix.android.internal.di
+
+import javax.inject.Qualifier
+
+@Qualifier
+@Retention(AnnotationRetention.RUNTIME)
+annotation class AuthDatabase
+
+@Qualifier
+@Retention(AnnotationRetention.RUNTIME)
+annotation class SessionDatabase
+
+@Qualifier
+@Retention(AnnotationRetention.RUNTIME)
+annotation class CryptoDatabase
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedInjectModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedInjectModule.kt
deleted file mode 100644
index 8f5723d0..00000000
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedInjectModule.kt
+++ /dev/null
@@ -1,26 +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.matrix.android.internal.di
-
-import com.squareup.inject.assisted.dagger2.AssistedModule
-import dagger.Module
-
-@Module(includes = [AssistedInject_MatrixAssistedInjectModule::class])
-@AssistedModule
-internal interface MatrixAssistedInjectModule
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedModule.kt
new file mode 100644
index 00000000..ce1804cb
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedModule.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.matrix.android.internal.di
+
+import com.squareup.inject.assisted.dagger2.AssistedModule
+import dagger.Module
+
+@Module(includes = [AssistedInject_MatrixAssistedModule::class])
+@AssistedModule
+internal class MatrixAssistedModule
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
index aa91eadc..8517a4b3 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
@@ -17,17 +17,24 @@
 package im.vector.matrix.android.internal.di
 
 import android.content.Context
+import android.content.res.Resources
 import com.squareup.moshi.Moshi
 import dagger.BindsInstance
 import dagger.Component
+import im.vector.matrix.android.api.Matrix
+import im.vector.matrix.android.api.auth.Authenticator
 import im.vector.matrix.android.internal.auth.AuthModule
+import im.vector.matrix.android.internal.auth.SessionParamsStore
+import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
+import im.vector.matrix.android.internal.task.TaskExecutor
+import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
 import im.vector.matrix.android.internal.worker.WorkerBindingModule
+import org.matrix.olm.OlmManager
 import retrofit2.Retrofit
-import java.net.Authenticator
 
 
-@Component(modules = [MatrixModule::class, NetworkModule::class, AuthModule::class])
+@Component(modules = [MatrixModule::class, NetworkModule::class, AuthModule::class, WorkerBindingModule::class])
 @MatrixScope
 internal interface MatrixComponent {
 
@@ -39,6 +46,22 @@ internal interface MatrixComponent {
 
     fun authenticator(): Authenticator
 
+    fun context(): Context
+
+    fun resources(): Resources
+
+    fun olmManager(): OlmManager
+
+    fun taskExecutor(): TaskExecutor
+
+    fun sessionParamsStore(): SessionParamsStore
+
+    fun networkConnectivityChecker(): NetworkConnectivityChecker
+
+    fun backgroundDetectionObserver(): BackgroundDetectionObserver
+
+    fun inject(matrix: Matrix)
+
     @Component.Factory
     interface Factory {
         fun create(@BindsInstance context: Context): MatrixComponent
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt
index b2bbefd5..a409c3d9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt
@@ -16,25 +16,43 @@
 
 package im.vector.matrix.android.internal.di
 
+import android.content.Context
+import android.content.res.Resources
 import dagger.Module
 import dagger.Provides
 import im.vector.matrix.android.internal.crypto.CryptoAsyncHelper
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.android.asCoroutineDispatcher
+import org.matrix.olm.OlmManager
 
 @Module
-internal class MatrixModule {
+internal object MatrixModule {
 
+    @JvmStatic
     @Provides
     @MatrixScope
     fun providesMatrixCoroutineDispatchers(): MatrixCoroutineDispatchers {
         val cryptoHandler = CryptoAsyncHelper.getDecryptBackgroundHandler()
         return MatrixCoroutineDispatchers(io = Dispatchers.IO,
-                computation = Dispatchers.IO,
-                main = Dispatchers.Main,
-                crypto = cryptoHandler.asCoroutineDispatcher("crypto")
+                                          computation = Dispatchers.IO,
+                                          main = Dispatchers.Main,
+                                          crypto = cryptoHandler.asCoroutineDispatcher("crypto")
         )
     }
 
+    @JvmStatic
+    @Provides
+    @MatrixScope
+    fun providesResources(context: Context): Resources {
+        return context.resources
+    }
+
+    @JvmStatic
+    @Provides
+    @MatrixScope
+    fun providesOlmManager(): OlmManager {
+        return OlmManager()
+    }
+
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt
index b11e5a1e..ed99dad3 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt
@@ -34,10 +34,11 @@ import retrofit2.converter.moshi.MoshiConverterFactory
 import java.util.concurrent.TimeUnit
 
 @Module
-internal class NetworkModule {
+internal object NetworkModule {
 
     @MatrixScope
     @Provides
+    @JvmStatic
     fun providesHttpLogingInterceptor(): HttpLoggingInterceptor {
         val logger = FormattedJsonHttpLogger()
         val interceptor = HttpLoggingInterceptor(logger)
@@ -47,18 +48,28 @@ internal class NetworkModule {
 
     @MatrixScope
     @Provides
+    @JvmStatic
     fun providesOkReplayInterceptor(): OkReplayInterceptor {
         return OkReplayInterceptor()
     }
 
     @MatrixScope
     @Provides
+    @JvmStatic
     fun providesStethoInterceptor(): StethoInterceptor {
         return StethoInterceptor()
     }
 
     @MatrixScope
     @Provides
+    @JvmStatic
+    fun providesCurlLoggingInterceptor(): CurlLoggingInterceptor {
+        return CurlLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT)
+    }
+
+    @MatrixScope
+    @Provides
+    @JvmStatic
     fun providesOkHttpClient(stethoInterceptor: StethoInterceptor,
                              userAgentInterceptor: UserAgentInterceptor,
                              accessTokenInterceptor: AccessTokenInterceptor,
@@ -84,11 +95,14 @@ internal class NetworkModule {
 
     @MatrixScope
     @Provides
+    @JvmStatic
     fun providesMoshi(): Moshi {
         return MoshiProvider.providesMoshi()
     }
 
+    @MatrixScope
     @Provides
+    @JvmStatic
     fun providesRetrofitBuilder(okHttpClient: OkHttpClient,
                                 moshi: Moshi): Retrofit.Builder {
         return Retrofit.Builder()
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
index ec272083..fcc3d5bb 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
@@ -19,8 +19,6 @@ package im.vector.matrix.android.internal.session
 import android.os.Looper
 import androidx.annotation.MainThread
 import androidx.lifecycle.LiveData
-import com.squareup.inject.assisted.Assisted
-import com.squareup.inject.assisted.AssistedInject
 import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.auth.data.SessionParams
@@ -41,23 +39,23 @@ import im.vector.matrix.android.internal.crypto.CryptoManager
 import im.vector.matrix.android.internal.database.LiveEntityObserver
 import im.vector.matrix.android.internal.session.sync.job.SyncThread
 import timber.log.Timber
+import javax.inject.Inject
 
 @SessionScope
-internal class DefaultSession @AssistedInject constructor(@Assisted override val sessionParams: SessionParams,
-                                                          private val monarchy: Monarchy,
-                                                          private val liveEntityUpdaters: List,
-                                                          private val sessionListeners: SessionListeners,
-                                                          private val roomService: RoomService,
-                                                          private val roomDirectoryService: RoomDirectoryService,
-                                                          private val groupService: GroupService,
-                                                          private val userService: UserService,
-                                                          private val filterService: FilterService,
-                                                          private val cacheService: CacheService,
-                                                          private val signOutService: SignOutService,
-                                                          private val cryptoService: CryptoManager,
-                                                          private val syncThread: SyncThread,
-                                                          private val contentUrlResolver: ContentUrlResolver,
-                                                          private val contentUploadProgressTracker: ContentUploadStateTracker)
+internal class DefaultSession @Inject constructor(override val sessionParams: SessionParams,
+                                                  private val monarchy: Monarchy,
+                                                  private val sessionListeners: SessionListeners,
+                                                  private val roomService: RoomService,
+                                                  private val roomDirectoryService: RoomDirectoryService,
+                                                  private val groupService: GroupService,
+                                                  private val userService: UserService,
+                                                  private val filterService: FilterService,
+                                                  private val cacheService: CacheService,
+                                                  private val signOutService: SignOutService,
+                                                  private val cryptoService: CryptoManager,
+                                                  private val syncThread: SyncThread,
+                                                  private val contentUrlResolver: ContentUrlResolver,
+                                                  private val contentUploadProgressTracker: ContentUploadStateTracker)
     : Session,
       RoomService by roomService,
       RoomDirectoryService by roomDirectoryService,
@@ -68,11 +66,6 @@ internal class DefaultSession @AssistedInject constructor(@Assisted override val
       SignOutService by signOutService,
       FilterService by filterService {
 
-    @AssistedInject.Factory
-    interface Factory {
-        fun create(sessionParams: SessionParams): DefaultSession
-    }
-
     private var isOpen = false
 
     @MainThread
@@ -83,7 +76,7 @@ internal class DefaultSession @AssistedInject constructor(@Assisted override val
         if (!monarchy.isMonarchyThreadOpen) {
             monarchy.openManually()
         }
-        liveEntityUpdaters.forEach { it.start() }
+        //liveEntityObservers.forEach { it.start() }
     }
 
     @MainThread
@@ -102,7 +95,7 @@ internal class DefaultSession @AssistedInject constructor(@Assisted override val
     override fun close() {
         assertMainThread()
         assert(isOpen)
-        liveEntityUpdaters.forEach { it.dispose() }
+        //liveEntityObservers.forEach { it.dispose() }
         cryptoService.close()
         if (monarchy.isMonarchyThreadOpen) {
             monarchy.closeManually()
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
index 1283f3b0..96419e6e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
@@ -19,37 +19,40 @@ package im.vector.matrix.android.internal.session
 import dagger.BindsInstance
 import dagger.Component
 import im.vector.matrix.android.api.auth.data.SessionParams
+import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.internal.crypto.CryptoModule
-import im.vector.matrix.android.internal.di.MatrixAssistedInjectModule
+import im.vector.matrix.android.internal.di.MatrixAssistedModule
 import im.vector.matrix.android.internal.di.MatrixComponent
-import im.vector.matrix.android.internal.session.content.ContentModule
 import im.vector.matrix.android.internal.session.cache.CacheModule
+import im.vector.matrix.android.internal.session.content.ContentModule
 import im.vector.matrix.android.internal.session.filter.FilterModule
 import im.vector.matrix.android.internal.session.group.GroupModule
 import im.vector.matrix.android.internal.session.room.RoomModule
 import im.vector.matrix.android.internal.session.signout.SignOutModule
 import im.vector.matrix.android.internal.session.sync.SyncModule
-import im.vector.matrix.android.internal.worker.WorkerBindingModule
+import im.vector.matrix.android.internal.session.user.UserModule
 
 @Component(dependencies = [MatrixComponent::class],
-        modules = [
-            SessionModule::class,
-            RoomModule::class,
-            SyncModule::class,
-            SignOutModule::class,
-            GroupModule::class,
-            FilterModule::class,
-            GroupModule::class,
-            ContentModule::class,
-            CacheModule::class,
-            CryptoModule::class,
-            MatrixAssistedInjectModule::class,
-            WorkerBindingModule::class
-        ]
+           modules = [
+               SessionModule::class,
+               RoomModule::class,
+               SyncModule::class,
+               SignOutModule::class,
+               GroupModule::class,
+               UserModule::class,
+               FilterModule::class,
+               GroupModule::class,
+               ContentModule::class,
+               CacheModule::class,
+               CryptoModule::class,
+               MatrixAssistedModule::class
+           ]
 )
 @SessionScope
 internal interface SessionComponent {
 
+    fun session(): Session
+
     @Component.Factory
     interface Factory {
         fun create(
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
index e68cd809..4c5a2c0c 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
@@ -18,13 +18,17 @@ package im.vector.matrix.android.internal.session
 
 import android.content.Context
 import com.zhuinden.monarchy.Monarchy
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
+import dagger.multibindings.IntoSet
 import im.vector.matrix.android.api.auth.data.Credentials
+import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
 import im.vector.matrix.android.api.auth.data.SessionParams
+import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.internal.database.LiveEntityObserver
 import im.vector.matrix.android.internal.database.model.SessionRealmModule
-import im.vector.matrix.android.internal.session.filter.FilterApi
+import im.vector.matrix.android.internal.di.SessionDatabase
 import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
 import im.vector.matrix.android.internal.session.room.EventRelationsAggregationUpdater
 import im.vector.matrix.android.internal.session.room.prune.EventsPruner
@@ -33,62 +37,86 @@ import im.vector.matrix.android.internal.util.md5
 import io.realm.RealmConfiguration
 import retrofit2.Retrofit
 import java.io.File
-import javax.inject.Named
 
 @Module
-internal object SessionModule {
+internal abstract class SessionModule {
 
-    @Provides
-    @SessionScope
-    fun providesCredentials(sessionParams: SessionParams): Credentials {
-        return sessionParams.credentials
+    @Module
+    companion object {
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesHomeServerConnectionConfig(sessionParams: SessionParams): HomeServerConnectionConfig {
+            return sessionParams.homeServerConnectionConfig
+        }
+
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesCredentials(sessionParams: SessionParams): Credentials {
+            return sessionParams.credentials
+        }
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        @SessionDatabase
+        fun providesRealmConfiguration(sessionParams: SessionParams, context: Context): RealmConfiguration {
+            val childPath = sessionParams.credentials.userId.md5()
+            val directory = File(context.filesDir, childPath)
+
+            return RealmConfiguration.Builder()
+                    .directory(directory)
+                    .name("disk_store.realm")
+                    .modules(SessionRealmModule())
+                    .deleteRealmIfMigrationNeeded()
+                    .build()
+        }
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesMonarchy(@SessionDatabase
+                             realmConfiguration: RealmConfiguration): Monarchy {
+            return Monarchy.Builder()
+                    .setRealmConfiguration(realmConfiguration)
+                    .build()
+        }
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesRetrofit(sessionParams: SessionParams, retrofitBuilder: Retrofit.Builder): Retrofit {
+            return retrofitBuilder
+                    .baseUrl(sessionParams.homeServerConnectionConfig.homeServerUri.toString())
+                    .build()
+        }
     }
 
-    @Provides
+    @Binds
     @SessionScope
-    @Named("SessionRealmConfiguration")
-    fun providesRealmConfiguration(sessionParams: SessionParams, context: Context): RealmConfiguration {
-        val childPath = sessionParams.credentials.userId.md5()
-        val directory = File(context.filesDir, childPath)
+    abstract fun bindSession(session: DefaultSession): Session
 
-        return RealmConfiguration.Builder()
-                .directory(directory)
-                .name("disk_store.realm")
-                .modules(SessionRealmModule())
-                .deleteRealmIfMigrationNeeded()
-                .build()
-    }
-
-    @Provides
+    @Binds
+    @IntoSet
     @SessionScope
-    fun providesMonarchy(@Named("SessionRealmConfiguration")
-                         realmConfiguration: RealmConfiguration): Monarchy {
-        return Monarchy.Builder()
-                .setRealmConfiguration(realmConfiguration)
-                .build()
-    }
+    abstract fun bindGroupSummaryUpdater(groupSummaryUpdater: GroupSummaryUpdater): LiveEntityObserver
 
-    @Provides
+    @Binds
+    @IntoSet
     @SessionScope
-    fun providesRetrofit(sessionParams: SessionParams, retrofitBuilder: Retrofit.Builder): Retrofit {
-        return retrofitBuilder
-                .baseUrl(sessionParams.homeServerConnectionConfig.homeServerUri.toString())
-                .build()
-    }
+    abstract fun bindEventsPruner(eventsPruner: EventsPruner): LiveEntityObserver
 
-    @Provides
+    @Binds
+    @IntoSet
     @SessionScope
-    fun providesFilterAPI(retrofit: Retrofit): FilterApi {
-        return retrofit.create(FilterApi::class.java)
-    }
+    abstract fun bindEventRelationsAggregationUpdater(groupSummaryUpdater: EventRelationsAggregationUpdater): LiveEntityObserver
 
-    @Provides
+    @Binds
+    @IntoSet
     @SessionScope
-    fun providesLiveEntityObservers(groupSummaryUpdater: GroupSummaryUpdater,
-                                    userEntityUpdater: UserEntityUpdater,
-                                    aggregationUpdater: EventRelationsAggregationUpdater,
-                                    eventsPruner: EventsPruner): List {
-        return listOf(groupSummaryUpdater, userEntityUpdater, aggregationUpdater, eventsPruner)
-    }
+    abstract fun bindUserEntityUpdater(groupSummaryUpdater: UserEntityUpdater): LiveEntityObserver
 
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/CacheModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/CacheModule.kt
index 349dc246..e536e81b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/CacheModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/CacheModule.kt
@@ -20,19 +20,28 @@ package im.vector.matrix.android.internal.session.cache
 
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
 import im.vector.matrix.android.api.session.cache.CacheService
+import im.vector.matrix.android.internal.di.SessionDatabase
 import im.vector.matrix.android.internal.session.SessionScope
+import io.realm.RealmConfiguration
 
 @Module
 internal abstract class CacheModule {
 
+    @Module
+    companion object {
+        @JvmStatic
+        @Provides
+        @SessionScope
+        @SessionDatabase
+        fun providesClearCacheTask(@SessionDatabase realmConfiguration: RealmConfiguration): ClearCacheTask {
+            return RealmClearCacheTask(realmConfiguration)
+        }
+    }
+
     @Binds
     @SessionScope
     abstract fun bindCacheService(cacheService: DefaultCacheService): CacheService
 
-    @Binds
-    @SessionScope
-    abstract fun bindClearCacheTask(clearCacheTask: RealmClearCacheTask): ClearCacheTask
-
-
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/ClearCacheTask.kt
similarity index 88%
rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt
rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/ClearCacheTask.kt
index 67ed54dc..bb756d3b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/ClearCacheTask.kt
@@ -22,11 +22,12 @@ import im.vector.matrix.android.internal.task.Task
 import io.realm.Realm
 import io.realm.RealmConfiguration
 import javax.inject.Inject
+import javax.inject.Named
 
 internal interface ClearCacheTask : Task
 
 @SessionScope
-internal class RealmClearCacheTask @Inject constructor(val realmConfiguration: RealmConfiguration) : ClearCacheTask {
+internal class RealmClearCacheTask @Inject constructor(private val realmConfiguration: RealmConfiguration) : ClearCacheTask {
 
     override suspend fun execute(params: Unit): Try {
         return Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
index 7dcb24e9..d38e7cb2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
@@ -18,13 +18,14 @@ package im.vector.matrix.android.internal.session.cache
 
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.cache.CacheService
+import im.vector.matrix.android.internal.di.SessionDatabase
 import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
 import javax.inject.Inject
 
 @SessionScope
-internal class DefaultCacheService @Inject constructor(private val clearCacheTask: ClearCacheTask,
+internal class DefaultCacheService @Inject constructor(@SessionDatabase private val clearCacheTask: ClearCacheTask,
                                                        private val taskExecutor: TaskExecutor) : CacheService {
 
     override fun clearCache(callback: MatrixCallback) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
index ce5c8e58..30c4b629 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
@@ -34,7 +34,7 @@ import im.vector.matrix.android.api.session.room.model.message.MessageVideoConte
 import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.ProgressRequestBody
 import im.vector.matrix.android.internal.session.room.send.SendEventWorker
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import timber.log.Timber
 import java.io.File
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt
index 690db907..f08c769f 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt
@@ -16,6 +16,7 @@
 
 package im.vector.matrix.android.internal.session.filter
 
+import im.vector.matrix.android.internal.di.SessionDatabase
 import im.vector.matrix.android.internal.database.model.FilterEntity
 import im.vector.matrix.android.internal.database.model.FilterEntityFields
 import im.vector.matrix.android.internal.database.query.getFilter
@@ -26,7 +27,9 @@ import io.realm.kotlin.where
 import javax.inject.Inject
 
 @SessionScope
-internal class DefaultFilterRepository @Inject constructor(val realmConfiguration: RealmConfiguration) : FilterRepository {
+internal class DefaultFilterRepository @Inject constructor(
+        @SessionDatabase private val realmConfiguration: RealmConfiguration
+) : FilterRepository {
 
     override fun storeFilter(filterBody: FilterBody, roomEventFilter: RoomEventFilter): Boolean {
         val result: Boolean
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
index 4d35d0c7..1a07fd93 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
@@ -24,13 +24,16 @@ import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 
 internal class GetGroupDataWorker @AssistedInject constructor(
         @Assisted context: Context,
-        @Assisted workerParameters: WorkerParameters,
+        @Assisted params: WorkerParameters,
         private val getGroupDataTask: GetGroupDataTask
-) : CoroutineWorker(context, workerParameters) {
+) : CoroutineWorker(context, params) {
+
+    @AssistedInject.Factory
+    interface Factory : DelegateWorkerFactory
 
     @JsonClass(generateAdapter = true)
     internal data class Params(
@@ -52,7 +55,4 @@ internal class GetGroupDataWorker @AssistedInject constructor(
         return getGroupDataTask.execute(GetGroupDataTask.Params(groupId))
     }
 
-    @AssistedInject.Factory
-    interface Factory  : DelegateWorkerFactory
-
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
index f1306b76..81b56c08 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
@@ -26,7 +26,7 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
 import im.vector.matrix.android.internal.database.model.GroupEntity
 import im.vector.matrix.android.internal.database.query.where
 import im.vector.matrix.android.internal.session.SessionScope
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import javax.inject.Inject
 
 private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
index cc5e7aa8..48616570 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
@@ -50,7 +50,9 @@ import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkers
 import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
 import im.vector.matrix.android.internal.session.room.relation.*
 import im.vector.matrix.android.internal.session.room.send.DefaultSendService
+import im.vector.matrix.android.internal.session.room.state.DefaultSendStateTask
 import im.vector.matrix.android.internal.session.room.state.DefaultStateService
+import im.vector.matrix.android.internal.session.room.state.SendStateTask
 import im.vector.matrix.android.internal.session.room.timeline.*
 import retrofit2.Retrofit
 
@@ -135,6 +137,10 @@ internal abstract class RoomModule {
     @SessionScope
     abstract fun bindUpdateQuickReactionTask(updateQuickReactionTask: DefaultUpdateQuickReactionTask): UpdateQuickReactionTask
 
+    @Binds
+    @SessionScope
+    abstract fun bindSendStateTask(sendStateTask: DefaultSendStateTask): SendStateTask
+
     @Binds
     @SessionScope
     abstract fun bindSendService(sendService: DefaultSendService): SendService
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt
index a1f10c62..50c102d3 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt
@@ -20,6 +20,7 @@ import arrow.core.Try
 import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
 import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse
 import im.vector.matrix.android.internal.database.RealmQueryLatch
+import im.vector.matrix.android.internal.di.SessionDatabase
 import im.vector.matrix.android.internal.database.model.RoomEntity
 import im.vector.matrix.android.internal.database.model.RoomEntityFields
 import im.vector.matrix.android.internal.network.executeRequest
@@ -33,7 +34,7 @@ internal interface CreateRoomTask : Task
 
 @SessionScope
 internal class DefaultCreateRoomTask @Inject constructor(private val roomAPI: RoomAPI,
-                                                         private val realmConfiguration: RealmConfiguration) : CreateRoomTask {
+                                                         @SessionDatabase private val realmConfiguration: RealmConfiguration) : CreateRoomTask {
 
 
     override suspend fun execute(params: CreateRoomParams): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt
index 4b663d5a..a1bb65af 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt
@@ -44,8 +44,7 @@ internal class EventsPruner @Inject constructor(monarchy: Monarchy,
 
     override fun processChanges(inserted: List, updated: List, deleted: List) {
         Timber.v("Event pruner called with ${inserted.size} insertions")
-        val redactionEvents = inserted
-                .mapNotNull { it.asDomain() }
+        val redactionEvents = inserted.map { it.asDomain() }
 
         val params = PruneEventTask.Params(
                 redactionEvents,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
index a48a0ad6..7ae4e5df 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
@@ -31,7 +31,6 @@ import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryE
 import im.vector.matrix.android.internal.database.model.RoomEntity
 import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
 import im.vector.matrix.android.internal.database.query.where
-import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
 import im.vector.matrix.android.internal.session.room.send.RedactEventWorker
 import im.vector.matrix.android.internal.session.room.send.SendEventWorker
@@ -39,10 +38,9 @@ import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEvent
 import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
 import im.vector.matrix.android.internal.util.CancelableWork
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import im.vector.matrix.android.internal.util.tryTransactionAsync
 import timber.log.Timber
-import javax.inject.Inject
 
 internal class DefaultRelationService constructor(private val roomId: String,
                                                           private val eventFactory: LocalEchoEventFactory,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
index de32c6f8..dbd97714 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
@@ -30,7 +30,7 @@ import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
 import im.vector.matrix.android.internal.session.room.send.SendResponse
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 
 internal class SendRelationWorker @AssistedInject constructor(
         @Assisted context: Context,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
index 62239a74..12fee962 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
@@ -28,7 +28,7 @@ import im.vector.matrix.android.api.util.addTo
 import im.vector.matrix.android.internal.session.content.UploadContentWorker
 import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEventWorkCommon
 import im.vector.matrix.android.internal.util.CancelableWork
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import timber.log.Timber
 import java.util.concurrent.TimeUnit
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
index 70a9ddf0..256f3d16 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
@@ -28,7 +28,7 @@ import im.vector.matrix.android.api.session.crypto.CryptoService
 import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.room.send.SendState
 import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import java.util.concurrent.CountDownLatch
 
@@ -49,7 +49,7 @@ internal class EncryptEventWorker @AssistedInject constructor(
     override fun doWork(): Result {
 
         val params = WorkerParamsFactory.fromData(inputData)
-                ?: return Result.success()
+                     ?: return Result.success()
 
         val localEvent = params.event
         if (localEvent.eventId == null) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
index 0054329f..7d45a2a6 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
@@ -24,7 +24,7 @@ import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 
 internal class RedactEventWorker @AssistedInject constructor(
@@ -43,7 +43,7 @@ internal class RedactEventWorker @AssistedInject constructor(
 
     override fun doWork(): Result {
         val params = WorkerParamsFactory.fromData(inputData)
-                ?: return Result.failure()
+                     ?: return Result.failure()
 
         val eventId = params.eventId
         val result = executeRequest {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
index 790db2ce..6ff60da0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
@@ -28,7 +28,7 @@ import im.vector.matrix.android.api.session.room.send.SendState
 import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
-import im.vector.matrix.android.internal.util.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 
 internal class SendEventWorker @AssistedInject constructor(
         @Assisted context: Context,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
index a7af1e34..fafc75f0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
@@ -20,6 +20,7 @@ import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
 import im.vector.matrix.android.internal.session.SessionScope
 import io.realm.Realm
 import timber.log.Timber
+import javax.inject.Inject
 
 
 // the receipts dictionnaries
@@ -30,7 +31,7 @@ import timber.log.Timber
 typealias ReadReceiptContent = Map>>>
 
 @SessionScope
-internal class ReadReceiptHandler internal constructor() {
+internal class ReadReceiptHandler @Inject constructor() {
 
     fun handle(realm: Realm, roomId: String, content: ReadReceiptContent?) {
         if (content == null) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
index d9a00636..17ca1680 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
@@ -16,6 +16,7 @@
 
 package im.vector.matrix.android.internal.session.sync
 
+import im.vector.matrix.android.internal.di.SessionDatabase
 import im.vector.matrix.android.internal.database.model.SyncEntity
 import im.vector.matrix.android.internal.session.SessionScope
 import io.realm.Realm
@@ -23,7 +24,7 @@ import io.realm.RealmConfiguration
 import javax.inject.Inject
 
 @SessionScope
-internal class SyncTokenStore @Inject constructor(private val realmConfiguration: RealmConfiguration) {
+internal class SyncTokenStore @Inject constructor(@SessionDatabase private val realmConfiguration: RealmConfiguration) {
 
     fun getLastToken(): String? {
         val realm = Realm.getInstance(realmConfiguration)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
index 228e83ba..944b62ee 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
@@ -16,8 +16,10 @@
 
 package im.vector.matrix.android.internal.task
 
+
 import arrow.core.Try
 import im.vector.matrix.android.api.util.Cancelable
+import im.vector.matrix.android.internal.di.MatrixScope
 import im.vector.matrix.android.internal.util.CancelableCoroutine
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
 import kotlinx.coroutines.GlobalScope
@@ -26,10 +28,9 @@ import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import timber.log.Timber
 import javax.inject.Inject
-import javax.inject.Singleton
 import kotlin.coroutines.EmptyCoroutineContext
 
-@Singleton
+@MatrixScope
 internal class TaskExecutor @Inject constructor(private val coroutineDispatchers: MatrixCoroutineDispatchers) {
 
     fun  execute(task: ConfigurableTask): Cancelable {
@@ -42,11 +43,11 @@ internal class TaskExecutor @Inject constructor(private val coroutineDispatchers
                 }
             }
             resultOrFailure.fold({
-                Timber.d(it, "Task failed")
-                task.callback.onFailure(it)
-            }, {
-                task.callback.onSuccess(it)
-            })
+                                     Timber.d(it, "Task failed")
+                                     task.callback.onFailure(it)
+                                 }, {
+                                     task.callback.onSuccess(it)
+                                 })
         }
         return CancelableCoroutine(job)
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/BackgroundDetectionObserver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/BackgroundDetectionObserver.kt
index 5f85804f..a426bdd0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/BackgroundDetectionObserver.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/BackgroundDetectionObserver.kt
@@ -19,12 +19,15 @@ package im.vector.matrix.android.internal.util
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleObserver
 import androidx.lifecycle.OnLifecycleEvent
+import im.vector.matrix.android.internal.di.MatrixScope
 import timber.log.Timber
+import javax.inject.Inject
 
 /**
  * To be attached to ProcessLifecycleOwner lifecycle
  */
-internal class BackgroundDetectionObserver : LifecycleObserver {
+@MatrixScope
+internal class BackgroundDetectionObserver @Inject constructor() : LifecycleObserver {
 
     var isIsBackground: Boolean = false
         private set
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringProvider.kt
index 14f2a825..479412cf 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringProvider.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringProvider.kt
@@ -19,11 +19,12 @@ package im.vector.matrix.android.internal.util
 import android.content.res.Resources
 import androidx.annotation.NonNull
 import androidx.annotation.StringRes
+import dagger.Reusable
 import im.vector.matrix.android.internal.di.MatrixScope
 import javax.inject.Inject
 import javax.inject.Singleton
 
-@MatrixScope
+@Reusable
 internal class StringProvider @Inject constructor(private val resources: Resources) {
 
     /**
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DelegateWorkerFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DelegateWorkerFactory.kt
index cb0c7580..5141e06f 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DelegateWorkerFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DelegateWorkerFactory.kt
@@ -24,6 +24,6 @@ import androidx.work.WorkerParameters
 
 interface DelegateWorkerFactory {
 
-    fun create(appContext: Context, workerParameters: WorkerParameters): ListenableWorker
+    fun create(context: Context, params: WorkerParameters): ListenableWorker
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/MatrixWorkerFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/MatrixWorkerFactory.kt
index 63d5836b..e31e300e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/MatrixWorkerFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/MatrixWorkerFactory.kt
@@ -26,7 +26,6 @@ import im.vector.matrix.android.internal.di.MatrixScope
 import javax.inject.Inject
 import javax.inject.Provider
 
-@MatrixScope
 class MatrixWorkerFactory @Inject constructor(
         private val workerFactories: Map, @JvmSuppressWildcards Provider>
 ) : WorkerFactory() {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerBindingModule.kt
similarity index 89%
rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DI.kt
rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerBindingModule.kt
index ec0d0866..20e75a8d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/DI.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerBindingModule.kt
@@ -18,9 +18,7 @@
 
 package im.vector.matrix.android.internal.worker
 
-import androidx.work.ListenableWorker
 import dagger.Binds
-import dagger.MapKey
 import dagger.Module
 import dagger.multibindings.IntoMap
 import im.vector.matrix.android.internal.session.content.UploadContentWorker
@@ -29,12 +27,7 @@ import im.vector.matrix.android.internal.session.room.relation.SendRelationWorke
 import im.vector.matrix.android.internal.session.room.send.EncryptEventWorker
 import im.vector.matrix.android.internal.session.room.send.RedactEventWorker
 import im.vector.matrix.android.internal.session.room.send.SendEventWorker
-import kotlin.reflect.KClass
 
-@MapKey
-@Target(AnnotationTarget.FUNCTION)
-@Retention(AnnotationRetention.RUNTIME)
-internal annotation class WorkerKey(val value: KClass)
 
 @Module
 internal interface WorkerBindingModule {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerKey.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerKey.kt
new file mode 100644
index 00000000..c5b0f45a
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerKey.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.matrix.android.internal.worker
+
+import androidx.work.ListenableWorker
+import dagger.MapKey
+import kotlin.reflect.KClass
+
+@MapKey
+@Target(AnnotationTarget.FUNCTION)
+@Retention(AnnotationRetention.RUNTIME)
+internal annotation class WorkerKey(val value: KClass)
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/WorkerParamsFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerParamsFactory.kt
similarity index 96%
rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/WorkerParamsFactory.kt
rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerParamsFactory.kt
index 7c1cc72d..87d17b9c 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/WorkerParamsFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerParamsFactory.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package im.vector.matrix.android.internal.util
+package im.vector.matrix.android.internal.worker
 
 import androidx.work.Data
 import im.vector.matrix.android.internal.di.MoshiProvider

From 9c1f8706946b11bb6c02651a810d2d670281e599 Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Tue, 18 Jun 2019 20:00:20 +0200
Subject: [PATCH 04/11] Dagger: start handling app dependencies [WIP]

---
 .../session/room/membership/RoomMembers.kt    |   2 +-
 vector/build.gradle                           |   7 +-
 .../riotredesign/EmojiCompatFontProvider.kt   |   4 +-
 .../vector/riotredesign/VectorApplication.kt  |  52 ++--
 .../vector/riotredesign/core/di/AppModule.kt  | 107 -------
 .../riotredesign/core/di/HasInjector.kt       |  23 ++
 .../riotredesign/core/di/ScreenComponent.kt   |  55 ++++
 .../di/ScreenModule.kt}                       |  26 +-
 .../riotredesign/core/di/ScreenScope.java     |  29 ++
 .../core/di/VectorAssistedModule.kt           |  25 ++
 .../riotredesign/core/di/VectorComponent.kt   |  65 +++++
 .../riotredesign/core/di/VectorModule.kt      |  67 +++++
 .../core/di/VectorViewModelFactory.kt         |  50 ++++
 .../riotredesign/core/di/ViewModelKey.kt      |  26 ++
 .../riotredesign/core/di/ViewModelModule.kt   | 150 ++++++++++
 .../riotredesign/core/error/ErrorFormatter.kt |   3 +-
 .../riotredesign/core/extensions/Activity.kt  |   2 +-
 .../riotredesign/core/extensions/Fragment.kt  |   2 +-
 .../core/platform/ConfigurationViewModel.kt   |  10 +-
 .../core/platform/SimpleFragmentActivity.kt   |  11 +-
 .../core/platform/VectorBaseActivity.kt       |  33 ++-
 .../core/platform/VectorBaseFragment.kt       |  22 +-
 .../core/resources/ColorProvider.kt           |   5 +-
 .../core/resources/LocaleProvider.kt          |   3 +-
 .../core/resources/StringArrayProvider.kt     |   3 +-
 .../core/resources/StringProvider.kt          |   3 +-
 .../core/services/EventStreamServiceX.kt      |  23 +-
 .../command/AutocompleteCommandController.kt  |   3 +-
 .../command/AutocompleteCommandPresenter.kt   |   5 +-
 .../command/CommandAutocompletePolicy.kt      |   5 +-
 .../user/AutocompleteUserController.kt        |   3 +-
 .../user/AutocompleteUserPresenter.kt         |   5 +-
 .../configuration/VectorConfiguration.kt      |  14 +-
 .../restore/KeysBackupRestoreActivity.kt      |   4 +-
 .../KeysBackupRestoreFromKeyFragment.kt       |   5 +-
 .../KeysBackupRestoreFromKeyViewModel.kt      |   4 +-
 ...KeysBackupRestoreFromPassphraseFragment.kt |   5 +-
 ...eysBackupRestoreFromPassphraseViewModel.kt |   4 +-
 .../KeysBackupRestoreSharedViewModel.kt       |   7 +-
 .../KeysBackupRestoreSuccessFragment.kt       |   3 +-
 .../settings/KeysBackupManageActivity.kt      |  15 +-
 .../settings/KeysBackupSettingsFragment.kt    |  14 +-
 ...eysBackupSettingsRecyclerViewController.kt |  12 +-
 .../settings/KeysBackupSettingsViewModel.kt   |  44 +--
 .../setup/KeysBackupSetupActivity.kt          |   3 +-
 .../setup/KeysBackupSetupSharedViewModel.kt   |   5 +-
 .../setup/KeysBackupSetupStep1Fragment.kt     |   3 +-
 .../setup/KeysBackupSetupStep2Fragment.kt     |   3 +-
 .../setup/KeysBackupSetupStep3Fragment.kt     |   3 +-
 .../crypto/keysrequest/KeyRequestHandler.kt   |  21 +-
 .../IncomingVerificationRequestHandler.kt     |  24 +-
 .../verification/SASVerificationActivity.kt   |   2 +-
 .../SASVerificationIncomingFragment.kt        |   2 +-
 .../SASVerificationShortCodeFragment.kt       |   2 +-
 .../SASVerificationStartFragment.kt           |  12 +-
 .../SASVerificationVerifiedFragment.kt        |   2 +-
 .../verification/SasVerificationViewModel.kt  |   5 +-
 .../features/home/HomeActivity.kt             |  15 +-
 .../features/home/HomeActivityViewModel.kt    |  27 +-
 .../features/home/HomeDetailFragment.kt       |   9 +-
 .../features/home/HomeDetailViewModel.kt      |  40 +--
 .../features/home/HomeDrawerFragment.kt       |   4 +-
 .../riotredesign/features/home/HomeModule.kt  |  93 +-----
 .../features/home/HomeNavigationViewModel.kt  |   3 +-
 .../features/home/HomeNavigator.kt            |   4 +-
 .../features/home/HomePermalinkHandler.kt     |  13 +-
 .../home/HomeRoomListObservableStore.kt       |   5 +-
 .../features/home/group/GroupListFragment.kt  |   8 +-
 .../features/home/group/GroupListViewModel.kt |  24 +-
 .../home/group/GroupSummaryController.kt      |   3 +-
 .../features/home/group/SelectedGroupStore.kt |   5 +-
 .../home/room/detail/RoomDetailFragment.kt    |  55 ++--
 .../home/room/detail/RoomDetailViewModel.kt   |  21 +-
 .../detail/composer/TextComposerViewModel.kt  |  21 +-
 .../timeline/TimelineEventController.kt       |  31 +-
 .../TimelineEventControllerHandler.kt         |  23 ++
 .../detail/timeline/action/ActionsHandler.kt  |   3 +-
 .../action/MessageActionsBottomSheet.kt       |   2 +
 .../action/MessageActionsViewModel.kt         | 128 +++++----
 .../timeline/action/MessageMenuFragment.kt    |   4 +-
 .../timeline/action/MessageMenuViewModel.kt   | 270 ++++++++++--------
 .../timeline/action/QuickReactionFragment.kt  |  17 +-
 .../timeline/action/QuickReactionViewModel.kt | 152 +++++-----
 .../timeline/factory/DefaultItemFactory.kt    |   3 +-
 .../timeline/factory/EncryptedItemFactory.kt  |   3 +-
 .../timeline/factory/EncryptionItemFactory.kt |   5 +-
 .../timeline/factory/MessageItemFactory.kt    | 113 +++++---
 .../timeline/factory/NoticeItemFactory.kt     |   3 +-
 .../timeline/factory/TimelineItemFactory.kt   |  30 +-
 .../timeline/format/NoticeEventFormatter.kt   |  16 +-
 .../timeline/helper/TimelineDateFormatter.kt  |   4 +-
 .../helper/TimelineMediaSizeProvider.kt       |   3 +-
 .../room/list/AlphabeticalRoomComparator.kt   |   4 +-
 .../room/list/ChronologicalRoomComparator.kt  |   3 +-
 .../home/room/list/RoomListFragment.kt        |  11 +-
 .../home/room/list/RoomListViewModel.kt       |  26 +-
 .../home/room/list/RoomSummaryController.kt   |   7 +-
 .../features/html/EventHtmlRenderer.kt        |  12 +-
 .../VectorActivityLifecycleCallbacks.kt       |   3 +-
 .../features/navigation/DefaultNavigator.kt   |   4 +-
 .../NotificationBroadcastReceiver.kt          |   7 +-
 .../NotificationDrawerManager.kt              |   6 +-
 .../reactions/EmojiChooserFragment.kt         |  24 +-
 .../reactions/EmojiChooserViewModel.kt        |   3 +-
 .../reactions/EmojiReactionPickerActivity.kt  |   6 +-
 .../roomdirectory/PublicRoomsFragment.kt      |  12 +-
 .../roomdirectory/RoomDirectoryActivity.kt    |  10 +-
 .../RoomDirectoryNavigationViewModel.kt       |   3 +-
 .../roomdirectory/RoomDirectoryViewModel.kt   |  93 +++---
 .../picker/RoomDirectoryListCreator.kt        |   9 +-
 .../picker/RoomDirectoryPickerController.kt   |   7 +-
 .../picker/RoomDirectoryPickerFragment.kt     |  13 +-
 .../picker/RoomDirectoryPickerViewModel.kt    |  19 +-
 .../roompreview/RoomPreviewActivity.kt        |  10 -
 .../RoomPreviewNoPreviewFragment.kt           |  11 +-
 .../roompreview/RoomPreviewViewModel.kt       |  18 +-
 .../SignOutBottomSheetDialogFragment.kt       |  21 +-
 .../workers/signout/SignOutViewModel.kt       |  23 +-
 118 files changed, 1562 insertions(+), 1010 deletions(-)
 delete mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/AppModule.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/HasInjector.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
 rename vector/src/main/java/im/vector/riotredesign/{features/crypto/keysbackup/KeysBackupModule.kt => core/di/ScreenModule.kt} (51%)
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/ScreenScope.java
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/VectorAssistedModule.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/VectorViewModelFactory.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/ViewModelKey.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventControllerHandler.kt

diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMembers.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMembers.kt
index ff8b8ce4..dd395909 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMembers.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMembers.kt
@@ -54,7 +54,7 @@ internal class RoomMembers(private val realm: Realm,
         }
         return EventEntity
                 .where(realm, roomId, EventType.STATE_ROOM_MEMBER)
-                .contains(EventEntityFields.CONTENT, displayName)
+                .equalTo(EventEntityFields.CONTENT, displayName)
                 .distinct(EventEntityFields.STATE_KEY)
                 .findAll()
                 .size == 1
diff --git a/vector/build.gradle b/vector/build.gradle
index 10953eb4..3754ceee 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -138,6 +138,7 @@ dependencies {
     def big_image_viewer_version = '1.5.6'
     def glide_version = '4.9.0'
     def moshi_version = '1.8.0'
+    def daggerVersion = '2.23.1'
 
     implementation project(":matrix-sdk-android")
     implementation project(":matrix-sdk-android-rx")
@@ -219,8 +220,10 @@ dependencies {
     implementation 'com.github.jaiselrahman:FilePicker:1.2.2'
 
     // DI
-    implementation "org.koin:koin-android:$koin_version"
-    implementation "org.koin:koin-android-scope:$koin_version"
+    implementation "com.google.dagger:dagger:$daggerVersion"
+    kapt "com.google.dagger:dagger-compiler:$daggerVersion"
+    compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
+    kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
 
     // gplay flavor only
     gplayImplementation 'com.google.firebase:firebase-core:16.0.8'
diff --git a/vector/src/main/java/im/vector/riotredesign/EmojiCompatFontProvider.kt b/vector/src/main/java/im/vector/riotredesign/EmojiCompatFontProvider.kt
index a928d48b..c7fc7a95 100644
--- a/vector/src/main/java/im/vector/riotredesign/EmojiCompatFontProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/EmojiCompatFontProvider.kt
@@ -3,9 +3,9 @@ package im.vector.riotredesign
 import android.graphics.Typeface
 import androidx.core.provider.FontsContractCompat
 import timber.log.Timber
+import javax.inject.Inject
 
-
-class EmojiCompatFontProvider : FontsContractCompat.FontRequestCallback() {
+class EmojiCompatFontProvider @Inject constructor(): FontsContractCompat.FontRequestCallback() {
 
     var typeface: Typeface? = null
         set(value) {
diff --git a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
index 3e51cdec..ed57d347 100644
--- a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
+++ b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
@@ -31,67 +31,56 @@ import com.github.piasy.biv.BigImageViewer
 import com.github.piasy.biv.loader.glide.GlideImageLoader
 import com.jakewharton.threetenabp.AndroidThreeTen
 import im.vector.matrix.android.api.Matrix
-import im.vector.riotredesign.core.di.AppModule
+import im.vector.riotredesign.core.di.HasInjector
+import im.vector.riotredesign.core.di.VectorComponent
 import im.vector.riotredesign.features.configuration.VectorConfiguration
-import im.vector.riotredesign.features.crypto.keysbackup.KeysBackupModule
-import im.vector.riotredesign.features.home.HomeModule
 import im.vector.riotredesign.features.lifecycle.VectorActivityLifecycleCallbacks
 import im.vector.riotredesign.features.rageshake.VectorFileLogger
 import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
-import im.vector.riotredesign.features.roomdirectory.RoomDirectoryModule
-import org.koin.android.ext.android.inject
-import org.koin.log.EmptyLogger
-import org.koin.standalone.StandAloneContext.startKoin
 import timber.log.Timber
+import javax.inject.Inject
 
 
-class VectorApplication : Application() {
+class VectorApplication : Application(), HasInjector {
 
     lateinit var appContext: Context
     //font thread handler
-    private var mFontThreadHandler: Handler? = null
-
-    val vectorConfiguration: VectorConfiguration by inject()
+    @Inject lateinit var vectorConfiguration: VectorConfiguration
+    @Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
+    lateinit var vectorComponent: VectorComponent
+    private var fontThreadHandler: Handler? = null
 
     override fun onCreate() {
         super.onCreate()
         appContext = this
-
         VectorUncaughtExceptionHandler.activate(this)
-
         // Log
         VectorFileLogger.init(this)
         Timber.plant(Timber.DebugTree(), VectorFileLogger)
-
         if (BuildConfig.DEBUG) {
             Stetho.initializeWithDefaults(this)
         }
-
         AndroidThreeTen.init(this)
         BigImageViewer.initialize(GlideImageLoader.with(applicationContext))
         EpoxyController.defaultDiffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
         EpoxyController.defaultModelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
-        val appModule = AppModule(applicationContext).definition
-        val homeModule = HomeModule().definition
-        val roomDirectoryModule = RoomDirectoryModule().definition
-        val keysBackupModule = KeysBackupModule().definition
-        val koin = startKoin(listOf(appModule, homeModule, roomDirectoryModule, keysBackupModule), logger = EmptyLogger())
+
         Matrix.getInstance().setApplicationFlavor(BuildConfig.FLAVOR_DESCRIPTION)
         registerActivityLifecycleCallbacks(VectorActivityLifecycleCallbacks())
-
         val fontRequest = FontRequest(
                 "com.google.android.gms.fonts",
                 "com.google.android.gms",
                 "Noto Color Emoji Compat",
                 R.array.com_google_android_gms_fonts_certs
         )
-
-//        val efp = koin.koinContext.get()
-        FontsContractCompat.requestFont(this, fontRequest, koin.koinContext.get(), getFontThreadHandler())
-
+        FontsContractCompat.requestFont(this, fontRequest, emojiCompatFontProvider, getFontThreadHandler())
         vectorConfiguration.initConfiguration()
     }
 
+    override fun injector(): VectorComponent {
+        return vectorComponent
+    }
+
     override fun attachBaseContext(base: Context) {
         super.attachBaseContext(base)
         MultiDex.install(this)
@@ -103,12 +92,15 @@ class VectorApplication : Application() {
     }
 
     private fun getFontThreadHandler(): Handler {
-        if (mFontThreadHandler == null) {
-            val handlerThread = HandlerThread("fonts")
-            handlerThread.start()
-            mFontThreadHandler = Handler(handlerThread.looper)
+        return fontThreadHandler ?: createFontThreadHandler().also {
+            fontThreadHandler = it
         }
-        return mFontThreadHandler!!
+    }
+
+    private fun createFontThreadHandler(): Handler {
+        val handlerThread = HandlerThread("fonts")
+        handlerThread.start()
+        return Handler(handlerThread.looper)
     }
 
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/AppModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/AppModule.kt
deleted file mode 100644
index 5b875fd1..00000000
--- a/vector/src/main/java/im/vector/riotredesign/core/di/AppModule.kt
+++ /dev/null
@@ -1,107 +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.riotredesign.core.di
-
-import android.content.Context
-import android.content.Context.MODE_PRIVATE
-import im.vector.matrix.android.api.Matrix
-import im.vector.riotredesign.EmojiCompatFontProvider
-import im.vector.riotredesign.core.error.ErrorFormatter
-import im.vector.riotredesign.core.resources.LocaleProvider
-import im.vector.riotredesign.core.resources.StringArrayProvider
-import im.vector.riotredesign.core.resources.StringProvider
-import im.vector.riotredesign.features.configuration.VectorConfiguration
-import im.vector.riotredesign.features.crypto.keysrequest.KeyRequestHandler
-import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
-import im.vector.riotredesign.features.home.HomeRoomListObservableStore
-import im.vector.riotredesign.features.home.group.SelectedGroupStore
-import im.vector.riotredesign.features.home.room.list.AlphabeticalRoomComparator
-import im.vector.riotredesign.features.home.room.list.ChronologicalRoomComparator
-import im.vector.riotredesign.features.navigation.DefaultNavigator
-import im.vector.riotredesign.features.navigation.Navigator
-import im.vector.riotredesign.features.notifications.NotificationDrawerManager
-import org.koin.dsl.module.module
-
-class AppModule(private val context: Context) {
-
-    val definition = module {
-
-        single {
-            VectorConfiguration(context)
-        }
-
-        single {
-            LocaleProvider(context.resources)
-        }
-
-        single {
-            StringProvider(context.resources)
-        }
-
-        single {
-            StringArrayProvider(context.resources)
-        }
-
-        single {
-            context.getSharedPreferences("im.vector.riot", MODE_PRIVATE)
-        }
-
-        single {
-            SelectedGroupStore()
-        }
-
-        single {
-            HomeRoomListObservableStore()
-        }
-
-        single {
-            ChronologicalRoomComparator()
-        }
-
-        single {
-            AlphabeticalRoomComparator()
-        }
-
-        single {
-            ErrorFormatter(get())
-        }
-
-        single {
-            NotificationDrawerManager(context)
-        }
-
-        factory {
-            Matrix.getInstance().currentSession!!
-        }
-
-        single {
-            KeyRequestHandler(context, get())
-        }
-
-        single {
-            IncomingVerificationRequestHandler(context, get())
-        }
-
-        factory {
-            DefaultNavigator() as Navigator
-        }
-
-        single {
-            EmojiCompatFontProvider()
-        }
-    }
-}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/HasInjector.kt b/vector/src/main/java/im/vector/riotredesign/core/di/HasInjector.kt
new file mode 100644
index 00000000..ca2e27ab
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/HasInjector.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.riotredesign.core.di
+
+interface HasInjector {
+
+    fun injector(): C
+
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
new file mode 100644
index 00000000..1f20979a
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.riotredesign.core.di
+
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.ViewModelProvider
+import dagger.BindsInstance
+import dagger.Component
+import im.vector.riotredesign.core.platform.SimpleFragmentActivity
+import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupSettingsFragment
+import im.vector.riotredesign.features.home.HomeActivity
+import im.vector.riotredesign.features.home.HomeModule
+import im.vector.riotredesign.features.home.room.detail.RoomDetailFragment
+import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerFragment
+import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment
+
+@Component(dependencies = [VectorComponent::class], modules = [ViewModelModule::class, HomeModule::class])
+@ScreenScope
+interface ScreenComponent {
+
+    fun viewModelFactory(): ViewModelProvider.Factory
+
+    fun inject(activity: SimpleFragmentActivity)
+
+    fun inject(activity: HomeActivity)
+
+    fun inject(roomDetailFragment: RoomDetailFragment)
+
+    fun inject(roomDirectoryPickerFragment: RoomDirectoryPickerFragment)
+
+    fun inject(roomPreviewNoPreviewFragment: RoomPreviewNoPreviewFragment)
+    
+    fun inject(keysBackupSettingsFragment: KeysBackupSettingsFragment)
+
+    @Component.Factory
+    interface Factory {
+        fun create(vectorComponent: VectorComponent,
+                   @BindsInstance context: AppCompatActivity
+        ): ScreenComponent
+    }
+}
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/KeysBackupModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenModule.kt
similarity index 51%
rename from vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/KeysBackupModule.kt
rename to vector/src/main/java/im/vector/riotredesign/core/di/ScreenModule.kt
index c9cebfc3..3ea64332 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/KeysBackupModule.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenModule.kt
@@ -5,7 +5,7 @@
  * 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
+ * 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,
@@ -14,22 +14,18 @@
  * limitations under the License.
  */
 
-package im.vector.riotredesign.features.crypto.keysbackup
+package im.vector.riotredesign.core.di
 
-import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupSettingsRecyclerViewController
-import org.koin.dsl.module.module
+import androidx.appcompat.app.AppCompatActivity
+import dagger.Module
+import dagger.Provides
+import im.vector.riotredesign.core.glide.GlideApp
 
-class KeysBackupModule {
+@Module
+object ScreenModule {
 
-    companion object {
-        const val KEYS_BACKUP_SCOPE = "KEYS_BACKUP_SCOPE"
-    }
+    @Provides
+    @JvmStatic
+    fun providesGlideRequests(context: AppCompatActivity) = GlideApp.with(context)
 
-    val definition = module(override = true) {
-
-        scope(KEYS_BACKUP_SCOPE) {
-            KeysBackupSettingsRecyclerViewController(get(), get())
-        }
-
-    }
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenScope.java b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenScope.java
new file mode 100644
index 00000000..d3915f7d
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenScope.java
@@ -0,0 +1,29 @@
+/*
+ * 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.riotredesign.core.di;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Scope
+@Documented
+@Retention(RUNTIME)
+public @interface ScreenScope {}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorAssistedModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorAssistedModule.kt
new file mode 100644
index 00000000..cd69d182
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorAssistedModule.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.riotredesign.core.di
+
+import com.squareup.inject.assisted.dagger2.AssistedModule
+import dagger.Module
+
+/*
+@Module(includes = [AssistedInject_VectorAssistedModule::class])
+@AssistedModule
+class VectorAssistedModule*/
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
new file mode 100644
index 00000000..6517c4b9
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.riotredesign.core.di
+
+import android.content.Context
+import android.content.res.Resources
+import dagger.BindsInstance
+import dagger.Component
+import im.vector.matrix.android.api.Matrix
+import im.vector.matrix.android.api.session.Session
+import im.vector.riotredesign.features.configuration.VectorConfiguration
+import im.vector.riotredesign.features.crypto.keysrequest.KeyRequestHandler
+import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
+import im.vector.riotredesign.features.home.HomeRoomListObservableStore
+import im.vector.riotredesign.features.home.group.SelectedGroupStore
+import im.vector.riotredesign.features.navigation.Navigator
+import im.vector.riotredesign.features.notifications.NotificationDrawerManager
+import javax.inject.Singleton
+
+@Component(modules = [VectorModule::class])
+@Singleton
+interface VectorComponent {
+
+    fun matrix(): Matrix
+
+    fun currentSession(): Session
+
+    fun notificationDrawerManager(): NotificationDrawerManager
+
+    fun appContext(): Context
+
+    fun resources(): Resources
+
+    fun vectorConfiguration(): VectorConfiguration
+
+    fun navigator(): Navigator
+
+    fun homeRoomListObservableStore(): HomeRoomListObservableStore
+
+    fun selectedGroupStore(): SelectedGroupStore
+
+    fun incomingVerificationRequestHandler(): IncomingVerificationRequestHandler
+
+    fun incomingKeyRequestHandler(): KeyRequestHandler
+
+    @Component.Factory
+    interface Factory {
+        fun create(@BindsInstance context: Context): VectorComponent
+    }
+
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
new file mode 100644
index 00000000..4b4f4467
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
@@ -0,0 +1,67 @@
+/*
+ * 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.riotredesign.core.di
+
+import android.content.Context
+import android.content.Context.MODE_PRIVATE
+import android.content.SharedPreferences
+import android.content.res.Resources
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import im.vector.matrix.android.api.Matrix
+import im.vector.matrix.android.api.session.Session
+import im.vector.riotredesign.features.navigation.DefaultNavigator
+import im.vector.riotredesign.features.navigation.Navigator
+
+@Module
+abstract class VectorModule {
+
+    @Module
+    companion object {
+
+        @Provides
+        @JvmStatic
+        fun providesResources(context: Context): Resources {
+            return context.resources
+        }
+
+        @Provides
+        @JvmStatic
+        fun providesSharedPreferences(context: Context): SharedPreferences {
+            return context.getSharedPreferences("im.vector.riot", MODE_PRIVATE)
+        }
+
+        @Provides
+        @JvmStatic
+        fun providesMatrix(): Matrix {
+            return Matrix.getInstance()
+        }
+
+        @Provides
+        @JvmStatic
+        fun providesCurrentSession(matrix: Matrix): Session {
+            //TODO: handle session injection better
+            return matrix.currentSession!!
+        }
+    }
+
+    @Binds
+    abstract fun bindNavigator(navigator: DefaultNavigator): Navigator
+
+
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorViewModelFactory.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorViewModelFactory.kt
new file mode 100644
index 00000000..eac1b52e
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorViewModelFactory.kt
@@ -0,0 +1,50 @@
+/*
+ * 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.riotredesign.core.di
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import javax.inject.Inject
+import javax.inject.Provider
+
+/**
+ * ViewModelFactory which uses Dagger to create the instances.
+ */
+class VectorViewModelFactory @Inject constructor(
+        private val creators: @JvmSuppressWildcards Map, Provider>
+) : ViewModelProvider.Factory {
+    override fun  create(modelClass: Class): T {
+        var creator: Provider? = creators[modelClass]
+        if (creator == null) {
+            for ((key, value) in creators) {
+                if (modelClass.isAssignableFrom(key)) {
+                    creator = value
+                    break
+                }
+            }
+        }
+        if (creator == null) {
+            throw IllegalArgumentException("Unknown model class: $modelClass")
+        }
+        try {
+            @Suppress("UNCHECKED_CAST")
+            return creator.get() as T
+        } catch (e: Exception) {
+            throw RuntimeException(e)
+        }
+    }
+}
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelKey.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelKey.kt
new file mode 100644
index 00000000..c0887423
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelKey.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.riotredesign.core.di
+
+import androidx.lifecycle.ViewModel
+import dagger.MapKey
+import kotlin.reflect.KClass
+
+@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
+@Retention(AnnotationRetention.RUNTIME)
+@MapKey
+annotation class ViewModelKey(val value: KClass)
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
new file mode 100644
index 00000000..c38608ff
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
@@ -0,0 +1,150 @@
+/*
+ * 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.riotredesign.core.di
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoMap
+import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromKeyViewModel
+import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
+import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel
+import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel
+import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel_AssistedFactory
+import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel
+import im.vector.riotredesign.features.crypto.verification.SasVerificationViewModel
+import im.vector.riotredesign.features.home.HomeActivityViewModel
+import im.vector.riotredesign.features.home.HomeActivityViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.HomeDetailViewModel
+import im.vector.riotredesign.features.home.HomeDetailViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.HomeNavigationViewModel
+import im.vector.riotredesign.features.home.group.GroupListViewModel
+import im.vector.riotredesign.features.home.group.GroupListViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.room.detail.RoomDetailViewModel
+import im.vector.riotredesign.features.home.room.detail.RoomDetailViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.room.detail.composer.TextComposerViewModel
+import im.vector.riotredesign.features.home.room.detail.composer.TextComposerViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageActionsViewModel
+import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageActionsViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageMenuViewModel
+import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageMenuViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.room.detail.timeline.action.QuickReactionViewModel
+import im.vector.riotredesign.features.home.room.detail.timeline.action.QuickReactionViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.room.list.RoomListViewModel
+import im.vector.riotredesign.features.home.room.list.RoomListViewModel_AssistedFactory
+import im.vector.riotredesign.features.reactions.EmojiChooserViewModel
+import im.vector.riotredesign.features.roomdirectory.RoomDirectoryNavigationViewModel
+import im.vector.riotredesign.features.roomdirectory.RoomDirectoryViewModel
+import im.vector.riotredesign.features.roomdirectory.RoomDirectoryViewModel_AssistedFactory
+import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerViewModel
+import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerViewModel_AssistedFactory
+import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewViewModel
+import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewViewModel_AssistedFactory
+import im.vector.riotredesign.features.workers.signout.SignOutViewModel
+
+@Module
+interface ViewModelModule {
+
+    @Binds
+    fun bindViewModelFactory(factory: VectorViewModelFactory): ViewModelProvider.Factory
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(SignOutViewModel::class)
+    fun bindSignOutViewModel(viewModel: SignOutViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(EmojiChooserViewModel::class)
+    fun bindEmojiChooserViewModel(viewModel: EmojiChooserViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(SasVerificationViewModel::class)
+    fun bindSasVerificationViewModel(viewModel: SasVerificationViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(KeysBackupRestoreFromKeyViewModel::class)
+    fun bindKeysBackupRestoreFromKeyViewModel(viewModel: KeysBackupRestoreFromKeyViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(KeysBackupRestoreSharedViewModel::class)
+    fun bindKeysBackupRestoreSharedViewModel(viewModel: KeysBackupRestoreSharedViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(KeysBackupRestoreFromPassphraseViewModel::class)
+    fun bindKeysBackupRestoreFromPassphraseViewModel(viewModel: KeysBackupRestoreFromPassphraseViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(RoomDirectoryNavigationViewModel::class)
+    fun bindRoomDirectoryNavigationViewModel(viewModel: RoomDirectoryNavigationViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(HomeNavigationViewModel::class)
+    fun bindHomeNavigationViewModel(viewModel: HomeNavigationViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(KeysBackupSetupSharedViewModel::class)
+    fun bindKeysBackupSetupSharedViewModel(viewModel: KeysBackupSetupSharedViewModel): ViewModel
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_HomeActivityViewModel(factory: HomeActivityViewModel_AssistedFactory): HomeActivityViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_room_detail_composer_TextComposerViewModel(factory: TextComposerViewModel_AssistedFactory): TextComposerViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_room_detail_RoomDetailViewModel(factory: RoomDetailViewModel_AssistedFactory): RoomDetailViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_room_detail_timeline_action_QuickReactionViewModel(factory: QuickReactionViewModel_AssistedFactory): QuickReactionViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_room_detail_timeline_action_MessageActionsViewModel(factory: MessageActionsViewModel_AssistedFactory): MessageActionsViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_room_detail_timeline_action_MessageMenuViewModel(factory: MessageMenuViewModel_AssistedFactory): MessageMenuViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_room_list_RoomListViewModel(factory: RoomListViewModel_AssistedFactory): RoomListViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_group_GroupListViewModel(factory: GroupListViewModel_AssistedFactory): GroupListViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_home_HomeDetailViewModel(factory: HomeDetailViewModel_AssistedFactory): HomeDetailViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_crypto_keysbackup_settings_KeysBackupSettingsViewModel(factory: KeysBackupSettingsViewModel_AssistedFactory): KeysBackupSettingsViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_roomdirectory_picker_RoomDirectoryPickerViewModel(factory: RoomDirectoryPickerViewModel_AssistedFactory): RoomDirectoryPickerViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_roomdirectory_RoomDirectoryViewModel(factory: RoomDirectoryViewModel_AssistedFactory): RoomDirectoryViewModel.Factory
+
+    @Binds
+    fun bind_im_vector_riotredesign_features_roomdirectory_roompreview_RoomPreviewViewModel(factory: RoomPreviewViewModel_AssistedFactory): RoomPreviewViewModel.Factory
+
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/riotredesign/core/error/ErrorFormatter.kt
index 114e08b8..284bd192 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/error/ErrorFormatter.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/error/ErrorFormatter.kt
@@ -19,8 +19,9 @@ package im.vector.riotredesign.core.error
 import im.vector.matrix.android.api.failure.Failure
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.resources.StringProvider
+import javax.inject.Inject
 
-class ErrorFormatter(val stringProvider: StringProvider) {
+class ErrorFormatter @Inject constructor(val stringProvider: StringProvider) {
 
 
     fun toHumanReadable(failure: Failure): String {
diff --git a/vector/src/main/java/im/vector/riotredesign/core/extensions/Activity.kt b/vector/src/main/java/im/vector/riotredesign/core/extensions/Activity.kt
index 8c23d795..78796d5e 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/extensions/Activity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/extensions/Activity.kt
@@ -33,4 +33,4 @@ fun AppCompatActivity.addFragmentToBackstack(fragment: Fragment, frameId: Int, t
 
 fun AppCompatActivity.hideKeyboard() {
     currentFocus?.hideKeyboard()
-}
\ No newline at end of file
+}
diff --git a/vector/src/main/java/im/vector/riotredesign/core/extensions/Fragment.kt b/vector/src/main/java/im/vector/riotredesign/core/extensions/Fragment.kt
index 1467071b..e0eb4bac 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/extensions/Fragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/extensions/Fragment.kt
@@ -40,4 +40,4 @@ fun Fragment.replaceChildFragment(fragment: Fragment, frameId: Int) {
 
 fun Fragment.addChildFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) {
     childFragmentManager.inTransaction { replace(frameId, fragment).addToBackStack(tag) }
-}
\ No newline at end of file
+}
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/ConfigurationViewModel.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/ConfigurationViewModel.kt
index af7d0e5d..24fa889b 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/ConfigurationViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/ConfigurationViewModel.kt
@@ -21,13 +21,12 @@ import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import im.vector.riotredesign.core.utils.LiveEvent
 import im.vector.riotredesign.features.configuration.VectorConfiguration
-import org.koin.standalone.KoinComponent
-import org.koin.standalone.inject
 import timber.log.Timber
+import javax.inject.Inject
 
-class ConfigurationViewModel : ViewModel(), KoinComponent {
-
-    private val vectorConfiguration: VectorConfiguration by inject()
+class ConfigurationViewModel @Inject constructor(
+        private val vectorConfiguration: VectorConfiguration
+) : ViewModel() {
 
     private var currentConfigurationValue: String? = null
 
@@ -47,7 +46,6 @@ class ConfigurationViewModel : ViewModel(), KoinComponent {
             if (newHash != currentConfigurationValue) {
                 Timber.v("Configuration: recreate the Activity")
                 currentConfigurationValue = newHash
-
                 _activityRestarter.postValue(LiveEvent(Unit))
             }
         }
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
index dfac10b5..2b891275 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
@@ -15,6 +15,7 @@
  */
 package im.vector.riotredesign.core.platform
 
+import android.os.Bundle
 import android.view.View
 import android.widget.ProgressBar
 import android.widget.TextView
@@ -25,7 +26,7 @@ import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.extensions.hideKeyboard
 import kotlinx.android.synthetic.main.activity.*
-import org.koin.android.ext.android.get
+import javax.inject.Inject
 
 /**
  * Simple activity with a toolbar, a waiting overlay, and a fragment container and a session.
@@ -43,7 +44,13 @@ abstract class SimpleFragmentActivity : VectorBaseActivity() {
     @BindView(R.id.waiting_view_status_horizontal_progress)
     lateinit var waitingHorizontalProgress: ProgressBar
 
-    protected val session = get()
+    @Inject
+    lateinit var session: Session
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        injector().inject(this)
+        super.onCreate(savedInstanceState)
+    }
 
     override fun initUiAndData() {
         configureToolbar(toolbar)
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
index 3507788b..830ebcf6 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
@@ -22,35 +22,48 @@ import android.os.Bundle
 import android.view.Menu
 import android.view.MenuItem
 import android.view.View
-import androidx.annotation.*
+import androidx.annotation.AttrRes
+import androidx.annotation.LayoutRes
+import androidx.annotation.MainThread
+import androidx.annotation.MenuRes
+import androidx.annotation.Nullable
+import androidx.annotation.StringRes
 import androidx.appcompat.widget.Toolbar
 import androidx.coordinatorlayout.widget.CoordinatorLayout
 import androidx.core.view.isVisible
 import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.ViewModelProviders
 import butterknife.BindView
 import butterknife.ButterKnife
 import butterknife.Unbinder
 import com.airbnb.mvrx.BaseMvRxActivity
+import com.airbnb.mvrx.MvRxState
 import com.bumptech.glide.util.Util
 import com.google.android.material.snackbar.Snackbar
 import im.vector.riotredesign.BuildConfig
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.HasInjector
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.utils.toast
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.rageshake.BugReportActivity
 import im.vector.riotredesign.features.rageshake.BugReporter
 import im.vector.riotredesign.features.rageshake.RageShake
+import im.vector.riotredesign.features.roomdirectory.PublicRoomsViewState
+import im.vector.riotredesign.features.roomdirectory.RoomDirectoryViewModel
 import im.vector.riotredesign.features.themes.ActivityOtherThemes
 import im.vector.riotredesign.features.themes.ThemeUtils
 import im.vector.riotredesign.receivers.DebugReceiver
 import io.reactivex.disposables.CompositeDisposable
 import io.reactivex.disposables.Disposable
-import org.koin.android.ext.android.inject
 import timber.log.Timber
+import javax.inject.Provider
+import kotlin.reflect.KClass
 
 
-abstract class VectorBaseActivity : BaseMvRxActivity() {
+abstract class VectorBaseActivity : BaseMvRxActivity(), HasInjector {
     /* ==========================================================================================
      * UI
      * ========================================================================================== */
@@ -64,8 +77,8 @@ abstract class VectorBaseActivity : BaseMvRxActivity() {
      * DATA
      * ========================================================================================== */
 
-    private val vectorConfiguration: VectorConfiguration by inject()
-
+    protected lateinit var viewModelFactory: ViewModelProvider.Factory
+    private lateinit var vectorConfiguration: VectorConfiguration
     private lateinit var configurationViewModel: ConfigurationViewModel
 
     private var unBinder: Unbinder? = null
@@ -79,6 +92,7 @@ abstract class VectorBaseActivity : BaseMvRxActivity() {
     private val restorables = ArrayList()
 
     private var rageShake: RageShake? = null
+    private lateinit var screenComponent: ScreenComponent
 
     override fun attachBaseContext(base: Context) {
         super.attachBaseContext(vectorConfiguration.getLocalisedContext(base))
@@ -107,10 +121,9 @@ abstract class VectorBaseActivity : BaseMvRxActivity() {
     }
 
     override fun onCreate(savedInstanceState: Bundle?) {
+
         super.onCreate(savedInstanceState)
-
-        configurationViewModel = ViewModelProviders.of(this).get(ConfigurationViewModel::class.java)
-
+        configurationViewModel = ViewModelProviders.of(this, viewModelFactory).get(ConfigurationViewModel::class.java)
         configurationViewModel.activityRestarter.observe(this, Observer {
             if (!it.hasBeenHandled) {
                 // Recreate the Activity because configuration has changed
@@ -202,6 +215,10 @@ abstract class VectorBaseActivity : BaseMvRxActivity() {
     }
 
 
+    override fun injector(): ScreenComponent {
+        return screenComponent
+    }
+
     /* ==========================================================================================
      * PRIVATE METHODS
      * ========================================================================================== */
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
index f291746e..137c680c 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
@@ -18,24 +18,29 @@ package im.vector.riotredesign.core.platform
 
 import android.os.Bundle
 import android.os.Parcelable
-import android.view.*
+import android.view.LayoutInflater
+import android.view.Menu
+import android.view.MenuInflater
+import android.view.View
+import android.view.ViewGroup
 import androidx.annotation.CallSuper
 import androidx.annotation.LayoutRes
 import androidx.annotation.MainThread
 import androidx.appcompat.widget.Toolbar
+import androidx.lifecycle.ViewModelProvider
 import butterknife.ButterKnife
 import butterknife.Unbinder
 import com.airbnb.mvrx.BaseMvRxFragment
 import com.airbnb.mvrx.MvRx
 import com.bumptech.glide.util.Util.assertMainThread
+import im.vector.riotredesign.core.di.HasInjector
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.features.navigation.Navigator
 import io.reactivex.disposables.CompositeDisposable
 import io.reactivex.disposables.Disposable
-import org.koin.android.ext.android.inject
-import org.koin.core.parameter.parametersOf
 import timber.log.Timber
 
-abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed {
+abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed, HasInjector {
 
     // Butterknife unbinder
     private var mUnBinder: Unbinder? = null
@@ -48,7 +53,8 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed {
      * Navigator
      * ========================================================================================== */
 
-    protected val navigator: Navigator  by inject { parametersOf(this) }
+    protected lateinit var viewModelFactory: ViewModelProvider.Factory
+    protected lateinit var navigator: Navigator
 
     /* ==========================================================================================
      * Life cycle
@@ -57,7 +63,6 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed {
     @CallSuper
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-
         if (getMenuRes() != -1) {
             setHasOptionsMenu(true)
         }
@@ -92,10 +97,13 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed {
 
     override fun onDestroy() {
         super.onDestroy()
-
         uiDisposables.dispose()
     }
 
+    override fun injector(): ScreenComponent {
+        return vectorBaseActivity.injector()
+    }
+
     /* ==========================================================================================
      * Restorable
      * ========================================================================================== */
diff --git a/vector/src/main/java/im/vector/riotredesign/core/resources/ColorProvider.kt b/vector/src/main/java/im/vector/riotredesign/core/resources/ColorProvider.kt
index cfc48891..88844be4 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/resources/ColorProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/resources/ColorProvider.kt
@@ -18,14 +18,15 @@
 
 package im.vector.riotredesign.core.resources
 
-import android.content.Context
 import androidx.annotation.AttrRes
 import androidx.annotation.ColorInt
 import androidx.annotation.ColorRes
+import androidx.appcompat.app.AppCompatActivity
 import androidx.core.content.ContextCompat
 import im.vector.riotredesign.features.themes.ThemeUtils
+import javax.inject.Inject
 
-class ColorProvider(private val context: Context) {
+class ColorProvider @Inject constructor(private val context: AppCompatActivity) {
 
     fun getColor(@ColorRes colorRes: Int): Int {
         return ContextCompat.getColor(context, colorRes)
diff --git a/vector/src/main/java/im/vector/riotredesign/core/resources/LocaleProvider.kt b/vector/src/main/java/im/vector/riotredesign/core/resources/LocaleProvider.kt
index 991177a7..f1f8fecf 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/resources/LocaleProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/resources/LocaleProvider.kt
@@ -19,8 +19,9 @@ package im.vector.riotredesign.core.resources
 import android.content.res.Resources
 import androidx.core.os.ConfigurationCompat
 import java.util.*
+import javax.inject.Inject
 
-class LocaleProvider(private val resources: Resources) {
+class LocaleProvider @Inject constructor(private val resources: Resources) {
 
     fun current(): Locale {
         return ConfigurationCompat.getLocales(resources.configuration)[0]
diff --git a/vector/src/main/java/im/vector/riotredesign/core/resources/StringArrayProvider.kt b/vector/src/main/java/im/vector/riotredesign/core/resources/StringArrayProvider.kt
index f8e58d76..fe058ca3 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/resources/StringArrayProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/resources/StringArrayProvider.kt
@@ -19,8 +19,9 @@ package im.vector.riotredesign.core.resources
 import android.content.res.Resources
 import androidx.annotation.ArrayRes
 import androidx.annotation.NonNull
+import javax.inject.Inject
 
-class StringArrayProvider(private val resources: Resources) {
+class StringArrayProvider @Inject constructor(private val resources: Resources) {
 
     /**
      * Returns a localized string array from the application's package's
diff --git a/vector/src/main/java/im/vector/riotredesign/core/resources/StringProvider.kt b/vector/src/main/java/im/vector/riotredesign/core/resources/StringProvider.kt
index e6b0452e..f575f354 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/resources/StringProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/resources/StringProvider.kt
@@ -20,8 +20,9 @@ import android.content.res.Resources
 import androidx.annotation.NonNull
 import androidx.annotation.PluralsRes
 import androidx.annotation.StringRes
+import javax.inject.Inject
 
-class StringProvider(private val resources: Resources) {
+class StringProvider @Inject constructor(private val resources: Resources) {
 
     /**
      * Returns a localized string from the application's package's
diff --git a/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt b/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
index 108b27d5..0f26887e 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
@@ -28,7 +28,6 @@ import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.riotredesign.R
 import im.vector.riotredesign.features.notifications.NotifiableEventResolver
 import im.vector.riotredesign.features.notifications.NotificationUtils
-import org.koin.android.ext.android.inject
 import timber.log.Timber
 import java.util.concurrent.TimeUnit
 
@@ -162,7 +161,7 @@ class EventStreamServiceX : VectorService() {
                 val notification = NotificationUtils.buildForegroundServiceNotification(this, R.string.notification_sync_in_progress)
                 startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification)
             }
-            ACTION_GO_TO_FOREGROUND -> {
+            ACTION_GO_TO_FOREGROUND        -> {
                 // Stop foreground notification display
                 Timber.i("stopForeground")
                 stopForeground(true)
@@ -177,9 +176,9 @@ class EventStreamServiceX : VectorService() {
 
         when (action) {
             ACTION_START,
-            ACTION_GO_TO_FOREGROUND ->
+            ACTION_GO_TO_FOREGROUND        ->
                 when (serviceState) {
-                    ServiceState.INIT ->
+                    ServiceState.INIT    ->
                         start(false)
                     ServiceState.CATCHUP ->
                         // A push has been received before, just change state, to avoid stopping the service when catchup is over
@@ -190,12 +189,12 @@ class EventStreamServiceX : VectorService() {
                 }
             ACTION_STOP,
             ACTION_GO_TO_BACKGROUND,
-            ACTION_LOGOUT ->
+            ACTION_LOGOUT                  ->
                 stop()
             ACTION_PUSH_RECEIVED,
             ACTION_SIMULATED_PUSH_RECEIVED ->
                 when (serviceState) {
-                    ServiceState.INIT ->
+                    ServiceState.INIT    ->
                         start(true)
                     ServiceState.CATCHUP ->
                         catchup(true)
@@ -203,17 +202,17 @@ class EventStreamServiceX : VectorService() {
                         // Nothing to do
                         Unit
                 }
-            ACTION_PUSH_UPDATE -> pushStatusUpdate()
-            ACTION_BOOT_COMPLETE -> {
+            ACTION_PUSH_UPDATE             -> pushStatusUpdate()
+            ACTION_BOOT_COMPLETE           -> {
                 // No FCM only
                 mSimulatePushImmediate = true
                 stop()
             }
-            ACTION_APPLICATION_UPGRADE -> {
+            ACTION_APPLICATION_UPGRADE     -> {
                 // FDroid only
                 catchup(true)
             }
-            else -> {
+            else                           -> {
                 // Should not happen
             }
         }
@@ -247,8 +246,8 @@ class EventStreamServiceX : VectorService() {
             val pushSimulatorRequest = OneTimeWorkRequestBuilder()
                     .setInitialDelay(delay.toLong(), TimeUnit.MILLISECONDS)
                     .setConstraints(Constraints.Builder()
-                            .setRequiredNetworkType(NetworkType.CONNECTED)
-                            .build())
+                                            .setRequiredNetworkType(NetworkType.CONNECTED)
+                                            .build())
                     .addTag(PUSH_SIMULATOR_REQUEST_TAG)
                     .build()
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/AutocompleteCommandController.kt b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/AutocompleteCommandController.kt
index 7356364c..484ee2ce 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/AutocompleteCommandController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/AutocompleteCommandController.kt
@@ -20,8 +20,9 @@ import com.airbnb.epoxy.TypedEpoxyController
 import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.features.autocomplete.AutocompleteClickListener
 import im.vector.riotredesign.features.command.Command
+import javax.inject.Inject
 
-class AutocompleteCommandController(private val stringProvider: StringProvider) : TypedEpoxyController>() {
+class AutocompleteCommandController @Inject constructor(private val stringProvider: StringProvider) : TypedEpoxyController>() {
 
     var listener: AutocompleteClickListener? = null
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/AutocompleteCommandPresenter.kt b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/AutocompleteCommandPresenter.kt
index ca894948..4449d2ed 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/AutocompleteCommandPresenter.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/AutocompleteCommandPresenter.kt
@@ -20,9 +20,10 @@ import android.content.Context
 import com.airbnb.epoxy.EpoxyController
 import im.vector.riotredesign.features.autocomplete.EpoxyAutocompletePresenter
 import im.vector.riotredesign.features.command.Command
+import javax.inject.Inject
 
-class AutocompleteCommandPresenter(context: Context,
-                                   private val controller: AutocompleteCommandController) :
+class AutocompleteCommandPresenter @Inject constructor(context: Context,
+                                               private val controller: AutocompleteCommandController) :
         EpoxyAutocompletePresenter(context) {
 
     init {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/CommandAutocompletePolicy.kt b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/CommandAutocompletePolicy.kt
index 38556cdb..a6f9aa72 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/CommandAutocompletePolicy.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/command/CommandAutocompletePolicy.kt
@@ -18,8 +18,9 @@ package im.vector.riotredesign.features.autocomplete.command
 
 import android.text.Spannable
 import com.otaliastudios.autocomplete.AutocompletePolicy
+import javax.inject.Inject
 
-class CommandAutocompletePolicy : AutocompletePolicy {
+class CommandAutocompletePolicy @Inject constructor() : AutocompletePolicy {
 
     var enabled: Boolean = true
 
@@ -37,7 +38,7 @@ class CommandAutocompletePolicy : AutocompletePolicy {
     // Only if text which starts with '/' and without space
     override fun shouldShowPopup(text: Spannable?, cursorPos: Int): Boolean {
         return enabled && text?.startsWith("/") == true
-                && !text.contains(" ")
+               && !text.contains(" ")
     }
 
     override fun shouldDismissPopup(text: Spannable?, cursorPos: Int): Boolean {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserController.kt b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserController.kt
index 6f174e0d..dfc1f93f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserController.kt
@@ -19,8 +19,9 @@ package im.vector.riotredesign.features.autocomplete.user
 import com.airbnb.epoxy.TypedEpoxyController
 import im.vector.matrix.android.api.session.user.model.User
 import im.vector.riotredesign.features.autocomplete.AutocompleteClickListener
+import javax.inject.Inject
 
-class AutocompleteUserController : TypedEpoxyController>() {
+class AutocompleteUserController @Inject constructor(): TypedEpoxyController>() {
 
     var listener: AutocompleteClickListener? = null
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserPresenter.kt b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserPresenter.kt
index be4ec7e7..b525cfac 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserPresenter.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserPresenter.kt
@@ -22,9 +22,10 @@ import com.airbnb.mvrx.Async
 import com.airbnb.mvrx.Success
 import im.vector.matrix.android.api.session.user.model.User
 import im.vector.riotredesign.features.autocomplete.EpoxyAutocompletePresenter
+import javax.inject.Inject
 
-class AutocompleteUserPresenter(context: Context,
-                                private val controller: AutocompleteUserController
+class AutocompleteUserPresenter @Inject constructor(context: Context,
+                                            private val controller: AutocompleteUserController
 ) : EpoxyAutocompletePresenter(context) {
 
     var callback: Callback? = null
diff --git a/vector/src/main/java/im/vector/riotredesign/features/configuration/VectorConfiguration.kt b/vector/src/main/java/im/vector/riotredesign/features/configuration/VectorConfiguration.kt
index 1f408554..3790661a 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/configuration/VectorConfiguration.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/configuration/VectorConfiguration.kt
@@ -25,20 +25,22 @@ import im.vector.riotredesign.features.settings.VectorLocale
 import im.vector.riotredesign.features.themes.ThemeUtils
 import timber.log.Timber
 import java.util.*
+import javax.inject.Inject
 
 /**
  * Handle locale configuration change, such as theme, font size and locale chosen by the user
  */
-class VectorConfiguration(private val context: Context) {
+
+class VectorConfiguration @Inject constructor(private val context: Context) {
 
     // TODO Import mLanguageReceiver From Riot?
     fun onConfigurationChanged(newConfig: Configuration?) {
         if (Locale.getDefault().toString() != VectorLocale.applicationLocale.toString()) {
             Timber.v("## onConfigurationChanged() : the locale has been updated to " + Locale.getDefault().toString()
-                    + ", restore the expected value " + VectorLocale.applicationLocale.toString())
+                     + ", restore the expected value " + VectorLocale.applicationLocale.toString())
             updateApplicationSettings(VectorLocale.applicationLocale,
-                    FontScale.getFontScalePrefValue(context),
-                    ThemeUtils.getApplicationTheme(context))
+                                      FontScale.getFontScalePrefValue(context),
+                                      ThemeUtils.getApplicationTheme(context))
         }
     }
 
@@ -65,8 +67,8 @@ class VectorConfiguration(private val context: Context) {
     fun updateApplicationTheme(theme: String) {
         ThemeUtils.setApplicationTheme(context, theme)
         updateApplicationSettings(VectorLocale.applicationLocale,
-                FontScale.getFontScalePrefValue(context),
-                theme)
+                                  FontScale.getFontScalePrefValue(context),
+                                  theme)
     }
 
     /**
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt
index 5083dd9a..333342e1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt
@@ -23,7 +23,6 @@ import androidx.fragment.app.FragmentManager
 import androidx.lifecycle.Observer
 import androidx.lifecycle.ViewModelProviders
 import im.vector.fragments.keysbackup.restore.KeysBackupRestoreFromPassphraseFragment
-import im.vector.fragments.keysbackup.restore.KeysBackupRestoreSharedViewModel
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.platform.SimpleFragmentActivity
@@ -43,9 +42,8 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() {
 
     override fun initUiAndData() {
         super.initUiAndData()
-        viewModel = ViewModelProviders.of(this).get(KeysBackupRestoreSharedViewModel::class.java)
+        viewModel = ViewModelProviders.of(this, viewModelFactory).get(KeysBackupRestoreSharedViewModel::class.java)
         viewModel.initSession(session)
-
         viewModel.keyVersionResult.observe(this, Observer { keyVersion ->
 
             if (keyVersion != null && supportFragmentManager.fragments.isEmpty()) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt
index 8d07b3af..f104791f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt
@@ -27,7 +27,6 @@ import butterknife.BindView
 import butterknife.OnClick
 import butterknife.OnTextChanged
 import com.google.android.material.textfield.TextInputLayout
-import im.vector.fragments.keysbackup.restore.KeysBackupRestoreSharedViewModel
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.utils.startImportTextFromFileIntent
@@ -53,9 +52,9 @@ class KeysBackupRestoreFromKeyFragment : VectorBaseFragment() {
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
-        viewModel = ViewModelProviders.of(this).get(KeysBackupRestoreFromKeyViewModel::class.java)
+        viewModel = ViewModelProviders.of(this, viewModelFactory).get(KeysBackupRestoreFromKeyViewModel::class.java)
         sharedViewModel = activity?.run {
-            ViewModelProviders.of(this).get(KeysBackupRestoreSharedViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(KeysBackupRestoreSharedViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
         mKeyTextEdit.setText(viewModel.recoveryCode.value)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt
index dd536944..99a36f30 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt
@@ -18,7 +18,6 @@ package im.vector.riotredesign.features.crypto.keysbackup.restore
 import android.content.Context
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import im.vector.fragments.keysbackup.restore.KeysBackupRestoreSharedViewModel
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.listeners.StepProgressListener
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupService
@@ -28,8 +27,9 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.WaitingViewData
 import im.vector.riotredesign.core.ui.views.KeysBackupBanner
 import timber.log.Timber
+import javax.inject.Inject
 
-class KeysBackupRestoreFromKeyViewModel : ViewModel() {
+class KeysBackupRestoreFromKeyViewModel @Inject constructor() : ViewModel() {
 
     var recoveryCode: MutableLiveData = MutableLiveData()
     var recoveryCodeErrorText: MutableLiveData = MutableLiveData()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt
index 41d0a4e5..57ca3743 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt
@@ -36,6 +36,7 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.extensions.showPassword
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
+import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel
 
 class KeysBackupRestoreFromPassphraseFragment : VectorBaseFragment() {
 
@@ -68,9 +69,9 @@ class KeysBackupRestoreFromPassphraseFragment : VectorBaseFragment() {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
 
-        viewModel = ViewModelProviders.of(this).get(KeysBackupRestoreFromPassphraseViewModel::class.java)
+        viewModel = ViewModelProviders.of(this, viewModelFactory).get(KeysBackupRestoreFromPassphraseViewModel::class.java)
         sharedViewModel = activity?.run {
-            ViewModelProviders.of(this).get(KeysBackupRestoreSharedViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(KeysBackupRestoreSharedViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseViewModel.kt
index e60923fd..bdbfd23b 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseViewModel.kt
@@ -18,7 +18,6 @@ package im.vector.riotredesign.features.crypto.keysbackup.restore
 import android.content.Context
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import im.vector.fragments.keysbackup.restore.KeysBackupRestoreSharedViewModel
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.listeners.StepProgressListener
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupService
@@ -28,8 +27,9 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.WaitingViewData
 import im.vector.riotredesign.core.ui.views.KeysBackupBanner
 import timber.log.Timber
+import javax.inject.Inject
 
-class KeysBackupRestoreFromPassphraseViewModel : ViewModel() {
+class KeysBackupRestoreFromPassphraseViewModel @Inject constructor() : ViewModel() {
 
     var passphrase: MutableLiveData = MutableLiveData()
     var passphraseErrorText: MutableLiveData = MutableLiveData()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
index 3db0191e..d6c618ba 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package im.vector.fragments.keysbackup.restore
+package im.vector.riotredesign.features.crypto.keysbackup.restore
 
 import android.content.Context
 import androidx.lifecycle.LiveData
@@ -21,13 +21,14 @@ import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
-import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
 import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersionResult
+import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.WaitingViewData
 import im.vector.riotredesign.core.utils.LiveEvent
+import javax.inject.Inject
 
-class KeysBackupRestoreSharedViewModel : ViewModel() {
+class KeysBackupRestoreSharedViewModel @Inject constructor() : ViewModel() {
 
     companion object {
         const val NAVIGATE_TO_RECOVER_WITH_KEY = "NAVIGATE_TO_RECOVER_WITH_KEY"
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt
index 106ed764..6b4cc8b7 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt
@@ -20,7 +20,6 @@ import android.widget.TextView
 import androidx.lifecycle.ViewModelProviders
 import butterknife.BindView
 import butterknife.OnClick
-import im.vector.fragments.keysbackup.restore.KeysBackupRestoreSharedViewModel
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.utils.LiveEvent
@@ -40,7 +39,7 @@ class KeysBackupRestoreSuccessFragment : VectorBaseFragment() {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         sharedViewModel = activity?.run {
-            ViewModelProviders.of(this).get(KeysBackupRestoreSharedViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(KeysBackupRestoreSharedViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
         sharedViewModel.importKeyResult?.let {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
index 98b6716b..bc83aaf9 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
@@ -17,16 +17,16 @@ package im.vector.riotredesign.features.crypto.keysbackup.settings
 
 import android.content.Context
 import android.content.Intent
+import android.os.Bundle
 import androidx.appcompat.app.AlertDialog
 import com.airbnb.mvrx.Fail
 import com.airbnb.mvrx.Loading
 import com.airbnb.mvrx.viewModel
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.extensions.injector
 import im.vector.riotredesign.core.platform.SimpleFragmentActivity
 import im.vector.riotredesign.core.platform.WaitingViewData
-import im.vector.riotredesign.features.crypto.keysbackup.KeysBackupModule
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
+import javax.inject.Inject
 
 
 class KeysBackupManageActivity : SimpleFragmentActivity() {
@@ -41,12 +41,15 @@ class KeysBackupManageActivity : SimpleFragmentActivity() {
     override fun getTitleRes() = R.string.encryption_message_recovery
 
     private val viewModel: KeysBackupSettingsViewModel by viewModel()
+    @Inject lateinit var keysBackupSettingsViewModelFactory: KeysBackupSettingsViewModel.Factory
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        injector.inject(this)
+        super.onCreate(savedInstanceState)
+    }
 
     override fun initUiAndData() {
         super.initUiAndData()
-
-        bindScope(getOrCreateScope(KeysBackupModule.KEYS_BACKUP_SCOPE))
-
         if (supportFragmentManager.fragments.isEmpty()) {
             supportFragmentManager.beginTransaction()
                     .replace(R.id.container, KeysBackupSettingsFragment.newInstance())
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt
index 983a3e2a..3a0239d0 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt
@@ -21,17 +21,15 @@ import androidx.appcompat.app.AlertDialog
 import com.airbnb.mvrx.activityViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.extensions.injector
 import im.vector.riotredesign.core.platform.VectorBaseFragment
-import im.vector.riotredesign.features.crypto.keysbackup.KeysBackupModule
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreActivity
 import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupActivity
 import kotlinx.android.synthetic.main.fragment_keys_backup_settings.*
-import org.koin.android.ext.android.inject
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
+import javax.inject.Inject
 
 class KeysBackupSettingsFragment : VectorBaseFragment(),
-        KeysBackupSettingsRecyclerViewController.Listener {
+                                   KeysBackupSettingsRecyclerViewController.Listener {
 
     companion object {
         fun newInstance() = KeysBackupSettingsFragment()
@@ -39,14 +37,12 @@ class KeysBackupSettingsFragment : VectorBaseFragment(),
 
     override fun getLayoutResId() = R.layout.fragment_keys_backup_settings
 
-    private val keysBackupSettingsRecyclerViewController: KeysBackupSettingsRecyclerViewController by inject()
-
+    @Inject lateinit var keysBackupSettingsRecyclerViewController: KeysBackupSettingsRecyclerViewController
     private val viewModel: KeysBackupSettingsViewModel by activityViewModel()
 
     override fun onCreate(savedInstanceState: Bundle?) {
+        injector().inject(this)
         super.onCreate(savedInstanceState)
-
-        bindScope(getOrCreateScope(KeysBackupModule.KEYS_BACKUP_SCOPE))
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
index 80e716cc..6e555b58 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
@@ -17,11 +17,14 @@ package im.vector.riotredesign.features.crypto.keysbackup.settings
 
 import android.view.View
 import com.airbnb.epoxy.TypedEpoxyController
-import com.airbnb.mvrx.*
+import com.airbnb.mvrx.Async
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Loading
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
 import im.vector.matrix.android.internal.crypto.keysbackup.model.KeysBackupVersionTrust
-import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersionResult
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.epoxy.errorWithRetryItem
 import im.vector.riotredesign.core.epoxy.loadingItem
@@ -29,9 +32,10 @@ import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.core.ui.list.GenericItem
 import im.vector.riotredesign.core.ui.list.genericItem
 import java.util.*
+import javax.inject.Inject
 
-class KeysBackupSettingsRecyclerViewController(val stringProvider: StringProvider,
-                                               val session: Session) : TypedEpoxyController() {
+class KeysBackupSettingsRecyclerViewController @Inject constructor(val stringProvider: StringProvider,
+                                                                   val session: Session) : TypedEpoxyController() {
 
     var listener: Listener? = null
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt
index 969ff028..d656d90c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt
@@ -15,7 +15,15 @@
  */
 package im.vector.riotredesign.features.crypto.keysbackup.settings
 
-import com.airbnb.mvrx.*
+import com.airbnb.mvrx.ActivityViewModelContext
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Loading
+import com.airbnb.mvrx.MvRxViewModelFactory
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
+import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupService
@@ -23,33 +31,37 @@ import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupStateListener
 import im.vector.matrix.android.internal.crypto.keysbackup.model.KeysBackupVersionTrust
 import im.vector.riotredesign.core.platform.VectorViewModel
-import org.koin.android.ext.android.get
 
 
-class KeysBackupSettingsViewModel(initialState: KeysBackupSettingViewState,
-                                  session: Session) : VectorViewModel(initialState),
-        KeysBackupStateListener {
+class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState,
+                                                              session: Session
+) : VectorViewModel(initialState),
+    KeysBackupStateListener {
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: KeysBackupSettingViewState): KeysBackupSettingsViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: KeysBackupSettingViewState): KeysBackupSettingsViewModel? {
-            val session = viewModelContext.activity.get()
-
-            val firstState = state.copy(
-                    keysBackupState = session.getKeysBackupService().state,
-                    keysBackupVersion = session.getKeysBackupService().keysBackupVersion
-            )
-
-            return KeysBackupSettingsViewModel(firstState, session)
+            val activity: KeysBackupManageActivity = (viewModelContext as ActivityViewModelContext).activity()
+            return activity.keysBackupSettingsViewModelFactory.create(state)
         }
     }
 
     private var keysBackupService: KeysBackupService = session.getKeysBackupService()
 
     init {
+        setState {
+            this.copy(
+                    keysBackupState = session.getKeysBackupService().state,
+                    keysBackupVersion = session.getKeysBackupService().keysBackupVersion
+            )
+        }
         keysBackupService.addListener(this)
-
         getKeysBackupTrust()
     }
 
@@ -90,8 +102,8 @@ class KeysBackupSettingsViewModel(initialState: KeysBackupSettingViewState,
     }
 
     override fun onCleared() {
-        super.onCleared()
         keysBackupService.removeListener(this)
+        super.onCleared()
     }
 
     override fun onStateChange(newState: KeysBackupState) {
@@ -142,6 +154,6 @@ class KeysBackupSettingsViewModel(initialState: KeysBackupSettingViewState,
         val currentBackupState = keysBackupService.state
 
         return currentBackupState == KeysBackupState.Unknown
-                || currentBackupState == KeysBackupState.CheckingBackUpOnHomeserver
+               || currentBackupState == KeysBackupState.CheckingBackUpOnHomeserver
     }
 }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt
index 7ab0ab49..c4b88ead 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt
@@ -22,7 +22,6 @@ import androidx.core.view.isVisible
 import androidx.fragment.app.FragmentManager
 import androidx.lifecycle.Observer
 import androidx.lifecycle.ViewModelProviders
-import im.vector.fragments.keysbackup.setup.KeysBackupSetupSharedViewModel
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.dialogs.ExportKeysDialog
 import im.vector.riotredesign.core.extensions.observeEvent
@@ -42,7 +41,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
                     .commitNow()
         }
 
-        viewModel = ViewModelProviders.of(this).get(KeysBackupSetupSharedViewModel::class.java)
+        viewModel = ViewModelProviders.of(this, viewModelFactory).get(KeysBackupSetupSharedViewModel::class.java)
         viewModel.showManualExport.value = intent.getBooleanExtra(EXTRA_SHOW_MANUAL_EXPORT, false)
         viewModel.initSession(session)
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt
index c9d11d16..81ccb5a0 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package im.vector.fragments.keysbackup.setup
+package im.vector.riotredesign.features.crypto.keysbackup.setup
 
 import android.content.Context
 import androidx.lifecycle.MutableLiveData
@@ -30,11 +30,12 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.WaitingViewData
 import im.vector.riotredesign.core.utils.LiveEvent
 import timber.log.Timber
+import javax.inject.Inject
 
 /**
  * The shared view model between all fragments.
  */
-class KeysBackupSetupSharedViewModel : ViewModel() {
+class KeysBackupSetupSharedViewModel @Inject constructor() : ViewModel() {
 
     companion object {
         const val NAVIGATE_TO_STEP_2 = "NAVIGATE_TO_STEP_2"
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep1Fragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep1Fragment.kt
index 0fccd510..f90983f7 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep1Fragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep1Fragment.kt
@@ -24,7 +24,6 @@ import androidx.lifecycle.Observer
 import androidx.lifecycle.ViewModelProviders
 import butterknife.BindView
 import butterknife.OnClick
-import im.vector.fragments.keysbackup.setup.KeysBackupSetupSharedViewModel
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.utils.LiveEvent
@@ -51,7 +50,7 @@ class KeysBackupSetupStep1Fragment : VectorBaseFragment() {
         super.onActivityCreated(savedInstanceState)
 
         viewModel = activity?.run {
-            ViewModelProviders.of(this).get(KeysBackupSetupSharedViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(KeysBackupSetupSharedViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
         viewModel.showManualExport.observe(this, Observer {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt
index 47ade276..5267c22b 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt
@@ -30,7 +30,6 @@ import butterknife.OnClick
 import butterknife.OnTextChanged
 import com.google.android.material.textfield.TextInputLayout
 import com.nulabinc.zxcvbn.Zxcvbn
-import im.vector.fragments.keysbackup.setup.KeysBackupSetupSharedViewModel
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.extensions.showPassword
 import im.vector.riotredesign.core.platform.VectorBaseFragment
@@ -82,7 +81,7 @@ class KeysBackupSetupStep2Fragment : VectorBaseFragment() {
         super.onActivityCreated(savedInstanceState)
 
         viewModel = activity?.run {
-            ViewModelProviders.of(this).get(KeysBackupSetupSharedViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(KeysBackupSetupSharedViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
         viewModel.shouldPromptOnBack = true
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
index a951b4c1..0a738bf5 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
@@ -28,7 +28,6 @@ import androidx.lifecycle.ViewModelProviders
 import butterknife.BindView
 import butterknife.OnClick
 import com.google.android.material.bottomsheet.BottomSheetDialog
-import im.vector.fragments.keysbackup.setup.KeysBackupSetupSharedViewModel
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.files.addEntryToDownloadManager
 import im.vector.riotredesign.core.files.saveStringToFile
@@ -58,7 +57,7 @@ class KeysBackupSetupStep3Fragment : VectorBaseFragment() {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         viewModel = activity?.run {
-            ViewModelProviders.of(this).get(KeysBackupSetupSharedViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(KeysBackupSetupSharedViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysrequest/KeyRequestHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysrequest/KeyRequestHandler.kt
index 30d16a62..a583760a 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysrequest/KeyRequestHandler.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysrequest/KeyRequestHandler.kt
@@ -40,6 +40,8 @@ import timber.log.Timber
 import java.text.DateFormat
 import java.text.SimpleDateFormat
 import java.util.*
+import javax.inject.Inject
+import javax.inject.Singleton
 import kotlin.collections.ArrayList
 import kotlin.collections.HashMap
 
@@ -50,21 +52,20 @@ import kotlin.collections.HashMap
  * If several requests come from same user/device, a single alert is displayed (this alert will accept/reject all request
  * depending on user action)
  */
-class KeyRequestHandler(val context: Context,
-                        val session: Session)
+
+@Singleton
+class KeyRequestHandler @Inject constructor(val context: Context,
+                                            val session: Session)
     : RoomKeysRequestListener,
-        SasVerificationService.SasVerificationListener {
+      SasVerificationService.SasVerificationListener {
 
     private val alertsToRequests = HashMap>()
 
     init {
         session.getSasVerificationService().addListener(this)
-
         session.addRoomKeysRequestListener(this)
     }
 
-    fun ensureStarted() = Unit
-
     /**
      * Handle incoming key request.
      *
@@ -194,8 +195,8 @@ class KeyRequestHandler(val context: Context,
                 Runnable {
                     alert.weakCurrentActivity?.get()?.let {
                         val intent = SASVerificationActivity.outgoingIntent(it,
-                                session.sessionParams.credentials.userId,
-                                userId, deviceId)
+                                                                            session.sessionParams.credentials.userId,
+                                                                            userId, deviceId)
                         it.startActivity(intent)
                     }
                 },
@@ -246,8 +247,8 @@ class KeyRequestHandler(val context: Context,
         val alertMgrUniqueKey = alertManagerId(deviceId!!, userId!!)
         alertsToRequests[alertMgrUniqueKey]?.removeAll {
             it.deviceId == request.deviceId
-                    && it.userId == request.userId
-                    && it.requestId == request.requestId
+            && it.userId == request.userId
+            && it.requestId == request.requestId
         }
         if (alertsToRequests[alertMgrUniqueKey]?.isEmpty() == true) {
             PopupAlertManager.cancelAlert(alertMgrUniqueKey)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/IncomingVerificationRequestHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/IncomingVerificationRequestHandler.kt
index 87cb3b54..f670a599 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/IncomingVerificationRequestHandler.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/IncomingVerificationRequestHandler.kt
@@ -23,19 +23,21 @@ import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTransactio
 import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTxState
 import im.vector.riotredesign.R
 import im.vector.riotredesign.features.popup.PopupAlertManager
+import javax.inject.Inject
+import javax.inject.Singleton
 
 /**
  * Listens to the VerificationManager and add a new notification when an incoming request is detected.
  */
-class IncomingVerificationRequestHandler(val context: Context,
-                                         private val session: Session) : SasVerificationService.SasVerificationListener {
+@Singleton
+class IncomingVerificationRequestHandler @Inject constructor(val context: Context,
+                                                             private val session: Session
+) : SasVerificationService.SasVerificationListener {
 
     init {
         session.getSasVerificationService().addListener(this)
     }
 
-    fun ensureStarted() = Unit
-
     override fun transactionCreated(tx: SasVerificationTransaction) {}
 
     override fun transactionUpdated(tx: SasVerificationTransaction) {
@@ -44,7 +46,7 @@ class IncomingVerificationRequestHandler(val context: Context,
                 //Add a notification for every incoming request
                 val session = Matrix.getInstance().currentSession!!
                 val name = session.getUser(tx.otherUserId)?.displayName
-                        ?: tx.otherUserId
+                           ?: tx.otherUserId
 
                 val alert = PopupAlertManager.VectorAlert(
                         "kvr_${tx.transactionId}",
@@ -54,9 +56,9 @@ class IncomingVerificationRequestHandler(val context: Context,
                         .apply {
                             contentAction = Runnable {
                                 val intent = SASVerificationActivity.incomingIntent(context,
-                                        session.sessionParams.credentials.userId,
-                                        tx.otherUserId,
-                                        tx.transactionId)
+                                                                                    session.sessionParams.credentials.userId,
+                                                                                    tx.otherUserId,
+                                                                                    tx.transactionId)
                                 weakCurrentActivity?.get()?.startActivity(intent)
                             }
                             dismissedAction = Runnable {
@@ -72,9 +74,9 @@ class IncomingVerificationRequestHandler(val context: Context,
                                     context.getString(R.string.action_open),
                                     Runnable {
                                         val intent = SASVerificationActivity.incomingIntent(context,
-                                                session.sessionParams.credentials.userId,
-                                                tx.otherUserId,
-                                                tx.transactionId)
+                                                                                            session.sessionParams.credentials.userId,
+                                                                                            tx.otherUserId,
+                                                                                            tx.transactionId)
                                         weakCurrentActivity?.get()?.startActivity(intent)
                                     }
                             )
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationActivity.kt
index 4fed4d96..c66a001c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationActivity.kt
@@ -84,7 +84,7 @@ class SASVerificationActivity : SimpleFragmentActivity() {
 
     override fun initUiAndData() {
         super.initUiAndData()
-        viewModel = ViewModelProviders.of(this).get(SasVerificationViewModel::class.java)
+        viewModel = ViewModelProviders.of(this, viewModelFactory).get(SasVerificationViewModel::class.java)
         val transactionID: String? = intent.getStringExtra(EXTRA_TRANSACTION_ID)
 
         if (isFirstCreation()) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
index 35ef1acc..9f893afc 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
@@ -53,7 +53,7 @@ class SASVerificationIncomingFragment : VectorBaseFragment() {
         super.onActivityCreated(savedInstanceState)
 
         viewModel = activity?.run {
-            ViewModelProviders.of(this).get(SasVerificationViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(SasVerificationViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
         otherUserDisplayNameTextView.text = viewModel.otherUser?.displayName ?: viewModel.otherUserId
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationShortCodeFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationShortCodeFragment.kt
index b0363fae..faf40995 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationShortCodeFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationShortCodeFragment.kt
@@ -69,7 +69,7 @@ class SASVerificationShortCodeFragment : VectorBaseFragment() {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         viewModel = activity?.run {
-            ViewModelProviders.of(this).get(SasVerificationViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(SasVerificationViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationStartFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationStartFragment.kt
index e41d0c73..ce92888c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationStartFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationStartFragment.kt
@@ -58,11 +58,7 @@ class SASVerificationStartFragment : VectorBaseFragment() {
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
-
-        viewModel = activity?.run {
-            ViewModelProviders.of(this).get(SasVerificationViewModel::class.java)
-        } ?: throw Exception("Invalid Activity")
-
+        viewModel = ViewModelProviders.of(vectorBaseActivity, viewModelFactory).get(SasVerificationViewModel::class.java)
         viewModel.transactionState.observe(this, Observer {
             val uxState = (viewModel.transaction as? OutgoingSasVerificationRequest)?.uxState
             when (uxState) {
@@ -75,14 +71,14 @@ class SASVerificationStartFragment : VectorBaseFragment() {
                     this.startButtonLoading.animate()
 
                 }
-                OutgoingSasVerificationRequest.UxState.SHOW_SAS -> {
+                OutgoingSasVerificationRequest.UxState.SHOW_SAS               -> {
                     viewModel.shortCodeReady()
                 }
                 OutgoingSasVerificationRequest.UxState.CANCELLED_BY_ME,
-                OutgoingSasVerificationRequest.UxState.CANCELLED_BY_OTHER -> {
+                OutgoingSasVerificationRequest.UxState.CANCELLED_BY_OTHER     -> {
                     viewModel.navigateCancel()
                 }
-                else -> {
+                else                                                          -> {
                     TransitionManager.beginDelayedTransition(this.rootLayout)
                     this.loadingText.isVisible = false
                     this.startButton.isVisible = true
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationVerifiedFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationVerifiedFragment.kt
index a14dc3ce..47e874be 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationVerifiedFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationVerifiedFragment.kt
@@ -35,7 +35,7 @@ class SASVerificationVerifiedFragment : VectorBaseFragment() {
         super.onActivityCreated(savedInstanceState)
 
         viewModel = activity?.run {
-            ViewModelProviders.of(this).get(SasVerificationViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(SasVerificationViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
 
     }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SasVerificationViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SasVerificationViewModel.kt
index 7f06bba8..31fc91a4 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SasVerificationViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SasVerificationViewModel.kt
@@ -25,10 +25,11 @@ import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTransactio
 import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTxState
 import im.vector.matrix.android.api.session.user.model.User
 import im.vector.riotredesign.core.utils.LiveEvent
+import javax.inject.Inject
 
 
-class SasVerificationViewModel : ViewModel(),
-        SasVerificationService.SasVerificationListener {
+class SasVerificationViewModel @Inject constructor() : ViewModel(),
+                                                       SasVerificationService.SasVerificationListener {
 
 
     companion object {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
index c507224d..fb5671d2 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
@@ -43,9 +43,7 @@ import im.vector.riotredesign.features.rageshake.BugReporter
 import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
 import im.vector.riotredesign.features.workers.signout.SignOutUiWorker
 import kotlinx.android.synthetic.main.activity_home.*
-import org.koin.android.ext.android.inject
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
+import javax.inject.Inject
 
 
 class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
@@ -57,12 +55,13 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
 
     private val homeActivityViewModel: HomeActivityViewModel by viewModel()
     private lateinit var navigationViewModel: HomeNavigationViewModel
-    private val homeNavigator by inject()
 
+    @Inject lateinit var homeActivityViewModelFactory: HomeActivityViewModel.Factory
+    @Inject lateinit var homeNavigator: HomeNavigator
     // TODO Move this elsewhere
-    private val incomingVerificationRequestHandler by inject()
+    @Inject lateinit var incomingVerificationRequestHandler: IncomingVerificationRequestHandler
     // TODO Move this elsewhere
-    private val keyRequestHandler by inject()
+    @Inject lateinit var keyRequestHandler: KeyRequestHandler
 
     private var progress: ProgressDialog? = null
 
@@ -76,10 +75,8 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        bindScope(getOrCreateScope(HomeModule.HOME_SCOPE))
         homeNavigator.activity = this
-
-        navigationViewModel = ViewModelProviders.of(this).get(HomeNavigationViewModel::class.java)
+        navigationViewModel = ViewModelProviders.of(this, viewModelFactory).get(HomeNavigationViewModel::class.java)
 
         drawerLayout.addDrawerListener(drawerListener)
         if (isFirstCreation()) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivityViewModel.kt
index c710b477..a2f373fa 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivityViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivityViewModel.kt
@@ -19,10 +19,12 @@ package im.vector.riotredesign.features.home
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import arrow.core.Option
+import com.airbnb.mvrx.ActivityViewModelContext
 import com.airbnb.mvrx.MvRxState
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
-import im.vector.matrix.android.api.Matrix
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.group.model.GroupSummary
@@ -34,28 +36,31 @@ import im.vector.riotredesign.features.home.group.ALL_COMMUNITIES_GROUP_ID
 import im.vector.riotredesign.features.home.group.SelectedGroupStore
 import io.reactivex.Observable
 import io.reactivex.functions.BiFunction
-import org.koin.android.ext.android.get
 import java.util.concurrent.TimeUnit
 
 data class EmptyState(val isEmpty: Boolean = true) : MvRxState
 
-class HomeActivityViewModel(state: EmptyState,
-                            private val session: Session,
-                            private val selectedGroupStore: SelectedGroupStore,
-                            private val homeRoomListStore: HomeRoomListObservableStore
-) : VectorViewModel(state), Session.Listener {
+class HomeActivityViewModel @AssistedInject constructor(@Assisted initialState: EmptyState,
+                                                        private val session: Session,
+                                                        private val selectedGroupStore: SelectedGroupStore,
+                                                        private val homeRoomListStore: HomeRoomListObservableStore
+) : VectorViewModel(initialState), Session.Listener {
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: EmptyState): HomeActivityViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: EmptyState): HomeActivityViewModel? {
-            val session = Matrix.getInstance().currentSession!!
-            val selectedGroupStore = viewModelContext.activity.get()
-            val homeRoomListObservableSource = viewModelContext.activity.get()
-            return HomeActivityViewModel(state, session, selectedGroupStore, homeRoomListObservableSource)
+            val homeActivity: HomeActivity = (viewModelContext as ActivityViewModelContext).activity()
+            return homeActivity.homeActivityViewModelFactory.create(state)
         }
     }
 
+
     private val _isLoading = MutableLiveData()
     val isLoading: LiveData
         get() = _isLoading
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
index 273a06d0..bb03f2cd 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
@@ -41,7 +41,7 @@ import im.vector.riotredesign.features.home.room.list.UnreadCounterBadgeView
 import im.vector.riotredesign.features.workers.signout.SignOutViewModel
 import kotlinx.android.parcel.Parcelize
 import kotlinx.android.synthetic.main.fragment_home_detail.*
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 
 @Parcelize
@@ -67,7 +67,8 @@ class HomeDetailFragment : VectorBaseFragment(), KeysBackupBanner.Delegate {
     private val viewModel: HomeDetailViewModel by fragmentViewModel()
     private lateinit var navigationViewModel: HomeNavigationViewModel
 
-    private val session by inject()
+    @Inject lateinit var session: Session
+    @Inject lateinit var homeDetailViewModelFactory: HomeDetailViewModel.Factory
 
     override fun getLayoutResId(): Int {
         return R.layout.fragment_home_detail
@@ -76,7 +77,7 @@ class HomeDetailFragment : VectorBaseFragment(), KeysBackupBanner.Delegate {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         currentDisplayMode = savedInstanceState?.getSerializable(CURRENT_DISPLAY_MODE) as? RoomListFragment.DisplayMode
-                ?: RoomListFragment.DisplayMode.HOME
+                             ?: RoomListFragment.DisplayMode.HOME
 
         navigationViewModel = ViewModelProviders.of(requireActivity()).get(HomeNavigationViewModel::class.java)
 
@@ -89,7 +90,7 @@ class HomeDetailFragment : VectorBaseFragment(), KeysBackupBanner.Delegate {
     private fun setupKeysBackupBanner() {
         // Keys backup banner
         // Use the SignOutViewModel, it observe the keys backup state and this is what we need here
-        val model = ViewModelProviders.of(this).get(SignOutViewModel::class.java)
+        val model = ViewModelProviders.of(this, viewModelFactory).get(SignOutViewModel::class.java)
 
         model.init(session)
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailViewModel.kt
index 7e2ebb7f..59ff9a75 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailViewModel.kt
@@ -16,28 +16,34 @@
 
 package im.vector.riotredesign.features.home
 
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.rx.rx
 import im.vector.riotredesign.core.platform.VectorViewModel
-import org.koin.android.ext.android.get
 
 /**
  * View model used to update the home bottom bar notification counts
  */
-class HomeDetailViewModel(initialState: HomeDetailViewState,
-                          private val session: Session,
-                          private val homeRoomListStore: HomeRoomListObservableStore)
+class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: HomeDetailViewState,
+                                                      private val session: Session,
+                                                      private val homeRoomListStore: HomeRoomListObservableStore)
     : VectorViewModel(initialState) {
 
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: HomeDetailViewState): HomeDetailViewModel
+    }
+
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: HomeDetailViewState): HomeDetailViewModel? {
-            val homeRoomListStore = viewModelContext.activity.get()
-            val session = viewModelContext.activity.get()
-            return HomeDetailViewModel(state, session, homeRoomListStore)
+            val fragment: HomeDetailFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.homeDetailViewModelFactory.create(state)
         }
     }
 
@@ -65,21 +71,21 @@ class HomeDetailViewModel(initialState: HomeDetailViewState,
                 .subscribe { list ->
                     list.let { summaries ->
                         val peopleNotifications = summaries
-                                .filter { it.isDirect }
-                                .map { it.notificationCount }
-                                .takeIf { it.isNotEmpty() }
-                                ?.sumBy { i -> i }
-                                ?: 0
+                                                          .filter { it.isDirect }
+                                                          .map { it.notificationCount }
+                                                          .takeIf { it.isNotEmpty() }
+                                                          ?.sumBy { i -> i }
+                                                  ?: 0
                         val peopleHasHighlight = summaries
                                 .filter { it.isDirect }
                                 .any { it.highlightCount > 0 }
 
                         val roomsNotifications = summaries
-                                .filter { !it.isDirect }
-                                .map { it.notificationCount }
-                                .takeIf { it.isNotEmpty() }
-                                ?.sumBy { i -> i }
-                                ?: 0
+                                                         .filter { !it.isDirect }
+                                                         .map { it.notificationCount }
+                                                         .takeIf { it.isNotEmpty() }
+                                                         ?.sumBy { i -> i }
+                                                 ?: 0
                         val roomsHasHighlight = summaries
                                 .filter { !it.isDirect }
                                 .any { it.highlightCount > 0 }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
index 66195881..49ee8f67 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
@@ -24,7 +24,7 @@ import im.vector.riotredesign.core.extensions.replaceChildFragment
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.home.group.GroupListFragment
 import kotlinx.android.synthetic.main.fragment_home_drawer.*
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 class HomeDrawerFragment : VectorBaseFragment() {
 
@@ -35,7 +35,7 @@ class HomeDrawerFragment : VectorBaseFragment() {
         }
     }
 
-    val session by inject()
+    @Inject lateinit var session: Session
 
     override fun getLayoutResId() = R.layout.fragment_home_drawer
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt
index 22d52787..eee5b8e8 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt
@@ -16,89 +16,20 @@
 
 package im.vector.riotredesign.features.home
 
-import androidx.fragment.app.Fragment
-import im.vector.riotredesign.core.glide.GlideApp
-import im.vector.riotredesign.core.resources.ColorProvider
-import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandController
-import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
-import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserController
-import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserPresenter
-import im.vector.riotredesign.features.home.group.GroupSummaryController
-import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
-import im.vector.riotredesign.features.home.room.detail.timeline.factory.*
-import im.vector.riotredesign.features.home.room.detail.timeline.format.NoticeEventFormatter
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
-import im.vector.riotredesign.features.home.room.list.RoomSummaryController
-import im.vector.riotredesign.features.html.EventHtmlRenderer
-import org.koin.core.parameter.parametersOf
-import org.koin.dsl.module.module
+import android.os.Handler
+import dagger.Module
+import dagger.Provides
+import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventControllerHandler
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineAsyncHelper
 
-class HomeModule {
+@Module
+object HomeModule {
 
-    companion object {
-        const val HOME_SCOPE = "HOME_SCOPE"
-        const val ROOM_DETAIL_SCOPE = "ROOM_DETAIL_SCOPE"
+    @Provides
+    @JvmStatic
+    @TimelineEventControllerHandler
+    fun providesTimelineBackgroundHandler(): Handler {
+        return TimelineAsyncHelper.getBackgroundHandler()
     }
 
-    val definition = module {
-
-        // Activity scope
-
-        scope(HOME_SCOPE) {
-            HomeNavigator()
-        }
-
-        scope(HOME_SCOPE) {
-            HomePermalinkHandler(get(), get())
-        }
-
-        // Fragment scopes
-
-        factory {
-            TimelineDateFormatter(get())
-        }
-
-        factory {
-            NoticeEventFormatter(get())
-        }
-
-        factory { (fragment: Fragment) ->
-            val colorProvider = ColorProvider(fragment.requireContext())
-            val timelineDateFormatter = get()
-            val eventHtmlRenderer = EventHtmlRenderer(GlideApp.with(fragment), fragment.requireContext(), get())
-            val noticeEventFormatter = get(parameters = { parametersOf(fragment) })
-            val timelineMediaSizeProvider = TimelineMediaSizeProvider()
-            val messageItemFactory = MessageItemFactory(colorProvider, timelineMediaSizeProvider,
-                    timelineDateFormatter, eventHtmlRenderer, get(), get())
-
-            val timelineItemFactory = TimelineItemFactory(
-                    messageItemFactory = messageItemFactory,
-                    noticeItemFactory = NoticeItemFactory(noticeEventFormatter),
-                    defaultItemFactory = DefaultItemFactory(),
-                    encryptionItemFactory = EncryptionItemFactory(get()),
-                    encryptedItemFactory = EncryptedItemFactory(get())
-            )
-            TimelineEventController(timelineDateFormatter, timelineItemFactory, timelineMediaSizeProvider)
-        }
-
-        factory {
-            RoomSummaryController(get(), get(), get())
-        }
-
-        factory {
-            GroupSummaryController()
-        }
-
-        scope(ROOM_DETAIL_SCOPE) { (fragment: Fragment) ->
-            val commandController = AutocompleteCommandController(get())
-            AutocompleteCommandPresenter(fragment.requireContext(), commandController)
-        }
-
-        scope(ROOM_DETAIL_SCOPE) { (fragment: Fragment) ->
-            val userController = AutocompleteUserController()
-            AutocompleteUserPresenter(fragment.requireContext(), userController)
-        }
-
-    }
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigationViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigationViewModel.kt
index d922f3ae..c678b5f5 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigationViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigationViewModel.kt
@@ -17,5 +17,6 @@
 package im.vector.riotredesign.features.home
 
 import im.vector.riotredesign.core.mvrx.NavigationViewModel
+import javax.inject.Inject
 
-class HomeNavigationViewModel : NavigationViewModel()
\ No newline at end of file
+class HomeNavigationViewModel @Inject constructor() : NavigationViewModel()
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigator.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigator.kt
index e46fd7f5..bc3b7bfb 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigator.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigator.kt
@@ -24,11 +24,11 @@ import im.vector.riotredesign.core.extensions.replaceFragment
 import im.vector.riotredesign.features.navigation.Navigator
 import kotlinx.android.synthetic.main.activity_home.*
 import timber.log.Timber
+import javax.inject.Inject
 
-class HomeNavigator {
+class HomeNavigator @Inject constructor() {
 
     var activity: HomeActivity? = null
-
     private var rootRoomId: String? = null
 
     fun openSelectedGroup(groupSummary: GroupSummary) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt
index dc387aa5..9041dec1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt
@@ -20,9 +20,10 @@ import android.net.Uri
 import im.vector.matrix.android.api.permalinks.PermalinkData
 import im.vector.matrix.android.api.permalinks.PermalinkParser
 import im.vector.riotredesign.features.navigation.Navigator
+import javax.inject.Inject
 
-class HomePermalinkHandler(private val homeNavigator: HomeNavigator,
-                           private val navigator: Navigator) {
+class HomePermalinkHandler @Inject constructor(private val homeNavigator: HomeNavigator,
+                                               private val navigator: Navigator) {
 
     fun launch(deepLink: String?) {
         val uri = deepLink?.let { Uri.parse(it) }
@@ -35,16 +36,16 @@ class HomePermalinkHandler(private val homeNavigator: HomeNavigator,
         }
         val permalinkData = PermalinkParser.parse(deepLink)
         when (permalinkData) {
-            is PermalinkData.EventLink -> {
+            is PermalinkData.EventLink    -> {
                 homeNavigator.openRoomDetail(permalinkData.roomIdOrAlias, permalinkData.eventId, navigator)
             }
-            is PermalinkData.RoomLink -> {
+            is PermalinkData.RoomLink     -> {
                 homeNavigator.openRoomDetail(permalinkData.roomIdOrAlias, null, navigator)
             }
-            is PermalinkData.GroupLink -> {
+            is PermalinkData.GroupLink    -> {
                 homeNavigator.openGroupDetail(permalinkData.groupId)
             }
-            is PermalinkData.UserLink -> {
+            is PermalinkData.UserLink     -> {
                 homeNavigator.openUserDetail(permalinkData.userId)
             }
             is PermalinkData.FallbackLink -> {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeRoomListObservableStore.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeRoomListObservableStore.kt
index 9eaa47a7..e455961f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeRoomListObservableStore.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeRoomListObservableStore.kt
@@ -21,8 +21,11 @@ import im.vector.riotredesign.core.utils.RxStore
 import im.vector.riotredesign.features.home.room.list.RoomListDisplayModeFilter
 import im.vector.riotredesign.features.home.room.list.RoomListFragment
 import io.reactivex.Observable
+import javax.inject.Inject
+import javax.inject.Singleton
 
-class HomeRoomListObservableStore : RxStore>() {
+@Singleton
+class HomeRoomListObservableStore @Inject constructor() : RxStore>() {
 
     fun observeFilteredBy(displayMode: RoomListFragment.DisplayMode): Observable> {
         return observe()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListFragment.kt
index ba65cf72..58715088 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListFragment.kt
@@ -27,7 +27,7 @@ import im.vector.riotredesign.core.platform.StateView
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.home.HomeNavigator
 import kotlinx.android.synthetic.main.fragment_group_list.*
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 class GroupListFragment : VectorBaseFragment(), GroupSummaryController.Callback {
 
@@ -38,8 +38,10 @@ class GroupListFragment : VectorBaseFragment(), GroupSummaryController.Callback
     }
 
     private val viewModel: GroupListViewModel by fragmentViewModel()
-    private val homeNavigator by inject()
-    private val groupController by inject()
+
+    @Inject lateinit var groupListViewModelFactory: GroupListViewModel.Factory
+    @Inject lateinit var homeNavigator: HomeNavigator
+    @Inject lateinit var groupController: GroupSummaryController
 
     override fun getLayoutResId() = R.layout.fragment_group_list
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListViewModel.kt
index c06cbe5e..d6095f03 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListViewModel.kt
@@ -19,8 +19,11 @@ package im.vector.riotredesign.features.home.group
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import arrow.core.Option
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.group.model.GroupSummary
 import im.vector.matrix.rx.rx
@@ -28,24 +31,27 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.VectorViewModel
 import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.core.utils.LiveEvent
-import org.koin.android.ext.android.get
 
 const val ALL_COMMUNITIES_GROUP_ID = "ALL_COMMUNITIES_GROUP_ID"
 
-class GroupListViewModel(initialState: GroupListViewState,
-                         private val selectedGroupHolder: SelectedGroupStore,
-                         private val session: Session,
-                         private val stringProvider: StringProvider
+class GroupListViewModel @AssistedInject constructor(@Assisted initialState: GroupListViewState,
+                                                     private val selectedGroupHolder: SelectedGroupStore,
+                                                     private val session: Session,
+                                                     private val stringProvider: StringProvider
 ) : VectorViewModel(initialState) {
 
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: GroupListViewState): GroupListViewModel
+    }
+
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: GroupListViewState): GroupListViewModel? {
-            val currentSession = viewModelContext.activity.get()
-            val selectedGroupHolder = viewModelContext.activity.get()
-            val stringProvider = viewModelContext.activity.get()
-            return GroupListViewModel(state, selectedGroupHolder, currentSession, stringProvider)
+            val groupListFragment: GroupListFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return groupListFragment.groupListViewModelFactory.create(state)
         }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryController.kt b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryController.kt
index fe40b162..e82afb54 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryController.kt
@@ -18,8 +18,9 @@ package im.vector.riotredesign.features.home.group
 
 import com.airbnb.epoxy.TypedEpoxyController
 import im.vector.matrix.android.api.session.group.model.GroupSummary
+import javax.inject.Inject
 
-class GroupSummaryController : TypedEpoxyController() {
+class GroupSummaryController @Inject constructor(): TypedEpoxyController() {
 
     var callback: Callback? = null
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/group/SelectedGroupStore.kt b/vector/src/main/java/im/vector/riotredesign/features/home/group/SelectedGroupStore.kt
index 5ee3cc4b..5bd0cc4e 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/group/SelectedGroupStore.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/group/SelectedGroupStore.kt
@@ -19,5 +19,8 @@ package im.vector.riotredesign.features.home.group
 import arrow.core.Option
 import im.vector.matrix.android.api.session.group.model.GroupSummary
 import im.vector.riotredesign.core.utils.RxStore
+import javax.inject.Inject
+import javax.inject.Singleton
 
-class SelectedGroupStore : RxStore>(Option.empty())
+@Singleton
+class SelectedGroupStore @Inject constructor() : RxStore>(Option.empty())
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
index 1cabc032..16124ccc 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
@@ -57,7 +57,13 @@ import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
 import im.vector.matrix.android.api.session.room.model.Membership
-import im.vector.matrix.android.api.session.room.model.message.*
+import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
+import im.vector.matrix.android.api.session.room.model.message.MessageContent
+import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
+import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
+import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
+import im.vector.matrix.android.api.session.room.model.message.MessageType
+import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.matrix.android.api.session.user.model.User
 import im.vector.riotredesign.R
@@ -67,13 +73,19 @@ import im.vector.riotredesign.core.extensions.hideKeyboard
 import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.glide.GlideApp
 import im.vector.riotredesign.core.platform.VectorBaseFragment
-import im.vector.riotredesign.core.utils.*
+import im.vector.riotredesign.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
+import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA
+import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_NATIVE_CAMERA
+import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_NATIVE_VIDEO_CAMERA
+import im.vector.riotredesign.core.utils.checkPermissions
+import im.vector.riotredesign.core.utils.copyToClipboard
+import im.vector.riotredesign.core.utils.openCamera
+import im.vector.riotredesign.core.utils.shareMedia
 import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
 import im.vector.riotredesign.features.autocomplete.command.CommandAutocompletePolicy
 import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserPresenter
 import im.vector.riotredesign.features.command.Command
 import im.vector.riotredesign.features.home.AvatarRenderer
-import im.vector.riotredesign.features.home.HomeModule
 import im.vector.riotredesign.features.home.HomePermalinkHandler
 import im.vector.riotredesign.features.home.getColorFromUserId
 import im.vector.riotredesign.features.home.room.detail.composer.TextComposerActions
@@ -99,14 +111,11 @@ import kotlinx.android.parcel.Parcelize
 import kotlinx.android.synthetic.main.fragment_room_detail.*
 import kotlinx.android.synthetic.main.merge_composer_layout.view.*
 import org.commonmark.parser.Parser
-import org.koin.android.ext.android.inject
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
-import org.koin.core.parameter.parametersOf
 import ru.noties.markwon.Markwon
 import ru.noties.markwon.html.HtmlPlugin
 import timber.log.Timber
 import java.io.File
+import javax.inject.Inject
 
 
 @Parcelize
@@ -156,19 +165,21 @@ class RoomDetailFragment :
     }
 
     private val roomDetailArgs: RoomDetailArgs by args()
-    private val session by inject()
     private val glideRequests by lazy {
         GlideApp.with(this)
     }
 
     private val roomDetailViewModel: RoomDetailViewModel by fragmentViewModel()
     private val textComposerViewModel: TextComposerViewModel by fragmentViewModel()
-    private val timelineEventController: TimelineEventController by inject { parametersOf(this) }
-    private val commandAutocompletePolicy = CommandAutocompletePolicy()
-    private val autocompleteCommandPresenter: AutocompleteCommandPresenter by inject { parametersOf(this) }
-    private val autocompleteUserPresenter: AutocompleteUserPresenter by inject { parametersOf(this) }
-    private val homePermalinkHandler: HomePermalinkHandler by inject()
 
+    @Inject lateinit var session: Session
+    @Inject lateinit var timelineEventController: TimelineEventController
+    @Inject lateinit var commandAutocompletePolicy: CommandAutocompletePolicy
+    @Inject lateinit var autocompleteCommandPresenter: AutocompleteCommandPresenter
+    @Inject lateinit var autocompleteUserPresenter: AutocompleteUserPresenter
+    @Inject lateinit var homePermalinkHandler: HomePermalinkHandler
+    @Inject lateinit var roomDetailViewModelFactory: RoomDetailViewModel.Factory
+    @Inject lateinit var textComposerViewModelFactory: TextComposerViewModel.Factory
     private lateinit var scrollOnNewMessageCallback: ScrollOnNewMessageCallback
 
     override fun getLayoutResId() = R.layout.fragment_room_detail
@@ -179,9 +190,9 @@ class RoomDetailFragment :
     lateinit var composerLayout: TextComposerView
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
+        injector().inject(this)
         super.onActivityCreated(savedInstanceState)
         actionViewModel = ViewModelProviders.of(requireActivity()).get(ActionsHandler::class.java)
-        bindScope(getOrCreateScope(HomeModule.ROOM_DETAIL_SCOPE))
         setupToolbar(roomToolbar)
         setupRecyclerView()
         setupComposer()
@@ -229,18 +240,18 @@ class RoomDetailFragment :
                     //TODO this is used at several places, find way to refactor?
                     val messageContent: MessageContent? =
                             event.annotations?.editSummary?.aggregatedContent?.toModel()
-                                    ?: event.root.content.toModel()
+                            ?: event.root.content.toModel()
                     val nonFormattedBody = messageContent?.body ?: ""
                     var formattedBody: CharSequence? = null
                     if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
                         val parser = Parser.builder().build()
                         val document = parser.parse(messageContent.formattedBody
-                                ?: messageContent.body)
+                                                    ?: messageContent.body)
                         formattedBody = Markwon.builder(requireContext())
                                 .usePlugin(HtmlPlugin.create()).build().render(document)
                     }
                     composerLayout.composerRelatedMessageContent.text = formattedBody
-                            ?: nonFormattedBody
+                                                                        ?: nonFormattedBody
 
 
                     if (mode == SendMode.EDIT) {
@@ -256,7 +267,7 @@ class RoomDetailFragment :
                     }
 
                     AvatarRenderer.render(event.senderAvatar, event.root.sender
-                            ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar)
+                                                              ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar)
 
                     composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text.length)
                     composerLayout.expand {
@@ -279,9 +290,9 @@ class RoomDetailFragment :
                 REQUEST_FILES_REQUEST_CODE, TAKE_IMAGE_REQUEST_CODE -> handleMediaIntent(data)
                 REACTION_SELECT_REQUEST_CODE                        -> {
                     val eventId = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_EVENT_ID)
-                            ?: return
+                                  ?: return
                     val reaction = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_REACTION_RESULT)
-                            ?: return
+                                   ?: return
                     //TODO check if already reacted with that?
                     roomDetailViewModel.process(RoomDetailActions.SendReaction(reaction, eventId))
                 }
@@ -363,7 +374,7 @@ class RoomDetailFragment :
 
                         // Add the span
                         val user = session.getUser(item.userId)
-                        val span = PillImageSpan(glideRequests, context!!, item.userId, user)
+                        val span = PillImageSpan(glideRequests, requireContext(), item.userId, user)
                         span.bind(composerLayout.composerEditText)
 
                         editable.setSpan(span, startIndex, startIndex + displayName.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
@@ -619,7 +630,7 @@ class RoomDetailFragment :
             }
             MessageMenuViewModel.ACTION_VIEW_REACTIONS -> {
                 val messageInformationData = actionData.data as? MessageInformationData
-                        ?: return
+                                             ?: return
                 ViewReactionBottomSheet.newInstance(roomDetailArgs.roomId, messageInformationData)
                         .show(requireActivity().supportFragmentManager, "DISPLAY_REACTIONS")
             }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt
index 476ff99b..f78efbff 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt
@@ -19,10 +19,13 @@ package im.vector.riotredesign.features.home.room.detail
 import android.text.TextUtils
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.Success
 import com.airbnb.mvrx.ViewModelContext
 import com.jakewharton.rxrelay2.BehaviorRelay
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.content.ContentAttachmentData
@@ -41,14 +44,13 @@ import im.vector.riotredesign.features.home.room.detail.timeline.helper.Timeline
 import io.reactivex.rxkotlin.subscribeBy
 import org.commonmark.parser.Parser
 import org.commonmark.renderer.html.HtmlRenderer
-import org.koin.android.ext.android.get
 import java.text.SimpleDateFormat
 import java.util.*
 import java.util.concurrent.TimeUnit
 
 
-class RoomDetailViewModel(initialState: RoomDetailViewState,
-                          private val session: Session
+class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState,
+                                                      private val session: Session
 ) : VectorViewModel(initialState) {
 
     private val room = session.getRoom(initialState.roomId)!!
@@ -62,14 +64,19 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
     }
     private val timeline = room.createTimeline(eventId, allowedTypes)
 
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: RoomDetailViewState): RoomDetailViewModel
+    }
+
     companion object : MvRxViewModelFactory {
 
         const val PAGINATION_COUNT = 50
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: RoomDetailViewState): RoomDetailViewModel? {
-            val currentSession = viewModelContext.activity.get()
-            return RoomDetailViewModel(state, currentSession)
+            val fragment: RoomDetailFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.roomDetailViewModelFactory.create(state)
         }
     }
 
@@ -201,7 +208,7 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
                 }
                 SendMode.EDIT    -> {
                     room.editTextMessage(state.selectedEvent?.root?.eventId
-                            ?: "", action.text, action.autoMarkdown)
+                                         ?: "", action.text, action.autoMarkdown)
                     setState {
                         copy(
                                 sendMode = SendMode.REGULAR,
@@ -213,7 +220,7 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
                 SendMode.QUOTE   -> {
                     val messageContent: MessageContent? =
                             state.selectedEvent?.annotations?.editSummary?.aggregatedContent?.toModel()
-                                    ?: state.selectedEvent?.root?.content.toModel()
+                            ?: state.selectedEvent?.root?.content.toModel()
                     val textMsg = messageContent?.body
 
                     val finalText = legacyRiotQuoteText(textMsg, action.text)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/composer/TextComposerViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/composer/TextComposerViewModel.kt
index 41c09a19..ef378a29 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/composer/TextComposerViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/composer/TextComposerViewModel.kt
@@ -17,35 +17,44 @@
 package im.vector.riotredesign.features.home.room.detail.composer
 
 import arrow.core.Option
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
 import com.jakewharton.rxrelay2.BehaviorRelay
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.user.model.User
 import im.vector.matrix.rx.rx
 import im.vector.riotredesign.core.platform.VectorViewModel
+import im.vector.riotredesign.features.home.room.detail.RoomDetailFragment
 import io.reactivex.Observable
 import io.reactivex.functions.BiFunction
-import org.koin.android.ext.android.get
 import java.util.concurrent.TimeUnit
 
 typealias AutocompleteUserQuery = CharSequence
 
-class TextComposerViewModel(initialState: TextComposerViewState,
-                            private val session: Session
+class TextComposerViewModel @AssistedInject constructor(@Assisted initialState: TextComposerViewState,
+                                                        private val session: Session
 ) : VectorViewModel(initialState) {
 
+
     private val room = session.getRoom(initialState.roomId)!!
     private val roomId = initialState.roomId
 
     private val usersQueryObservable = BehaviorRelay.create>()
 
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: TextComposerViewState): TextComposerViewModel
+    }
+
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: TextComposerViewState): TextComposerViewModel? {
-            val currentSession = viewModelContext.activity.get()
-            return TextComposerViewModel(state, currentSession)
+            val fragment : RoomDetailFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.textComposerViewModelFactory.create(state)
         }
     }
 
@@ -80,7 +89,7 @@ class TextComposerViewModel(initialState: TextComposerViewState,
                     } else {
                         users.filter {
                             it.displayName?.startsWith(prefix = filter, ignoreCase = true)
-                                    ?: false
+                            ?: false
                         }
                     }
                 }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
index 5b325c4a..d4505b40 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
@@ -25,13 +25,25 @@ import androidx.recyclerview.widget.RecyclerView
 import com.airbnb.epoxy.EpoxyController
 import com.airbnb.epoxy.EpoxyModel
 import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
-import im.vector.matrix.android.api.session.room.model.message.*
+import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
+import im.vector.matrix.android.api.session.room.model.message.MessageContent
+import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
+import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
+import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
 import im.vector.matrix.android.api.session.room.timeline.Timeline
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.core.epoxy.LoadingItem_
 import im.vector.riotredesign.core.extensions.localDateTime
 import im.vector.riotredesign.features.home.room.detail.timeline.factory.TimelineItemFactory
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.*
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineEventDiffUtilCallback
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineEventVisibilityStateChangedListener
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.canBeMerged
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.nextDisplayableEvent
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.prevSameTypeEvents
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderAvatar
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderName
 import im.vector.riotredesign.features.home.room.detail.timeline.item.DaySeparatorItem
 import im.vector.riotredesign.features.home.room.detail.timeline.item.DaySeparatorItem_
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MergedHeaderItem
@@ -39,11 +51,12 @@ import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInf
 import im.vector.riotredesign.features.media.ImageContentRenderer
 import im.vector.riotredesign.features.media.VideoContentRenderer
 import org.threeten.bp.LocalDateTime
+import javax.inject.Inject
 
-class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
-                              private val timelineItemFactory: TimelineItemFactory,
-                              private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
-                              private val backgroundHandler: Handler = TimelineAsyncHelper.getBackgroundHandler()
+class TimelineEventController @Inject constructor(private val dateFormatter: TimelineDateFormatter,
+                                                  private val timelineItemFactory: TimelineItemFactory,
+                                                  private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
+                                                  @TimelineEventControllerHandler private val backgroundHandler: Handler
 ) : EpoxyController(backgroundHandler, backgroundHandler), Timeline.Listener {
 
     interface Callback : ReactionPillCallback, AvatarCallback, BaseCallback {
@@ -175,8 +188,8 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
             // Should be build if not cached or if cached but contains mergedHeader or formattedDay
             // We then are sure we always have items up to date.
             if (modelCache[position] == null
-                    || modelCache[position]?.mergedHeaderModel != null
-                    || modelCache[position]?.formattedDayModel != null) {
+                || modelCache[position]?.mergedHeaderModel != null
+                || modelCache[position]?.formattedDayModel != null) {
                 modelCache[position] = buildItemModels(position, currentSnapshot)
             }
         }
@@ -248,7 +261,7 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
                 // => handle case where paginating from mergeable events and we get more
                 val previousCollapseStateKey = mergedEventIds.intersect(mergeItemCollapseStates.keys).firstOrNull()
                 val initialCollapseState = mergeItemCollapseStates.remove(previousCollapseStateKey)
-                        ?: true
+                                           ?: true
                 val isCollapsed = mergeItemCollapseStates.getOrPut(event.localId) { initialCollapseState }
                 if (isCollapsed) {
                     collapsedEventIds.addAll(mergedEventIds)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventControllerHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventControllerHandler.kt
new file mode 100644
index 00000000..7ac38d97
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventControllerHandler.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.riotredesign.features.home.room.detail.timeline
+
+import javax.inject.Qualifier
+
+@Qualifier
+@Retention(AnnotationRetention.RUNTIME)
+annotation class TimelineEventControllerHandler
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ActionsHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ActionsHandler.kt
index 84cfc40f..1755fe6b 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ActionsHandler.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ActionsHandler.kt
@@ -18,11 +18,12 @@ package im.vector.riotredesign.features.home.room.detail.timeline.action
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import im.vector.riotredesign.core.utils.LiveEvent
+import javax.inject.Inject
 
 /**
  * Activity shared view model to handle message actions
  */
-class ActionsHandler : ViewModel() {
+class ActionsHandler @Inject constructor() : ViewModel() {
 
     data class ActionData(
             val actionId: String,
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
index 9c9bbc2d..9a321c24 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
@@ -36,6 +36,7 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 import kotlinx.android.synthetic.main.bottom_sheet_message_actions.*
+import javax.inject.Inject
 
 /**
  * Bottom sheet fragment that shows a message preview with list of contextual actions
@@ -43,6 +44,7 @@ import kotlinx.android.synthetic.main.bottom_sheet_message_actions.*
  */
 class MessageActionsBottomSheet : BaseMvRxBottomSheetDialog() {
 
+    @Inject lateinit var messageActionViewModelFactory: MessageActionsViewModel.Factory
     private val viewModel: MessageActionsViewModel by fragmentViewModel(MessageActionsViewModel::class)
 
     private lateinit var actionHandlerModel: ActionsHandler
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsViewModel.kt
index 998ddf81..7cb3164f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsViewModel.kt
@@ -19,6 +19,8 @@ import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxState
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.events.model.toModel
@@ -27,17 +29,16 @@ import im.vector.matrix.android.api.session.room.model.message.MessageTextConten
 import im.vector.matrix.android.api.session.room.model.message.MessageType
 import im.vector.riotredesign.core.platform.VectorViewModel
 import im.vector.riotredesign.features.home.room.detail.timeline.format.NoticeEventFormatter
-import org.commonmark.parser.Parser
-import org.koin.android.ext.android.get
-import org.koin.core.parameter.parametersOf
-import ru.noties.markwon.Markwon
-import ru.noties.markwon.html.HtmlPlugin
-import timber.log.Timber
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
+import im.vector.riotredesign.features.html.EventHtmlRenderer
 import java.text.SimpleDateFormat
 import java.util.*
 
 
 data class MessageActionState(
+        val roomId: String,
+        val eventId: String,
+        val informationData: MessageInformationData,
         val userId: String = "",
         val senderName: String = "",
         val messageBody: CharSequence? = null,
@@ -45,64 +46,77 @@ data class MessageActionState(
         val showPreview: Boolean = false,
         val canReact: Boolean = false,
         val senderAvatarPath: String? = null)
-    : MvRxState
+    : MvRxState {
+
+    constructor(args: TimelineEventFragmentArgs) : this(roomId = args.roomId, eventId = args.eventId, informationData = args.informationData)
+
+}
 
 /**
  * Information related to an event and used to display preview in contextual bottomsheet.
  */
-class MessageActionsViewModel(initialState: MessageActionState) : VectorViewModel(initialState) {
+class MessageActionsViewModel @AssistedInject constructor(@Assisted initialState: MessageActionState,
+                                                          private val eventHtmlRenderer: EventHtmlRenderer,
+                                                          private val session: Session,
+                                                          private val noticeEventFormatter: NoticeEventFormatter
+) : VectorViewModel(initialState) {
+
+    private val roomId = initialState.roomId
+    private val eventId = initialState.eventId
+    private val informationData = initialState.informationData
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: MessageActionState): MessageActionsViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
-        override fun initialState(viewModelContext: ViewModelContext): MessageActionState? {
-            val currentSession = viewModelContext.activity.get()
-            val fragment = (viewModelContext as? FragmentViewModelContext)?.fragment
-            val noticeFormatter = fragment?.get(parameters = { parametersOf(fragment) })
-            val parcel = viewModelContext.args as TimelineEventFragmentArgs
-
-            val dateFormat = SimpleDateFormat("EEE, d MMM yyyy HH:mm", Locale.getDefault())
-
-            val event = currentSession.getRoom(parcel.roomId)?.getTimeLineEvent(parcel.eventId)
-            var body: CharSequence? = null
-            val originTs = event?.root?.originServerTs
-            return if (event != null) {
-                when (event.root.type) {
-                    EventType.MESSAGE     -> {
-                        val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
-                                ?: event.root.content.toModel()
-                        body = messageContent?.body
-                        if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
-                            val parser = Parser.builder().build()
-                            val document = parser.parse(messageContent.formattedBody
-                                    ?: messageContent.body)
-                            body = Markwon.builder(viewModelContext.activity)
-                                    .usePlugin(HtmlPlugin.create()).build().render(document)
-                        }
-                    }
-                    EventType.STATE_ROOM_NAME,
-                    EventType.STATE_ROOM_TOPIC,
-                    EventType.STATE_ROOM_MEMBER,
-                    EventType.STATE_HISTORY_VISIBILITY,
-                    EventType.CALL_INVITE,
-                    EventType.CALL_HANGUP,
-                    EventType.CALL_ANSWER -> {
-                        body = noticeFormatter?.format(event)
-                    }
-                }
-                MessageActionState(
-                        userId = event.root.sender ?: "",
-                        senderName = parcel.informationData.memberName?.toString() ?: "",
-                        messageBody = body,
-                        ts = dateFormat.format(Date(originTs ?: 0)),
-                        showPreview = body != null,
-                        canReact = event.root.type == EventType.MESSAGE && event.sendState.isSent(),
-                        senderAvatarPath = parcel.informationData.avatarUrl
-                )
-            } else {
-                //can this happen?
-                Timber.e("Failed to retrieve event")
-                null
-            }
+        override fun create(viewModelContext: ViewModelContext, state: MessageActionState): MessageActionsViewModel? {
+            val fragment: MessageActionsBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.messageActionViewModelFactory.create(state)
         }
     }
+
+
+    init {
+        setState { reduceState(this) }
+    }
+
+    private fun reduceState(state: MessageActionState): MessageActionState {
+        val dateFormat = SimpleDateFormat("EEE, d MMM yyyy HH:mm", Locale.getDefault())
+        val event = session.getRoom(roomId)?.getTimeLineEvent(eventId) ?: return state
+        var body: CharSequence? = null
+        val originTs = event.root.originServerTs
+        when (event.root.type) {
+            EventType.MESSAGE     -> {
+                val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
+                                                      ?: event.root.content.toModel()
+                body = messageContent?.body
+                if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
+                    body = eventHtmlRenderer.render(messageContent.formattedBody
+                                                    ?: messageContent.body)
+                }
+            }
+            EventType.STATE_ROOM_NAME,
+            EventType.STATE_ROOM_TOPIC,
+            EventType.STATE_ROOM_MEMBER,
+            EventType.STATE_HISTORY_VISIBILITY,
+            EventType.CALL_INVITE,
+            EventType.CALL_HANGUP,
+            EventType.CALL_ANSWER -> {
+                body = noticeEventFormatter.format(event)
+            }
+        }
+        return state.copy(
+                userId = event.root.sender ?: "",
+                senderName = informationData.memberName?.toString() ?: "",
+                messageBody = body,
+                ts = dateFormat.format(Date(originTs ?: 0)),
+                showPreview = body != null,
+                canReact = event.root.type == EventType.MESSAGE && event.sendState.isSent(),
+                senderAvatarPath = informationData.avatarUrl
+        )
+    }
+
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuFragment.kt
index 2b47eae3..116c792c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuFragment.kt
@@ -29,16 +29,16 @@ import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.R
 import im.vector.riotredesign.features.themes.ThemeUtils
+import javax.inject.Inject
 
 /**
  * Fragment showing the list of available contextual action for a given message.
  */
 class MessageMenuFragment : BaseMvRxFragment() {
 
+    @Inject lateinit var messageMenuViewModelFactory: MessageMenuViewModel.Factory
     private val viewModel: MessageMenuViewModel by fragmentViewModel(MessageMenuViewModel::class)
-
     private var addSeparators = false
-
     var interactionListener: InteractionListener? = null
 
     override fun invalidate() = withState(viewModel) { state ->
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuViewModel.kt
index f74a953e..e4554143 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuViewModel.kt
@@ -15,9 +15,12 @@
  */
 package im.vector.riotredesign.features.home.room.detail.timeline.action
 
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxState
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.events.model.toContent
@@ -29,44 +32,76 @@ import im.vector.matrix.android.api.session.room.send.SendState
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.VectorViewModel
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 import org.json.JSONObject
-import org.koin.android.ext.android.get
 
 data class SimpleAction(val uid: String, val titleRes: Int, val iconResId: Int?, val data: Any? = null)
 
-data class MessageMenuState(val actions: List = emptyList()) : MvRxState
+data class MessageMenuState(
+        val roomId: String,
+        val eventId: String,
+        val informationData: MessageInformationData,
+        val actions: List = emptyList()
+) : MvRxState {
+
+    constructor(args: TimelineEventFragmentArgs) : this(roomId = args.roomId, eventId = args.eventId, informationData = args.informationData)
+
+}
 
 /**
  * Manages list actions for a given message (copy / paste / forward...)
  */
-class MessageMenuViewModel(initialState: MessageMenuState) : VectorViewModel(initialState) {
+class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: MessageMenuState,
+                                                       private val session: Session) : VectorViewModel(initialState) {
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: MessageMenuState): MessageMenuViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
-        override fun initialState(viewModelContext: ViewModelContext): MessageMenuState? {
-            // Args are accessible from the context.
-            val currentSession = viewModelContext.activity.get()
-            val parcel = viewModelContext.args as TimelineEventFragmentArgs
-            val event = currentSession.getRoom(parcel.roomId)?.getTimeLineEvent(parcel.eventId)
-                    ?: return null
+        const val ACTION_ADD_REACTION = "add_reaction"
+        const val ACTION_COPY = "copy"
+        const val ACTION_EDIT = "edit"
+        const val ACTION_QUOTE = "quote"
+        const val ACTION_REPLY = "reply"
+        const val ACTION_SHARE = "share"
+        const val ACTION_RESEND = "resend"
+        const val ACTION_DELETE = "delete"
+        const val VIEW_SOURCE = "VIEW_SOURCE"
+        const val VIEW_DECRYPTED_SOURCE = "VIEW_DECRYPTED_SOURCE"
+        const val ACTION_COPY_PERMALINK = "ACTION_COPY_PERMALINK"
+        const val ACTION_FLAG = "ACTION_FLAG"
+        const val ACTION_QUICK_REACT = "ACTION_QUICK_REACT"
+        const val ACTION_VIEW_REACTIONS = "ACTION_VIEW_REACTIONS"
 
-            val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
-                    ?: event.root.content.toModel()
-            val type = messageContent?.type
+        override fun create(viewModelContext: ViewModelContext, state: MessageMenuState): MessageMenuViewModel? {
+            val fragment: MessageMenuFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.messageMenuViewModelFactory.create(state)
+        }
+    }
 
-            if (!event.sendState.isSent()) {
-                //Resend and Delete
-                return MessageMenuState(
-                        //TODO
-                        listOf(
+    init {
+        setState { reduceState(this) }
+    }
+
+    private fun reduceState(state: MessageMenuState): MessageMenuState {
+        val event = session.getRoom(state.roomId)?.getTimeLineEvent(state.eventId) ?: return state
+
+        val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
+                                              ?: event.root.content.toModel()
+        val type = messageContent?.type
+
+        val actions = if (!event.sendState.isSent()) {
+            //Resend and Delete
+            listOf(
 //                                SimpleAction(ACTION_RESEND, R.string.resend, R.drawable.ic_send, event.root.eventId),
 //                                //TODO delete icon
 //                                SimpleAction(ACTION_DELETE, R.string.delete, R.drawable.ic_delete, event.root.eventId)
-                        )
-                )
-            }
-
-            val actions = ArrayList().apply {
+            )
+        } else {
+            ArrayList().apply {
 
                 if (event.sendState == SendState.SENDING) {
                     //TODO add cancel?
@@ -86,28 +121,28 @@ class MessageMenuViewModel(initialState: MessageMenuState) : VectorViewModel true
-                else                     -> false
+
+    private fun canReply(event: TimelineEvent, messageContent: MessageContent?): Boolean {
+        //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
+        if (event.root.getClearType() != EventType.MESSAGE) return false
+        return when (messageContent?.type) {
+            MessageType.MSGTYPE_TEXT,
+            MessageType.MSGTYPE_NOTICE,
+            MessageType.MSGTYPE_EMOTE,
+            MessageType.MSGTYPE_IMAGE,
+            MessageType.MSGTYPE_VIDEO,
+            MessageType.MSGTYPE_AUDIO,
+            MessageType.MSGTYPE_FILE -> true
+            else                     -> false
+        }
+    }
+
+    private fun canReact(event: TimelineEvent, messageContent: MessageContent?): Boolean {
+        //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
+        return event.root.getClearType() == EventType.MESSAGE
+    }
+
+    private fun canQuote(event: TimelineEvent, messageContent: MessageContent?): Boolean {
+        //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
+        if (event.root.getClearType() != EventType.MESSAGE) return false
+        return when (messageContent?.type) {
+            MessageType.MSGTYPE_TEXT,
+            MessageType.MSGTYPE_NOTICE,
+            MessageType.MSGTYPE_EMOTE,
+            MessageType.FORMAT_MATRIX_HTML,
+            MessageType.MSGTYPE_LOCATION -> {
+                true
             }
+            else                         -> false
         }
+    }
 
-        private fun canReact(event: TimelineEvent, messageContent: MessageContent?): Boolean {
-            //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
-            return event.root.getClearType() == EventType.MESSAGE
-        }
+    private fun canRedact(event: TimelineEvent, myUserId: String): Boolean {
+        //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
+        if (event.root.getClearType() != EventType.MESSAGE) return false
+        //TODO if user is admin or moderator
+        return event.root.sender == myUserId
+    }
 
-        private fun canQuote(event: TimelineEvent, messageContent: MessageContent?): Boolean {
-            //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
-            if (event.root.getClearType() != EventType.MESSAGE) return false
-            return when (messageContent?.type) {
-                MessageType.MSGTYPE_TEXT,
-                MessageType.MSGTYPE_NOTICE,
-                MessageType.MSGTYPE_EMOTE,
-                MessageType.FORMAT_MATRIX_HTML,
-                MessageType.MSGTYPE_LOCATION -> {
-                    true
-                }
-                else                         -> false
+    private fun canViewReactions(event: TimelineEvent): Boolean {
+        //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
+        if (event.root.getClearType() != EventType.MESSAGE) return false
+        //TODO if user is admin or moderator
+        return event.annotations?.reactionsSummary?.isNotEmpty() ?: false
+    }
+
+    private fun canEdit(event: TimelineEvent, myUserId: String): Boolean {
+        //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
+        if (event.root.getClearType() != EventType.MESSAGE) return false
+        //TODO if user is admin or moderator
+        val messageContent = event.root.content.toModel()
+        return event.root.sender == myUserId && (
+                messageContent?.type == MessageType.MSGTYPE_TEXT
+                || messageContent?.type == MessageType.MSGTYPE_EMOTE
+                                                )
+    }
+
+
+    private fun canCopy(type: String?): Boolean {
+        return when (type) {
+            MessageType.MSGTYPE_TEXT,
+            MessageType.MSGTYPE_NOTICE,
+            MessageType.MSGTYPE_EMOTE,
+            MessageType.FORMAT_MATRIX_HTML,
+            MessageType.MSGTYPE_LOCATION -> {
+                true
             }
+            else                         -> false
         }
-
-        private fun canRedact(event: TimelineEvent, myUserId: String): Boolean {
-            //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
-            if (event.root.getClearType() != EventType.MESSAGE) return false
-            //TODO if user is admin or moderator
-            return event.root.sender == myUserId
-        }
-
-        private fun canViewReactions(event: TimelineEvent): Boolean {
-            //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
-            if (event.root.getClearType() != EventType.MESSAGE) return false
-            //TODO if user is admin or moderator
-            return event.annotations?.reactionsSummary?.isNotEmpty() ?: false
-        }
-
-        private fun canEdit(event: TimelineEvent, myUserId: String): Boolean {
-            //Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
-            if (event.root.getClearType() != EventType.MESSAGE) return false
-            //TODO if user is admin or moderator
-            val messageContent = event.root.content.toModel()
-            return event.root.sender == myUserId && (
-                    messageContent?.type == MessageType.MSGTYPE_TEXT
-                            || messageContent?.type == MessageType.MSGTYPE_EMOTE
-                    )
-        }
+    }
 
 
-        private fun canCopy(type: String?): Boolean {
-            return when (type) {
-                MessageType.MSGTYPE_TEXT,
-                MessageType.MSGTYPE_NOTICE,
-                MessageType.MSGTYPE_EMOTE,
-                MessageType.FORMAT_MATRIX_HTML,
-                MessageType.MSGTYPE_LOCATION -> {
-                    true
-                }
-                else                         -> false
+    private fun canShare(type: String?): Boolean {
+        return when (type) {
+            MessageType.MSGTYPE_IMAGE,
+            MessageType.MSGTYPE_AUDIO,
+            MessageType.MSGTYPE_VIDEO -> {
+                true
             }
+            else                      -> false
         }
-
-
-        private fun canShare(type: String?): Boolean {
-            return when (type) {
-                MessageType.MSGTYPE_IMAGE,
-                MessageType.MSGTYPE_AUDIO,
-                MessageType.MSGTYPE_VIDEO -> {
-                    true
-                }
-                else                      -> false
-            }
-        }
-
-        const val ACTION_ADD_REACTION = "add_reaction"
-        const val ACTION_COPY = "copy"
-        const val ACTION_EDIT = "edit"
-        const val ACTION_QUOTE = "quote"
-        const val ACTION_REPLY = "reply"
-        const val ACTION_SHARE = "share"
-        const val ACTION_RESEND = "resend"
-        const val ACTION_DELETE = "delete"
-        const val VIEW_SOURCE = "VIEW_SOURCE"
-        const val VIEW_DECRYPTED_SOURCE = "VIEW_DECRYPTED_SOURCE"
-        const val ACTION_COPY_PERMALINK = "ACTION_COPY_PERMALINK"
-        const val ACTION_FLAG = "ACTION_FLAG"
-        const val ACTION_QUICK_REACT = "ACTION_QUICK_REACT"
-        const val ACTION_VIEW_REACTIONS = "ACTION_VIEW_REACTIONS"
-
-
     }
 }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
index b1074480..96d7052c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
@@ -31,7 +31,7 @@ import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.EmojiCompatFontProvider
 import im.vector.riotredesign.R
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 /**
  * Quick Reaction Fragment (agree / like reactions)
@@ -57,7 +57,8 @@ class QuickReactionFragment : BaseMvRxFragment() {
 
     var interactionListener: InteractionListener? = null
 
-    val fontProvider by inject()
+    @Inject lateinit var fontProvider: EmojiCompatFontProvider
+    @Inject lateinit var quickReactionViewModelFactory: QuickReactionViewModel.Factory
 
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         val view = inflater.inflate(R.layout.adapter_item_action_quick_reaction, container, false)
@@ -68,10 +69,10 @@ class QuickReactionFragment : BaseMvRxFragment() {
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
-        quickReact1Text.text = QuickReactionViewModel.agreePositive
-        quickReact2Text.text = QuickReactionViewModel.agreeNegative
-        quickReact3Text.text = QuickReactionViewModel.likePositive
-        quickReact4Text.text = QuickReactionViewModel.likeNegative
+        quickReact1Text.text = QuickReactionViewModel.AGREE_POSITIVE
+        quickReact2Text.text = QuickReactionViewModel.AGREE_NEGATIVE
+        quickReact3Text.text = QuickReactionViewModel.LIKE_POSITIVE
+        quickReact4Text.text = QuickReactionViewModel.LIKE_NEGATIVE
 
         listOf(quickReact1Text, quickReact2Text, quickReact3Text, quickReact4Text).forEach {
             it.typeface = fontProvider.typeface ?: Typeface.DEFAULT
@@ -96,7 +97,7 @@ class QuickReactionFragment : BaseMvRxFragment() {
     override fun invalidate() = withState(viewModel) {
 
         TransitionManager.beginDelayedTransition(rootLayout)
-        when (it.agreeTrigleState) {
+        when (it.agreeTriggleState) {
             TriggleState.NONE   -> {
                 quickReact1Text.alpha = 1f
                 quickReact2Text.alpha = 1f
@@ -130,7 +131,7 @@ class QuickReactionFragment : BaseMvRxFragment() {
         if (it.selectionResult != null) {
             val clikedOn = it.selectionResult.first
             interactionListener?.didQuickReactWith(clikedOn, QuickReactionViewModel.getOpposite(clikedOn)
-                    ?: "", it.selectionResult.second, it.eventId)
+                                                             ?: "", it.selectionResult.second, it.eventId)
         }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionViewModel.kt
index 5252e51b..91abbb05 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionViewModel.kt
@@ -15,12 +15,15 @@
  */
 package im.vector.riotredesign.features.home.room.detail.timeline.action
 
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxState
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.core.platform.VectorViewModel
-import org.koin.android.ext.android.get
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 
 /**
  * Quick reactions state, it's a toggle with 3rd state
@@ -32,33 +35,99 @@ enum class TriggleState {
 }
 
 data class QuickReactionState(
-        val agreeTrigleState: TriggleState = TriggleState.NONE,
+        val roomId: String,
+        val eventId: String,
+        val informationData: MessageInformationData,
+        val agreeTriggleState: TriggleState = TriggleState.NONE,
         val likeTriggleState: TriggleState = TriggleState.NONE,
         /** Pair of 'clickedOn' and current toggles state*/
-        val selectionResult: Pair>? = null,
-        val eventId: String = "") : MvRxState
+        val selectionResult: Pair>? = null
+) : MvRxState {
+
+    constructor(args: TimelineEventFragmentArgs) : this(roomId = args.roomId, eventId = args.eventId, informationData = args.informationData)
+
+}
+
 
 /**
  * Quick reaction view model
  */
-class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel(initialState) {
+class QuickReactionViewModel @AssistedInject constructor(@Assisted initialState: QuickReactionState,
+                                                         private val session: Session) : VectorViewModel(initialState) {
 
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: QuickReactionState): QuickReactionViewModel
+    }
+
+    companion object : MvRxViewModelFactory {
+
+        const val AGREE_POSITIVE = "👍"
+        const val AGREE_NEGATIVE = "👎"
+        const val LIKE_POSITIVE = "🙂"
+        const val LIKE_NEGATIVE = "😔"
+
+        fun getOpposite(reaction: String): String? {
+            return when (reaction) {
+                AGREE_POSITIVE -> AGREE_NEGATIVE
+                AGREE_NEGATIVE -> AGREE_POSITIVE
+                LIKE_POSITIVE  -> LIKE_NEGATIVE
+                LIKE_NEGATIVE  -> LIKE_POSITIVE
+                else           -> null
+            }
+        }
+
+        override fun create(viewModelContext: ViewModelContext, state: QuickReactionState): QuickReactionViewModel? {
+            val fragment: QuickReactionFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.quickReactionViewModelFactory.create(state)
+        }
+    }
+
+    init {
+        setState { reduceState(this) }
+    }
+
+    private fun reduceState(state: QuickReactionState): QuickReactionState {
+        val event = session.getRoom(state.roomId)?.getTimeLineEvent(state.eventId) ?: return state
+        var agreeTriggle: TriggleState = TriggleState.NONE
+        var likeTriggle: TriggleState = TriggleState.NONE
+        event.annotations?.reactionsSummary?.forEach {
+            //it.addedByMe
+            if (it.addedByMe) {
+                if (AGREE_POSITIVE == it.key) {
+                    agreeTriggle = TriggleState.FIRST
+                } else if (AGREE_NEGATIVE == it.key) {
+                    agreeTriggle = TriggleState.SECOND
+                }
+
+                if (LIKE_POSITIVE == it.key) {
+                    likeTriggle = TriggleState.FIRST
+                } else if (LIKE_NEGATIVE == it.key) {
+                    likeTriggle = TriggleState.SECOND
+                }
+            }
+        }
+        return state.copy(
+                agreeTriggleState = agreeTriggle,
+                likeTriggleState = likeTriggle
+        )
+    }
 
     fun toggleAgree(isFirst: Boolean) = withState {
         if (isFirst) {
             setState {
-                val newTriggle = if (it.agreeTrigleState == TriggleState.FIRST) TriggleState.NONE else TriggleState.FIRST
+                val newTriggle = if (it.agreeTriggleState == TriggleState.FIRST) TriggleState.NONE else TriggleState.FIRST
                 copy(
-                        agreeTrigleState = newTriggle,
-                        selectionResult = Pair(agreePositive, getReactions(this, newTriggle, null))
+                        agreeTriggleState = newTriggle,
+                        selectionResult = Pair(AGREE_POSITIVE, getReactions(this, newTriggle, null))
                 )
             }
         } else {
             setState {
-                val newTriggle = if (it.agreeTrigleState == TriggleState.SECOND) TriggleState.NONE else TriggleState.SECOND
+                val newTriggle = if (it.agreeTriggleState == TriggleState.SECOND) TriggleState.NONE else TriggleState.SECOND
                 copy(
-                        agreeTrigleState = agreeTrigleState,
-                        selectionResult = Pair(agreeNegative, getReactions(this, newTriggle, null))
+                        agreeTriggleState = agreeTriggleState,
+                        selectionResult = Pair(AGREE_NEGATIVE, getReactions(this, newTriggle, null))
                 )
             }
         }
@@ -70,7 +139,7 @@ class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel
                 val newTriggle = if (it.likeTriggleState == TriggleState.FIRST) TriggleState.NONE else TriggleState.FIRST
                 copy(
                         likeTriggleState = newTriggle,
-                        selectionResult = Pair(likePositive, getReactions(this, null, newTriggle))
+                        selectionResult = Pair(LIKE_POSITIVE, getReactions(this, null, newTriggle))
                 )
             }
         } else {
@@ -78,7 +147,7 @@ class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel
                 val newTriggle = if (it.likeTriggleState == TriggleState.SECOND) TriggleState.NONE else TriggleState.SECOND
                 copy(
                         likeTriggleState = newTriggle,
-                        selectionResult = Pair(likeNegative, getReactions(this, null, newTriggle))
+                        selectionResult = Pair(LIKE_NEGATIVE, getReactions(this, null, newTriggle))
                 )
             }
         }
@@ -87,64 +156,17 @@ class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel
     private fun getReactions(state: QuickReactionState, newState1: TriggleState?, newState2: TriggleState?): List {
         return ArrayList(4).apply {
             when (newState2 ?: state.likeTriggleState) {
-                TriggleState.FIRST  -> add(likePositive)
-                TriggleState.SECOND -> add(likeNegative)
+                TriggleState.FIRST  -> add(LIKE_POSITIVE)
+                TriggleState.SECOND -> add(LIKE_NEGATIVE)
                 else                -> {
                 }
             }
-            when (newState1 ?: state.agreeTrigleState) {
-                TriggleState.FIRST  -> add(agreePositive)
-                TriggleState.SECOND -> add(agreeNegative)
+            when (newState1 ?: state.agreeTriggleState) {
+                TriggleState.FIRST  -> add(AGREE_POSITIVE)
+                TriggleState.SECOND -> add(AGREE_NEGATIVE)
                 else                -> {
                 }
             }
         }
     }
-
-
-    companion object : MvRxViewModelFactory {
-
-        val agreePositive = "👍"
-        val agreeNegative = "👎"
-        val likePositive = "🙂"
-        val likeNegative = "😔"
-
-        fun getOpposite(reaction: String): String? {
-            return when (reaction) {
-                agreePositive -> agreeNegative
-                agreeNegative -> agreePositive
-                likePositive  -> likeNegative
-                likeNegative  -> likePositive
-                else          -> null
-            }
-        }
-
-        override fun initialState(viewModelContext: ViewModelContext): QuickReactionState? {
-            // Args are accessible from the context.
-            // val foo = vieWModelContext.args.foo
-            val currentSession = viewModelContext.activity.get()
-            val parcel = viewModelContext.args as TimelineEventFragmentArgs
-            val event = currentSession.getRoom(parcel.roomId)?.getTimeLineEvent(parcel.eventId)
-                    ?: return null
-            var agreeTriggle: TriggleState = TriggleState.NONE
-            var likeTriggle: TriggleState = TriggleState.NONE
-            event.annotations?.reactionsSummary?.forEach {
-                //it.addedByMe
-                if (it.addedByMe) {
-                    if (agreePositive == it.key) {
-                        agreeTriggle = TriggleState.FIRST
-                    } else if (agreeNegative == it.key) {
-                        agreeTriggle = TriggleState.SECOND
-                    }
-
-                    if (likePositive == it.key) {
-                        likeTriggle = TriggleState.FIRST
-                    } else if (likeNegative == it.key) {
-                        likeTriggle = TriggleState.SECOND
-                    }
-                }
-            }
-            return QuickReactionState(agreeTriggle, likeTriggle, null, event.root.eventId ?: "")
-        }
-    }
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/DefaultItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/DefaultItemFactory.kt
index c44af0ea..b64b6adc 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/DefaultItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/DefaultItemFactory.kt
@@ -19,8 +19,9 @@ package im.vector.riotredesign.features.home.room.detail.timeline.factory
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem
 import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem_
+import javax.inject.Inject
 
-class DefaultItemFactory {
+class DefaultItemFactory @Inject constructor(){
 
     fun create(event: TimelineEvent, exception: Exception? = null): DefaultItem? {
         val text = if (exception == null) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
index 4e892183..46f5b7eb 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
@@ -30,9 +30,10 @@ import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderAv
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderName
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_
+import javax.inject.Inject
 
 // This class handles timeline event who haven't been successfully decrypted
-class EncryptedItemFactory(private val stringProvider: StringProvider) {
+class EncryptedItemFactory @Inject constructor(private val stringProvider: StringProvider) {
 
     fun create(timelineEvent: TimelineEvent): VectorEpoxyModel<*>? {
         return when {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
index d0ca0ffc..cd8f34d5 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
@@ -28,8 +28,9 @@ import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderNa
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem
 import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_
+import javax.inject.Inject
 
-class EncryptionItemFactory(private val stringProvider: StringProvider) {
+class EncryptionItemFactory @Inject constructor(private val stringProvider: StringProvider) {
 
     fun create(event: TimelineEvent): NoticeItem? {
         val text = buildNoticeText(event.root, event.senderName) ?: return null
@@ -52,7 +53,7 @@ class EncryptionItemFactory(private val stringProvider: StringProvider) {
                 val content = event.content.toModel() ?: return null
                 stringProvider.getString(R.string.notice_end_to_end, senderName, content.algorithm)
             }
-            else -> null
+            else                                         -> null
         }
 
     }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
index a4b31251..9ddd4d34 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
@@ -29,7 +29,14 @@ import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.events.model.RelationType
 import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
-import im.vector.matrix.android.api.session.room.model.message.*
+import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
+import im.vector.matrix.android.api.session.room.model.message.MessageContent
+import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent
+import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
+import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
+import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent
+import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
+import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
 import im.vector.matrix.android.api.session.room.send.SendState
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.EmojiCompatFontProvider
@@ -44,18 +51,32 @@ import im.vector.riotredesign.features.home.getColorFromUserId
 import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
-import im.vector.riotredesign.features.home.room.detail.timeline.item.*
+import im.vector.riotredesign.features.home.room.detail.timeline.item.BlankItem_
+import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem
+import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem_
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageFileItem
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageFileItem_
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem_
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem
+import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem_
+import im.vector.riotredesign.features.home.room.detail.timeline.item.ReactionInfoData
+import im.vector.riotredesign.features.home.room.detail.timeline.item.RedactedMessageItem
+import im.vector.riotredesign.features.home.room.detail.timeline.item.RedactedMessageItem_
 import im.vector.riotredesign.features.html.EventHtmlRenderer
 import im.vector.riotredesign.features.media.ImageContentRenderer
 import im.vector.riotredesign.features.media.VideoContentRenderer
 import me.gujun.android.span.span
+import javax.inject.Inject
 
-class MessageItemFactory(private val colorProvider: ColorProvider,
-                         private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
-                         private val timelineDateFormatter: TimelineDateFormatter,
-                         private val htmlRenderer: EventHtmlRenderer,
-                         private val stringProvider: StringProvider,
-                         private val emojiCompatFontProvider: EmojiCompatFontProvider) {
+class MessageItemFactory @Inject constructor(
+        private val colorProvider: ColorProvider,
+        private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
+        private val timelineDateFormatter: TimelineDateFormatter,
+        private val htmlRenderer: EventHtmlRenderer,
+        private val stringProvider: StringProvider,
+        private val emojiCompatFontProvider: EmojiCompatFontProvider) {
 
     fun create(event: TimelineEvent,
                nextEvent: TimelineEvent?,
@@ -68,33 +89,33 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
         val nextDate = nextEvent?.root?.localDateTime()
         val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
         val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60))
-                ?: false
+                                                      ?: false
 
         val showInformation = addDaySeparator
-                || event.senderAvatar != nextEvent?.senderAvatar
-                || event.senderName != nextEvent?.senderName
-                || nextEvent?.root?.getClearType() != EventType.MESSAGE
-                || isNextMessageReceivedMoreThanOneHourAgo
+                              || event.senderAvatar != nextEvent?.senderAvatar
+                              || event.senderName != nextEvent?.senderName
+                              || nextEvent?.root?.getClearType() != EventType.MESSAGE
+                              || isNextMessageReceivedMoreThanOneHourAgo
 
         val time = timelineDateFormatter.formatMessageHour(date)
         val avatarUrl = event.senderAvatar
         val memberName = event.senderName ?: event.root.sender ?: ""
         val formattedMemberName = span(memberName) {
             textColor = colorProvider.getColor(getColorFromUserId(event.root.sender
-                    ?: ""))
+                                                                  ?: ""))
         }
         val hasBeenEdited = event.annotations?.editSummary != null
         val informationData = MessageInformationData(eventId = eventId,
-                senderId = event.root.sender ?: "",
-                sendState = event.sendState,
-                time = time,
-                avatarUrl = avatarUrl,
-                memberName = formattedMemberName,
-                showInformation = showInformation,
-                orderedReactionList = event.annotations?.reactionsSummary?.map {
-                    ReactionInfoData(it.key, it.count, it.addedByMe, it.localEchoEvents.isEmpty())
-                },
-                hasBeenEdited = hasBeenEdited
+                                                     senderId = event.root.sender ?: "",
+                                                     sendState = event.sendState,
+                                                     time = time,
+                                                     avatarUrl = avatarUrl,
+                                                     memberName = formattedMemberName,
+                                                     showInformation = showInformation,
+                                                     orderedReactionList = event.annotations?.reactionsSummary?.map {
+                                                         ReactionInfoData(it.key, it.count, it.addedByMe, it.localEchoEvents.isEmpty())
+                                                     },
+                                                     hasBeenEdited = hasBeenEdited
         )
 
         if (event.root.unsignedData?.redactedEvent != null) {
@@ -104,9 +125,9 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
 
         val messageContent: MessageContent =
                 event.annotations?.editSummary?.aggregatedContent?.toModel()
-                        ?: event.root.getClearContent().toModel()
-                        ?: //Malformed content, we should echo something on screen
-                        return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
+                ?: event.root.getClearContent().toModel()
+                ?: //Malformed content, we should echo something on screen
+                return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
 
         if (messageContent.relatesTo?.type == RelationType.REPLACE) {
             // ignore replace event, the targeted id is already edited
@@ -116,16 +137,16 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
 //        val ev = all.toModel()
         return when (messageContent) {
             is MessageEmoteContent  -> buildEmoteMessageItem(messageContent,
-                    informationData,
-                    hasBeenEdited,
-                    event.annotations?.editSummary,
-                    callback)
+                                                             informationData,
+                                                             hasBeenEdited,
+                                                             event.annotations?.editSummary,
+                                                             callback)
             is MessageTextContent   -> buildTextMessageItem(event.sendState,
-                    messageContent,
-                    informationData,
-                    hasBeenEdited,
-                    event.annotations?.editSummary,
-                    callback
+                                                            messageContent,
+                                                            informationData,
+                                                            hasBeenEdited,
+                                                            event.annotations?.editSummary,
+                                                            callback
             )
             is MessageImageContent  -> buildImageMessageItem(messageContent, informationData, callback)
             is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback)
@@ -156,7 +177,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                            ?: false
+                                             ?: false
                 }
     }
 
@@ -176,7 +197,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                            ?: false
+                                             ?: false
                 }
                 .clickListener(
                         DebouncedClickListener(View.OnClickListener { _ ->
@@ -221,7 +242,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                            ?: false
+                                             ?: false
                 }
     }
 
@@ -259,7 +280,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
                 .clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) }
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                            ?: false
+                                             ?: false
                 }
     }
 
@@ -296,7 +317,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                            ?: false
+                                             ?: false
                 }
     }
 
@@ -328,9 +349,9 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
                 //nop
             }
         },
-                editStart,
-                editEnd,
-                Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
+                          editStart,
+                          editEnd,
+                          Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
         return spannable
     }
 
@@ -362,7 +383,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                            ?: false
+                                             ?: false
                 }
     }
 
@@ -395,7 +416,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                            ?: false
+                                             ?: false
                 }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/NoticeItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/NoticeItemFactory.kt
index dabebd28..00d8070f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/NoticeItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/NoticeItemFactory.kt
@@ -24,8 +24,9 @@ import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderNa
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem
 import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_
+import javax.inject.Inject
 
-class NoticeItemFactory(private val eventFormatter: NoticeEventFormatter) {
+class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEventFormatter) {
 
     fun create(event: TimelineEvent,
                callback: TimelineEventController.Callback?): NoticeItem? {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/TimelineItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/TimelineItemFactory.kt
index c4609f88..6db6a2a2 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/TimelineItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/TimelineItemFactory.kt
@@ -28,12 +28,13 @@ import im.vector.riotredesign.features.home.room.detail.timeline.helper.Timeline
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem_
 import timber.log.Timber
+import javax.inject.Inject
 
-class TimelineItemFactory(private val messageItemFactory: MessageItemFactory,
-                          private val encryptionItemFactory: EncryptionItemFactory,
-                          private val encryptedItemFactory: EncryptedItemFactory,
-                          private val noticeItemFactory: NoticeItemFactory,
-                          private val defaultItemFactory: DefaultItemFactory) {
+class TimelineItemFactory @Inject constructor(private val messageItemFactory: MessageItemFactory,
+                                              private val encryptionItemFactory: EncryptionItemFactory,
+                                              private val encryptedItemFactory: EncryptedItemFactory,
+                                              private val noticeItemFactory: NoticeItemFactory,
+                                              private val defaultItemFactory: DefaultItemFactory) {
 
     fun create(event: TimelineEvent,
                nextEvent: TimelineEvent?,
@@ -64,22 +65,23 @@ class TimelineItemFactory(private val messageItemFactory: MessageItemFactory,
                     //These are just for debug to display hidden event, they should be filtered out in normal mode
                     if (TimelineDisplayableEvents.DEBUG_HIDDEN_EVENT) {
                         val informationData = MessageInformationData(eventId = event.root.eventId
-                                ?: "?",
-                                senderId = event.root.sender ?: "",
-                                sendState = event.sendState,
-                                time = "",
-                                avatarUrl = null,
-                                memberName = "",
-                                showInformation = false
+                                                                               ?: "?",
+                                                                     senderId = event.root.sender
+                                                                                ?: "",
+                                                                     sendState = event.sendState,
+                                                                     time = "",
+                                                                     avatarUrl = null,
+                                                                     memberName = "",
+                                                                     showInformation = false
                         )
                         val messageContent = event.root.content.toModel()
-                                ?: MessageDefaultContent("", "", null, null)
+                                             ?: MessageDefaultContent("", "", null, null)
                         MessageTextItem_()
                                 .informationData(informationData)
                                 .message("{ \"type\": ${event.root.type} }")
                                 .longClickListener { view ->
                                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                                            ?: false
+                                                             ?: false
                                 }
                     } else {
                         Timber.w("Ignored event (type: ${event.root.type}")
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/format/NoticeEventFormatter.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
index 70d0f68e..187c98b3 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
@@ -20,15 +20,21 @@ import android.text.TextUtils
 import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.events.model.toModel
-import im.vector.matrix.android.api.session.room.model.*
+import im.vector.matrix.android.api.session.room.model.Membership
+import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
+import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibilityContent
+import im.vector.matrix.android.api.session.room.model.RoomMember
+import im.vector.matrix.android.api.session.room.model.RoomNameContent
+import im.vector.matrix.android.api.session.room.model.RoomTopicContent
 import im.vector.matrix.android.api.session.room.model.call.CallInviteContent
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderName
 import timber.log.Timber
+import javax.inject.Inject
 
-class NoticeEventFormatter(private val stringProvider: StringProvider) {
+class NoticeEventFormatter @Inject constructor(private val stringProvider: StringProvider) {
 
     fun format(timelineEvent: TimelineEvent): CharSequence? {
         return when (val type = timelineEvent.root.getClearType()) {
@@ -66,7 +72,7 @@ class NoticeEventFormatter(private val stringProvider: StringProvider) {
 
     private fun formatRoomHistoryVisibilityEvent(event: Event, senderName: String?): CharSequence? {
         val historyVisibility = event.getClearContent().toModel()?.historyVisibility
-                ?: return null
+                                ?: return null
 
         val formattedVisibility = when (historyVisibility) {
             RoomHistoryVisibility.SHARED         -> stringProvider.getString(R.string.notice_room_visibility_shared)
@@ -116,7 +122,7 @@ class NoticeEventFormatter(private val stringProvider: StringProvider) {
                     stringProvider.getString(R.string.notice_display_name_removed, event.sender, prevEventContent?.displayName)
                 else                                          ->
                     stringProvider.getString(R.string.notice_display_name_changed_from,
-                            event.sender, prevEventContent?.displayName, eventContent?.displayName)
+                                             event.sender, prevEventContent?.displayName, eventContent?.displayName)
             }
             displayText.append(displayNameText)
         }
@@ -143,7 +149,7 @@ class NoticeEventFormatter(private val stringProvider: StringProvider) {
                 when {
                     eventContent.thirdPartyInvite != null        ->
                         stringProvider.getString(R.string.notice_room_third_party_registered_invite,
-                                targetDisplayName, eventContent.thirdPartyInvite?.displayName)
+                                                 targetDisplayName, eventContent.thirdPartyInvite?.displayName)
                     TextUtils.equals(event.stateKey, selfUserId) ->
                         stringProvider.getString(R.string.notice_room_invite_you, senderDisplayName)
                     event.stateKey.isNullOrEmpty()               ->
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineDateFormatter.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineDateFormatter.kt
index 0a4ed952..bd2b630f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineDateFormatter.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineDateFormatter.kt
@@ -19,8 +19,10 @@ package im.vector.riotredesign.features.home.room.detail.timeline.helper
 import im.vector.riotredesign.core.resources.LocaleProvider
 import org.threeten.bp.LocalDateTime
 import org.threeten.bp.format.DateTimeFormatter
+import javax.inject.Inject
 
-class TimelineDateFormatter(private val localeProvider: LocaleProvider) {
+
+class TimelineDateFormatter @Inject constructor (private val localeProvider: LocaleProvider) {
 
     private val messageHourFormatter by lazy {
         DateTimeFormatter.ofPattern("H:mm", localeProvider.current())
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt
index c4e74f3f..4f509798 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt
@@ -17,8 +17,9 @@
 package im.vector.riotredesign.features.home.room.detail.timeline.helper
 
 import androidx.recyclerview.widget.RecyclerView
+import javax.inject.Inject
 
-class TimelineMediaSizeProvider {
+class TimelineMediaSizeProvider @Inject constructor() {
 
     lateinit var recyclerView: RecyclerView
     private var cachedSize: Pair? = null
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/AlphabeticalRoomComparator.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/AlphabeticalRoomComparator.kt
index c1031c45..1c86d908 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/AlphabeticalRoomComparator.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/AlphabeticalRoomComparator.kt
@@ -17,9 +17,9 @@
 package im.vector.riotredesign.features.home.room.list
 
 import im.vector.matrix.android.api.session.room.model.RoomSummary
+import javax.inject.Inject
 
-class AlphabeticalRoomComparator
-    : Comparator {
+class AlphabeticalRoomComparator @Inject constructor() : Comparator {
 
     override fun compare(leftRoomSummary: RoomSummary?, rightRoomSummary: RoomSummary?): Int {
         return when {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/ChronologicalRoomComparator.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/ChronologicalRoomComparator.kt
index 2ffe559d..ccbe89bf 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/ChronologicalRoomComparator.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/ChronologicalRoomComparator.kt
@@ -17,8 +17,9 @@
 package im.vector.riotredesign.features.home.room.list
 
 import im.vector.matrix.android.api.session.room.model.RoomSummary
+import javax.inject.Inject
 
-class ChronologicalRoomComparator : Comparator {
+class ChronologicalRoomComparator @Inject constructor() : Comparator {
 
     override fun compare(leftRoomSummary: RoomSummary?, rightRoomSummary: RoomSummary?): Int {
         var rightTimestamp = 0L
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListFragment.kt
index e354be2f..06415a05 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListFragment.kt
@@ -23,7 +23,11 @@ import androidx.core.content.ContextCompat
 import androidx.core.view.isVisible
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
-import com.airbnb.mvrx.*
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.args
+import com.airbnb.mvrx.fragmentViewModel
 import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.api.session.room.model.Membership
 import im.vector.matrix.android.api.session.room.model.RoomSummary
@@ -36,7 +40,7 @@ import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.home.room.list.widget.FabMenuView
 import kotlinx.android.parcel.Parcelize
 import kotlinx.android.synthetic.main.fragment_room_list.*
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 @Parcelize
 data class RoomListParams(
@@ -61,7 +65,8 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Callback, O
     }
 
     private val roomListParams: RoomListParams by args()
-    private val roomController by inject()
+    @Inject lateinit var roomController: RoomSummaryController
+    @Inject lateinit var roomListViewModelFactory: RoomListViewModel.Factory
     private val roomListViewModel: RoomListViewModel by fragmentViewModel()
 
     override fun getLayoutResId() = R.layout.fragment_room_list
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListViewModel.kt
index c9ead506..7c6f7484 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListViewModel.kt
@@ -19,9 +19,12 @@ package im.vector.riotredesign.features.home.room.list
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import arrow.core.Option
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
 import com.jakewharton.rxrelay2.BehaviorRelay
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.room.model.Membership
 import im.vector.matrix.android.api.session.room.model.RoomSummary
@@ -29,26 +32,27 @@ import im.vector.matrix.android.api.session.room.model.tag.RoomTag
 import im.vector.riotredesign.core.platform.VectorViewModel
 import im.vector.riotredesign.core.utils.LiveEvent
 import im.vector.riotredesign.features.home.HomeRoomListObservableStore
-import org.koin.android.ext.android.get
 
 typealias RoomListFilterName = CharSequence
 
-class RoomListViewModel(initialState: RoomListViewState,
-                        private val session: Session,
-                        private val homeRoomListObservableSource: HomeRoomListObservableStore,
-                        private val alphabeticalRoomComparator: AlphabeticalRoomComparator,
-                        private val chronologicalRoomComparator: ChronologicalRoomComparator)
+class RoomListViewModel @AssistedInject constructor(@Assisted initialState: RoomListViewState,
+                                                    private val session: Session,
+                                                    private val homeRoomListObservableSource: HomeRoomListObservableStore,
+                                                    private val alphabeticalRoomComparator: AlphabeticalRoomComparator,
+                                                    private val chronologicalRoomComparator: ChronologicalRoomComparator)
     : VectorViewModel(initialState) {
 
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: RoomListViewState): RoomListViewModel
+    }
+
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: RoomListViewState): RoomListViewModel? {
-            val currentSession = viewModelContext.activity.get()
-            val homeRoomListObservableSource = viewModelContext.activity.get()
-            val chronologicalRoomComparator = viewModelContext.activity.get()
-            val alphabeticalRoomComparator = viewModelContext.activity.get()
-            return RoomListViewModel(state, currentSession, homeRoomListObservableSource, alphabeticalRoomComparator, chronologicalRoomComparator)
+            val fragment: RoomListFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.roomListViewModelFactory.create(state)
         }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt
index eafcb7dd..08f7fdb3 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt
@@ -27,10 +27,11 @@ import im.vector.riotredesign.core.resources.DateProvider
 import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.features.home.room.detail.timeline.format.NoticeEventFormatter
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
+import javax.inject.Inject
 
-class RoomSummaryController(private val stringProvider: StringProvider,
-                            private val eventFormatter: NoticeEventFormatter,
-                            private val timelineDateFormatter: TimelineDateFormatter
+class RoomSummaryController @Inject constructor(private val stringProvider: StringProvider,
+                                                private val eventFormatter: NoticeEventFormatter,
+                                                private val timelineDateFormatter: TimelineDateFormatter
 ) : TypedEpoxyController() {
 
     var callback: Callback? = null
diff --git a/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt
index d8012607..e57de8d1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt
@@ -19,11 +19,12 @@
 package im.vector.riotredesign.features.html
 
 import android.content.Context
-import android.text.style.ClickableSpan
 import android.text.style.URLSpan
+import androidx.appcompat.app.AppCompatActivity
 import im.vector.matrix.android.api.permalinks.PermalinkData
 import im.vector.matrix.android.api.permalinks.PermalinkParser
 import im.vector.matrix.android.api.session.Session
+import im.vector.riotredesign.core.glide.GlideApp
 import im.vector.riotredesign.core.glide.GlideRequests
 import org.commonmark.node.BlockQuote
 import org.commonmark.node.HtmlBlock
@@ -50,13 +51,12 @@ import ru.noties.markwon.html.tag.SubScriptHandler
 import ru.noties.markwon.html.tag.SuperScriptHandler
 import ru.noties.markwon.html.tag.UnderlineHandler
 import java.util.Arrays.asList
+import javax.inject.Inject
 
-class EventHtmlRenderer(glideRequests: GlideRequests,
-                        context: Context,
-                        session: Session) {
-
+class EventHtmlRenderer @Inject constructor(context: AppCompatActivity,
+                                            session: Session) {
     private val markwon = Markwon.builder(context)
-            .usePlugin(MatrixPlugin.create(glideRequests, context, session))
+            .usePlugin(MatrixPlugin.create(GlideApp.with(context), context, session))
             .build()
 
     fun render(text: String): CharSequence {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/lifecycle/VectorActivityLifecycleCallbacks.kt b/vector/src/main/java/im/vector/riotredesign/features/lifecycle/VectorActivityLifecycleCallbacks.kt
index 9a2a5e1e..b3ac5726 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/lifecycle/VectorActivityLifecycleCallbacks.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/lifecycle/VectorActivityLifecycleCallbacks.kt
@@ -20,8 +20,9 @@ import android.app.Activity
 import android.app.Application
 import android.os.Bundle
 import im.vector.riotredesign.features.popup.PopupAlertManager
+import javax.inject.Inject
 
-class VectorActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
+class VectorActivityLifecycleCallbacks @Inject constructor() : Application.ActivityLifecycleCallbacks {
     override fun onActivityPaused(activity: Activity) {
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotredesign/features/navigation/DefaultNavigator.kt
index 3dd5c6d9..c13f8b84 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/navigation/DefaultNavigator.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/navigation/DefaultNavigator.kt
@@ -27,9 +27,9 @@ import im.vector.riotredesign.features.home.room.detail.RoomDetailArgs
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
 import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewActivity
 import im.vector.riotredesign.features.settings.VectorSettingsActivity
+import javax.inject.Inject
 
-class DefaultNavigator : Navigator {
-
+class DefaultNavigator @Inject constructor() : Navigator {
 
     override fun openRoom(roomId: String, context: Context) {
         val args = RoomDetailArgs(roomId)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt
index 36692b7d..ae847d1c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt
@@ -22,16 +22,15 @@ import android.content.Intent
 import androidx.core.app.RemoteInput
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.room.Room
-import org.koin.standalone.KoinComponent
-import org.koin.standalone.inject
 import timber.log.Timber
+import javax.inject.Inject
 
 /**
  * Receives actions broadcast by notification (on click, on dismiss, inline replies, etc.)
  */
-class NotificationBroadcastReceiver : BroadcastReceiver(), KoinComponent {
+class NotificationBroadcastReceiver : BroadcastReceiver() {
 
-    private val notificationDrawerManager by inject()
+    @Inject lateinit var notificationDrawerManager: NotificationDrawerManager
 
     override fun onReceive(context: Context?, intent: Intent?) {
         if (intent == null || context == null) return
diff --git a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationDrawerManager.kt
index ce207397..7ada17d6 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationDrawerManager.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationDrawerManager.kt
@@ -30,13 +30,17 @@ import timber.log.Timber
 import java.io.File
 import java.io.FileInputStream
 import java.io.FileOutputStream
+import javax.inject.Inject
+import javax.inject.Singleton
 
 /**
  * The NotificationDrawerManager receives notification events as they arrived (from event stream or fcm) and
  * organise them in order to display them in the notification drawer.
  * Events can be grouped into the same notification, old (already read) events can be removed to do some cleaning.
  */
-class NotificationDrawerManager(val context: Context) {
+
+@Singleton
+class NotificationDrawerManager @Inject constructor(val context: Context) {
 
     //The first time the notification drawer is refreshed, we force re-render of all notifications
     private var firstTime = true
diff --git a/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiChooserFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiChooserFragment.kt
index 6f47538a..13ade472 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiChooserFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiChooserFragment.kt
@@ -15,34 +15,27 @@
  */
 package im.vector.riotredesign.features.reactions
 
-import androidx.lifecycle.ViewModelProviders
 import android.os.Bundle
-import android.util.Log
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
+import androidx.lifecycle.ViewModelProviders
 import androidx.recyclerview.widget.RecyclerView
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.platform.VectorBaseFragment
 
 
-class EmojiChooserFragment : Fragment() {
+class EmojiChooserFragment : VectorBaseFragment() {
 
     companion object {
         fun newInstance() = EmojiChooserFragment()
     }
 
-    private lateinit var viewModel: EmojiChooserViewModel
+    override fun getLayoutResId() = R.layout.emoji_chooser_fragment
 
-    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
-                              savedInstanceState: Bundle?): View? {
-        return inflater.inflate(R.layout.emoji_chooser_fragment, container, false)
-    }
+    private lateinit var viewModel: EmojiChooserViewModel
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         viewModel = activity?.run {
-            ViewModelProviders.of(this).get(EmojiChooserViewModel::class.java)
+            ViewModelProviders.of(this, viewModelFactory).get(EmojiChooserViewModel::class.java)
         } ?: throw Exception("Invalid Activity")
         viewModel.initWithContect(context!!)
         (view as? RecyclerView)?.let {
@@ -53,9 +46,4 @@ class EmojiChooserFragment : Fragment() {
 //        val ds = EmojiDataSource(this.context!!)
     }
 
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-
-
-    }
 }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiChooserViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiChooserViewModel.kt
index 7b11adcd..47f2dbf1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiChooserViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiChooserViewModel.kt
@@ -19,8 +19,9 @@ import android.content.Context
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import im.vector.riotredesign.core.utils.LiveEvent
+import javax.inject.Inject
 
-class EmojiChooserViewModel : ViewModel() {
+class EmojiChooserViewModel @Inject constructor() : ViewModel() {
 
     var adapter: EmojiRecyclerAdapter? = null
     val emojiSourceLiveData: MutableLiveData = MutableLiveData()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiReactionPickerActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiReactionPickerActivity.kt
index 8e362b61..72d3b19f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiReactionPickerActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiReactionPickerActivity.kt
@@ -33,7 +33,6 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import kotlinx.android.synthetic.main.activity_emoji_reaction_picker.*
-import org.koin.android.ext.android.inject
 
 /**
  *
@@ -55,7 +54,7 @@ class EmojiReactionPickerActivity : VectorBaseActivity(), EmojiCompatFontProvide
 
     override fun getTitleRes(): Int = R.string.title_activity_emoji_reaction_picker
 
-    val emojiCompatFontProvider by inject()
+    lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
 
     private var tabLayoutSelectionListener = object : TabLayout.BaseOnTabSelectedListener {
         override fun onTabReselected(p0: TabLayout.Tab) {
@@ -72,7 +71,6 @@ class EmojiReactionPickerActivity : VectorBaseActivity(), EmojiCompatFontProvide
 
     override fun initUiAndData() {
         configureToolbar(emojiPickerToolbar)
-
         emojiCompatFontProvider.let {
             EmojiDrawView.configureTextPaint(this, it.typeface)
             it.addListener(this)
@@ -80,7 +78,7 @@ class EmojiReactionPickerActivity : VectorBaseActivity(), EmojiCompatFontProvide
 
         tabLayout = findViewById(R.id.tabs)
 
-        viewModel = ViewModelProviders.of(this).get(EmojiChooserViewModel::class.java)
+        viewModel = ViewModelProviders.of(this, viewModelFactory).get(EmojiChooserViewModel::class.java)
 
         viewModel.eventId = intent.getStringExtra(EXTRA_EVENT_ID)
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsFragment.kt
index 1f680b9e..7f701af8 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsFragment.kt
@@ -34,11 +34,9 @@ import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.themes.ThemeUtils
 import io.reactivex.rxkotlin.subscribeBy
 import kotlinx.android.synthetic.main.fragment_public_rooms.*
-import org.koin.android.ext.android.inject
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
 import timber.log.Timber
 import java.util.concurrent.TimeUnit
+import javax.inject.Inject
 
 
 /**
@@ -49,8 +47,9 @@ class PublicRoomsFragment : VectorBaseFragment(), PublicRoomsController.Callback
 
     private val viewModel: RoomDirectoryViewModel by activityViewModel()
     private lateinit var navigationViewModel: RoomDirectoryNavigationViewModel
-    private val publicRoomsController: PublicRoomsController by inject()
-    private val errorFormatter: ErrorFormatter by inject()
+
+    @Inject lateinit var publicRoomsController: PublicRoomsController
+    @Inject lateinit var errorFormatter: ErrorFormatter
 
     override fun getLayoutResId() = R.layout.fragment_public_rooms
 
@@ -98,10 +97,7 @@ class PublicRoomsFragment : VectorBaseFragment(), PublicRoomsController.Callback
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
-        bindScope(getOrCreateScope(RoomDirectoryModule.ROOM_DIRECTORY_SCOPE))
-
         navigationViewModel = ViewModelProviders.of(requireActivity()).get(RoomDirectoryNavigationViewModel::class.java)
-
         setupRecyclerView()
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryActivity.kt
index 6f1e79e4..64853b8d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryActivity.kt
@@ -25,8 +25,7 @@ import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomFragment
 import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerFragment
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
+import javax.inject.Inject
 
 class RoomDirectoryActivity : VectorBaseActivity() {
 
@@ -39,17 +38,14 @@ class RoomDirectoryActivity : VectorBaseActivity() {
     }
 
 
+    @Inject lateinit var roomDirectoryViewModelFactory: RoomDirectoryViewModel.Factory
     private lateinit var navigationViewModel: RoomDirectoryNavigationViewModel
 
     override fun getLayoutRes() = R.layout.activity_simple
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-
-        bindScope(getOrCreateScope(RoomDirectoryModule.ROOM_DIRECTORY_SCOPE))
-
-        navigationViewModel = ViewModelProviders.of(this).get(RoomDirectoryNavigationViewModel::class.java)
-
+        navigationViewModel = ViewModelProviders.of(this, viewModelFactory).get(RoomDirectoryNavigationViewModel::class.java)
         navigationViewModel.navigateTo.observeEvent(this) { navigation ->
             when (navigation) {
                 is Navigation.Back           -> onBackPressed()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryNavigationViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryNavigationViewModel.kt
index 8183b787..e92cd883 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryNavigationViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryNavigationViewModel.kt
@@ -17,5 +17,6 @@
 package im.vector.riotredesign.features.roomdirectory
 
 import im.vector.riotredesign.core.mvrx.NavigationViewModel
+import javax.inject.Inject
 
-class RoomDirectoryNavigationViewModel : NavigationViewModel()
\ No newline at end of file
+class RoomDirectoryNavigationViewModel @Inject constructor(): NavigationViewModel()
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryViewModel.kt
index fa980b20..f06a2bea 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryViewModel.kt
@@ -18,7 +18,15 @@ package im.vector.riotredesign.features.roomdirectory
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
-import com.airbnb.mvrx.*
+import com.airbnb.mvrx.ActivityViewModelContext
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Loading
+import com.airbnb.mvrx.MvRxViewModelFactory
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.ViewModelContext
+import com.airbnb.mvrx.appendAt
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.room.model.Membership
@@ -31,21 +39,24 @@ import im.vector.matrix.android.api.util.Cancelable
 import im.vector.matrix.rx.rx
 import im.vector.riotredesign.core.platform.VectorViewModel
 import im.vector.riotredesign.core.utils.LiveEvent
-import org.koin.android.ext.android.get
 import timber.log.Timber
 
 private const val PUBLIC_ROOMS_LIMIT = 20
 
-class RoomDirectoryViewModel(initialState: PublicRoomsViewState,
-                             private val session: Session) : VectorViewModel(initialState) {
+class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState: PublicRoomsViewState,
+                                                         private val session: Session) : VectorViewModel(initialState) {
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: PublicRoomsViewState): RoomDirectoryViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: PublicRoomsViewState): RoomDirectoryViewModel? {
-            val currentSession = viewModelContext.activity.get()
-
-            return RoomDirectoryViewModel(state, currentSession)
+            val activity: RoomDirectoryActivity = (viewModelContext as ActivityViewModelContext).activity()
+            return activity.roomDirectoryViewModelFactory.create(state)
         }
     }
 
@@ -84,11 +95,11 @@ class RoomDirectoryViewModel(initialState: PublicRoomsViewState,
                 .liveRoomSummaries()
                 .subscribe { list ->
                     val joinedRoomIds = list
-                            // Keep only joined room
-                            ?.filter { it.membership == Membership.JOIN }
-                            ?.map { it.roomId }
-                            ?.toList()
-                            ?: emptyList()
+                                                // Keep only joined room
+                                                ?.filter { it.membership == Membership.JOIN }
+                                                ?.map { it.roomId }
+                                                ?.toList()
+                                        ?: emptyList()
 
                     setState {
                         copy(
@@ -155,39 +166,39 @@ class RoomDirectoryViewModel(initialState: PublicRoomsViewState,
 
     private fun load() {
         currentTask = session.getPublicRooms(roomDirectoryData.homeServer,
-                PublicRoomsParams(
-                        limit = PUBLIC_ROOMS_LIMIT,
-                        filter = PublicRoomsFilter(searchTerm = currentFilter),
-                        includeAllNetworks = roomDirectoryData.includeAllNetworks,
-                        since = since,
-                        thirdPartyInstanceId = roomDirectoryData.thirdPartyInstanceId
-                ),
-                object : MatrixCallback {
-                    override fun onSuccess(data: PublicRoomsResponse) {
-                        currentTask = null
+                                             PublicRoomsParams(
+                                                     limit = PUBLIC_ROOMS_LIMIT,
+                                                     filter = PublicRoomsFilter(searchTerm = currentFilter),
+                                                     includeAllNetworks = roomDirectoryData.includeAllNetworks,
+                                                     since = since,
+                                                     thirdPartyInstanceId = roomDirectoryData.thirdPartyInstanceId
+                                             ),
+                                             object : MatrixCallback {
+                                                 override fun onSuccess(data: PublicRoomsResponse) {
+                                                     currentTask = null
 
-                        since = data.nextBatch
+                                                     since = data.nextBatch
 
-                        setState {
-                            copy(
-                                    asyncPublicRoomsRequest = Success(data.chunk!!),
-                                    // It's ok to append at the end of the list, so I use publicRooms.size()
-                                    publicRooms = publicRooms.appendAt(data.chunk!!, publicRooms.size),
-                                    hasMore = since != null
-                            )
-                        }
-                    }
+                                                     setState {
+                                                         copy(
+                                                                 asyncPublicRoomsRequest = Success(data.chunk!!),
+                                                                 // It's ok to append at the end of the list, so I use publicRooms.size()
+                                                                 publicRooms = publicRooms.appendAt(data.chunk!!, publicRooms.size),
+                                                                 hasMore = since != null
+                                                         )
+                                                     }
+                                                 }
 
-                    override fun onFailure(failure: Throwable) {
-                        currentTask = null
+                                                 override fun onFailure(failure: Throwable) {
+                                                     currentTask = null
 
-                        setState {
-                            copy(
-                                    asyncPublicRoomsRequest = Fail(failure)
-                            )
-                        }
-                    }
-                })
+                                                     setState {
+                                                         copy(
+                                                                 asyncPublicRoomsRequest = Fail(failure)
+                                                         )
+                                                     }
+                                                 }
+                                             })
     }
 
     fun joinRoom(publicRoom: PublicRoom) = withState { state ->
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryListCreator.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryListCreator.kt
index 49fed53e..dadb4fa9 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryListCreator.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryListCreator.kt
@@ -16,14 +16,17 @@
 
 package im.vector.riotredesign.features.roomdirectory.picker
 
-import im.vector.matrix.android.api.auth.data.Credentials
+import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.room.model.thirdparty.RoomDirectoryData
 import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.resources.StringArrayProvider
+import javax.inject.Inject
 
-class RoomDirectoryListCreator(private val stringArrayProvider: StringArrayProvider,
-                               private val credentials: Credentials) {
+class RoomDirectoryListCreator @Inject constructor(private val stringArrayProvider: StringArrayProvider,
+                                                   private val session: Session) {
+
+    private val credentials = session.sessionParams.credentials
 
     fun computeDirectories(thirdPartyProtocolData: Map): List {
         val result = ArrayList()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerController.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerController.kt
index e19c7a0b..b80944b9 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerController.kt
@@ -26,10 +26,11 @@ import im.vector.riotredesign.core.epoxy.errorWithRetryItem
 import im.vector.riotredesign.core.epoxy.loadingItem
 import im.vector.riotredesign.core.error.ErrorFormatter
 import im.vector.riotredesign.core.resources.StringProvider
+import javax.inject.Inject
 
-class RoomDirectoryPickerController(private val stringProvider: StringProvider,
-                                    private val errorFormatter: ErrorFormatter,
-                                    private val roomDirectoryListCreator: RoomDirectoryListCreator
+class RoomDirectoryPickerController @Inject constructor(private val stringProvider: StringProvider,
+                                                        private val errorFormatter: ErrorFormatter,
+                                                        private val roomDirectoryListCreator: RoomDirectoryListCreator
 ) : TypedEpoxyController() {
 
     var callback: Callback? = null
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt
index 4d1ca98b..38cf4a3d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt
@@ -28,14 +28,11 @@ import im.vector.matrix.android.api.session.room.model.thirdparty.RoomDirectoryD
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
-import im.vector.riotredesign.features.roomdirectory.RoomDirectoryModule
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryNavigationViewModel
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryViewModel
 import kotlinx.android.synthetic.main.fragment_room_directory_picker.*
-import org.koin.android.ext.android.inject
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
 import timber.log.Timber
+import javax.inject.Inject
 
 // TODO Set title to R.string.select_room_directory
 // TODO Menu to add custom room directory (not done in RiotWeb so far...)
@@ -44,7 +41,9 @@ class RoomDirectoryPickerFragment : VectorBaseFragment(), RoomDirectoryPickerCon
     private val viewModel: RoomDirectoryViewModel by activityViewModel()
     private lateinit var navigationViewModel: RoomDirectoryNavigationViewModel
     private val pickerViewModel: RoomDirectoryPickerViewModel by fragmentViewModel()
-    private val roomDirectoryPickerController: RoomDirectoryPickerController by inject()
+
+    @Inject lateinit var roomDirectoryPickerViewModelFactory: RoomDirectoryPickerViewModel.Factory
+    @Inject lateinit var roomDirectoryPickerController: RoomDirectoryPickerController
 
     override fun getLayoutResId() = R.layout.fragment_room_directory_picker
 
@@ -72,11 +71,9 @@ class RoomDirectoryPickerFragment : VectorBaseFragment(), RoomDirectoryPickerCon
     }
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
+        injector().inject(this)
         super.onActivityCreated(savedInstanceState)
-        bindScope(getOrCreateScope(RoomDirectoryModule.ROOM_DIRECTORY_SCOPE))
-
         navigationViewModel = ViewModelProviders.of(requireActivity()).get(RoomDirectoryNavigationViewModel::class.java)
-
         setupRecyclerView()
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt
index 30e687e9..6b5d86fb 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt
@@ -17,25 +17,32 @@
 package im.vector.riotredesign.features.roomdirectory.picker
 
 import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.Success
 import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol
 import im.vector.riotredesign.core.platform.VectorViewModel
-import org.koin.android.ext.android.get
 
-class RoomDirectoryPickerViewModel(initialState: RoomDirectoryPickerViewState,
-                                   private val session: Session) : VectorViewModel(initialState) {
+class RoomDirectoryPickerViewModel @AssistedInject constructor(@Assisted initialState: RoomDirectoryPickerViewState,
+                                                               private val session: Session) : VectorViewModel(initialState) {
+
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: RoomDirectoryPickerViewState): RoomDirectoryPickerViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: RoomDirectoryPickerViewState): RoomDirectoryPickerViewModel? {
-            val currentSession = viewModelContext.activity.get()
-
-            return RoomDirectoryPickerViewModel(state, currentSession)
+            val fragment: RoomDirectoryPickerFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.roomDirectoryPickerViewModelFactory.create(state)
         }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewActivity.kt
index 0728ad56..46044914 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewActivity.kt
@@ -18,7 +18,6 @@ package im.vector.riotredesign.features.roomdirectory.roompreview
 
 import android.content.Context
 import android.content.Intent
-import android.os.Bundle
 import android.os.Parcelable
 import androidx.appcompat.widget.Toolbar
 import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom
@@ -26,10 +25,7 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.extensions.addFragment
 import im.vector.riotredesign.core.platform.ToolbarConfigurable
 import im.vector.riotredesign.core.platform.VectorBaseActivity
-import im.vector.riotredesign.features.roomdirectory.RoomDirectoryModule
 import kotlinx.android.parcel.Parcelize
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
 
 @Parcelize
 data class RoomPreviewData(
@@ -65,12 +61,6 @@ class RoomPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
         configureToolbar(toolbar)
     }
 
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-
-        bindScope(getOrCreateScope(RoomDirectoryModule.ROOM_DIRECTORY_SCOPE))
-    }
-
     override fun initUiAndData() {
         if (isFirstCreation()) {
             val args = intent.getParcelableExtra(ARG)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
index 3f389a46..d1960614 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
@@ -30,11 +30,8 @@ import im.vector.riotredesign.core.platform.ButtonStateView
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.roomdirectory.JoinState
-import im.vector.riotredesign.features.roomdirectory.RoomDirectoryModule
 import kotlinx.android.synthetic.main.fragment_room_preview_no_preview.*
-import org.koin.android.ext.android.get
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
+import javax.inject.Inject
 
 /**
  * Note: this Fragment is also used for world readable room for the moment
@@ -47,14 +44,14 @@ class RoomPreviewNoPreviewFragment : VectorBaseFragment() {
         }
     }
 
-    private val errorFormatter = get()
+    @Inject lateinit var errorFormatter: ErrorFormatter
+    @Inject lateinit var roomPreviewViewModelFactory: RoomPreviewViewModel.Factory
     private val roomPreviewViewModel: RoomPreviewViewModel by fragmentViewModel()
-
     private val roomPreviewData: RoomPreviewData by args()
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
+        injector().inject(this)
         super.onActivityCreated(savedInstanceState)
-        bindScope(getOrCreateScope(RoomDirectoryModule.ROOM_DIRECTORY_SCOPE))
         setupToolbar(roomPreviewNoPreviewToolbar)
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewViewModel.kt
index 131f2719..61102f11 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewViewModel.kt
@@ -16,27 +16,33 @@
 
 package im.vector.riotredesign.features.roomdirectory.roompreview
 
+import com.airbnb.mvrx.FragmentViewModelContext
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.room.model.Membership
 import im.vector.matrix.rx.rx
 import im.vector.riotredesign.core.platform.VectorViewModel
 import im.vector.riotredesign.features.roomdirectory.JoinState
-import org.koin.android.ext.android.get
 import timber.log.Timber
 
-class RoomPreviewViewModel(initialState: RoomPreviewViewState,
-                           private val session: Session) : VectorViewModel(initialState) {
+class RoomPreviewViewModel @AssistedInject constructor(@Assisted initialState: RoomPreviewViewState,
+                                                       private val session: Session) : VectorViewModel(initialState) {
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: RoomPreviewViewState): RoomPreviewViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: RoomPreviewViewState): RoomPreviewViewModel? {
-            val currentSession = viewModelContext.activity.get()
-
-            return RoomPreviewViewModel(state, currentSession)
+            val fragment: RoomPreviewNoPreviewFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.roomPreviewViewModelFactory.create(state)
         }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutBottomSheetDialogFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutBottomSheetDialogFragment.kt
index 2d53f36a..f420a2ac 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutBottomSheetDialogFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutBottomSheetDialogFragment.kt
@@ -30,6 +30,7 @@ import android.widget.TextView
 import androidx.appcompat.app.AlertDialog
 import androidx.core.view.isVisible
 import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.ViewModelProviders
 import androidx.transition.TransitionManager
 import butterknife.BindView
@@ -40,15 +41,19 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.HasInjector
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.utils.toast
 import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupManageActivity
 import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupActivity
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 
 class SignOutBottomSheetDialogFragment : BottomSheetDialogFragment() {
 
-    val session by inject()
+    @Inject lateinit var session: Session
+    @Inject lateinit var viewModelFactory: ViewModelProvider.Factory
+
 
     @BindView(R.id.bottom_sheet_signout_warning_text)
     lateinit var sheetTitle: TextView
@@ -99,7 +104,7 @@ class SignOutBottomSheetDialogFragment : BottomSheetDialogFragment() {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
 
-        viewModel = ViewModelProviders.of(this).get(SignOutViewModel::class.java)
+        viewModel = ViewModelProviders.of(this, viewModelFactory).get(SignOutViewModel::class.java)
 
         viewModel.init(session)
 
@@ -131,7 +136,7 @@ class SignOutBottomSheetDialogFragment : BottomSheetDialogFragment() {
                                         startActivity(KeysBackupManageActivity.intent(context))
                                     }
                                 }
-                                KeysBackupState.Disabled -> {
+                                KeysBackupState.Disabled   -> {
                                     context?.let { context ->
                                         startActivityForResult(KeysBackupSetupActivity.intent(context, true), EXPORT_REQ)
                                     }
@@ -141,7 +146,7 @@ class SignOutBottomSheetDialogFragment : BottomSheetDialogFragment() {
                                     //keys are already backing up please wait
                                     context?.toast(R.string.keys_backup_is_not_finished_please_wait)
                                 }
-                                else -> {
+                                else                       -> {
                                     //nop
                                 }
                             }
@@ -190,7 +195,7 @@ class SignOutBottomSheetDialogFragment : BottomSheetDialogFragment() {
                     sheetTitle.text = getString(R.string.action_sign_out_confirmation_simple)
                 }
                 KeysBackupState.BackingUp,
-                KeysBackupState.WillBackUp -> {
+                KeysBackupState.WillBackUp    -> {
                     backingUpStatusGroup.isVisible = true
                     sheetTitle.text = getString(R.string.sign_out_bottom_sheet_warning_backing_up)
                     dontWantClickableView.isVisible = true
@@ -202,14 +207,14 @@ class SignOutBottomSheetDialogFragment : BottomSheetDialogFragment() {
                     backupStatusTex.text = getString(R.string.sign_out_bottom_sheet_backing_up_keys)
 
                 }
-                KeysBackupState.NotTrusted -> {
+                KeysBackupState.NotTrusted    -> {
                     backingUpStatusGroup.isVisible = false
                     dontWantClickableView.isVisible = true
                     setupClickableView.isVisible = false
                     activateClickableView.isVisible = true
                     sheetTitle.text = getString(R.string.sign_out_bottom_sheet_warning_backup_not_active)
                 }
-                else -> {
+                else                          -> {
                     backingUpStatusGroup.isVisible = false
                     dontWantClickableView.isVisible = true
                     setupClickableView.isVisible = true
diff --git a/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutViewModel.kt
index ea3989ee..c923adab 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutViewModel.kt
@@ -21,8 +21,9 @@ import androidx.lifecycle.ViewModel
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupStateListener
+import javax.inject.Inject
 
-class SignOutViewModel : ViewModel(), KeysBackupStateListener {
+class SignOutViewModel @Inject constructor() : ViewModel(), KeysBackupStateListener {
     // Keys exported manually
     var keysExportedToFile = MutableLiveData()
 
@@ -47,9 +48,9 @@ class SignOutViewModel : ViewModel(), KeysBackupStateListener {
      */
     fun getCurrentBackupVersion(): String {
         return mxSession
-                ?.getKeysBackupService()
-                ?.currentBackupVersion
-                ?: ""
+                       ?.getKeysBackupService()
+                       ?.currentBackupVersion
+               ?: ""
     }
 
     /**
@@ -57,8 +58,8 @@ class SignOutViewModel : ViewModel(), KeysBackupStateListener {
      */
     fun getNumberOfKeysToBackup(): Int {
         return mxSession
-                ?.inboundGroupSessionsCount(false)
-                ?: 0
+                       ?.inboundGroupSessionsCount(false)
+               ?: 0
     }
 
     /**
@@ -87,11 +88,11 @@ class SignOutViewModel : ViewModel(), KeysBackupStateListener {
          */
         fun doYouNeedToBeDisplayed(session: Session?): Boolean {
             return session
-                    ?.inboundGroupSessionsCount(false)
-                    ?: 0 > 0
-                    && session
-                    ?.getKeysBackupService()
-                    ?.state != KeysBackupState.ReadyToBackUp
+                           ?.inboundGroupSessionsCount(false)
+                   ?: 0 > 0
+                   && session
+                           ?.getKeysBackupService()
+                           ?.state != KeysBackupState.ReadyToBackUp
         }
     }
 }
\ No newline at end of file

From ee87c253fec6433705c0660aa8cc40334b3d7b73 Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Wed, 19 Jun 2019 19:40:59 +0200
Subject: [PATCH 05/11] Dagger: continue working on app side. Now compile but
 some DI are not branched yet.

---
 .../main/java/im/vector/matrix/rx/RxRoom.kt   |   5 +
 .../vector/riotredesign/VectorApplication.kt  |   3 +
 .../riotredesign/core/di/ScreenComponent.kt   |  58 ++++++++
 .../riotredesign/core/di/VectorComponent.kt   |   6 +
 .../riotredesign/core/di/ViewModelModule.kt   |  47 ++++---
 .../core/platform/SimpleFragmentActivity.kt   |   9 +-
 .../core/platform/VectorBaseActivity.kt       |  14 +-
 .../core/platform/VectorBaseFragment.kt       |  16 ++-
 .../core/services/EventStreamServiceX.kt      |  14 +-
 .../KeysBackupRestoreFromKeyFragment.kt       |   5 +
 ...KeysBackupRestoreFromPassphraseFragment.kt |   5 +
 .../KeysBackupRestoreSuccessFragment.kt       |   5 +
 .../settings/KeysBackupManageActivity.kt      |   5 +-
 .../settings/KeysBackupSettingsFragment.kt    |   7 +-
 .../setup/KeysBackupSetupStep1Fragment.kt     |   5 +
 .../setup/KeysBackupSetupStep2Fragment.kt     |   5 +
 .../setup/KeysBackupSetupStep3Fragment.kt     |   5 +
 .../SASVerificationIncomingFragment.kt        |   5 +
 .../features/home/HomeActivity.kt             |   8 +-
 .../features/home/HomeDetailFragment.kt       |   5 +
 .../features/home/HomeDrawerFragment.kt       |   7 +-
 .../features/home/HomeNavigator.kt            |   3 +
 .../features/home/group/GroupListFragment.kt  |   6 +
 .../home/room/detail/RoomDetailFragment.kt    |   6 +-
 .../action/MessageActionsBottomSheet.kt       |   6 +-
 .../timeline/action/MessageMenuFragment.kt    |  19 ++-
 .../timeline/action/QuickReactionFragment.kt  |  16 +--
 ...=> VectorBaseBottomSheetDialogFragment.kt} |  20 ++-
 .../action/ViewReactionBottomSheet.kt         |  12 +-
 .../timeline/action/ViewReactionViewModel.kt  | 125 ++++++++----------
 .../home/room/list/RoomListFragment.kt        |   5 +
 .../features/navigation/DefaultNavigator.kt   |   2 +
 .../reactions/EmojiReactionPickerActivity.kt  |   8 +-
 .../roomdirectory/PublicRoomsController.kt    |   3 +-
 .../roomdirectory/PublicRoomsFragment.kt      |   5 +
 .../roomdirectory/RoomDirectoryModule.kt      |  54 --------
 .../createroom/CreateRoomController.kt        |   3 +-
 .../createroom/CreateRoomFragment.kt          |  18 ++-
 .../createroom/CreateRoomViewModel.kt         |  18 ++-
 .../picker/RoomDirectoryPickerFragment.kt     |   6 +-
 .../RoomPreviewNoPreviewFragment.kt           |   6 +-
 .../settings/VectorSettingsActivity.kt        |   9 +-
 ...sAdvancedNotificationPreferenceFragment.kt |   4 +-
 ...ttingsNotificationsTroubleshootFragment.kt |   6 +-
 .../VectorSettingsPreferencesFragment.kt      |  42 +++---
 .../main/res/layout/fragment_message_menu.xml |   5 +
 46 files changed, 406 insertions(+), 240 deletions(-)
 rename vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/{BaseMvRxBottomSheetDialog.kt => VectorBaseBottomSheetDialogFragment.kt} (73%)
 delete mode 100644 vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryModule.kt
 create mode 100644 vector/src/main/res/layout/fragment_message_menu.xml

diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt
index c9dbbdd0..ec6e1203 100644
--- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt
+++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt
@@ -17,6 +17,7 @@
 package im.vector.matrix.rx
 
 import im.vector.matrix.android.api.session.room.Room
+import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
 import im.vector.matrix.android.api.session.room.model.RoomSummary
 import io.reactivex.Observable
 
@@ -30,6 +31,10 @@ class RxRoom(private val room: Room) {
         return room.getRoomMemberIdsLive().asObservable()
     }
 
+    fun liveAnnotationSummary(eventId: String): Observable> {
+        return room.getEventSummaryLive(eventId).asObservable()
+    }
+
 }
 
 fun Room.rx(): RxRoom {
diff --git a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
index ed57d347..f740bec0 100644
--- a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
+++ b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
@@ -31,6 +31,7 @@ import com.github.piasy.biv.BigImageViewer
 import com.github.piasy.biv.loader.glide.GlideImageLoader
 import com.jakewharton.threetenabp.AndroidThreeTen
 import im.vector.matrix.android.api.Matrix
+import im.vector.riotredesign.core.di.DaggerVectorComponent
 import im.vector.riotredesign.core.di.HasInjector
 import im.vector.riotredesign.core.di.VectorComponent
 import im.vector.riotredesign.features.configuration.VectorConfiguration
@@ -53,6 +54,8 @@ class VectorApplication : Application(), HasInjector {
     override fun onCreate() {
         super.onCreate()
         appContext = this
+        vectorComponent = DaggerVectorComponent.factory().create(this)
+        vectorComponent.inject(this)
         VectorUncaughtExceptionHandler.activate(this)
         // Log
         VectorFileLogger.init(this)
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
index 1f20979a..46320f4e 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
@@ -20,13 +20,32 @@ import androidx.appcompat.app.AppCompatActivity
 import androidx.lifecycle.ViewModelProvider
 import dagger.BindsInstance
 import dagger.Component
+import im.vector.fragments.keysbackup.restore.KeysBackupRestoreFromPassphraseFragment
 import im.vector.riotredesign.core.platform.SimpleFragmentActivity
+import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromKeyFragment
+import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreSuccessFragment
 import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupSettingsFragment
+import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupStep1Fragment
+import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupStep2Fragment
+import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupStep3Fragment
+import im.vector.riotredesign.features.crypto.verification.SASVerificationIncomingFragment
 import im.vector.riotredesign.features.home.HomeActivity
+import im.vector.riotredesign.features.home.HomeDetailFragment
+import im.vector.riotredesign.features.home.HomeDrawerFragment
 import im.vector.riotredesign.features.home.HomeModule
+import im.vector.riotredesign.features.home.group.GroupListFragment
 import im.vector.riotredesign.features.home.room.detail.RoomDetailFragment
+import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageActionsBottomSheet
+import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageMenuFragment
+import im.vector.riotredesign.features.home.room.detail.timeline.action.QuickReactionFragment
+import im.vector.riotredesign.features.home.room.detail.timeline.action.ViewReactionBottomSheet
+import im.vector.riotredesign.features.home.room.list.RoomListFragment
+import im.vector.riotredesign.features.reactions.EmojiReactionPickerActivity
+import im.vector.riotredesign.features.roomdirectory.PublicRoomsFragment
+import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomFragment
 import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerFragment
 import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment
+import im.vector.riotredesign.features.settings.VectorSettingsActivity
 
 @Component(dependencies = [VectorComponent::class], modules = [ViewModelModule::class, HomeModule::class])
 @ScreenScope
@@ -40,12 +59,51 @@ interface ScreenComponent {
 
     fun inject(roomDetailFragment: RoomDetailFragment)
 
+    fun inject(roomListFragment: RoomListFragment)
+
+    fun inject(groupListFragment: GroupListFragment)
+
     fun inject(roomDirectoryPickerFragment: RoomDirectoryPickerFragment)
 
     fun inject(roomPreviewNoPreviewFragment: RoomPreviewNoPreviewFragment)
     
     fun inject(keysBackupSettingsFragment: KeysBackupSettingsFragment)
 
+    fun inject(homeDrawerFragment: HomeDrawerFragment)
+
+    fun inject(homeDetailFragment: HomeDetailFragment)
+
+    fun inject(messageActionsBottomSheet: MessageActionsBottomSheet)
+
+    fun inject(viewReactionBottomSheet: ViewReactionBottomSheet)
+
+    fun inject(messageMenuFragment: MessageMenuFragment)
+
+    fun inject(vectorSettingsActivity: VectorSettingsActivity)
+
+    fun inject(createRoomFragment: CreateRoomFragment)
+
+    fun inject(keysBackupRestoreFromKeyFragment: KeysBackupRestoreFromKeyFragment)
+
+    fun inject(keysBackupRestoreFromPassphraseFragment: KeysBackupRestoreFromPassphraseFragment)
+
+    fun inject(keysBackupRestoreSuccessFragment: KeysBackupRestoreSuccessFragment)
+
+    fun inject(keysBackupSetupStep1Fragment: KeysBackupSetupStep1Fragment)
+
+    fun inject(keysBackupSetupStep2Fragment: KeysBackupSetupStep2Fragment)
+
+    fun inject(keysBackupSetupStep3Fragment: KeysBackupSetupStep3Fragment)
+
+    fun inject(publicRoomsFragment: PublicRoomsFragment)
+
+    fun inject(sasVerificationIncomingFragment: SASVerificationIncomingFragment)
+
+    fun inject(quickReactionFragment: QuickReactionFragment)
+
+    fun inject(emojiReactionPickerActivity: EmojiReactionPickerActivity)
+
+
     @Component.Factory
     interface Factory {
         fun create(vectorComponent: VectorComponent,
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
index 6517c4b9..100716f6 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
@@ -22,9 +22,11 @@ import dagger.BindsInstance
 import dagger.Component
 import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.session.Session
+import im.vector.riotredesign.VectorApplication
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.crypto.keysrequest.KeyRequestHandler
 import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
+import im.vector.riotredesign.features.home.HomeNavigator
 import im.vector.riotredesign.features.home.HomeRoomListObservableStore
 import im.vector.riotredesign.features.home.group.SelectedGroupStore
 import im.vector.riotredesign.features.navigation.Navigator
@@ -49,6 +51,8 @@ interface VectorComponent {
 
     fun navigator(): Navigator
 
+    fun homeNavigator(): HomeNavigator
+
     fun homeRoomListObservableStore(): HomeRoomListObservableStore
 
     fun selectedGroupStore(): SelectedGroupStore
@@ -57,6 +61,8 @@ interface VectorComponent {
 
     fun incomingKeyRequestHandler(): KeyRequestHandler
 
+    fun inject(vectorApplication: VectorApplication)
+
     @Component.Factory
     interface Factory {
         fun create(@BindsInstance context: Context): VectorComponent
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
index c38608ff..34b3e150 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
@@ -21,6 +21,7 @@ import androidx.lifecycle.ViewModelProvider
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.IntoMap
+import im.vector.riotredesign.core.platform.ConfigurationViewModel
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromKeyViewModel
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel
@@ -39,18 +40,15 @@ import im.vector.riotredesign.features.home.room.detail.RoomDetailViewModel
 import im.vector.riotredesign.features.home.room.detail.RoomDetailViewModel_AssistedFactory
 import im.vector.riotredesign.features.home.room.detail.composer.TextComposerViewModel
 import im.vector.riotredesign.features.home.room.detail.composer.TextComposerViewModel_AssistedFactory
-import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageActionsViewModel
-import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageActionsViewModel_AssistedFactory
-import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageMenuViewModel
-import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageMenuViewModel_AssistedFactory
-import im.vector.riotredesign.features.home.room.detail.timeline.action.QuickReactionViewModel
-import im.vector.riotredesign.features.home.room.detail.timeline.action.QuickReactionViewModel_AssistedFactory
+import im.vector.riotredesign.features.home.room.detail.timeline.action.*
 import im.vector.riotredesign.features.home.room.list.RoomListViewModel
 import im.vector.riotredesign.features.home.room.list.RoomListViewModel_AssistedFactory
 import im.vector.riotredesign.features.reactions.EmojiChooserViewModel
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryNavigationViewModel
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryViewModel
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryViewModel_AssistedFactory
+import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomViewModel
+import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomViewModel_AssistedFactory
 import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerViewModel
 import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerViewModel_AssistedFactory
 import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewViewModel
@@ -109,42 +107,53 @@ interface ViewModelModule {
     fun bindKeysBackupSetupSharedViewModel(viewModel: KeysBackupSetupSharedViewModel): ViewModel
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_HomeActivityViewModel(factory: HomeActivityViewModel_AssistedFactory): HomeActivityViewModel.Factory
+    @IntoMap
+    @ViewModelKey(ConfigurationViewModel::class)
+    fun bindConfigurationViewModel(viewModel: ConfigurationViewModel): ViewModel
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_room_detail_composer_TextComposerViewModel(factory: TextComposerViewModel_AssistedFactory): TextComposerViewModel.Factory
+    fun bindHomeActivityViewModelFactory(factory: HomeActivityViewModel_AssistedFactory): HomeActivityViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_room_detail_RoomDetailViewModel(factory: RoomDetailViewModel_AssistedFactory): RoomDetailViewModel.Factory
+    fun bindTextComposerViewModelFactory(factory: TextComposerViewModel_AssistedFactory): TextComposerViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_room_detail_timeline_action_QuickReactionViewModel(factory: QuickReactionViewModel_AssistedFactory): QuickReactionViewModel.Factory
+    fun bindRoomDetailViewModelFactory(factory: RoomDetailViewModel_AssistedFactory): RoomDetailViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_room_detail_timeline_action_MessageActionsViewModel(factory: MessageActionsViewModel_AssistedFactory): MessageActionsViewModel.Factory
+    fun bindQuickReactionViewModelFactory(factory: QuickReactionViewModel_AssistedFactory): QuickReactionViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_room_detail_timeline_action_MessageMenuViewModel(factory: MessageMenuViewModel_AssistedFactory): MessageMenuViewModel.Factory
+    fun bindMessageActionsViewModelFactory(factory: MessageActionsViewModel_AssistedFactory): MessageActionsViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_room_list_RoomListViewModel(factory: RoomListViewModel_AssistedFactory): RoomListViewModel.Factory
+    fun bindMessageMenuViewModelFactory(factory: MessageMenuViewModel_AssistedFactory): MessageMenuViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_group_GroupListViewModel(factory: GroupListViewModel_AssistedFactory): GroupListViewModel.Factory
+    fun bindRoomListViewModelFactory(factory: RoomListViewModel_AssistedFactory): RoomListViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_home_HomeDetailViewModel(factory: HomeDetailViewModel_AssistedFactory): HomeDetailViewModel.Factory
+    fun bindGroupListViewModelFactory(factory: GroupListViewModel_AssistedFactory): GroupListViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_crypto_keysbackup_settings_KeysBackupSettingsViewModel(factory: KeysBackupSettingsViewModel_AssistedFactory): KeysBackupSettingsViewModel.Factory
+    fun bindHomeDetailViewModelFactory(factory: HomeDetailViewModel_AssistedFactory): HomeDetailViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_roomdirectory_picker_RoomDirectoryPickerViewModel(factory: RoomDirectoryPickerViewModel_AssistedFactory): RoomDirectoryPickerViewModel.Factory
+    fun bindKeysBackupSettingsViewModelFactory(factory: KeysBackupSettingsViewModel_AssistedFactory): KeysBackupSettingsViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_roomdirectory_RoomDirectoryViewModel(factory: RoomDirectoryViewModel_AssistedFactory): RoomDirectoryViewModel.Factory
+    fun bindRoomDirectoryPickerViewModelFactory(factory: RoomDirectoryPickerViewModel_AssistedFactory): RoomDirectoryPickerViewModel.Factory
 
     @Binds
-    fun bind_im_vector_riotredesign_features_roomdirectory_roompreview_RoomPreviewViewModel(factory: RoomPreviewViewModel_AssistedFactory): RoomPreviewViewModel.Factory
+    fun bindRoomDirectoryViewModelFactory(factory: RoomDirectoryViewModel_AssistedFactory): RoomDirectoryViewModel.Factory
+
+    @Binds
+    fun bindRoomPreviewViewModelFactory(factory: RoomPreviewViewModel_AssistedFactory): RoomPreviewViewModel.Factory
+
+    @Binds
+    fun bindViewReactionViewModelFactory(factory: ViewReactionViewModel_AssistedFactory): ViewReactionViewModel.Factory
+
+    @Binds
+    fun bindCreateRoomViewModelFactory(factory: CreateRoomViewModel_AssistedFactory): CreateRoomViewModel.Factory
 
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
index 2b891275..8c9bfbde 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
@@ -24,6 +24,7 @@ import androidx.core.view.isVisible
 import butterknife.BindView
 import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.hideKeyboard
 import kotlinx.android.synthetic.main.activity.*
 import javax.inject.Inject
@@ -44,12 +45,10 @@ abstract class SimpleFragmentActivity : VectorBaseActivity() {
     @BindView(R.id.waiting_view_status_horizontal_progress)
     lateinit var waitingHorizontalProgress: ProgressBar
 
-    @Inject
-    lateinit var session: Session
+    @Inject lateinit var session: Session
 
-    override fun onCreate(savedInstanceState: Bundle?) {
-        injector().inject(this)
-        super.onCreate(savedInstanceState)
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
     }
 
     override fun initUiAndData() {
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
index 830ebcf6..7296b7d5 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
@@ -44,8 +44,10 @@ import com.bumptech.glide.util.Util
 import com.google.android.material.snackbar.Snackbar
 import im.vector.riotredesign.BuildConfig
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.DaggerScreenComponent
 import im.vector.riotredesign.core.di.HasInjector
 import im.vector.riotredesign.core.di.ScreenComponent
+import im.vector.riotredesign.core.di.VectorComponent
 import im.vector.riotredesign.core.utils.toast
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.rageshake.BugReportActivity
@@ -78,7 +80,6 @@ abstract class VectorBaseActivity : BaseMvRxActivity(), HasInjector).injector()
+    }
+
     /**
      * Force to render the activity in fullscreen
      */
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
index 137c680c..f1fa25f7 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
@@ -16,6 +16,7 @@
 
 package im.vector.riotredesign.core.platform
 
+import android.content.Context
 import android.os.Bundle
 import android.os.Parcelable
 import android.view.LayoutInflater
@@ -33,6 +34,7 @@ import butterknife.Unbinder
 import com.airbnb.mvrx.BaseMvRxFragment
 import com.airbnb.mvrx.MvRx
 import com.bumptech.glide.util.Util.assertMainThread
+import im.vector.riotredesign.core.di.DaggerScreenComponent
 import im.vector.riotredesign.core.di.HasInjector
 import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.features.navigation.Navigator
@@ -55,11 +57,22 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed, HasInject
 
     protected lateinit var viewModelFactory: ViewModelProvider.Factory
     protected lateinit var navigator: Navigator
+    private lateinit var screenComponent: ScreenComponent
 
     /* ==========================================================================================
      * Life cycle
      * ========================================================================================== */
 
+    override fun onAttach(context: Context) {
+        screenComponent = DaggerScreenComponent.factory().create(vectorBaseActivity.getVectorComponent(), vectorBaseActivity)
+        super.onAttach(context)
+        navigator = vectorBaseActivity.getVectorComponent().navigator()
+        viewModelFactory = screenComponent.viewModelFactory()
+        injectWith(injector())
+    }
+
+    protected open fun injectWith(injector: ScreenComponent) = Unit
+
     @CallSuper
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -78,7 +91,6 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed, HasInject
     @CallSuper
     override fun onResume() {
         super.onResume()
-
         Timber.v("onResume Fragment ${this.javaClass.simpleName}")
     }
 
@@ -101,7 +113,7 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed, HasInject
     }
 
     override fun injector(): ScreenComponent {
-        return vectorBaseActivity.injector()
+        return screenComponent
     }
 
     /* ==========================================================================================
diff --git a/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt b/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
index 0f26887e..6c4b7043 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
@@ -30,6 +30,7 @@ import im.vector.riotredesign.features.notifications.NotifiableEventResolver
 import im.vector.riotredesign.features.notifications.NotificationUtils
 import timber.log.Timber
 import java.util.concurrent.TimeUnit
+import javax.inject.Inject
 
 /**
  * A service in charge of controlling whether the event stream is running or not.
@@ -41,7 +42,7 @@ class EventStreamServiceX : VectorService() {
     /**
      * Managed session (no multi session for Riot)
      */
-    private val mSession by inject()
+    @Inject lateinit var session: Session
 
     /**
      * Set to true to simulate a push immediately when service is destroyed
@@ -135,6 +136,11 @@ class EventStreamServiceX : VectorService() {
         STARTED
     }
 
+    override fun onCreate() {
+        //setup injector
+        super.onCreate()
+    }
+
     override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
         // Cancel any previous worker
         cancelAnySimulatedPushSchedule()
@@ -168,7 +174,7 @@ class EventStreamServiceX : VectorService() {
             }
         }
 
-        if (null == mSession) {
+        if (null == session) {
             Timber.e("onStartCommand : no sessions")
             myStopSelf()
             return START_NOT_STICKY
@@ -334,7 +340,7 @@ class EventStreamServiceX : VectorService() {
         // TODO mPushManager = Matrix.getInstance(applicationContext)!!.pushManager
         mNotifiableEventResolver = NotifiableEventResolver(applicationContext)
 
-        monitorSession(mSession!!)
+        monitorSession(session!!)
 
         serviceState = if (forPush) {
             ServiceState.CATCHUP
@@ -387,7 +393,7 @@ class EventStreamServiceX : VectorService() {
         }
 
         if (canCatchup) {
-            if (mSession != null) {
+            if (session != null) {
                 // TODO session!!.catchupEventStream()
             } else {
                 Timber.i("catchup no session")
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt
index f104791f..0c2eb788 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt
@@ -28,6 +28,7 @@ import butterknife.OnClick
 import butterknife.OnTextChanged
 import com.google.android.material.textfield.TextInputLayout
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.utils.startImportTextFromFileIntent
 import timber.log.Timber
@@ -50,6 +51,10 @@ class KeysBackupRestoreFromKeyFragment : VectorBaseFragment() {
     @BindView(R.id.keys_restore_key_enter_edittext)
     lateinit var mKeyTextEdit: EditText
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         viewModel = ViewModelProviders.of(this, viewModelFactory).get(KeysBackupRestoreFromKeyViewModel::class.java)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt
index 57ca3743..a0da69fb 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt
@@ -33,6 +33,7 @@ import butterknife.OnClick
 import butterknife.OnTextChanged
 import com.google.android.material.textfield.TextInputLayout
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.showPassword
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
@@ -66,6 +67,10 @@ class KeysBackupRestoreFromPassphraseFragment : VectorBaseFragment() {
         fun newInstance() = KeysBackupRestoreFromPassphraseFragment()
     }
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt
index 6b4cc8b7..def561ac 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt
@@ -21,6 +21,7 @@ import androidx.lifecycle.ViewModelProviders
 import butterknife.BindView
 import butterknife.OnClick
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.utils.LiveEvent
 
@@ -36,6 +37,10 @@ class KeysBackupRestoreSuccessFragment : VectorBaseFragment() {
 
     private lateinit var sharedViewModel: KeysBackupRestoreSharedViewModel
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         sharedViewModel = activity?.run {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
index bc83aaf9..273b32aa 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
@@ -23,7 +23,7 @@ import com.airbnb.mvrx.Fail
 import com.airbnb.mvrx.Loading
 import com.airbnb.mvrx.viewModel
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.extensions.injector
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.SimpleFragmentActivity
 import im.vector.riotredesign.core.platform.WaitingViewData
 import javax.inject.Inject
@@ -43,9 +43,8 @@ class KeysBackupManageActivity : SimpleFragmentActivity() {
     private val viewModel: KeysBackupSettingsViewModel by viewModel()
     @Inject lateinit var keysBackupSettingsViewModelFactory: KeysBackupSettingsViewModel.Factory
 
-    override fun onCreate(savedInstanceState: Bundle?) {
+    override fun injectWith(injector: ScreenComponent) {
         injector.inject(this)
-        super.onCreate(savedInstanceState)
     }
 
     override fun initUiAndData() {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt
index 3a0239d0..72a97f37 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt
@@ -21,7 +21,7 @@ import androidx.appcompat.app.AlertDialog
 import com.airbnb.mvrx.activityViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.extensions.injector
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreActivity
 import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupActivity
@@ -40,9 +40,8 @@ class KeysBackupSettingsFragment : VectorBaseFragment(),
     @Inject lateinit var keysBackupSettingsRecyclerViewController: KeysBackupSettingsRecyclerViewController
     private val viewModel: KeysBackupSettingsViewModel by activityViewModel()
 
-    override fun onCreate(savedInstanceState: Bundle?) {
-        injector().inject(this)
-        super.onCreate(savedInstanceState)
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep1Fragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep1Fragment.kt
index f90983f7..d1fe142a 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep1Fragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep1Fragment.kt
@@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModelProviders
 import butterknife.BindView
 import butterknife.OnClick
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.utils.LiveEvent
 
@@ -45,6 +46,10 @@ class KeysBackupSetupStep1Fragment : VectorBaseFragment() {
     @BindView(R.id.keys_backup_setup_step1_manualExport)
     lateinit var manualExportButton: Button
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt
index 5267c22b..7d0ca797 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt
@@ -31,6 +31,7 @@ import butterknife.OnTextChanged
 import com.google.android.material.textfield.TextInputLayout
 import com.nulabinc.zxcvbn.Zxcvbn
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.showPassword
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.ui.views.PasswordStrengthBar
@@ -77,6 +78,10 @@ class KeysBackupSetupStep2Fragment : VectorBaseFragment() {
 
     private lateinit var viewModel: KeysBackupSetupSharedViewModel
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
index 0a738bf5..bf44cac4 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
@@ -29,6 +29,7 @@ import butterknife.BindView
 import butterknife.OnClick
 import com.google.android.material.bottomsheet.BottomSheetDialog
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.files.addEntryToDownloadManager
 import im.vector.riotredesign.core.files.saveStringToFile
 import im.vector.riotredesign.core.platform.VectorBaseFragment
@@ -54,6 +55,10 @@ class KeysBackupSetupStep3Fragment : VectorBaseFragment() {
 
     private lateinit var viewModel: KeysBackupSetupSharedViewModel
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         viewModel = activity?.run {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
index 9f893afc..b8549995 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
@@ -24,6 +24,7 @@ import butterknife.BindView
 import butterknife.OnClick
 import im.vector.matrix.android.api.session.crypto.sas.IncomingSasVerificationTransaction
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.home.AvatarRenderer
 
@@ -49,6 +50,10 @@ class SASVerificationIncomingFragment : VectorBaseFragment() {
 
     private lateinit var viewModel: SasVerificationViewModel
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
index fb5671d2..497d108b 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
@@ -31,6 +31,7 @@ import androidx.lifecycle.ViewModelProviders
 import com.airbnb.mvrx.viewModel
 import im.vector.matrix.android.api.Matrix
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.hideKeyboard
 import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.extensions.replaceFragment
@@ -73,6 +74,10 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
 
     override fun getLayoutRes() = R.layout.activity_home
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         homeNavigator.activity = this
@@ -103,9 +108,6 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
                 is Navigation.OpenDrawer -> drawerLayout.openDrawer(GravityCompat.START)
             }
         }
-
-        incomingVerificationRequestHandler.ensureStarted()
-        keyRequestHandler.ensureStarted()
     }
 
     override fun onDestroy() {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
index bb03f2cd..23eb943d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
@@ -32,6 +32,7 @@ import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
 import im.vector.matrix.android.api.session.sync.SyncState
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.ToolbarConfigurable
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.ui.views.KeysBackupBanner
@@ -74,6 +75,10 @@ class HomeDetailFragment : VectorBaseFragment(), KeysBackupBanner.Delegate {
         return R.layout.fragment_home_detail
     }
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         currentDisplayMode = savedInstanceState?.getSerializable(CURRENT_DISPLAY_MODE) as? RoomListFragment.DisplayMode
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
index 49ee8f67..28b8cf20 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
@@ -19,6 +19,7 @@ package im.vector.riotredesign.features.home
 import android.os.Bundle
 import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.observeK
 import im.vector.riotredesign.core.extensions.replaceChildFragment
 import im.vector.riotredesign.core.platform.VectorBaseFragment
@@ -39,6 +40,10 @@ class HomeDrawerFragment : VectorBaseFragment() {
 
     override fun getLayoutResId() = R.layout.fragment_home_drawer
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         if (savedInstanceState == null) {
@@ -62,4 +67,4 @@ class HomeDrawerFragment : VectorBaseFragment() {
             navigator.openDebug(requireActivity())
         }
     }
-}
\ No newline at end of file
+}
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigator.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigator.kt
index bc3b7bfb..35031bd2 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigator.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeNavigator.kt
@@ -20,12 +20,15 @@ import androidx.core.view.GravityCompat
 import androidx.fragment.app.FragmentManager
 import im.vector.matrix.android.api.session.group.model.GroupSummary
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenScope
 import im.vector.riotredesign.core.extensions.replaceFragment
 import im.vector.riotredesign.features.navigation.Navigator
 import kotlinx.android.synthetic.main.activity_home.*
 import timber.log.Timber
 import javax.inject.Inject
+import javax.inject.Singleton
 
+@Singleton
 class HomeNavigator @Inject constructor() {
 
     var activity: HomeActivity? = null
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListFragment.kt
index 58715088..30f6d0d8 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupListFragment.kt
@@ -16,12 +16,14 @@
 
 package im.vector.riotredesign.features.home.group
 
+import android.content.Context
 import android.os.Bundle
 import com.airbnb.mvrx.Incomplete
 import com.airbnb.mvrx.Success
 import com.airbnb.mvrx.fragmentViewModel
 import im.vector.matrix.android.api.session.group.model.GroupSummary
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.platform.StateView
 import im.vector.riotredesign.core.platform.VectorBaseFragment
@@ -45,6 +47,10 @@ class GroupListFragment : VectorBaseFragment(), GroupSummaryController.Callback
 
     override fun getLayoutResId() = R.layout.fragment_group_list
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         groupController.callback = this
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
index 16124ccc..f2eeaa99 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
@@ -67,6 +67,7 @@ import im.vector.matrix.android.api.session.room.model.message.MessageVideoConte
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.matrix.android.api.session.user.model.User
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.dialogs.DialogListItem
 import im.vector.riotredesign.core.epoxy.LayoutManagerStateRestorer
 import im.vector.riotredesign.core.extensions.hideKeyboard
@@ -189,8 +190,11 @@ class RoomDetailFragment :
     @BindView(R.id.composerLayout)
     lateinit var composerLayout: TextComposerView
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
-        injector().inject(this)
         super.onActivityCreated(savedInstanceState)
         actionViewModel = ViewModelProviders.of(requireActivity()).get(ActionsHandler::class.java)
         setupToolbar(roomToolbar)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
index 9a321c24..d32e83a6 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
@@ -33,6 +33,7 @@ import com.airbnb.mvrx.withState
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import com.google.android.material.bottomsheet.BottomSheetDialog
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 import kotlinx.android.synthetic.main.bottom_sheet_message_actions.*
@@ -42,7 +43,7 @@ import javax.inject.Inject
  * Bottom sheet fragment that shows a message preview with list of contextual actions
  * (Includes fragments for quick reactions and list of actions)
  */
-class MessageActionsBottomSheet : BaseMvRxBottomSheetDialog() {
+class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment() {
 
     @Inject lateinit var messageActionViewModelFactory: MessageActionsViewModel.Factory
     private val viewModel: MessageActionsViewModel by fragmentViewModel(MessageActionsViewModel::class)
@@ -61,6 +62,9 @@ class MessageActionsBottomSheet : BaseMvRxBottomSheetDialog() {
     @BindView(R.id.bottom_sheet_message_preview_body)
     lateinit var messageBodyTextView: TextView
 
+    override fun injectWith(screenComponent: ScreenComponent) {
+        screenComponent.inject(this)
+    }
 
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         val view = inflater.inflate(R.layout.bottom_sheet_message_actions, container, false)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuFragment.kt
index 116c792c..a45df7e1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuFragment.kt
@@ -23,24 +23,31 @@ import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.TextView
-import com.airbnb.mvrx.BaseMvRxFragment
 import com.airbnb.mvrx.MvRx
 import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
+import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.themes.ThemeUtils
 import javax.inject.Inject
 
 /**
  * Fragment showing the list of available contextual action for a given message.
  */
-class MessageMenuFragment : BaseMvRxFragment() {
+class MessageMenuFragment : VectorBaseFragment() {
 
     @Inject lateinit var messageMenuViewModelFactory: MessageMenuViewModel.Factory
     private val viewModel: MessageMenuViewModel by fragmentViewModel(MessageMenuViewModel::class)
     private var addSeparators = false
     var interactionListener: InteractionListener? = null
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
+    override fun getLayoutResId() = R.layout.fragment_message_menu
+
     override fun invalidate() = withState(viewModel) { state ->
 
         val linearLayout = view as? LinearLayout
@@ -68,14 +75,6 @@ class MessageMenuFragment : BaseMvRxFragment() {
     }
 
 
-    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
-        //we just create programmatically
-        val contentView = LinearLayout(context)
-        contentView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
-        contentView.orientation = LinearLayout.VERTICAL
-        return contentView
-    }
-
     private fun inflateActionView(action: SimpleAction, inflater: LayoutInflater, container: ViewGroup?): View? {
         return inflater.inflate(R.layout.adapter_item_action, container, false)?.apply {
             if (action.iconResId != null) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
index 96d7052c..cd58c9cf 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
@@ -17,26 +17,24 @@ package im.vector.riotredesign.features.home.room.detail.timeline.action
 
 import android.graphics.Typeface
 import android.os.Bundle
-import android.view.LayoutInflater
 import android.view.View
-import android.view.ViewGroup
 import android.widget.TextView
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.transition.TransitionManager
 import butterknife.BindView
-import butterknife.ButterKnife
-import com.airbnb.mvrx.BaseMvRxFragment
 import com.airbnb.mvrx.MvRx
 import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.EmojiCompatFontProvider
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
+import im.vector.riotredesign.core.platform.VectorBaseFragment
 import javax.inject.Inject
 
 /**
  * Quick Reaction Fragment (agree / like reactions)
  */
-class QuickReactionFragment : BaseMvRxFragment() {
+class QuickReactionFragment : VectorBaseFragment() {
 
     private val viewModel: QuickReactionViewModel by fragmentViewModel(QuickReactionViewModel::class)
 
@@ -60,10 +58,10 @@ class QuickReactionFragment : BaseMvRxFragment() {
     @Inject lateinit var fontProvider: EmojiCompatFontProvider
     @Inject lateinit var quickReactionViewModelFactory: QuickReactionViewModel.Factory
 
-    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
-        val view = inflater.inflate(R.layout.adapter_item_action_quick_reaction, container, false)
-        ButterKnife.bind(this, view)
-        return view
+    override fun getLayoutResId() = R.layout.adapter_item_action_quick_reaction
+
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/BaseMvRxBottomSheetDialog.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/VectorBaseBottomSheetDialogFragment.kt
similarity index 73%
rename from vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/BaseMvRxBottomSheetDialog.kt
rename to vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/VectorBaseBottomSheetDialogFragment.kt
index c3a068be..54b518bc 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/BaseMvRxBottomSheetDialog.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/VectorBaseBottomSheetDialogFragment.kt
@@ -15,24 +15,40 @@
  */
 package im.vector.riotredesign.features.home.room.detail.timeline.action
 
+import android.content.Context
 import android.os.Bundle
 import android.os.Parcelable
 import com.airbnb.mvrx.MvRx
 import com.airbnb.mvrx.MvRxView
 import com.airbnb.mvrx.MvRxViewModelStore
 import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import im.vector.riotredesign.core.di.DaggerScreenComponent
+import im.vector.riotredesign.core.di.ScreenComponent
+import im.vector.riotredesign.core.platform.VectorBaseActivity
 import java.util.*
 
 /**
  * Add MvRx capabilities to bottomsheetdialog (like BaseMvRxFragment)
  */
-abstract class BaseMvRxBottomSheetDialog : BottomSheetDialogFragment(), MvRxView {
+abstract class VectorBaseBottomSheetDialogFragment : BottomSheetDialogFragment(), MvRxView {
 
     override val mvrxViewModelStore by lazy { MvRxViewModelStore(viewModelStore) }
     private lateinit var mvrxPersistedViewId: String
-
+    private lateinit var screenComponent: ScreenComponent
     final override val mvrxViewId: String by lazy { mvrxPersistedViewId }
 
+    val vectorBaseActivity: VectorBaseActivity by lazy {
+        activity as VectorBaseActivity
+    }
+
+    override fun onAttach(context: Context) {
+        screenComponent = DaggerScreenComponent.factory().create(vectorBaseActivity.getVectorComponent(), vectorBaseActivity)
+        super.onAttach(context)
+        injectWith(screenComponent)
+    }
+
+    protected open fun injectWith(screenComponent: ScreenComponent) = Unit
+
     override fun onCreate(savedInstanceState: Bundle?) {
         mvrxViewModelStore.restoreViewModels(this, savedInstanceState)
         mvrxPersistedViewId = savedInstanceState?.getString(PERSISTED_VIEW_ID_KEY)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionBottomSheet.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionBottomSheet.kt
index 308c68bf..9c9a58d1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionBottomSheet.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionBottomSheet.kt
@@ -15,24 +15,30 @@ import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.EmojiCompatFontProvider
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
 import kotlinx.android.synthetic.main.bottom_sheet_display_reactions.*
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 /**
  * Bottom sheet displaying list of reactions for a given event ordered by timestamp
  */
-class ViewReactionBottomSheet : BaseMvRxBottomSheetDialog() {
+class ViewReactionBottomSheet : VectorBaseBottomSheetDialogFragment() {
 
     private val viewModel: ViewReactionViewModel by fragmentViewModel(ViewReactionViewModel::class)
 
-    private val emojiCompatFontProvider by inject()
+    @Inject lateinit var viewReactionViewModelFactory: ViewReactionViewModel.Factory
+    @Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
 
     @BindView(R.id.bottom_sheet_display_reactions_list)
     lateinit var epoxyRecyclerView: EpoxyRecyclerView
 
     private val epoxyController by lazy { ViewReactionsEpoxyController(emojiCompatFontProvider.typeface) }
 
+    override fun injectWith(screenComponent: ScreenComponent) {
+        screenComponent.inject(this)
+    }
+
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         val view = inflater.inflate(R.layout.bottom_sheet_display_reactions, container, false)
         ButterKnife.bind(this, view)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionViewModel.kt
index 88548865..27a85abb 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionViewModel.kt
@@ -1,20 +1,25 @@
 package im.vector.riotredesign.features.home.room.detail.timeline.action
 
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.Observer
 import com.airbnb.mvrx.*
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
+import im.vector.matrix.rx.RxRoom
 import im.vector.riotredesign.core.extensions.localDateTime
 import im.vector.riotredesign.core.platform.VectorViewModel
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
-import org.koin.android.ext.android.get
+import io.reactivex.Observable
 
 
 data class DisplayReactionsViewState(
-        val eventId: String = "",
-        val roomId: String = "",
+        val eventId: String,
+        val roomId: String,
         val mapReactionKeyToMemberList: Async> = Uninitialized)
-    : MvRxState
+    : MvRxState {
+
+    constructor(args: TimelineEventFragmentArgs) : this(roomId = args.roomId, eventId = args.eventId)
+
+}
 
 data class ReactionInfo(
         val eventId: String,
@@ -27,75 +32,59 @@ data class ReactionInfo(
 /**
  * Used to display the list of members that reacted to a given event
  */
-class ViewReactionViewModel(private val session: Session,
-                            private val timelineDateFormatter: TimelineDateFormatter,
-                            initialState: DisplayReactionsViewState) : VectorViewModel(initialState) {
+class ViewReactionViewModel @AssistedInject constructor(@Assisted
+                                                        initialState: DisplayReactionsViewState,
+                                                        private val session: Session,
+                                                        private val timelineDateFormatter: TimelineDateFormatter
+) : VectorViewModel(initialState) {
 
-    init {
-        loadReaction()
+    private val roomId = initialState.roomId
+    private val eventId = initialState.eventId
+    private val room = session.getRoom(roomId)
+            ?: throw IllegalStateException("Shouldn't use this ViewModel without a room")
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: DisplayReactionsViewState): ViewReactionViewModel
     }
 
-    fun loadReaction() = withState { state ->
-
-        try {
-            val room = session.getRoom(state.roomId)
-            val event = room?.getTimeLineEvent(state.eventId)
-            if (event == null) {
-                setState { copy(mapReactionKeyToMemberList = Fail(Throwable())) }
-                return@withState
-            }
-            var results = ArrayList()
-            event.annotations?.reactionsSummary?.forEach { sum ->
-
-                sum.sourceEvents.mapNotNull { room.getTimeLineEvent(it) }.forEach {
-                    val localDate = it.root.localDateTime()
-                    results.add(ReactionInfo(it.root.eventId!!, sum.key, it.root.sender
-                            ?: "", it.senderName, timelineDateFormatter.formatMessageHour(localDate)))
-                }
-            }
-            setState {
-                copy(
-                        mapReactionKeyToMemberList = Success(results.sortedBy { it.timestamp })
-                )
-            }
-        } catch (t: Throwable) {
-            setState {
-                copy(
-                        mapReactionKeyToMemberList = Fail(t)
-                )
-            }
-        }
-    }
-
-
     companion object : MvRxViewModelFactory {
 
-        override fun initialState(viewModelContext: ViewModelContext): DisplayReactionsViewState? {
-
-            val roomId = (viewModelContext.args as? TimelineEventFragmentArgs)?.roomId
-                    ?: return null
-            val info = (viewModelContext.args as? TimelineEventFragmentArgs)?.informationData
-                    ?: return null
-            return DisplayReactionsViewState(info.eventId, roomId)
-        }
-
         override fun create(viewModelContext: ViewModelContext, state: DisplayReactionsViewState): ViewReactionViewModel? {
-            val session = viewModelContext.activity.get()
-            val eventId = (viewModelContext.args as TimelineEventFragmentArgs).eventId
-            val lifecycleOwner = (viewModelContext as FragmentViewModelContext).fragment()
-            val liveSummary = session.getRoom(state.roomId)?.getEventSummaryLive(eventId)
-            val viewReactionViewModel = ViewReactionViewModel(session, viewModelContext.activity.get(), state)
-            // This states observes the live summary
-            // When fragment context will be destroyed the observer will automatically removed
-            liveSummary?.observe(lifecycleOwner, Observer {
-                it?.firstOrNull()?.let {
-                    viewReactionViewModel.loadReaction()
-                }
-            })
-
-            return viewReactionViewModel
+            val fragment: ViewReactionBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.viewReactionViewModelFactory.create(state)
         }
 
-
+    }
+
+
+    init {
+        observeEventAnnotationSummaries()
+    }
+
+    private fun observeEventAnnotationSummaries() {
+        RxRoom(room)
+                .liveAnnotationSummary(eventId)
+                .flatMapSingle { summaries ->
+                    Observable
+                            .fromIterable(summaries)
+                            .flatMapIterable { it.reactionsSummary }
+                            .map {
+                                val event = room.getTimeLineEvent(eventId)
+                                        ?: throw RuntimeException("Your eventId is not valid")
+                                val localDate = event.root.localDateTime()
+                                ReactionInfo(
+                                        event.root.eventId!!,
+                                        it.key,
+                                        event.root.sender ?: "",
+                                        event.senderName,
+                                        timelineDateFormatter.formatMessageHour(localDate)
+                                )
+                            }
+                            .toList()
+                }
+                .execute {
+                    copy(mapReactionKeyToMemberList = it)
+                }
     }
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListFragment.kt
index 06415a05..13f71e31 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListFragment.kt
@@ -32,6 +32,7 @@ import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.api.session.room.model.Membership
 import im.vector.matrix.android.api.session.room.model.RoomSummary
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.epoxy.LayoutManagerStateRestorer
 import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.platform.OnBackPressed
@@ -71,6 +72,10 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Callback, O
 
     override fun getLayoutResId() = R.layout.fragment_room_list
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         setupCreateRoomButton()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotredesign/features/navigation/DefaultNavigator.kt
index c13f8b84..9e8c33b9 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/navigation/DefaultNavigator.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/navigation/DefaultNavigator.kt
@@ -28,7 +28,9 @@ import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
 import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewActivity
 import im.vector.riotredesign.features.settings.VectorSettingsActivity
 import javax.inject.Inject
+import javax.inject.Singleton
 
+@Singleton
 class DefaultNavigator @Inject constructor() : Navigator {
 
     override fun openRoom(roomId: String, context: Context) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiReactionPickerActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiReactionPickerActivity.kt
index 72d3b19f..5944c81d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiReactionPickerActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/reactions/EmojiReactionPickerActivity.kt
@@ -30,9 +30,11 @@ import androidx.lifecycle.ViewModelProviders
 import com.google.android.material.tabs.TabLayout
 import im.vector.riotredesign.EmojiCompatFontProvider
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import kotlinx.android.synthetic.main.activity_emoji_reaction_picker.*
+import javax.inject.Inject
 
 /**
  *
@@ -54,7 +56,7 @@ class EmojiReactionPickerActivity : VectorBaseActivity(), EmojiCompatFontProvide
 
     override fun getTitleRes(): Int = R.string.title_activity_emoji_reaction_picker
 
-    lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
+    @Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
 
     private var tabLayoutSelectionListener = object : TabLayout.BaseOnTabSelectedListener {
         override fun onTabReselected(p0: TabLayout.Tab) {
@@ -69,6 +71,10 @@ class EmojiReactionPickerActivity : VectorBaseActivity(), EmojiCompatFontProvide
 
     }
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun initUiAndData() {
         configureToolbar(emojiPickerToolbar)
         emojiCompatFontProvider.let {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsController.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsController.kt
index 01309e9e..bf395868 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsController.kt
@@ -28,8 +28,9 @@ import im.vector.riotredesign.core.epoxy.loadingItem
 import im.vector.riotredesign.core.epoxy.noResultItem
 import im.vector.riotredesign.core.error.ErrorFormatter
 import im.vector.riotredesign.core.resources.StringProvider
+import javax.inject.Inject
 
-class PublicRoomsController(private val stringProvider: StringProvider,
+class PublicRoomsController @Inject constructor(private val stringProvider: StringProvider,
                             private val errorFormatter: ErrorFormatter) : TypedEpoxyController() {
 
     var callback: Callback? = null
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsFragment.kt
index 7f701af8..fbf6d68e 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsFragment.kt
@@ -28,6 +28,7 @@ import com.google.android.material.snackbar.Snackbar
 import com.jakewharton.rxbinding2.widget.RxTextView
 import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.error.ErrorFormatter
 import im.vector.riotredesign.core.extensions.observeEvent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
@@ -55,6 +56,10 @@ class PublicRoomsFragment : VectorBaseFragment(), PublicRoomsController.Callback
 
     override fun getMenuRes() = R.menu.menu_room_directory
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryModule.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryModule.kt
deleted file mode 100644
index 2ac22864..00000000
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryModule.kt
+++ /dev/null
@@ -1,54 +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.riotredesign.features.roomdirectory
-
-import im.vector.matrix.android.api.session.Session
-import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomController
-import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryListCreator
-import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerController
-import org.koin.dsl.module.module
-
-class RoomDirectoryModule {
-
-    companion object {
-        const val ROOM_DIRECTORY_SCOPE = "ROOM_DIRECTORY_SCOPE"
-    }
-
-    val definition = module(override = true) {
-
-        scope(ROOM_DIRECTORY_SCOPE) {
-            RoomDirectoryPickerController(get(), get(), get())
-        }
-
-        scope(ROOM_DIRECTORY_SCOPE) {
-            RoomDirectoryListCreator(get(), get().sessionParams.credentials)
-        }
-
-        scope(ROOM_DIRECTORY_SCOPE) {
-            PublicRoomsController(get(), get())
-        }
-
-        /* ==========================================================================================
-         * Create room
-         * ========================================================================================== */
-
-        scope(ROOM_DIRECTORY_SCOPE) {
-            CreateRoomController(get(), get())
-        }
-
-    }
-}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomController.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomController.kt
index 6d925e08..abd78d96 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomController.kt
@@ -28,8 +28,9 @@ import im.vector.riotredesign.core.error.ErrorFormatter
 import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.features.form.formEditTextItem
 import im.vector.riotredesign.features.form.formSwitchItem
+import javax.inject.Inject
 
-class CreateRoomController(private val stringProvider: StringProvider,
+class CreateRoomController @Inject constructor(private val stringProvider: StringProvider,
                            private val errorFormatter: ErrorFormatter
 ) : TypedEpoxyController() {
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomFragment.kt
index 96e7c60c..31eaabe2 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomFragment.kt
@@ -24,36 +24,34 @@ import com.airbnb.mvrx.Success
 import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
-import im.vector.riotredesign.features.roomdirectory.RoomDirectoryModule
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryNavigationViewModel
 import kotlinx.android.synthetic.main.fragment_create_room.*
-import org.koin.android.ext.android.inject
-import org.koin.android.scope.ext.android.bindScope
-import org.koin.android.scope.ext.android.getOrCreateScope
 import timber.log.Timber
+import javax.inject.Inject
 
 class CreateRoomFragment : VectorBaseFragment(), CreateRoomController.Listener {
 
     private lateinit var navigationViewModel: RoomDirectoryNavigationViewModel
     private val viewModel: CreateRoomViewModel by fragmentViewModel()
-    private val createRoomController: CreateRoomController by inject()
+    @Inject lateinit var createRoomController: CreateRoomController
+    @Inject lateinit var createRoomViewModelFactory: CreateRoomViewModel.Factory
 
     override fun getLayoutResId() = R.layout.fragment_create_room
 
     override fun getMenuRes() = R.menu.vector_room_creation
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
-        bindScope(getOrCreateScope(RoomDirectoryModule.ROOM_DIRECTORY_SCOPE))
-
         vectorBaseActivity.setSupportActionBar(createRoomToolbar)
-
         navigationViewModel = ViewModelProviders.of(requireActivity()).get(RoomDirectoryNavigationViewModel::class.java)
-
         setupRecyclerView()
-
         createRoomClose.setOnClickListener {
             navigationViewModel.goTo(RoomDirectoryActivity.Navigation.Back)
         }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomViewModel.kt
index 3790381a..f928e20c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/createroom/CreateRoomViewModel.kt
@@ -17,24 +17,30 @@
 package im.vector.riotredesign.features.roomdirectory.createroom
 
 import com.airbnb.mvrx.*
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
 import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
 import im.vector.matrix.android.api.session.room.model.create.CreateRoomPreset
 import im.vector.riotredesign.core.platform.VectorViewModel
-import org.koin.android.ext.android.get
 
-class CreateRoomViewModel(initialState: CreateRoomViewState,
-                          private val session: Session) : VectorViewModel(initialState) {
+class CreateRoomViewModel @AssistedInject constructor(@Assisted initialState: CreateRoomViewState,
+                                                      private val session: Session
+) : VectorViewModel(initialState) {
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: CreateRoomViewState): CreateRoomViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
         @JvmStatic
         override fun create(viewModelContext: ViewModelContext, state: CreateRoomViewState): CreateRoomViewModel? {
-            val currentSession = viewModelContext.activity.get()
-
-            return CreateRoomViewModel(state, currentSession)
+            val fragment: CreateRoomFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.createRoomViewModelFactory.create(state)
         }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt
index 38cf4a3d..bde76fd2 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt
@@ -26,6 +26,7 @@ import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import im.vector.matrix.android.api.session.room.model.thirdparty.RoomDirectoryData
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryNavigationViewModel
@@ -70,8 +71,11 @@ class RoomDirectoryPickerFragment : VectorBaseFragment(), RoomDirectoryPickerCon
         return super.onOptionsItemSelected(item)
     }
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
-        injector().inject(this)
         super.onActivityCreated(savedInstanceState)
         navigationViewModel = ViewModelProviders.of(requireActivity()).get(RoomDirectoryNavigationViewModel::class.java)
         setupRecyclerView()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
index d1960614..d94503a1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
@@ -24,6 +24,7 @@ import com.airbnb.mvrx.args
 import com.airbnb.mvrx.fragmentViewModel
 import com.airbnb.mvrx.withState
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.error.ErrorFormatter
 import im.vector.riotredesign.core.extensions.setTextOrHide
 import im.vector.riotredesign.core.platform.ButtonStateView
@@ -49,8 +50,11 @@ class RoomPreviewNoPreviewFragment : VectorBaseFragment() {
     private val roomPreviewViewModel: RoomPreviewViewModel by fragmentViewModel()
     private val roomPreviewData: RoomPreviewData by args()
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onActivityCreated(savedInstanceState: Bundle?) {
-        injector().inject(this)
         super.onActivityCreated(savedInstanceState)
         setupToolbar(roomPreviewNoPreviewToolbar)
     }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsActivity.kt
index 6208c75e..6ac278a7 100755
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsActivity.kt
@@ -23,9 +23,10 @@ import androidx.preference.Preference
 import androidx.preference.PreferenceFragmentCompat
 import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import kotlinx.android.synthetic.main.activity_vector_settings.*
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 /**
  * Displays the client settings.
@@ -43,7 +44,11 @@ class VectorSettingsActivity : VectorBaseActivity(),
 
     private var keyToHighlight: String? = null
 
-    private val session by inject()
+    @Inject lateinit var session: Session
+
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
 
     override fun initUiAndData() {
         configureToolbar(settingsToolbar)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt
index eee04547..0bf93ce3 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt
@@ -34,12 +34,12 @@ import im.vector.riotredesign.core.preference.BingRule
 import im.vector.riotredesign.core.preference.BingRulePreference
 import im.vector.riotredesign.features.notifications.NotificationUtils
 import im.vector.riotredesign.features.notifications.supportNotificationChannels
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 class VectorSettingsAdvancedNotificationPreferenceFragment : VectorPreferenceFragment() {
 
     // members
-    private val mSession by inject()
+    @Inject lateinit var session: Session
     private var mLoadingView: View? = null
 
     // events listener
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt
index 0fb39fff..b176362a 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt
@@ -37,7 +37,7 @@ import im.vector.riotredesign.features.rageshake.BugReporter
 import im.vector.riotredesign.features.settings.troubleshoot.NotificationTroubleshootTestManager
 import im.vector.riotredesign.features.settings.troubleshoot.TroubleshootTest
 import im.vector.riotredesign.push.fcm.NotificationTroubleshootTestManagerFactory
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 class VectorSettingsNotificationsTroubleshootFragment : VectorBaseFragment() {
 
@@ -54,7 +54,7 @@ class VectorSettingsNotificationsTroubleshootFragment : VectorBaseFragment() {
 
     private var testManager: NotificationTroubleshootTestManager? = null
     // members
-    private val mSession by inject()
+    @Inject lateinit var session: Session
 
     override fun getLayoutResId() = R.layout.fragment_settings_notifications_troubleshoot
 
@@ -92,7 +92,7 @@ class VectorSettingsNotificationsTroubleshootFragment : VectorBaseFragment() {
         mSummaryDescription.text = getString(R.string.settings_troubleshoot_diagnostic_running_status,
                 0, 0)
 
-        testManager = NotificationTroubleshootTestManagerFactory.createTestManager(this, mSession)
+        testManager = NotificationTroubleshootTestManagerFactory.createTestManager(this, session)
 
         testManager?.statusListener = { troubleshootTestManager ->
             if (isAdded) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
index e30f9bb7..1d2371c8 100755
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
@@ -64,17 +64,18 @@ import im.vector.riotredesign.features.MainActivity
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupManageActivity
 import im.vector.riotredesign.features.themes.ThemeUtils
-import org.koin.android.ext.android.inject
 import timber.log.Timber
 import java.lang.ref.WeakReference
 import java.text.DateFormat
 import java.text.SimpleDateFormat
 import java.util.*
+import javax.inject.Inject
 
 class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
 
     // members
-    private val mSession by inject()
+    @Inject lateinit var session: Session
+    @Inject lateinit var vectorConfiguration: VectorConfiguration
 
     // disable some updates if there is
     // TODO private val mNetworkListener = IMXNetworkEventListener { refreshDisplay() }
@@ -111,7 +112,6 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
     // used to avoid requesting to enter the password for each deletion
     private var mAccountPassword: String = ""
 
-    private val vectorConfiguration by inject()
 
     // current publicised group list
     private var mPublicisedGroups: MutableSet? = null
@@ -272,7 +272,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
 
         // Avatar
         mUserAvatarPreference.let {
-            it.setSession(mSession)
+            it.setSession(session)
             it.onPreferenceClickListener = Preference.OnPreferenceClickListener {
                 onUpdateAvatarClick()
                 false
@@ -479,7 +479,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
         val cryptoIsEnabledPref = findPreference(PreferencesManager.SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY)
 
 
-        if (mSession.isCryptoEnabled()) {
+        if (session.isCryptoEnabled()) {
             mLabsCategory.removePreference(useCryptoPref)
 
             cryptoIsEnabledPref.isEnabled = false
@@ -489,7 +489,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
             useCryptoPref.isChecked = false
 
             useCryptoPref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValueAsVoid ->
-                if (TextUtils.isEmpty(mSession.sessionParams.credentials.deviceId)) {
+                if (TextUtils.isEmpty(session.sessionParams.credentials.deviceId)) {
                     activity?.let { activity ->
                         AlertDialog.Builder(activity)
                                 .setMessage(R.string.room_settings_labs_end_to_end_warnings)
@@ -508,7 +508,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
                 } else {
                     val newValue = newValueAsVoid as Boolean
 
-                    if (mSession.isCryptoEnabled() != newValue) {
+                    if (session.isCryptoEnabled() != newValue) {
                         notImplemented()
                         /* TODO
                         displayLoadingView()
@@ -575,15 +575,15 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
 
         // user account
         findPreference(PreferencesManager.SETTINGS_LOGGED_IN_PREFERENCE_KEY)
-                .summary = mSession.sessionParams.credentials.userId
+                .summary = session.sessionParams.credentials.userId
 
         // home server
         findPreference(PreferencesManager.SETTINGS_HOME_SERVER_PREFERENCE_KEY)
-                .summary = mSession.sessionParams.homeServerConnectionConfig.homeServerUri.toString()
+                .summary = session.sessionParams.homeServerConnectionConfig.homeServerUri.toString()
 
         // identity server
         findPreference(PreferencesManager.SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY)
-                .summary = mSession.sessionParams.homeServerConnectionConfig.identityServerUri.toString()
+                .summary = session.sessionParams.homeServerConnectionConfig.identityServerUri.toString()
 
         // Analytics
 
@@ -641,7 +641,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
 
         // olm version
         findPreference(PreferencesManager.SETTINGS_OLM_VERSION_PREFERENCE_KEY)
-                .summary = mSession.getCryptoVersion(requireContext(), false)
+                .summary = session.getCryptoVersion(requireContext(), false)
 
         // copyright
         findPreference(PreferencesManager.SETTINGS_COPYRIGHT_PREFERENCE_KEY)
@@ -2163,8 +2163,8 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
      * @param aMyDeviceInfo the device info
      */
     private fun refreshCryptographyPreference(aMyDeviceInfo: DeviceInfo?) {
-        val userId = mSession.sessionParams.credentials.userId
-        val deviceId = mSession.sessionParams.credentials.deviceId
+        val userId = session.sessionParams.credentials.userId
+        val deviceId = session.sessionParams.credentials.deviceId
 
         // device name
         if (null != aMyDeviceInfo) {
@@ -2195,7 +2195,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
 
         // crypto section: device key (fingerprint)
         if (!TextUtils.isEmpty(deviceId) && !TextUtils.isEmpty(userId)) {
-            val deviceInfo = mSession.getDeviceInfo(userId, deviceId)
+            val deviceInfo = session.getDeviceInfo(userId, deviceId)
 
             if (null != deviceInfo && !TextUtils.isEmpty(deviceInfo.fingerprint())) {
                 cryptoInfoTextPreference.summary = deviceInfo.getFingerprintHumanReadable()
@@ -2211,10 +2211,10 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
 
         sendToUnverifiedDevicesPref.isChecked = false
 
-        sendToUnverifiedDevicesPref.isChecked = mSession.getGlobalBlacklistUnverifiedDevices()
+        sendToUnverifiedDevicesPref.isChecked = session.getGlobalBlacklistUnverifiedDevices()
 
         sendToUnverifiedDevicesPref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
-            mSession.setGlobalBlacklistUnverifiedDevices(sendToUnverifiedDevicesPref.isChecked)
+            session.setGlobalBlacklistUnverifiedDevices(sendToUnverifiedDevicesPref.isChecked)
 
             true
         }
@@ -2258,7 +2258,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
      * It can be any mobile device, as any browser.
      */
     private fun refreshDevicesList() {
-        if (mSession.isCryptoEnabled() && !TextUtils.isEmpty(mSession.sessionParams.credentials.deviceId)) {
+        if (session.isCryptoEnabled() && !TextUtils.isEmpty(session.sessionParams.credentials.deviceId)) {
             // display a spinner while loading the devices list
             if (0 == mDevicesListSettingsCategory.preferenceCount) {
                 activity?.let {
@@ -2267,7 +2267,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
                 }
             }
 
-            mSession.getDevicesList(object : MatrixCallback {
+            session.getDevicesList(object : MatrixCallback {
                 override fun onSuccess(data: DevicesListResponse) {
                     if (!isAdded) {
                         return
@@ -2306,7 +2306,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
         var preference: VectorPreference
         var typeFaceHighlight: Int
         var isNewList = true
-        val myDeviceId = mSession.sessionParams.credentials.deviceId
+        val myDeviceId = session.sessionParams.credentials.deviceId
 
         if (aDeviceInfoList.size == mDevicesNameList.size) {
             isNewList = !mDevicesNameList.containsAll(aDeviceInfoList)
@@ -2412,7 +2412,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
                     .setPositiveButton(R.string.rename) { _, _ -> displayDeviceRenameDialog(aDeviceInfo) }
 
             // disable the deletion for our own device
-            if (!TextUtils.equals(mSession.getMyDevice()?.deviceId, aDeviceInfo.deviceId)) {
+            if (!TextUtils.equals(session.getMyDevice()?.deviceId, aDeviceInfo.deviceId)) {
                 builder.setNegativeButton(R.string.delete) { _, _ -> displayDeviceDeletionDialog(aDeviceInfo) }
             }
 
@@ -2449,7 +2449,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
 
                         val newName = input.text.toString()
 
-                        mSession.setDeviceName(aDeviceInfoToRename.deviceId!!, newName, object : MatrixCallback {
+                        session.setDeviceName(aDeviceInfoToRename.deviceId!!, newName, object : MatrixCallback {
                             override fun onSuccess(data: Unit) {
                                 hideLoadingView()
 
diff --git a/vector/src/main/res/layout/fragment_message_menu.xml b/vector/src/main/res/layout/fragment_message_menu.xml
new file mode 100644
index 00000000..4538ac93
--- /dev/null
+++ b/vector/src/main/res/layout/fragment_message_menu.xml
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file

From 07fee8ed3d24670fbad13c15e1d6c3c8c9f2cdc7 Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Thu, 20 Jun 2019 19:26:59 +0200
Subject: [PATCH 06/11] Dagger: continue reworking on app and sdk [WIP]

---
 matrix-sdk-android-rx/build.gradle            |  5 +-
 matrix-sdk-android/build.gradle               |  2 +-
 .../matrix/android/auth/AuthenticatorTest.kt  | 12 +---
 .../src/main/AndroidManifest.xml              |  8 ++-
 .../im/vector/matrix/android/api/Matrix.kt    | 50 ++++++++++-----
 .../android/internal/MatrixInitProvider.kt    | 52 ---------------
 .../matrix/android/internal/SessionManager.kt |  4 ++
 .../android/internal/auth/AuthModule.kt       |  3 -
 .../internal/auth/DefaultAuthenticator.kt     |  1 -
 .../auth/db/RealmSessionParamsStore.kt        |  1 -
 .../internal/auth/db/SessionParamsMapper.kt   |  1 -
 .../android/internal/crypto/CryptoManager.kt  |  4 +-
 .../android/internal/crypto/CryptoModule.kt   | 26 +-------
 .../internal/crypto/DeviceListManager.kt      |  1 -
 .../android/internal/crypto/ObjectSigner.kt   |  1 -
 .../EnsureOlmSessionsForDevicesAction.kt      |  1 -
 .../EnsureOlmSessionsForUsersAction.kt        |  1 -
 .../actions/MegolmSessionDataImporter.kt      |  1 -
 .../crypto/actions/MessageEncrypter.kt        |  1 -
 .../actions/SetDeviceVerificationAction.kt    |  1 -
 .../megolm/MXMegolmDecryptionFactory.kt       |  1 -
 .../megolm/MXMegolmEncryptionFactory.kt       |  1 -
 .../algorithms/olm/MXOlmDecryptionFactory.kt  |  1 -
 .../algorithms/olm/MXOlmEncryptionFactory.kt  |  1 -
 .../tasks/CreateKeysBackupVersionTask.kt      |  2 -
 .../keysbackup/tasks/DeleteBackupTask.kt      |  1 -
 .../tasks/DeleteRoomSessionDataTask.kt        |  1 -
 .../tasks/DeleteRoomSessionsDataTask.kt       |  1 -
 .../tasks/DeleteSessionsDataTask.kt           |  1 -
 .../tasks/GetKeysBackupLastVersionTask.kt     |  2 -
 .../tasks/GetKeysBackupVersionTask.kt         |  2 -
 .../tasks/GetRoomSessionDataTask.kt           |  1 -
 .../tasks/GetRoomSessionsDataTask.kt          |  1 -
 .../keysbackup/tasks/GetSessionsDataTask.kt   |  1 -
 .../tasks/StoreRoomSessionDataTask.kt         |  1 -
 .../tasks/StoreRoomSessionsDataTask.kt        |  1 -
 .../keysbackup/tasks/StoreSessionsDataTask.kt |  1 -
 .../tasks/UpdateKeysBackupVersionTask.kt      |  2 -
 .../WarnOnUnknownDeviceRepository.kt          |  2 +-
 .../crypto/store/db/RealmCryptoStore.kt       |  2 +
 .../ClaimOneTimeKeysForUsersDeviceTask.kt     |  1 -
 .../internal/crypto/tasks/DeleteDeviceTask.kt |  1 -
 .../crypto/tasks/DownloadKeysForUsersTask.kt  |  1 -
 .../internal/crypto/tasks/GetDevicesTask.kt   |  1 -
 .../crypto/tasks/GetKeyChangesTask.kt         |  1 -
 .../internal/crypto/tasks/SendToDeviceTask.kt |  1 -
 .../crypto/tasks/SetDeviceNameTask.kt         |  1 -
 .../internal/crypto/tasks/UploadKeysTask.kt   |  1 -
 .../android/internal/di/MatrixComponent.kt    |  6 +-
 .../android/internal/di/MatrixModule.kt       |  2 -
 .../android/internal/di/NetworkModule.kt      |  6 --
 .../network/AccessTokenInterceptor.kt         |  1 -
 .../internal/network/UserAgentInterceptor.kt  |  1 -
 .../internal/session/DefaultSession.kt        |  8 +--
 .../internal/session/SessionComponent.kt      | 23 ++++++-
 .../android/internal/session/SessionModule.kt |  9 +--
 .../internal/session/cache/CacheModule.kt     |  2 -
 .../internal/session/cache/ClearCacheTask.kt  |  1 -
 .../session/cache/DefaultCacheService.kt      |  1 -
 .../internal/session/content/ContentModule.kt |  2 -
 .../DefaultContentUploadStateTracker.kt       |  1 +
 .../content/DefaultContentUrlResolver.kt      |  1 -
 .../internal/session/content/FileUploader.kt  |  1 -
 .../session/content/UploadContentWorker.kt    | 27 ++++----
 .../session/filter/DefaultFilterRepository.kt |  1 -
 .../session/filter/DefaultFilterService.kt    |  1 -
 .../session/filter/DefaultSaveFilterTask.kt   |  1 -
 .../internal/session/filter/FilterModule.kt   |  5 +-
 .../session/group/DefaultGetGroupDataTask.kt  |  1 -
 .../session/group/DefaultGroupService.kt      |  1 -
 .../session/group/GetGroupDataWorker.kt       | 20 +++---
 .../internal/session/group/GroupModule.kt     |  4 +-
 .../session/group/GroupSummaryUpdater.kt      | 12 ++--
 .../internal/session/room/DefaultRoom.kt      | 34 +++++-----
 .../session/room/DefaultRoomService.kt        |  1 -
 .../session/room/EventRelationExtractor.kt    |  1 -
 .../room/EventRelationsAggregationTask.kt     |  1 -
 .../room/EventRelationsAggregationUpdater.kt  |  1 -
 .../session/room/RoomAvatarResolver.kt        |  1 -
 .../internal/session/room/RoomFactory.kt      | 12 ++--
 .../internal/session/room/RoomModule.kt       | 25 +-------
 .../session/room/RoomSummaryUpdater.kt        |  1 -
 .../session/room/create/CreateRoomTask.kt     |  1 -
 .../room/directory/GetPublicRoomTask.kt       |  1 -
 .../directory/GetThirdPartyProtocolsTask.kt   |  1 -
 .../membership/DefaultMembershipService.kt    |  1 -
 .../room/membership/LoadRoomMembersTask.kt    |  1 -
 .../membership/SenderRoomMemberExtractor.kt   |  3 +-
 .../room/membership/joining/InviteTask.kt     |  1 -
 .../room/membership/joining/JoinRoomTask.kt   |  1 -
 .../room/membership/leaving/LeaveRoomTask.kt  |  1 -
 .../session/room/prune/EventsPruner.kt        |  1 -
 .../session/room/prune/PruneEventTask.kt      |  1 -
 .../session/room/read/DefaultReadService.kt   |  1 -
 .../session/room/read/SetReadMarkersTask.kt   |  1 -
 .../room/relation/DefaultRelationService.kt   | 34 +++++-----
 .../relation/FindReactionEventForUndoTask.kt  |  1 -
 .../room/relation/SendRelationWorker.kt       | 23 +++----
 .../room/relation/UpdateQuickReactionTask.kt  |  1 -
 .../session/room/send/DefaultSendService.kt   | 49 ++++++++------
 .../session/room/send/EncryptEventWorker.kt   | 25 ++++----
 .../session/room/send/EventFactory.kt         |  1 -
 .../room/send/LocalEchoEventFactory.kt        |  1 -
 .../session/room/send/LocalEchoUpdater.kt     |  1 -
 .../session/room/send/RedactEventWorker.kt    | 45 ++++++-------
 .../session/room/send/SendEventWorker.kt      | 27 ++++----
 .../session/room/state/DefaultStateService.kt |  1 -
 .../session/room/state/SendStateTask.kt       |  1 -
 .../timeline/DefaultGetContextOfEventTask.kt  |  1 -
 .../room/timeline/DefaultPaginationTask.kt    |  1 -
 .../room/timeline/DefaultTimelineService.kt   | 24 +++----
 .../session/room/timeline/GetEventTask.kt     |  1 -
 .../timeline/TimelineSendEventWorkCommon.kt   | 11 ++--
 .../room/timeline/TokenChunkEventPersistor.kt | 13 ++--
 .../session/signout/DefaultSignOutService.kt  |  1 -
 .../internal/session/signout/SignOutModule.kt |  4 +-
 .../internal/session/signout/SignOutTask.kt   |  1 -
 .../session/sync/CryptoSyncHandler.kt         |  1 -
 .../internal/session/sync/GroupSyncHandler.kt |  1 -
 .../session/sync/ReadReceiptHandler.kt        |  1 -
 .../internal/session/sync/RoomSyncHandler.kt  |  8 ++-
 .../internal/session/sync/RoomTagHandler.kt   |  1 -
 .../internal/session/sync/SyncModule.kt       |  2 +-
 .../session/sync/SyncResponseHandler.kt       |  1 -
 .../android/internal/session/sync/SyncTask.kt |  1 -
 .../internal/session/sync/SyncTokenStore.kt   |  4 +-
 .../sync/UserAccountDataSyncHandler.kt        |  1 -
 .../internal/session/sync/job/SyncThread.kt   |  1 -
 .../session/user/DefaultUserService.kt        |  1 -
 .../internal/session/user/UpdateUserTask.kt   |  1 -
 .../session/user/UserEntityUpdater.kt         |  1 -
 .../internal/session/user/UserModule.kt       |  3 -
 .../android/internal/task/TaskExecutor.kt     |  1 -
 .../android/internal/util/CancelableWork.kt   |  6 +-
 .../SessionWorkerParams.kt}                   | 11 ++--
 .../matrix/android/internal/worker/Worker.kt  | 25 ++++++++
 .../internal/worker/WorkerBindingModule.kt    | 64 -------------------
 vector/build.gradle                           |  2 +-
 .../fcm/VectorFirebaseMessagingService.kt     |  3 +-
 .../riotredesign/EmojiCompatFontProvider.kt   |  2 +
 .../vector/riotredesign/VectorApplication.kt  |  9 ++-
 .../riotredesign/core/di/ScreenComponent.kt   |  8 ++-
 .../riotredesign/core/di/VectorComponent.kt   |  6 ++
 .../riotredesign/core/di/VectorModule.kt      | 11 +++-
 .../riotredesign/features/MainActivity.kt     | 15 +++--
 .../IncomingVerificationRequestHandler.kt     |  2 +-
 .../features/home/AvatarRenderer.kt           |  7 +-
 .../features/home/HomeActivity.kt             |  2 +-
 .../home/room/detail/RoomDetailViewModel.kt   |  5 ++
 .../helper/ContentUploadStateTrackerBinder.kt |  6 +-
 .../helper/TimelineMediaSizeProvider.kt       |  2 +
 .../timeline/item/MessageImageVideoItem.kt    |  2 +-
 .../features/login/LoginActivity.kt           | 11 +++-
 .../features/media/ImageContentRenderer.kt    |  4 +-
 .../features/media/VideoContentRenderer.kt    |  2 +-
 .../features/rageshake/BugReporter.kt         |  4 +-
 156 files changed, 393 insertions(+), 552 deletions(-)
 delete mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/MatrixInitProvider.kt
 rename matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/{di/MatrixAssistedModule.kt => worker/SessionWorkerParams.kt} (71%)
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Worker.kt
 delete mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerBindingModule.kt

diff --git a/matrix-sdk-android-rx/build.gradle b/matrix-sdk-android-rx/build.gradle
index 26d141c3..183f3be1 100644
--- a/matrix-sdk-android-rx/build.gradle
+++ b/matrix-sdk-android-rx/build.gradle
@@ -37,10 +37,7 @@ dependencies {
     implementation project(":matrix-sdk-android")
     implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
     implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
-    implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
-
-    // Paging
-    implementation 'androidx.paging:paging-runtime:2.0.0'
+    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
 
     testImplementation 'junit:junit:4.12'
     androidTestImplementation 'androidx.test:runner:1.1.1'
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index 4119c03c..0bb1dbfb 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -120,7 +120,7 @@ dependencies {
     kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
 
     // Work
-    implementation "android.arch.work:work-runtime-ktx:1.0.0"
+    implementation "androidx.work:work-runtime-ktx:2.1.0-beta01"
 
     // FP
     implementation "io.arrow-kt:arrow-core:$arrow_version"
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/auth/AuthenticatorTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/auth/AuthenticatorTest.kt
index 27c1c4da..398507fa 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/auth/AuthenticatorTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/auth/AuthenticatorTest.kt
@@ -39,16 +39,8 @@ import org.koin.test.KoinTest
 @RunWith(AndroidJUnit4::class)
 internal class AuthenticatorTest : InstrumentedTest, KoinTest {
 
-    init {
-        Monarchy.init(context())
-        val matrixModule = MatrixModule(context()).definition
-        val networkModule = NetworkModule().definition
-        val authModule = AuthModule().definition
-        loadKoinModules(listOf(matrixModule, networkModule, authModule))
-    }
-
-    private val authenticator: Authenticator by inject()
-    private val okReplayInterceptor: OkReplayInterceptor by inject()
+    lateinit var authenticator: Authenticator
+    lateinit var okReplayInterceptor: OkReplayInterceptor
 
     private val okReplayConfig = OkReplayConfig.Builder()
             .tapeRoot(AndroidTapeRoot(
diff --git a/matrix-sdk-android/src/main/AndroidManifest.xml b/matrix-sdk-android/src/main/AndroidManifest.xml
index f4e0e50f..7191d9c8 100644
--- a/matrix-sdk-android/src/main/AndroidManifest.xml
+++ b/matrix-sdk-android/src/main/AndroidManifest.xml
@@ -1,4 +1,5 @@
 
 
     
@@ -7,9 +8,10 @@
 
     
 
-        
+        
 
     
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
index c4d128ea..3ea61119 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
@@ -18,10 +18,13 @@ package im.vector.matrix.android.api
 
 import android.content.Context
 import androidx.lifecycle.ProcessLifecycleOwner
+import androidx.work.Configuration
+import androidx.work.WorkManager
 import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.api.auth.Authenticator
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.sync.FilterService
+import im.vector.matrix.android.internal.SessionManager
 import im.vector.matrix.android.internal.di.DaggerMatrixComponent
 import im.vector.matrix.android.internal.network.UserAgentHolder
 import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
@@ -29,23 +32,37 @@ import org.matrix.olm.OlmManager
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
 
+data class MatrixConfiguration(
+        val applicationFlavor: String = "Default-application-flavor"
+) {
+
+    interface Provider {
+        fun providesMatrixConfiguration(): MatrixConfiguration
+    }
+
+}
+
 /**
  * This is the main entry point to the matrix sdk.
- * This class is automatically init by a provider.
  * To get the singleton instance, use getInstance static method.
  */
-class Matrix private constructor(context: Context) {
+class Matrix private constructor(context: Context, matrixConfiguration: MatrixConfiguration) {
 
-    @Inject internal lateinit var olmManager: OlmManager
     @Inject internal lateinit var authenticator: Authenticator
     @Inject internal lateinit var userAgentHolder: UserAgentHolder
     @Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
+    @Inject internal lateinit var olmManager: OlmManager
+    @Inject internal lateinit var sessionManager: SessionManager
     var currentSession: Session? = null
 
     init {
         Monarchy.init(context)
         DaggerMatrixComponent.factory().create(context).inject(this)
+        if (context.applicationContext !is Configuration.Provider) {
+            WorkManager.initialize(context, Configuration.Builder().build())
+        }
         ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
+        userAgentHolder.setApplicationFlavor(matrixConfiguration.applicationFlavor)
         authenticator.getLastActiveSession()?.also {
             currentSession = it
             it.open()
@@ -54,30 +71,33 @@ class Matrix private constructor(context: Context) {
         }
     }
 
+    fun getUserAgent() = userAgentHolder.userAgent
+
     fun authenticator(): Authenticator {
         return authenticator
     }
 
-    /**
-     * Set application flavor, to alter user agent.
-     */
-    fun setApplicationFlavor(flavor: String) {
-        userAgentHolder.setApplicationFlavor(flavor)
-    }
-
-    fun getUserAgent() = userAgentHolder.userAgent
-
     companion object {
+
         private lateinit var instance: Matrix
         private val isInit = AtomicBoolean(false)
 
-        internal fun initialize(context: Context) {
+        fun initialize(context: Context, matrixConfiguration: MatrixConfiguration) {
             if (isInit.compareAndSet(false, true)) {
-                instance = Matrix(context.applicationContext)
+                instance = Matrix(context.applicationContext, matrixConfiguration)
             }
         }
 
-        fun getInstance(): Matrix {
+        fun getInstance(context: Context): Matrix {
+            if (isInit.compareAndSet(false, true)) {
+                val appContext = context.applicationContext
+                if (appContext is MatrixConfiguration.Provider) {
+                    val matrixConfiguration = (appContext as MatrixConfiguration.Provider).providesMatrixConfiguration()
+                    instance = Matrix(appContext, matrixConfiguration)
+                } else {
+                    throw IllegalStateException("Matrix is not initialized properly.  You should call Matrix.initialize or let your application implements MatrixConfiguration.Provider.")
+                }
+            }
             return instance
         }
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/MatrixInitProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/MatrixInitProvider.kt
deleted file mode 100644
index 9167cbc5..00000000
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/MatrixInitProvider.kt
+++ /dev/null
@@ -1,52 +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.matrix.android.internal
-
-import android.content.ContentProvider
-import android.content.ContentValues
-import android.database.Cursor
-import android.net.Uri
-import im.vector.matrix.android.api.Matrix
-
-internal class MatrixInitProvider : ContentProvider() {
-
-    override fun onCreate(): Boolean {
-        Matrix.initialize(context!!)
-        return true
-    }
-
-    override fun insert(uri: Uri, values: ContentValues?): Uri? {
-        return null
-    }
-
-    override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? {
-        return null
-    }
-
-    override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?): Int {
-        return 0
-    }
-
-    override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int {
-        return 0
-    }
-
-    override fun getType(uri: Uri): String? {
-        return null
-    }
-
-}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
index 74124bba..d70052ef 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
@@ -31,6 +31,10 @@ internal class SessionManager @Inject constructor(private val matrixComponent: M
 
     private val sessionComponents = HashMap()
 
+    fun getSessionComponent(userId: String): SessionComponent? {
+        return sessionComponents[userId]
+    }
+
     fun createSession(sessionParams: SessionParams): Session {
         val userId = sessionParams.credentials.userId
         if (sessionComponents.containsKey(userId)) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
index 2f774647..71e7d371 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
@@ -35,7 +35,6 @@ internal abstract class AuthModule {
     companion object {
         @JvmStatic
         @Provides
-        @MatrixScope
         @AuthDatabase
         fun providesRealmConfiguration(context: Context): RealmConfiguration {
             val old = File(context.filesDir, "matrix-sdk-auth")
@@ -51,11 +50,9 @@ internal abstract class AuthModule {
     }
 
     @Binds
-    @MatrixScope
     abstract fun bindSessionParamsStore(sessionParamsStore: RealmSessionParamsStore): SessionParamsStore
 
     @Binds
-    @MatrixScope
     abstract fun bindAuthenticator(authenticator: DefaultAuthenticator): Authenticator
 
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
index 56571fa8..c19ec005 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
@@ -37,7 +37,6 @@ import kotlinx.coroutines.withContext
 import retrofit2.Retrofit
 import javax.inject.Inject
 
-@MatrixScope
 internal class DefaultAuthenticator @Inject constructor(private val retrofitBuilder: Retrofit.Builder,
                                                         private val coroutineDispatchers: MatrixCoroutineDispatchers,
                                                         private val sessionParamsStore: SessionParamsStore,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
index 3b742e65..4a202e3a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
@@ -25,7 +25,6 @@ import io.realm.Realm
 import io.realm.RealmConfiguration
 import javax.inject.Inject
 
-@MatrixScope
 internal class RealmSessionParamsStore @Inject constructor(private val mapper: SessionParamsMapper,
                                                            @AuthDatabase private val realmConfiguration: RealmConfiguration
 ) : SessionParamsStore {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
index 53e3a98a..a8738cb4 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
@@ -23,7 +23,6 @@ import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.internal.di.MatrixScope
 import javax.inject.Inject
 
-@MatrixScope
 internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
 
     private val credentialsAdapter = moshi.adapter(Credentials::class.java)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt
index 4c011bfd..5213b6c7 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt
@@ -93,6 +93,8 @@ import kotlin.coroutines.EmptyCoroutineContext
  */
 @SessionScope
 internal class CryptoManager @Inject constructor(
+        // Olm Manager
+        private val olmManager: OlmManager,
         // The credentials,
         private val credentials: Credentials,
         private val myDeviceInfoHolder: MyDeviceInfoHolder,
@@ -118,8 +120,6 @@ internal class CryptoManager @Inject constructor(
         private val incomingRoomKeyRequestManager: IncomingRoomKeyRequestManager,
         //
         private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
-        // Olm Manager
-        private val olmManager: OlmManager,
         // Actions
         private val setDeviceVerificationAction: SetDeviceVerificationAction,
         private val megolmSessionDataImporter: MegolmSessionDataImporter,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
index ccaa6c56..f5ed61b6 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt
@@ -88,8 +88,8 @@ internal abstract class CryptoModule {
         // Realm configuration, named to avoid clash with main cache realm configuration
         @JvmStatic
         @Provides
-        @SessionScope
         @CryptoDatabase
+        @SessionScope
         fun providesRealmConfiguration(context: Context, credentials: Credentials): RealmConfiguration {
             return RealmConfiguration.Builder()
                     .directory(File(context.filesDir, credentials.userId.hash()))
@@ -102,7 +102,6 @@ internal abstract class CryptoModule {
 
         @JvmStatic
         @Provides
-        @SessionScope
         @CryptoDatabase
         fun providesClearCacheTask(@CryptoDatabase realmConfiguration: RealmConfiguration): ClearCacheTask {
             return RealmClearCacheTask(realmConfiguration)
@@ -111,7 +110,6 @@ internal abstract class CryptoModule {
 
         @JvmStatic
         @Provides
-        @SessionScope
         fun providesCryptoStore(@CryptoDatabase realmConfiguration: RealmConfiguration, credentials: Credentials): IMXCryptoStore {
             return RealmCryptoStore(false /* TODO*/,
                                     realmConfiguration,
@@ -142,91 +140,69 @@ internal abstract class CryptoModule {
     }
 
     @Binds
-    @SessionScope
     abstract fun bindCryptoService(cryptoManager: CryptoManager): CryptoService
 
     @Binds
-    @SessionScope
     abstract fun bindDeleteDeviceTask(deleteDeviceTask: DefaultDeleteDeviceTask): DeleteDeviceTask
 
     @Binds
-    @SessionScope
     abstract fun bindGetDevicesTask(getDevicesTask: DefaultGetDevicesTask): GetDevicesTask
 
     @Binds
-    @SessionScope
     abstract fun bindSetDeviceNameTask(getDevicesTask: DefaultSetDeviceNameTask): SetDeviceNameTask
 
     @Binds
-    @SessionScope
     abstract fun bindUploadKeysTask(getDevicesTask: DefaultUploadKeysTask): UploadKeysTask
 
     @Binds
-    @SessionScope
     abstract fun bindDownloadKeysForUsersTask(downloadKeysForUsers: DefaultDownloadKeysForUsers): DownloadKeysForUsersTask
 
     @Binds
-    @SessionScope
     abstract fun bindCreateKeysBackupVersionTask(createKeysBackupVersionTask: DefaultCreateKeysBackupVersionTask): CreateKeysBackupVersionTask
 
     @Binds
-    @SessionScope
     abstract fun bindDeleteBackupTask(deleteBackupTask: DefaultDeleteBackupTask): DeleteBackupTask
 
     @Binds
-    @SessionScope
     abstract fun bindDeleteRoomSessionDataTask(deleteRoomSessionDataTask: DefaultDeleteRoomSessionDataTask): DeleteRoomSessionDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindDeleteRoomSessionsDataTask(deleteRoomSessionDataTask: DefaultDeleteRoomSessionsDataTask): DeleteRoomSessionsDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindDeleteSessionsDataTask(deleteRoomSessionDataTask: DefaultDeleteSessionsDataTask): DeleteSessionsDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindGetKeysBackupLastVersionTask(getKeysBackupLastVersionTask: DefaultGetKeysBackupLastVersionTask): GetKeysBackupLastVersionTask
 
     @Binds
-    @SessionScope
     abstract fun bindGetKeysBackupVersionTask(getKeysBackupVersionTask: DefaultGetKeysBackupVersionTask) : GetKeysBackupVersionTask
 
     @Binds
-    @SessionScope
     abstract fun bindGetRoomSessionDataTask(getRoomSessionDataTask: DefaultGetRoomSessionDataTask) : GetRoomSessionDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindGetRoomSessionsDataTask(getRoomSessionDataTask: DefaultGetRoomSessionsDataTask) : GetRoomSessionsDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindGetSessionsDataTask(getRoomSessionDataTask: DefaultGetSessionsDataTask) : GetSessionsDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindStoreRoomSessionDataTask(storeRoomSessionDataTask: DefaultStoreRoomSessionDataTask) : StoreRoomSessionDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindStoreRoomSessionsDataTask(storeRoomSessionDataTask: DefaultStoreRoomSessionsDataTask) : StoreRoomSessionsDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindStoreSessionsDataTask(storeRoomSessionDataTask: DefaultStoreSessionsDataTask) : StoreSessionsDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindUpdateKeysBackupVersionTask(updateKeysBackupVersionTask: DefaultUpdateKeysBackupVersionTask) : UpdateKeysBackupVersionTask
 
     @Binds
-    @SessionScope
     abstract fun bindSendToDeviceTask(sendToDeviceTask: DefaultSendToDeviceTask) : SendToDeviceTask
 
     @Binds
-    @SessionScope
     abstract fun bindClaimOneTimeKeysForUsersDeviceTask(claimOneTimeKeysForUsersDevice: DefaultClaimOneTimeKeysForUsersDevice) : ClaimOneTimeKeysForUsersDeviceTask
 
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt
index f58901d1..d6450f9c 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt
@@ -33,7 +33,6 @@ import java.util.*
 import javax.inject.Inject
 
 // Legacy name: MXDeviceList
-
 @SessionScope
 internal class DeviceListManager @Inject constructor(private val cryptoStore: IMXCryptoStore,
                                                      private val olmDevice: MXOlmDevice,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/ObjectSigner.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/ObjectSigner.kt
index 2e91cb7a..8ca33ea4 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/ObjectSigner.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/ObjectSigner.kt
@@ -21,7 +21,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import java.util.*
 import javax.inject.Inject
 
-@SessionScope
 internal class ObjectSigner @Inject constructor(private val credentials: Credentials,
                             private val olmDevice: MXOlmDevice) {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt
index 6ea04594..36a5b5cd 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt
@@ -29,7 +29,6 @@ import timber.log.Timber
 import java.util.*
 import javax.inject.Inject
 
-@SessionScope
 internal class EnsureOlmSessionsForDevicesAction @Inject constructor(private val olmDevice: MXOlmDevice,
                                                                      private val oneTimeKeysForUsersDeviceTask: ClaimOneTimeKeysForUsersDeviceTask) {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt
index 0f784b69..f6817e14 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt
@@ -29,7 +29,6 @@ import timber.log.Timber
 import java.util.*
 import javax.inject.Inject
 
-@SessionScope
 internal class EnsureOlmSessionsForUsersAction @Inject constructor(private val olmDevice: MXOlmDevice,
                                                private val cryptoStore: IMXCryptoStore,
                                                private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt
index a311ee0a..34124cec 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt
@@ -30,7 +30,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import timber.log.Timber
 import javax.inject.Inject
 
-@SessionScope
 internal class MegolmSessionDataImporter @Inject constructor(private val olmDevice: MXOlmDevice,
                                                              private val roomDecryptorProvider: RoomDecryptorProvider,
                                                              private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt
index fd063df9..4703237e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt
@@ -29,7 +29,6 @@ import timber.log.Timber
 import java.util.*
 import javax.inject.Inject
 
-@SessionScope
 internal class MessageEncrypter @Inject constructor(private val credentials: Credentials,
                                                     private val olmDevice: MXOlmDevice) {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt
index d5450077..dfc54ffe 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt
@@ -23,7 +23,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import timber.log.Timber
 import javax.inject.Inject
 
-@SessionScope
 internal class SetDeviceVerificationAction @Inject constructor(private val cryptoStore: IMXCryptoStore,
                                            private val credentials: Credentials,
                                            private val keysBackup: KeysBackup) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt
index 2f9a61cf..43c485df 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt
@@ -28,7 +28,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
 import javax.inject.Inject
 
-@SessionScope
 internal class MXMegolmDecryptionFactory @Inject constructor(private val credentials: Credentials,
                                          private val olmDevice: MXOlmDevice,
                                          private val deviceListManager: DeviceListManager,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt
index 0fad79a6..2807863e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt
@@ -29,7 +29,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.task.TaskExecutor
 import javax.inject.Inject
 
-@SessionScope
 internal class MXMegolmEncryptionFactory @Inject constructor(
         private val olmDevice: MXOlmDevice,
         private val keysBackup: KeysBackup,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt
index 4fbf88bf..a8b4b1a0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt
@@ -21,7 +21,6 @@ import im.vector.matrix.android.internal.crypto.MXOlmDevice
 import im.vector.matrix.android.internal.session.SessionScope
 import javax.inject.Inject
 
-@SessionScope
 internal class MXOlmDecryptionFactory @Inject constructor(private val olmDevice: MXOlmDevice,
                                                           private val credentials: Credentials) {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt
index ef047d6c..99ab8eda 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt
@@ -25,7 +25,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
 import javax.inject.Inject
 
-@SessionScope
 internal class MXOlmEncryptionFactory @Inject constructor(private val olmDevice: MXOlmDevice,
                                                           private val cryptoStore: IMXCryptoStore,
                                                           private val messageEncrypter: MessageEncrypter,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt
index feb4a189..f0c5037f 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt
@@ -21,13 +21,11 @@ import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi
 import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody
 import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersion
 import im.vector.matrix.android.internal.network.executeRequest
-import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.task.Task
 import javax.inject.Inject
 
 internal interface CreateKeysBackupVersionTask : Task
 
-@SessionScope
 internal class DefaultCreateKeysBackupVersionTask @Inject constructor(private val roomKeysApi: RoomKeysApi)
     : CreateKeysBackupVersionTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt
index 6d857636..a1ad84ab 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt
@@ -30,7 +30,6 @@ internal interface DeleteBackupTask : Task {
     )
 }
 
-@SessionScope
 internal class DefaultDeleteBackupTask @Inject constructor(private val roomKeysApi: RoomKeysApi)
     : DeleteBackupTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt
index 3edd90a8..c24d314c 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt
@@ -31,7 +31,6 @@ internal interface DeleteRoomSessionDataTask : Task
 
-@SessionScope
 internal class DefaultGetKeysBackupLastVersionTask @Inject constructor(private val roomKeysApi: RoomKeysApi)
     : GetKeysBackupLastVersionTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt
index 0016a01b..dfaeafa1 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt
@@ -20,13 +20,11 @@ import arrow.core.Try
 import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi
 import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersionResult
 import im.vector.matrix.android.internal.network.executeRequest
-import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.task.Task
 import javax.inject.Inject
 
 internal interface GetKeysBackupVersionTask : Task
 
-@SessionScope
 internal class DefaultGetKeysBackupVersionTask @Inject constructor(private val roomKeysApi: RoomKeysApi)
     : GetKeysBackupVersionTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt
index 05aee672..253a2a5a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt
@@ -32,7 +32,6 @@ internal interface GetRoomSessionDataTask : Task {
     )
 }
 
-@SessionScope
 internal class DefaultDeleteDeviceTask @Inject constructor(private val cryptoApi: CryptoApi)
     : DeleteDeviceTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt
index 09539ade..00ea7178 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt
@@ -35,7 +35,6 @@ internal interface DownloadKeysForUsersTask : Task
 
-@SessionScope
 internal class DefaultGetDevicesTask @Inject constructor(private val cryptoApi: CryptoApi)
     : GetDevicesTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt
index a89dabea..21eabc22 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt
@@ -33,7 +33,6 @@ internal interface GetKeyChangesTask : Task {
     )
 }
 
-@SessionScope
 internal class DefaultSendToDeviceTask @Inject constructor(private val cryptoApi: CryptoApi)
     : SendToDeviceTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt
index 0997a4b2..04613ddd 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt
@@ -34,7 +34,6 @@ internal interface SetDeviceNameTask : Task {
     )
 }
 
-@SessionScope
 internal class DefaultSetDeviceNameTask @Inject constructor(private val cryptoApi: CryptoApi)
     : SetDeviceNameTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt
index 434803c2..96c3a558 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt
@@ -38,7 +38,6 @@ internal interface UploadKeysTask : Task
 
-@SessionScope
 internal class RealmClearCacheTask @Inject constructor(private val realmConfiguration: RealmConfiguration) : ClearCacheTask {
 
     override suspend fun execute(params: Unit): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
index d38e7cb2..34c5c5be 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/DefaultCacheService.kt
@@ -24,7 +24,6 @@ import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultCacheService @Inject constructor(@SessionDatabase private val clearCacheTask: ClearCacheTask,
                                                        private val taskExecutor: TaskExecutor) : CacheService {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt
index 66b75a54..f87d0fd6 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/ContentModule.kt
@@ -26,10 +26,8 @@ import im.vector.matrix.android.internal.session.SessionScope
 internal abstract class ContentModule {
 
     @Binds
-    @SessionScope
     abstract fun bindContentUploadStateTracker(contentUploadStateTracker: DefaultContentUploadStateTracker): ContentUploadStateTracker
 
     @Binds
-    @SessionScope
     abstract fun bindContentUrlResolver(contentUrlResolver: DefaultContentUrlResolver): ContentUrlResolver
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt
index fbd7983d..33941729 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt
@@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.session.content
 import android.os.Handler
 import android.os.Looper
 import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
+import im.vector.matrix.android.internal.di.MatrixScope
 import im.vector.matrix.android.internal.session.SessionScope
 import javax.inject.Inject
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUrlResolver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUrlResolver.kt
index bfba5bb7..50fe285a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUrlResolver.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUrlResolver.kt
@@ -25,7 +25,6 @@ import javax.inject.Inject
 private const val MATRIX_CONTENT_URI_SCHEME = "mxc://"
 private const val URI_PREFIX_CONTENT_API = "_matrix/media/v1/"
 
-@SessionScope
 internal class DefaultContentUrlResolver @Inject constructor(private val homeServerConnectionConfig: HomeServerConnectionConfig) : ContentUrlResolver {
 
     companion object {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
index 71906b11..217c06ba 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
@@ -29,7 +29,6 @@ import java.io.IOException
 import javax.inject.Inject
 
 
-@SessionScope
 internal class FileUploader @Inject constructor(private val okHttpClient: OkHttpClient,
                                                 private val sessionParams: SessionParams,
                                                 private val moshi: Moshi) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
index 30c4b629..80b9b0a2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt
@@ -19,7 +19,6 @@ package im.vector.matrix.android.internal.session.content
 import android.content.Context
 import androidx.work.CoroutineWorker
 import androidx.work.WorkerParameters
-import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.api.session.content.ContentAttachmentData
@@ -31,32 +30,37 @@ import im.vector.matrix.android.api.session.room.model.message.MessageContent
 import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
 import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
 import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
-import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.ProgressRequestBody
 import im.vector.matrix.android.internal.session.room.send.SendEventWorker
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
+import im.vector.matrix.android.internal.worker.SessionWorkerParams
 import im.vector.matrix.android.internal.worker.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.getSessionComponent
 import timber.log.Timber
 import java.io.File
+import javax.inject.Inject
 
 
-internal class UploadContentWorker @AssistedInject constructor(
-        @Assisted context: Context,
-        @Assisted params: WorkerParameters,
-        private val fileUploader: FileUploader,
-        private val contentUploadStateTracker: DefaultContentUploadStateTracker)
-    : CoroutineWorker(context, params) {
+internal class UploadContentWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
 
     @JsonClass(generateAdapter = true)
     internal data class Params(
+            override val userId: String,
             val roomId: String,
             val event: Event,
             val attachment: ContentAttachmentData
-    )
+    ) : SessionWorkerParams
+
+    @Inject lateinit var fileUploader: FileUploader
+    @Inject lateinit var contentUploadStateTracker: DefaultContentUploadStateTracker
 
     override suspend fun doWork(): Result {
         val params = WorkerParamsFactory.fromData(inputData)
                      ?: return Result.success()
 
+        val sessionComponent = getSessionComponent(params.userId) ?: return Result.success()
+        sessionComponent.inject(this)
+
         val eventId = params.event.eventId ?: return Result.success()
         val attachment = params.attachment
 
@@ -105,7 +109,7 @@ internal class UploadContentWorker @AssistedInject constructor(
                               thumbnailUrl: String?): Result {
         contentUploadStateTracker.setSuccess(params.event.eventId!!)
         val event = updateEvent(params.event, attachmentUrl, thumbnailUrl)
-        val sendParams = SendEventWorker.Params(params.roomId, event)
+        val sendParams = SendEventWorker.Params(params.userId, params.roomId, event)
         return Result.success(WorkerParamsFactory.toData(sendParams))
     }
 
@@ -137,8 +141,5 @@ internal class UploadContentWorker @AssistedInject constructor(
         return copy(url = url)
     }
 
-    @AssistedInject.Factory
-    interface Factory : DelegateWorkerFactory
-
 }
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt
index f08c769f..f6a0a13b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt
@@ -26,7 +26,6 @@ import io.realm.RealmConfiguration
 import io.realm.kotlin.where
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultFilterRepository @Inject constructor(
         @SessionDatabase private val realmConfiguration: RealmConfiguration
 ) : FilterRepository {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt
index 033838ee..e64bce19 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt
@@ -22,7 +22,6 @@ import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultFilterService @Inject constructor(private val filterRepository: FilterRepository,
                                                         private val saveFilterTask: SaveFilterTask,
                                                         private val taskExecutor: TaskExecutor) : FilterService {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt
index a3c7fea8..26612b23 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt
@@ -35,7 +35,6 @@ internal interface SaveFilterTask : Task {
 
 }
 
-@SessionScope
 internal class DefaultSaveFilterTask @Inject constructor(private val sessionParams: SessionParams,
                                                          private val filterAPI: FilterApi,
                                                          private val filterRepository: FilterRepository
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterModule.kt
index fed83d87..a43e19bd 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterModule.kt
@@ -30,24 +30,21 @@ internal abstract class FilterModule {
 
     @Module
     companion object {
-        @SessionScope
         @Provides
         @JvmStatic
+        @SessionScope
         fun providesFilterApi(retrofit: Retrofit): FilterApi {
             return retrofit.create(FilterApi::class.java)
         }
     }
 
     @Binds
-    @SessionScope
     abstract fun bindFilterRepository(filterRepository: DefaultFilterRepository): FilterRepository
 
     @Binds
-    @SessionScope
     abstract fun bindFilterService(filterService: DefaultFilterService): FilterService
 
     @Binds
-    @SessionScope
     abstract fun bindSaveFilterTask(saveFilterTask_Factory: DefaultSaveFilterTask): SaveFilterTask
 
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt
index 15d4d55f..3c763d98 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt
@@ -39,7 +39,6 @@ internal interface GetGroupDataTask : Task {
 
 }
 
-@SessionScope
 internal class DefaultGetGroupDataTask @Inject constructor(
         private val groupAPI: GroupAPI,
         private val monarchy: Monarchy
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt
index 90ee7d58..ed0552da 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGroupService.kt
@@ -28,7 +28,6 @@ import im.vector.matrix.android.internal.database.query.where
 import im.vector.matrix.android.internal.session.SessionScope
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultGroupService @Inject constructor(private val monarchy: Monarchy) : GroupService {
 
     override fun getGroup(groupId: String): Group? {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
index 1a07fd93..4b3d6453 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
@@ -24,26 +24,28 @@ import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
+import im.vector.matrix.android.internal.worker.SessionWorkerParams
 import im.vector.matrix.android.internal.worker.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.getSessionComponent
+import javax.inject.Inject
 
-internal class GetGroupDataWorker @AssistedInject constructor(
-        @Assisted context: Context,
-        @Assisted params: WorkerParameters,
-        private val getGroupDataTask: GetGroupDataTask
-) : CoroutineWorker(context, params) {
-
-    @AssistedInject.Factory
-    interface Factory : DelegateWorkerFactory
+internal class GetGroupDataWorker (context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
 
     @JsonClass(generateAdapter = true)
     internal data class Params(
+            override val userId: String,
             val groupIds: List
-    )
+    ): SessionWorkerParams
+
+    @Inject lateinit var getGroupDataTask: GetGroupDataTask
 
     override suspend fun doWork(): Result {
         val params = WorkerParamsFactory.fromData(inputData)
                      ?: return Result.failure()
 
+        val sessionComponent = getSessionComponent(params.userId) ?: return Result.success()
+        sessionComponent.inject(this)
+
         val results = params.groupIds.map { groupId ->
             fetchGroupData(groupId)
         }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt
index 518585d3..cdb698b0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt
@@ -28,19 +28,17 @@ internal abstract class GroupModule {
 
     @Module
     companion object {
-        @SessionScope
         @Provides
         @JvmStatic
+        @SessionScope
         fun providesGroupAPI(retrofit: Retrofit): GroupAPI {
             return retrofit.create(GroupAPI::class.java)
         }
     }
 
     @Binds
-    @SessionScope
     abstract fun bindGetGroupDataTask(getGroupDataTask: DefaultGetGroupDataTask): GetGroupDataTask
 
     @Binds
-    @SessionScope
     abstract fun bindGroupService(groupService: DefaultGroupService): GroupService
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
index 81b56c08..43bad2bc 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
@@ -16,23 +16,25 @@
 
 package im.vector.matrix.android.internal.session.group
 
+import android.content.Context
 import androidx.work.Constraints
 import androidx.work.ExistingWorkPolicy
 import androidx.work.NetworkType
 import androidx.work.OneTimeWorkRequestBuilder
 import androidx.work.WorkManager
 import com.zhuinden.monarchy.Monarchy
+import im.vector.matrix.android.api.auth.data.Credentials
 import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
 import im.vector.matrix.android.internal.database.model.GroupEntity
 import im.vector.matrix.android.internal.database.query.where
-import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import javax.inject.Inject
 
 private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
 
-@SessionScope
-internal class GroupSummaryUpdater @Inject constructor(monarchy: Monarchy) : RealmLiveEntityObserver(monarchy) {
+internal class GroupSummaryUpdater @Inject constructor(private val context: Context,
+                                                       private val credentials: Credentials,
+                                                       monarchy: Monarchy) : RealmLiveEntityObserver(monarchy) {
 
     override val query = Monarchy.Query { GroupEntity.where(it) }
 
@@ -42,7 +44,7 @@ internal class GroupSummaryUpdater @Inject constructor(monarchy: Monarchy) : Rea
 
     override fun processChanges(inserted: List, updated: List, deleted: List) {
         val newGroupIds = inserted.map { it.groupId }
-        val getGroupDataWorkerParams = GetGroupDataWorker.Params(newGroupIds)
+        val getGroupDataWorkerParams = GetGroupDataWorker.Params(credentials.userId, newGroupIds)
         val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
 
         val sendWork = OneTimeWorkRequestBuilder()
@@ -50,7 +52,7 @@ internal class GroupSummaryUpdater @Inject constructor(monarchy: Monarchy) : Rea
                 .setConstraints(workConstraints)
                 .build()
 
-        WorkManager.getInstance()
+        WorkManager.getInstance(context)
                 .beginUniqueWork(GET_GROUP_DATA_WORKER, ExistingWorkPolicy.APPEND, sendWork)
                 .enqueue()
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt
index 51f93873..44249c59 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt
@@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.room
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.Transformations
+import com.squareup.inject.assisted.AssistedInject
 import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.api.session.crypto.CryptoService
 import im.vector.matrix.android.api.session.room.Room
@@ -33,27 +34,24 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
 import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
 import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
 import im.vector.matrix.android.internal.database.query.where
-import im.vector.matrix.android.internal.session.SessionScope
 import javax.inject.Inject
 
-@SessionScope
-internal class DefaultRoom @Inject constructor(
-        override val roomId: String,
-        private val monarchy: Monarchy,
-        private val timelineService: TimelineService,
-        private val sendService: SendService,
-        private val stateService: StateService,
-        private val readService: ReadService,
-        private val cryptoService: CryptoService,
-        private val relationService: RelationService,
-        private val roomMembersService: MembershipService
+internal class DefaultRoom @Inject constructor(override val roomId: String,
+                                               private val monarchy: Monarchy,
+                                               private val timelineService: TimelineService,
+                                               private val sendService: SendService,
+                                               private val stateService: StateService,
+                                               private val readService: ReadService,
+                                               private val cryptoService: CryptoService,
+                                               private val relationService: RelationService,
+                                               private val roomMembersService: MembershipService
 ) : Room,
-        TimelineService by timelineService,
-        SendService by sendService,
-        StateService by stateService,
-        ReadService by readService,
-        RelationService by relationService,
-        MembershipService by roomMembersService {
+    TimelineService by timelineService,
+    SendService by sendService,
+    StateService by stateService,
+    ReadService by readService,
+    RelationService by relationService,
+    MembershipService by roomMembersService {
 
     override val roomSummary: LiveData by lazy {
         val liveRealmData = RealmLiveData(monarchy.realmConfiguration) { realm ->
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt
index 571a50d2..cd729c93 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt
@@ -35,7 +35,6 @@ import im.vector.matrix.android.internal.task.configureWith
 import im.vector.matrix.android.internal.util.fetchManaged
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultRoomService @Inject constructor(private val monarchy: Monarchy,
                                                       private val createRoomTask: CreateRoomTask,
                                                       private val roomFactory: RoomFactory,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationExtractor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationExtractor.kt
index 78e24b2d..147726b1 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationExtractor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationExtractor.kt
@@ -28,7 +28,6 @@ import javax.inject.Inject
  * Fetches annotations (reactions, edits...) associated to a given eventEntity from the data layer.
  */
 
-@SessionScope
 internal class EventRelationExtractor @Inject constructor() {
 
     fun extractFrom(event: EventEntity, realm: Realm = event.realm): EventAnnotationsSummary? {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt
index 18d0896e..2ed98f92 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt
@@ -44,7 +44,6 @@ internal interface EventRelationsAggregationTask : Task
 
-@SessionScope
 internal class DefaultCreateRoomTask @Inject constructor(private val roomAPI: RoomAPI,
                                                          @SessionDatabase private val realmConfiguration: RealmConfiguration) : CreateRoomTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetPublicRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetPublicRoomTask.kt
index e3fbed1e..b2cc1a74 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetPublicRoomTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetPublicRoomTask.kt
@@ -32,7 +32,6 @@ internal interface GetPublicRoomTask : Task {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetThirdPartyProtocolsTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetThirdPartyProtocolsTask.kt
index d72c3b5a..cd53c92d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetThirdPartyProtocolsTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/directory/GetThirdPartyProtocolsTask.kt
@@ -26,7 +26,6 @@ import javax.inject.Inject
 
 internal interface GetThirdPartyProtocolsTask : Task>
 
-@SessionScope
 internal class DefaultGetThirdPartyProtocolsTask @Inject constructor (private val roomAPI: RoomAPI) : GetThirdPartyProtocolsTask {
 
     override suspend fun execute(params: Unit): Try> {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt
index 9f51ade0..a64071a5 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt
@@ -36,7 +36,6 @@ import im.vector.matrix.android.internal.task.configureWith
 import im.vector.matrix.android.internal.util.fetchCopied
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultMembershipService @Inject constructor(private val roomId: String,
                                                             private val monarchy: Monarchy,
                                                             private val taskExecutor: TaskExecutor,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt
index d49448a0..4dbb60b8 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt
@@ -40,7 +40,6 @@ internal interface LoadRoomMembersTask : Task {
     )
 }
 
-@SessionScope
 internal class DefaultInviteTask @Inject constructor(private val roomAPI: RoomAPI) : InviteTask {
 
     override suspend fun execute(params: InviteTask.Params): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/JoinRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/JoinRoomTask.kt
index 37f4a2fa..96454cbf 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/JoinRoomTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/joining/JoinRoomTask.kt
@@ -29,7 +29,6 @@ internal interface JoinRoomTask : Task {
     )
 }
 
-@SessionScope
 internal class DefaultJoinRoomTask @Inject constructor(private val roomAPI: RoomAPI) : JoinRoomTask {
 
     override suspend fun execute(params: JoinRoomTask.Params): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/leaving/LeaveRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/leaving/LeaveRoomTask.kt
index 30c73035..fe055e99 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/leaving/LeaveRoomTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/leaving/LeaveRoomTask.kt
@@ -29,7 +29,6 @@ internal interface LeaveRoomTask : Task {
     )
 }
 
-@SessionScope
 internal class DefaultLeaveRoomTask @Inject constructor(private val roomAPI: RoomAPI) : LeaveRoomTask {
 
     override suspend fun execute(params: LeaveRoomTask.Params): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt
index a1bb65af..456cbde7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt
@@ -33,7 +33,6 @@ import javax.inject.Inject
  * Listens to the database for the insertion of any redaction event.
  * As it will actually delete the content, it should be called last in the list of listener.
  */
-@SessionScope
 internal class EventsPruner @Inject constructor(monarchy: Monarchy,
                                                 private val credentials: Credentials,
                                                 private val pruneEventTask: PruneEventTask,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt
index 08d52e24..56b40f2d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt
@@ -43,7 +43,6 @@ internal interface PruneEventTask : Task {
 
 }
 
-@SessionScope
 internal class DefaultPruneEventTask @Inject constructor(private val monarchy: Monarchy) : PruneEventTask {
 
     override suspend fun execute(params: PruneEventTask.Params): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/DefaultReadService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/DefaultReadService.kt
index ad3ad3b6..321e9890 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/DefaultReadService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/DefaultReadService.kt
@@ -27,7 +27,6 @@ import im.vector.matrix.android.internal.task.configureWith
 import im.vector.matrix.android.internal.util.fetchCopied
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultReadService @Inject constructor(private val roomId: String,
                                   private val monarchy: Monarchy,
                                   private val taskExecutor: TaskExecutor,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt
index aef52f5f..2146fdf0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt
@@ -47,7 +47,6 @@ internal interface SetReadMarkersTask : Task {
 private const val READ_MARKER = "m.fully_read"
 private const val READ_RECEIPT = "m.read"
 
-@SessionScope
 internal class DefaultSetReadMarkersTask @Inject constructor(private val roomAPI: RoomAPI,
                                          private val credentials: Credentials,
                                          private val monarchy: Monarchy
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
index 7ae4e5df..bbac2d0a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
@@ -15,10 +15,12 @@
  */
 package im.vector.matrix.android.internal.session.room.relation
 
+import android.content.Context
 import androidx.lifecycle.LiveData
 import androidx.work.OneTimeWorkRequest
 import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.api.MatrixCallback
+import im.vector.matrix.android.api.auth.data.Credentials
 import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
 import im.vector.matrix.android.api.session.room.model.message.MessageType
@@ -38,11 +40,14 @@ import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEvent
 import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
 import im.vector.matrix.android.internal.util.CancelableWork
-import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import im.vector.matrix.android.internal.util.tryTransactionAsync
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import timber.log.Timber
+import javax.inject.Inject
 
-internal class DefaultRelationService constructor(private val roomId: String,
+internal class DefaultRelationService @Inject constructor(private val context: Context,
+                                                          private val credentials: Credentials,
+                                                          private val roomId: String,
                                                           private val eventFactory: LocalEchoEventFactory,
                                                           private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
                                                           private val updateQuickReactionTask: UpdateQuickReactionTask,
@@ -57,14 +62,13 @@ internal class DefaultRelationService constructor(private val roomId: String,
                     saveLocalEcho(it)
                 }
         val sendRelationWork = createSendRelationWork(event)
-        TimelineSendEventWorkCommon.postWork(roomId, sendRelationWork)
-        return CancelableWork(sendRelationWork.id)
+        TimelineSendEventWorkCommon.postWork(context, roomId, sendRelationWork)
+        return CancelableWork(context, sendRelationWork.id)
     }
 
 
     private fun createSendRelationWork(event: Event): OneTimeWorkRequest {
-        val sendContentWorkerParams = SendEventWorker.Params(
-                roomId, event)
+        val sendContentWorkerParams = SendEventWorker.Params(credentials.userId,roomId, event)
         val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
 
         return TimelineSendEventWorkCommon.createWork(sendWorkData)
@@ -94,7 +98,7 @@ internal class DefaultRelationService constructor(private val roomId: String,
                             }
                             val redactWork = createRedactEventWork(redactEvent, toRedact, null)
 
-                            TimelineSendEventWorkCommon.postWork(roomId, redactWork)
+                            TimelineSendEventWorkCommon.postWork(context, roomId, redactWork)
 
                         }
                     }
@@ -123,7 +127,7 @@ internal class DefaultRelationService constructor(private val roomId: String,
                                 saveLocalEcho(it)
                             }
                             val redactWork = createRedactEventWork(redactEvent, it, null)
-                            TimelineSendEventWorkCommon.postWork(roomId, redactWork)
+                            TimelineSendEventWorkCommon.postWork(context, roomId, redactWork)
                         }
                     }
                 })
@@ -137,7 +141,7 @@ internal class DefaultRelationService constructor(private val roomId: String,
     //TODO duplicate with send service?
     private fun createRedactEventWork(localEvent: Event, eventId: String, reason: String?): OneTimeWorkRequest {
 
-        val sendContentWorkerParams = RedactEventWorker.Params(localEvent.eventId!!,
+        val sendContentWorkerParams = RedactEventWorker.Params(credentials.userId ,localEvent.eventId!!,
                                                                roomId, eventId, reason)
         val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
         return TimelineSendEventWorkCommon.createWork(redactWorkData)
@@ -147,14 +151,14 @@ internal class DefaultRelationService constructor(private val roomId: String,
         val event = eventFactory.createReplaceTextEvent(roomId, targetEventId, newBodyText, newBodyAutoMarkdown, MessageType.MSGTYPE_TEXT, compatibilityBodyText).also {
             saveLocalEcho(it)
         }
-        val sendContentWorkerParams = SendEventWorker.Params(roomId, event)
+        val sendContentWorkerParams = SendEventWorker.Params(credentials.userId ,roomId, event)
         val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
 
         //TODO use relation API?
 
         val workRequest = TimelineSendEventWorkCommon.createWork(sendWorkData)
-        TimelineSendEventWorkCommon.postWork(roomId, workRequest)
-        return CancelableWork(workRequest.id)
+        TimelineSendEventWorkCommon.postWork(context, roomId, workRequest)
+        return CancelableWork(context, workRequest.id)
 
     }
 
@@ -163,13 +167,13 @@ internal class DefaultRelationService constructor(private val roomId: String,
         val event = eventFactory.createReplyTextEvent(roomId, eventReplied, replyText)?.also {
             saveLocalEcho(it)
         } ?: return null
-        val sendContentWorkerParams = SendEventWorker.Params(roomId, event)
+        val sendContentWorkerParams = SendEventWorker.Params(credentials.userId ,roomId, event)
         val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
 
 
         val workRequest = TimelineSendEventWorkCommon.createWork(sendWorkData)
-        TimelineSendEventWorkCommon.postWork(roomId, workRequest)
-        return CancelableWork(workRequest.id)
+        TimelineSendEventWorkCommon.postWork(context, roomId, workRequest)
+        return CancelableWork(context, workRequest.id)
     }
 
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FindReactionEventForUndoTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FindReactionEventForUndoTask.kt
index 7a7abdbe..8841819e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FindReactionEventForUndoTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/FindReactionEventForUndoTask.kt
@@ -42,7 +42,6 @@ internal interface FindReactionEventForUndoTask : Task {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
index dbd97714..b269f161 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/SendRelationWorker.kt
@@ -18,7 +18,6 @@ package im.vector.matrix.android.internal.session.room.relation
 import android.content.Context
 import androidx.work.Worker
 import androidx.work.WorkerParameters
-import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.api.failure.Failure
@@ -26,30 +25,34 @@ import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.model.relation.ReactionContent
 import im.vector.matrix.android.api.session.room.model.relation.ReactionInfo
-import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
 import im.vector.matrix.android.internal.session.room.send.SendResponse
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
+import im.vector.matrix.android.internal.worker.SessionWorkerParams
 import im.vector.matrix.android.internal.worker.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.getSessionComponent
+import javax.inject.Inject
 
-internal class SendRelationWorker @AssistedInject constructor(
-        @Assisted context: Context,
-        @Assisted params: WorkerParameters,
-        private val roomAPI: RoomAPI)
-    : Worker(context, params) {
-
+internal class SendRelationWorker(context: Context, params: WorkerParameters): Worker(context, params) {
 
     @JsonClass(generateAdapter = true)
     internal data class Params(
+            override val userId: String,
             val roomId: String,
             val event: Event,
             val relationType: String? = null
-    )
+    ): SessionWorkerParams
+
+    @Inject lateinit var roomAPI: RoomAPI
 
     override fun doWork(): Result {
         val params = WorkerParamsFactory.fromData(inputData)
                      ?: return Result.failure()
 
+        val sessionComponent = getSessionComponent(params.userId) ?: return Result.success()
+        sessionComponent.inject(this)
+
         val localEvent = params.event
         if (localEvent.eventId == null) {
             return Result.failure()
@@ -81,6 +84,4 @@ internal class SendRelationWorker @AssistedInject constructor(
                            }, { Result.success() })
     }
 
-    @AssistedInject.Factory
-    interface Factory : DelegateWorkerFactory
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/UpdateQuickReactionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/UpdateQuickReactionTask.kt
index 2169adeb..66e02ce9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/UpdateQuickReactionTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/UpdateQuickReactionTask.kt
@@ -43,7 +43,6 @@ internal interface UpdateQuickReactionTask : Task {
         return Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
index 12fee962..c5a775b7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
@@ -16,8 +16,16 @@
 
 package im.vector.matrix.android.internal.session.room.send
 
-import androidx.work.*
+import android.content.Context
+import androidx.work.BackoffPolicy
+import androidx.work.Constraints
+import androidx.work.ExistingWorkPolicy
+import androidx.work.NetworkType
+import androidx.work.OneTimeWorkRequest
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkManager
 import com.zhuinden.monarchy.Monarchy
+import im.vector.matrix.android.api.auth.data.Credentials
 import im.vector.matrix.android.api.session.content.ContentAttachmentData
 import im.vector.matrix.android.api.session.crypto.CryptoService
 import im.vector.matrix.android.api.session.events.model.Event
@@ -31,6 +39,7 @@ import im.vector.matrix.android.internal.util.CancelableWork
 import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import timber.log.Timber
 import java.util.concurrent.TimeUnit
+import javax.inject.Inject
 
 private const val UPLOAD_WORK = "UPLOAD_WORK"
 private const val BACKOFF_DELAY = 10_000L
@@ -39,10 +48,12 @@ private val WORK_CONSTRAINTS = Constraints.Builder()
         .setRequiredNetworkType(NetworkType.CONNECTED)
         .build()
 
-internal class DefaultSendService(private val roomId: String,
-                                  private val localEchoEventFactory: LocalEchoEventFactory,
-                                  private val cryptoService: CryptoService,
-                                  private val monarchy: Monarchy)
+internal class DefaultSendService @Inject constructor(private val context: Context,
+                                                      private val credentials: Credentials,
+                                                      private val roomId: String,
+                                                      private val localEchoEventFactory: LocalEchoEventFactory,
+                                                      private val cryptoService: CryptoService,
+                                                      private val monarchy: Monarchy)
     : SendService {
 
     override fun sendTextMessage(text: String, msgType: String, autoMarkdown: Boolean): Cancelable {
@@ -54,8 +65,8 @@ internal class DefaultSendService(private val roomId: String,
             Timber.v("Send event in encrypted room")
             val encryptWork = createEncryptEventWork(event)
             val sendWork = createSendEventWork(event)
-            TimelineSendEventWorkCommon.postSequentialWorks(roomId, encryptWork, sendWork)
-            CancelableWork(encryptWork.id)
+            TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, sendWork)
+            CancelableWork(context, encryptWork.id)
         } else {
             sendEvent(event)
         }
@@ -63,8 +74,8 @@ internal class DefaultSendService(private val roomId: String,
 
     private fun sendEvent(event: Event): Cancelable {
         val sendWork = createSendEventWork(event)
-        TimelineSendEventWorkCommon.postWork(roomId, sendWork)
-        return CancelableWork(sendWork.id)
+        TimelineSendEventWorkCommon.postWork(context, roomId, sendWork)
+        return CancelableWork(context, sendWork.id)
     }
 
     override fun sendFormattedTextMessage(text: String, formattedText: String): Cancelable {
@@ -72,8 +83,8 @@ internal class DefaultSendService(private val roomId: String,
             saveLocalEcho(it)
         }
         val sendWork = createSendEventWork(event)
-        TimelineSendEventWorkCommon.postWork(roomId, sendWork)
-        return CancelableWork(sendWork.id)
+        TimelineSendEventWorkCommon.postWork(context, roomId, sendWork)
+        return CancelableWork(context, sendWork.id)
     }
 
     override fun sendMedias(attachments: List): Cancelable {
@@ -87,8 +98,8 @@ internal class DefaultSendService(private val roomId: String,
     override fun redactEvent(event: Event, reason: String?): Cancelable {
         //TODO manage media/attachements?
         val redactWork = createRedactEventWork(event, reason)
-        TimelineSendEventWorkCommon.postWork(roomId, redactWork)
-        return CancelableWork(redactWork.id)
+        TimelineSendEventWorkCommon.postWork(context, roomId, redactWork)
+        return CancelableWork(context, redactWork.id)
     }
 
     override fun sendMedia(attachment: ContentAttachmentData): Cancelable {
@@ -99,12 +110,12 @@ internal class DefaultSendService(private val roomId: String,
         val uploadWork = createUploadMediaWork(event, attachment)
         val sendWork = createSendEventWork(event)
 
-        WorkManager.getInstance()
+        WorkManager.getInstance(context)
                 .beginUniqueWork(buildWorkIdentifier(UPLOAD_WORK), ExistingWorkPolicy.APPEND, uploadWork)
                 .then(sendWork)
                 .enqueue()
 
-        return CancelableWork(sendWork.id)
+        return CancelableWork(context, sendWork.id)
     }
 
     private fun saveLocalEcho(event: Event) {
@@ -117,7 +128,7 @@ internal class DefaultSendService(private val roomId: String,
 
     private fun createEncryptEventWork(event: Event): OneTimeWorkRequest {
         // Same parameter
-        val params = EncryptEventWorker.Params(roomId, event)
+        val params = EncryptEventWorker.Params(credentials.userId ,roomId, event)
         val sendWorkData = WorkerParamsFactory.toData(params)
 
         return OneTimeWorkRequestBuilder()
@@ -128,7 +139,7 @@ internal class DefaultSendService(private val roomId: String,
     }
 
     private fun createSendEventWork(event: Event): OneTimeWorkRequest {
-        val sendContentWorkerParams = SendEventWorker.Params(roomId, event)
+        val sendContentWorkerParams = SendEventWorker.Params(credentials.userId ,roomId, event)
         val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
 
         return TimelineSendEventWorkCommon.createWork(sendWorkData)
@@ -138,13 +149,13 @@ internal class DefaultSendService(private val roomId: String,
         val redactEvent = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason).also {
             saveLocalEcho(it)
         }
-        val sendContentWorkerParams = RedactEventWorker.Params(redactEvent.eventId!!, roomId, event.eventId, reason)
+        val sendContentWorkerParams = RedactEventWorker.Params(credentials.userId ,redactEvent.eventId!!, roomId, event.eventId, reason)
         val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
         return TimelineSendEventWorkCommon.createWork(redactWorkData)
     }
 
     private fun createUploadMediaWork(event: Event, attachment: ContentAttachmentData): OneTimeWorkRequest {
-        val uploadMediaWorkerParams = UploadContentWorker.Params(roomId, event, attachment)
+        val uploadMediaWorkerParams = UploadContentWorker.Params(credentials.userId ,roomId, event, attachment)
         val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)
 
         return OneTimeWorkRequestBuilder()
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
index 256f3d16..4e6537b7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EncryptEventWorker.kt
@@ -30,27 +30,32 @@ import im.vector.matrix.android.api.session.room.send.SendState
 import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
 import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
+import im.vector.matrix.android.internal.worker.SessionWorkerParams
+import im.vector.matrix.android.internal.worker.getSessionComponent
 import java.util.concurrent.CountDownLatch
+import javax.inject.Inject
 
-internal class EncryptEventWorker @AssistedInject constructor(
-        @Assisted context: Context,
-        @Assisted params: WorkerParameters,
-        private val crypto: CryptoService,
-        private val localEchoUpdater: LocalEchoUpdater)
+internal class EncryptEventWorker(context: Context, params: WorkerParameters)
     : Worker(context, params) {
 
-
     @JsonClass(generateAdapter = true)
     internal data class Params(
+            override val userId: String,
             val roomId: String,
             val event: Event
-    )
+    ): SessionWorkerParams
+
+    @Inject  lateinit var crypto: CryptoService
+    @Inject lateinit var localEchoUpdater: LocalEchoUpdater
 
     override fun doWork(): Result {
 
         val params = WorkerParamsFactory.fromData(inputData)
                      ?: return Result.success()
 
+        val sessionComponent = getSessionComponent(params.userId) ?: return Result.success()
+        sessionComponent.inject(this)
+
         val localEvent = params.event
         if (localEvent.eventId == null) {
             return Result.success()
@@ -87,7 +92,7 @@ internal class EncryptEventWorker @AssistedInject constructor(
                     type = safeResult.eventType,
                     content = safeResult.eventContent
             )
-            val nextWorkerParams = SendEventWorker.Params(params.roomId, encryptedEvent)
+            val nextWorkerParams = SendEventWorker.Params(params.userId, params.roomId, encryptedEvent)
             return Result.success(WorkerParamsFactory.toData(nextWorkerParams))
         }
         val safeError = error
@@ -99,8 +104,4 @@ internal class EncryptEventWorker @AssistedInject constructor(
         //always return success, or the chain will be stuck for ever!
         return Result.success()
     }
-
-    @AssistedInject.Factory
-    interface Factory : DelegateWorkerFactory
-
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt
index 7ebab9d6..d76b730e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt
@@ -25,7 +25,6 @@ import im.vector.matrix.android.internal.di.MoshiProvider
 import im.vector.matrix.android.internal.session.SessionScope
 import javax.inject.Inject
 
-@SessionScope
 internal class EventFactory @Inject constructor(private val credentials: Credentials) {
 
     private val moshi = MoshiProvider.providesMoshi()
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt
index 585b925a..924025f3 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt
@@ -52,7 +52,6 @@ import javax.inject.Inject
  * The transactionID is used as loc
  */
 
-@SessionScope
 internal class LocalEchoEventFactory @Inject constructor(private val credentials: Credentials, private val stringProvider: StringProvider) {
 
     fun createTextEvent(roomId: String, msgType: String, text: String, autoMarkdown: Boolean): Event {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoUpdater.kt
index 689d2b48..ec063f3a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoUpdater.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoUpdater.kt
@@ -26,7 +26,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.util.tryTransactionAsync
 import javax.inject.Inject
 
-@SessionScope
 internal class LocalEchoUpdater @Inject constructor(private val monarchy: Monarchy) {
 
     fun updateSendState(eventId: String, sendState: SendState) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
index 7d45a2a6..23e1d92d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/RedactEventWorker.kt
@@ -18,33 +18,37 @@ package im.vector.matrix.android.internal.session.room.send
 import android.content.Context
 import androidx.work.Worker
 import androidx.work.WorkerParameters
-import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
-import im.vector.matrix.android.internal.worker.WorkerParamsFactory
 import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
+import im.vector.matrix.android.internal.worker.SessionWorkerParams
+import im.vector.matrix.android.internal.worker.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.getSessionComponent
+import javax.inject.Inject
 
-internal class RedactEventWorker @AssistedInject constructor(
-        @Assisted context: Context,
-        @Assisted params: WorkerParameters,
-        private val roomAPI: RoomAPI)
-    : Worker(context, params) {
+internal class RedactEventWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
 
     @JsonClass(generateAdapter = true)
     internal data class Params(
+            override val userId: String,
             val txID: String,
             val roomId: String,
             val eventId: String,
             val reason: String?
-    )
+    ) : SessionWorkerParams
+
+    @Inject lateinit var roomAPI: RoomAPI
 
     override fun doWork(): Result {
         val params = WorkerParamsFactory.fromData(inputData)
                      ?: return Result.failure()
 
+        val sessionComponent = getSessionComponent(params.userId) ?: return Result.success()
+        sessionComponent.inject(this)
+
         val eventId = params.eventId
         val result = executeRequest {
             apiCall = roomAPI.redactEvent(
@@ -55,20 +59,17 @@ internal class RedactEventWorker @AssistedInject constructor(
             )
         }
         return result.fold({
-            when (it) {
-                is Failure.NetworkConnection -> Result.retry()
-                else -> {
-                    //TODO mark as failed to send?
-                    //always return success, or the chain will be stuck for ever!
-                    Result.success()
-                }
-            }
-        }, {
-            Result.success()
-        })
+                               when (it) {
+                                   is Failure.NetworkConnection -> Result.retry()
+                                   else                         -> {
+                                       //TODO mark as failed to send?
+                                       //always return success, or the chain will be stuck for ever!
+                                       Result.success()
+                                   }
+                               }
+                           }, {
+                               Result.success()
+                           })
     }
 
-    @AssistedInject.Factory
-    interface Factory : DelegateWorkerFactory
-
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
index 6ff60da0..948eb25b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
@@ -19,36 +19,40 @@ package im.vector.matrix.android.internal.session.room.send
 import android.content.Context
 import androidx.work.Worker
 import androidx.work.WorkerParameters
-import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import com.squareup.moshi.JsonClass
+import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.room.send.SendState
-import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
+import im.vector.matrix.android.internal.worker.DelegateWorkerFactory
+import im.vector.matrix.android.internal.worker.SessionWorkerParams
 import im.vector.matrix.android.internal.worker.WorkerParamsFactory
+import im.vector.matrix.android.internal.worker.getSessionComponent
+import javax.inject.Inject
 
-internal class SendEventWorker @AssistedInject constructor(
-        @Assisted context: Context,
-        @Assisted params: WorkerParameters,
-        private val roomAPI: RoomAPI,
-        private val localEchoUpdater: LocalEchoUpdater)
+internal class SendEventWorker constructor(context: Context, params: WorkerParameters)
     : Worker(context, params) {
 
-
     @JsonClass(generateAdapter = true)
     internal data class Params(
+            override val userId: String,
             val roomId: String,
             val event: Event
-    )
+    ) : SessionWorkerParams
+
+    @Inject lateinit var localEchoUpdater: LocalEchoUpdater
+    @Inject lateinit var roomAPI: RoomAPI
 
     override fun doWork(): Result {
-
         val params = WorkerParamsFactory.fromData(inputData)
                      ?: return Result.success()
 
+        val sessionComponent = getSessionComponent(params.userId) ?: return Result.success()
+        sessionComponent.inject(this)
+
         val event = params.event
         if (event.eventId == null) {
             return Result.success()
@@ -75,7 +79,4 @@ internal class SendEventWorker @AssistedInject constructor(
                            }, { Result.success() })
     }
 
-    @AssistedInject.Factory
-    interface Factory : DelegateWorkerFactory
-
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt
index 6988b6f8..b3ae4442 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt
@@ -24,7 +24,6 @@ import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultStateService @Inject constructor(private val roomId: String,
                                    private val taskExecutor: TaskExecutor,
                                    private val sendStateTask: SendStateTask) : StateService {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt
index 45e714e1..085340e6 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt
@@ -31,7 +31,6 @@ internal interface SendStateTask : Task {
     )
 }
 
-@SessionScope
 internal class DefaultSendStateTask @Inject constructor(private val roomAPI: RoomAPI) : SendStateTask {
     override suspend fun execute(params: SendStateTask.Params): Try {
         return executeRequest {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt
index 49c69a00..a47bab62 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt
@@ -33,7 +33,6 @@ internal interface GetContextOfEventTask : Task?): Timeline {
@@ -38,11 +39,12 @@ internal class DefaultTimelineService(private val roomId: String,
     }
 
     override fun getTimeLineEvent(eventId: String): TimelineEvent? {
-        return monarchy.fetchCopyMap({
-            EventEntity.where(it, eventId = eventId).findFirst()
-        }, { entity, realm ->
-            timelineEventFactory.create(entity, realm)
-        })
+        return monarchy
+                .fetchCopyMap({
+                                  EventEntity.where(it, eventId = eventId).findFirst()
+                              }, { entity, realm ->
+                                  timelineEventFactory.create(entity, realm)
+                              })
     }
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt
index e791ba76..5ce58e02 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt
@@ -24,7 +24,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.room.RoomAPI
 import javax.inject.Inject
 
-@SessionScope
 internal class GetEventTask @Inject constructor(private val roomAPI: RoomAPI
 ) : Task {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
index b47fad21..ca2007a1 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
@@ -15,6 +15,7 @@
  */
 package im.vector.matrix.android.internal.session.room.timeline
 
+import android.content.Context
 import androidx.work.*
 import java.util.concurrent.TimeUnit
 
@@ -35,13 +36,13 @@ private val WORK_CONSTRAINTS = Constraints.Builder()
  */
 internal object TimelineSendEventWorkCommon {
 
-    fun postSequentialWorks(roomId: String, vararg workRequests: OneTimeWorkRequest) {
+    fun postSequentialWorks(context: Context, roomId: String, vararg workRequests: OneTimeWorkRequest) {
         when {
             workRequests.isEmpty() -> return
-            workRequests.size == 1 -> postWork(roomId, workRequests.first())
+            workRequests.size == 1 -> postWork(context, roomId, workRequests.first())
             else                   -> {
                 val firstWork = workRequests.first()
-                var continuation = WorkManager.getInstance()
+                var continuation = WorkManager.getInstance(context)
                         .beginUniqueWork(buildWorkIdentifier(roomId), ExistingWorkPolicy.APPEND, firstWork)
                 for (i in 1 until workRequests.size) {
                     val workRequest = workRequests[i]
@@ -52,8 +53,8 @@ internal object TimelineSendEventWorkCommon {
         }
     }
 
-    fun postWork(roomId: String, workRequest: OneTimeWorkRequest) {
-        WorkManager.getInstance()
+    fun postWork(context: Context, roomId: String, workRequest: OneTimeWorkRequest) {
+        WorkManager.getInstance(context)
                 .beginUniqueWork(buildWorkIdentifier(roomId), ExistingWorkPolicy.APPEND, workRequest)
                 .enqueue()
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt
index 3aa07b00..50881854 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt
@@ -18,14 +18,18 @@ package im.vector.matrix.android.internal.session.room.timeline
 
 import arrow.core.Try
 import com.zhuinden.monarchy.Monarchy
-import im.vector.matrix.android.internal.database.helper.*
+import im.vector.matrix.android.internal.database.helper.addAll
+import im.vector.matrix.android.internal.database.helper.addOrUpdate
+import im.vector.matrix.android.internal.database.helper.addStateEvents
+import im.vector.matrix.android.internal.database.helper.deleteOnCascade
+import im.vector.matrix.android.internal.database.helper.isUnlinked
+import im.vector.matrix.android.internal.database.helper.merge
 import im.vector.matrix.android.internal.database.model.ChunkEntity
 import im.vector.matrix.android.internal.database.model.RoomEntity
 import im.vector.matrix.android.internal.database.query.create
 import im.vector.matrix.android.internal.database.query.find
 import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
 import im.vector.matrix.android.internal.database.query.where
-import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.util.tryTransactionSync
 import io.realm.kotlin.createObject
 import timber.log.Timber
@@ -34,7 +38,6 @@ import javax.inject.Inject
 /**
  * Insert Chunk in DB, and eventually merge with existing chunk event
  */
-@SessionScope
 internal class TokenChunkEventPersistor @Inject constructor(private val monarchy: Monarchy) {
 
     /**
@@ -114,7 +117,7 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
                     Timber.v("Start persisting ${receivedChunk.events.size} events in $roomId towards $direction")
 
                     val roomEntity = RoomEntity.where(realm, roomId).findFirst()
-                            ?: realm.createObject(roomId)
+                                     ?: realm.createObject(roomId)
 
                     val nextToken: String?
                     val prevToken: String?
@@ -137,7 +140,7 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
                     } else {
                         nextChunk?.apply { this.prevToken = prevToken }
                     }
-                            ?: ChunkEntity.create(realm, prevToken, nextToken)
+                                       ?: ChunkEntity.create(realm, prevToken, nextToken)
 
                     if (receivedChunk.events.isEmpty() && receivedChunk.end == receivedChunk.start) {
                         Timber.v("Reach end of $roomId")
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
index 3589df3d..2b240ff9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
@@ -23,7 +23,6 @@ import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultSignOutService @Inject constructor(private val signOutTask: SignOutTask,
                                                          private val taskExecutor: TaskExecutor) : SignOutService {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
index 63df5a03..b4863090 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutModule.kt
@@ -30,20 +30,18 @@ internal abstract class SignOutModule {
 
     @Module
     companion object {
-        @SessionScope
         @Provides
         @JvmStatic
+        @SessionScope
         fun providesSignOutAPI(retrofit: Retrofit): SignOutAPI {
             return retrofit.create(SignOutAPI::class.java)
         }
     }
 
     @Binds
-    @SessionScope
     abstract fun bindSignOutTask(signOutTask: DefaultSignOutTask): SignOutTask
 
     @Binds
-    @SessionScope
     abstract fun bindSignOutService(signOutService: DefaultSignOutService): SignOutService
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
index ab34e0f8..b627ebd6 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
@@ -25,7 +25,6 @@ import javax.inject.Inject
 
 internal interface SignOutTask : Task
 
-@SessionScope
 internal class DefaultSignOutTask @Inject constructor(private val signOutAPI: SignOutAPI,
                                                       private val sessionParamsStore: SessionParamsStore) : SignOutTask {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt
index 5930d861..8992091b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt
@@ -32,7 +32,6 @@ import timber.log.Timber
 import javax.inject.Inject
 
 
-@SessionScope
 internal class CryptoSyncHandler @Inject constructor(private val cryptoManager: CryptoManager,
                                                      private val sasVerificationService: DefaultSasVerificationService) {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt
index 7c9248c9..d7b8328c 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt
@@ -26,7 +26,6 @@ import im.vector.matrix.android.internal.session.sync.model.InvitedGroupSync
 import io.realm.Realm
 import javax.inject.Inject
 
-@SessionScope
 internal class GroupSyncHandler @Inject constructor(private val monarchy: Monarchy) {
 
     sealed class HandlingStrategy {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
index fafc75f0..930f20f2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/ReadReceiptHandler.kt
@@ -30,7 +30,6 @@ import javax.inject.Inject
 //                    dict value ts value
 typealias ReadReceiptContent = Map>>>
 
-@SessionScope
 internal class ReadReceiptHandler @Inject constructor() {
 
     fun handle(realm: Realm, roomId: String, content: ReadReceiptContent?) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
index f8fb285d..4c80fbcc 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
@@ -32,16 +32,18 @@ import im.vector.matrix.android.internal.database.model.RoomEntity
 import im.vector.matrix.android.internal.database.query.find
 import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
 import im.vector.matrix.android.internal.database.query.where
-import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
 import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
-import im.vector.matrix.android.internal.session.sync.model.*
+import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
+import im.vector.matrix.android.internal.session.sync.model.RoomSync
+import im.vector.matrix.android.internal.session.sync.model.RoomSyncAccountData
+import im.vector.matrix.android.internal.session.sync.model.RoomSyncEphemeral
+import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse
 import io.realm.Realm
 import io.realm.kotlin.createObject
 import timber.log.Timber
 import javax.inject.Inject
 
-@SessionScope
 internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarchy,
                                                    private val readReceiptHandler: ReadReceiptHandler,
                                                    private val roomSummaryUpdater: RoomSummaryUpdater,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomTagHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomTagHandler.kt
index 9bec48dd..49038eed 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomTagHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomTagHandler.kt
@@ -25,7 +25,6 @@ import io.realm.Realm
 import java.util.*
 import javax.inject.Inject
 
-@SessionScope
 internal class RoomTagHandler @Inject constructor() {
 
     fun handle(realm: Realm, roomId: String, content: RoomTagContent?) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
index cd8b7605..3d84d63e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
@@ -29,9 +29,9 @@ internal abstract class SyncModule {
 
     @Module
     companion object {
-        @SessionScope
         @Provides
         @JvmStatic
+        @SessionScope
         fun providesSyncAPI(retrofit: Retrofit): SyncAPI {
             return retrofit.create(SyncAPI::class.java)
         }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt
index 174f2de9..593bb924 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt
@@ -24,7 +24,6 @@ import timber.log.Timber
 import javax.inject.Inject
 import kotlin.system.measureTimeMillis
 
-@SessionScope
 internal class SyncResponseHandler @Inject constructor(private val roomSyncHandler: RoomSyncHandler,
                                                        private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
                                                        private val groupSyncHandler: GroupSyncHandler,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
index 920fb389..6acd82c9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
@@ -35,7 +35,6 @@ internal interface SyncTask : Task {
 
 }
 
-@SessionScope
 internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
                                                    private val filterRepository: FilterRepository,
                                                    private val syncResponseHandler: SyncResponseHandler,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
index 17ca1680..8823f2e3 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt
@@ -16,14 +16,12 @@
 
 package im.vector.matrix.android.internal.session.sync
 
-import im.vector.matrix.android.internal.di.SessionDatabase
 import im.vector.matrix.android.internal.database.model.SyncEntity
-import im.vector.matrix.android.internal.session.SessionScope
+import im.vector.matrix.android.internal.di.SessionDatabase
 import io.realm.Realm
 import io.realm.RealmConfiguration
 import javax.inject.Inject
 
-@SessionScope
 internal class SyncTokenStore @Inject constructor(@SessionDatabase private val realmConfiguration: RealmConfiguration) {
 
     fun getLastToken(): String? {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt
index db377599..52f66fa4 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt
@@ -25,7 +25,6 @@ import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirec
 import im.vector.matrix.android.internal.session.sync.model.UserAccountDataSync
 import javax.inject.Inject
 
-@SessionScope
 internal class UserAccountDataSyncHandler @Inject constructor(private val monarchy: Monarchy) {
 
     fun handle(accountData: UserAccountDataSync) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt
index db79d392..8825c4f4 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt
@@ -40,7 +40,6 @@ import javax.inject.Inject
 
 private const val RETRY_WAIT_TIME_MS = 10_000L
 
-@SessionScope
 internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
                                               private val networkConnectivityChecker: NetworkConnectivityChecker,
                                               private val syncTokenStore: SyncTokenStore,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt
index 4f79a9f1..cb1bcdce 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt
@@ -31,7 +31,6 @@ import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.util.fetchCopied
 import javax.inject.Inject
 
-@SessionScope
 internal class DefaultUserService @Inject constructor(private val monarchy: Monarchy) : UserService {
 
     override fun getUser(userId: String): User? {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt
index b653e48f..eb331e41 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt
@@ -35,7 +35,6 @@ internal interface UpdateUserTask : Task {
 
 }
 
-@SessionScope
 internal class DefaultUpdateUserTask @Inject constructor(private val monarchy: Monarchy) : UpdateUserTask {
 
     override suspend fun execute(params: UpdateUserTask.Params): Try {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt
index 40998d04..df9dc277 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt
@@ -31,7 +31,6 @@ import im.vector.matrix.android.internal.task.configureWith
 import io.realm.Sort
 import javax.inject.Inject
 
-@SessionScope
 internal class UserEntityUpdater @Inject constructor(monarchy: Monarchy,
                                                      private val updateUserTask: UpdateUserTask,
                                                      private val taskExecutor: TaskExecutor)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt
index 00714c77..b3af7e45 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserModule.kt
@@ -21,17 +21,14 @@ package im.vector.matrix.android.internal.session.user
 import dagger.Binds
 import dagger.Module
 import im.vector.matrix.android.api.session.user.UserService
-import im.vector.matrix.android.internal.session.SessionScope
 
 @Module
 internal abstract class UserModule {
 
     @Binds
-    @SessionScope
     abstract fun bindUserService(userService: DefaultUserService): UserService
 
     @Binds
-    @SessionScope
     abstract fun bindUpdateUserTask(updateUserTask: DefaultUpdateUserTask): UpdateUserTask
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
index 944b62ee..cfab8ef4 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt
@@ -30,7 +30,6 @@ import timber.log.Timber
 import javax.inject.Inject
 import kotlin.coroutines.EmptyCoroutineContext
 
-@MatrixScope
 internal class TaskExecutor @Inject constructor(private val coroutineDispatchers: MatrixCoroutineDispatchers) {
 
     fun  execute(task: ConfigurableTask): Cancelable {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CancelableWork.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CancelableWork.kt
index f144ed5c..ebd20ec6 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CancelableWork.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CancelableWork.kt
@@ -16,14 +16,16 @@
 
 package im.vector.matrix.android.internal.util
 
+import android.content.Context
 import androidx.work.WorkManager
 import im.vector.matrix.android.api.util.Cancelable
 import java.util.*
 
-internal class CancelableWork(private val workId: UUID) : Cancelable {
+internal class CancelableWork(private val context: Context,
+                              private val workId: UUID) : Cancelable {
 
     override fun cancel() {
-        WorkManager.getInstance().cancelWorkById(workId)
+        WorkManager.getInstance(context).cancelWorkById(workId)
     }
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/SessionWorkerParams.kt
similarity index 71%
rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedModule.kt
rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/SessionWorkerParams.kt
index ce1804cb..874254cc 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixAssistedModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/SessionWorkerParams.kt
@@ -14,11 +14,8 @@
  * limitations under the License.
  */
 
-package im.vector.matrix.android.internal.di
+package im.vector.matrix.android.internal.worker
 
-import com.squareup.inject.assisted.dagger2.AssistedModule
-import dagger.Module
-
-@Module(includes = [AssistedInject_MatrixAssistedModule::class])
-@AssistedModule
-internal class MatrixAssistedModule
\ No newline at end of file
+interface SessionWorkerParams {
+    val userId: String
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Worker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Worker.kt
new file mode 100644
index 00000000..4a4b5e3b
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Worker.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.matrix.android.internal.worker
+
+import androidx.work.ListenableWorker
+import im.vector.matrix.android.api.Matrix
+import im.vector.matrix.android.internal.session.SessionComponent
+
+internal fun ListenableWorker.getSessionComponent(userId: String): SessionComponent? {
+    return Matrix.getInstance(applicationContext).sessionManager.getSessionComponent(userId)
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerBindingModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerBindingModule.kt
deleted file mode 100644
index 20e75a8d..00000000
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerBindingModule.kt
+++ /dev/null
@@ -1,64 +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.matrix.android.internal.worker
-
-import dagger.Binds
-import dagger.Module
-import dagger.multibindings.IntoMap
-import im.vector.matrix.android.internal.session.content.UploadContentWorker
-import im.vector.matrix.android.internal.session.group.GetGroupDataWorker
-import im.vector.matrix.android.internal.session.room.relation.SendRelationWorker
-import im.vector.matrix.android.internal.session.room.send.EncryptEventWorker
-import im.vector.matrix.android.internal.session.room.send.RedactEventWorker
-import im.vector.matrix.android.internal.session.room.send.SendEventWorker
-
-
-@Module
-internal interface WorkerBindingModule {
-
-    @Binds
-    @IntoMap
-    @WorkerKey(SendEventWorker::class)
-    fun bindSendEventWorker(factory: SendEventWorker.Factory): DelegateWorkerFactory
-
-    @Binds
-    @IntoMap
-    @WorkerKey(SendRelationWorker::class)
-    fun bindSendRelationWorker(factory: SendRelationWorker.Factory): DelegateWorkerFactory
-
-    @Binds
-    @IntoMap
-    @WorkerKey(EncryptEventWorker::class)
-    fun bindEncryptEventWorker(factory: EncryptEventWorker.Factory): DelegateWorkerFactory
-
-    @Binds
-    @IntoMap
-    @WorkerKey(RedactEventWorker::class)
-    fun bindRedactEventWorker(factory: RedactEventWorker.Factory): DelegateWorkerFactory
-
-    @Binds
-    @IntoMap
-    @WorkerKey(GetGroupDataWorker::class)
-    fun bindGetGroupDataWorker(factory: GetGroupDataWorker.Factory): DelegateWorkerFactory
-
-    @Binds
-    @IntoMap
-    @WorkerKey(UploadContentWorker::class)
-    fun bindUploadContentWorker(factory: UploadContentWorker.Factory): DelegateWorkerFactory
-}
\ No newline at end of file
diff --git a/vector/build.gradle b/vector/build.gradle
index 3754ceee..2d773481 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -173,7 +173,7 @@ dependencies {
     implementation 'com.airbnb.android:mvrx:1.0.1'
 
     // Work
-    implementation "android.arch.work:work-runtime-ktx:1.0.0"
+    implementation "androidx.work:work-runtime-ktx:2.1.0-beta01"
 
     // FP
     implementation "io.arrow-kt:arrow-core:$arrow_version"
diff --git a/vector/src/gplay/java/im/vector/riotredesign/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/gplay/java/im/vector/riotredesign/push/fcm/VectorFirebaseMessagingService.kt
index 47d4c1b1..1387e865 100755
--- a/vector/src/gplay/java/im/vector/riotredesign/push/fcm/VectorFirebaseMessagingService.kt
+++ b/vector/src/gplay/java/im/vector/riotredesign/push/fcm/VectorFirebaseMessagingService.kt
@@ -34,7 +34,6 @@ import im.vector.riotredesign.features.notifications.NotifiableEventResolver
 import im.vector.riotredesign.features.notifications.NotifiableMessageEvent
 import im.vector.riotredesign.features.notifications.NotificationDrawerManager
 import im.vector.riotredesign.features.notifications.SimpleNotifiableEvent
-import org.koin.android.ext.android.inject
 import timber.log.Timber
 
 /**
@@ -42,7 +41,7 @@ import timber.log.Timber
  */
 class VectorFirebaseMessagingService : FirebaseMessagingService() {
 
-    val notificationDrawerManager by inject()
+    @Inject lateinit var notificationDrawerManager: NotificationDrawerManager
 
     private val notifiableEventResolver by lazy {
         NotifiableEventResolver(this)
diff --git a/vector/src/main/java/im/vector/riotredesign/EmojiCompatFontProvider.kt b/vector/src/main/java/im/vector/riotredesign/EmojiCompatFontProvider.kt
index c7fc7a95..6647cbea 100644
--- a/vector/src/main/java/im/vector/riotredesign/EmojiCompatFontProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/EmojiCompatFontProvider.kt
@@ -4,7 +4,9 @@ import android.graphics.Typeface
 import androidx.core.provider.FontsContractCompat
 import timber.log.Timber
 import javax.inject.Inject
+import javax.inject.Singleton
 
+@Singleton
 class EmojiCompatFontProvider @Inject constructor(): FontsContractCompat.FontRequestCallback() {
 
     var typeface: Typeface? = null
diff --git a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
index f740bec0..b2ce3c8a 100644
--- a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
+++ b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
@@ -31,6 +31,7 @@ import com.github.piasy.biv.BigImageViewer
 import com.github.piasy.biv.loader.glide.GlideImageLoader
 import com.jakewharton.threetenabp.AndroidThreeTen
 import im.vector.matrix.android.api.Matrix
+import im.vector.matrix.android.api.MatrixConfiguration
 import im.vector.riotredesign.core.di.DaggerVectorComponent
 import im.vector.riotredesign.core.di.HasInjector
 import im.vector.riotredesign.core.di.VectorComponent
@@ -42,7 +43,7 @@ import timber.log.Timber
 import javax.inject.Inject
 
 
-class VectorApplication : Application(), HasInjector {
+class VectorApplication : Application(), HasInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider {
 
     lateinit var appContext: Context
     //font thread handler
@@ -67,8 +68,6 @@ class VectorApplication : Application(), HasInjector {
         BigImageViewer.initialize(GlideImageLoader.with(applicationContext))
         EpoxyController.defaultDiffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
         EpoxyController.defaultModelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
-
-        Matrix.getInstance().setApplicationFlavor(BuildConfig.FLAVOR_DESCRIPTION)
         registerActivityLifecycleCallbacks(VectorActivityLifecycleCallbacks())
         val fontRequest = FontRequest(
                 "com.google.android.gms.fonts",
@@ -80,6 +79,10 @@ class VectorApplication : Application(), HasInjector {
         vectorConfiguration.initConfiguration()
     }
 
+    override fun providesMatrixConfiguration() = MatrixConfiguration(BuildConfig.FLAVOR_DESCRIPTION)
+
+    override fun getWorkManagerConfiguration() = androidx.work.Configuration.Builder().build()
+
     override fun injector(): VectorComponent {
         return vectorComponent
     }
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
index 46320f4e..1c28b8ef 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
@@ -22,6 +22,7 @@ import dagger.BindsInstance
 import dagger.Component
 import im.vector.fragments.keysbackup.restore.KeysBackupRestoreFromPassphraseFragment
 import im.vector.riotredesign.core.platform.SimpleFragmentActivity
+import im.vector.riotredesign.features.MainActivity
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromKeyFragment
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreSuccessFragment
 import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupSettingsFragment
@@ -40,6 +41,7 @@ import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageM
 import im.vector.riotredesign.features.home.room.detail.timeline.action.QuickReactionFragment
 import im.vector.riotredesign.features.home.room.detail.timeline.action.ViewReactionBottomSheet
 import im.vector.riotredesign.features.home.room.list.RoomListFragment
+import im.vector.riotredesign.features.login.LoginActivity
 import im.vector.riotredesign.features.reactions.EmojiReactionPickerActivity
 import im.vector.riotredesign.features.roomdirectory.PublicRoomsFragment
 import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomFragment
@@ -66,7 +68,7 @@ interface ScreenComponent {
     fun inject(roomDirectoryPickerFragment: RoomDirectoryPickerFragment)
 
     fun inject(roomPreviewNoPreviewFragment: RoomPreviewNoPreviewFragment)
-    
+
     fun inject(keysBackupSettingsFragment: KeysBackupSettingsFragment)
 
     fun inject(homeDrawerFragment: HomeDrawerFragment)
@@ -103,6 +105,10 @@ interface ScreenComponent {
 
     fun inject(emojiReactionPickerActivity: EmojiReactionPickerActivity)
 
+    fun inject(loginActivity: LoginActivity)
+
+    fun inject(mainActivity: MainActivity)
+
 
     @Component.Factory
     interface Factory {
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
index 100716f6..3e21cbac 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
@@ -21,7 +21,9 @@ import android.content.res.Resources
 import dagger.BindsInstance
 import dagger.Component
 import im.vector.matrix.android.api.Matrix
+import im.vector.matrix.android.api.auth.Authenticator
 import im.vector.matrix.android.api.session.Session
+import im.vector.riotredesign.EmojiCompatFontProvider
 import im.vector.riotredesign.VectorApplication
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.crypto.keysrequest.KeyRequestHandler
@@ -49,6 +51,8 @@ interface VectorComponent {
 
     fun vectorConfiguration(): VectorConfiguration
 
+    fun emojiCompatFontProvider(): EmojiCompatFontProvider
+
     fun navigator(): Navigator
 
     fun homeNavigator(): HomeNavigator
@@ -63,6 +67,8 @@ interface VectorComponent {
 
     fun inject(vectorApplication: VectorApplication)
 
+    fun authenticator(): Authenticator
+
     @Component.Factory
     interface Factory {
         fun create(@BindsInstance context: Context): VectorComponent
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
index 4b4f4467..ec8db244 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
@@ -24,6 +24,7 @@ import dagger.Binds
 import dagger.Module
 import dagger.Provides
 import im.vector.matrix.android.api.Matrix
+import im.vector.matrix.android.api.auth.Authenticator
 import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.features.navigation.DefaultNavigator
 import im.vector.riotredesign.features.navigation.Navigator
@@ -48,8 +49,8 @@ abstract class VectorModule {
 
         @Provides
         @JvmStatic
-        fun providesMatrix(): Matrix {
-            return Matrix.getInstance()
+        fun providesMatrix(context: Context): Matrix {
+            return Matrix.getInstance(context)
         }
 
         @Provides
@@ -58,6 +59,12 @@ abstract class VectorModule {
             //TODO: handle session injection better
             return matrix.currentSession!!
         }
+
+        @Provides
+        @JvmStatic
+        fun providesAuthenticator(matrix: Matrix): Authenticator{
+            return matrix.authenticator()
+        }
     }
 
     @Binds
diff --git a/vector/src/main/java/im/vector/riotredesign/features/MainActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/MainActivity.kt
index 2cc31dff..a87753e6 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/MainActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/MainActivity.kt
@@ -21,10 +21,13 @@ import android.content.Intent
 import android.os.Bundle
 import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.MatrixCallback
+import im.vector.matrix.android.api.auth.Authenticator
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import im.vector.riotredesign.features.home.HomeActivity
 import im.vector.riotredesign.features.login.LoginActivity
 import timber.log.Timber
+import javax.inject.Inject
 
 
 class MainActivity : VectorBaseActivity() {
@@ -44,16 +47,18 @@ class MainActivity : VectorBaseActivity() {
         }
     }
 
-    private val authenticator = Matrix.getInstance().authenticator()
+    @Inject lateinit var matrix: Matrix
+    @Inject lateinit var authenticator: Authenticator
+
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-
-        val session = Matrix.getInstance().currentSession
-
         val clearCache = intent.getBooleanExtra(EXTRA_CLEAR_CACHE, false)
         val clearCredentials = intent.getBooleanExtra(EXTRA_CLEAR_CREDENTIALS, false)
-
+        val session = matrix.currentSession
         if (session == null) {
             start()
         } else {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/IncomingVerificationRequestHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/IncomingVerificationRequestHandler.kt
index f670a599..6349534f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/IncomingVerificationRequestHandler.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/IncomingVerificationRequestHandler.kt
@@ -44,7 +44,7 @@ class IncomingVerificationRequestHandler @Inject constructor(val context: Contex
         when (tx.state) {
             SasVerificationTxState.OnStarted -> {
                 //Add a notification for every incoming request
-                val session = Matrix.getInstance().currentSession!!
+                val session = Matrix.getInstance(context).currentSession!!
                 val name = session.getUser(tx.otherUserId)?.displayName
                            ?: tx.otherUserId
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/AvatarRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/home/AvatarRenderer.kt
index 84d61fe6..451a49c2 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/AvatarRenderer.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/AvatarRenderer.kt
@@ -20,7 +20,6 @@ import android.content.Context
 import android.graphics.drawable.Drawable
 import android.widget.ImageView
 import androidx.annotation.AnyThread
-import androidx.annotation.ColorRes
 import androidx.annotation.UiThread
 import androidx.core.content.ContextCompat
 import com.amulyakhare.textdrawable.TextDrawable
@@ -79,7 +78,7 @@ object AvatarRenderer {
             name
         }
         val placeholder = getPlaceholderDrawable(context, identifier, displayName)
-        buildGlideRequest(glideRequest, avatarUrl)
+        buildGlideRequest(context, glideRequest, avatarUrl)
                 .placeholder(placeholder)
                 .into(target)
     }
@@ -116,8 +115,8 @@ object AvatarRenderer {
 //        return AVATAR_COLOR_LIST[colorIndex.toInt()]
 //    }
 
-    private fun buildGlideRequest(glideRequest: GlideRequests, avatarUrl: String?): GlideRequest {
-        val resolvedUrl = Matrix.getInstance().currentSession!!.contentUrlResolver()
+    private fun buildGlideRequest(context: Context, glideRequest: GlideRequests, avatarUrl: String?): GlideRequest {
+        val resolvedUrl = Matrix.getInstance(context).currentSession!!.contentUrlResolver()
                 .resolveThumbnail(avatarUrl, THUMBNAIL_SIZE, THUMBNAIL_SIZE, ContentUrlResolver.ThumbnailMethod.SCALE)
 
         return glideRequest
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
index 497d108b..d0e05f87 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
@@ -140,7 +140,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
         when (item.itemId) {
             R.id.sliding_menu_sign_out -> {
-                SignOutUiWorker(this).perform(Matrix.getInstance().currentSession!!)
+                SignOutUiWorker(this).perform(Matrix.getInstance(this).currentSession!!)
                 return true
             }
         }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt
index f78efbff..cf678897 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt
@@ -78,6 +78,11 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
             val fragment: RoomDetailFragment = (viewModelContext as FragmentViewModelContext).fragment()
             return fragment.roomDetailViewModelFactory.create(state)
         }
+
+        override fun initialState(viewModelContext: ViewModelContext): RoomDetailViewState? {
+
+            return super.initialState(viewModelContext)
+        }
     }
 
     init {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
index 8d395668..93b567b1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
@@ -36,7 +36,7 @@ object ContentUploadStateTrackerBinder {
              mediaData: ImageContentRenderer.Data,
              progressLayout: ViewGroup) {
 
-        Matrix.getInstance().currentSession?.also { session ->
+        Matrix.getInstance(progressLayout.context).currentSession?.also { session ->
             val uploadStateTracker = session.contentUploadProgressTracker()
             val updateListener = ContentMediaProgressUpdater(progressLayout, mediaData)
             updateListeners[eventId] = updateListener
@@ -44,8 +44,8 @@ object ContentUploadStateTrackerBinder {
         }
     }
 
-    fun unbind(eventId: String) {
-        Matrix.getInstance().currentSession?.also { session ->
+    fun unbind(eventId: String, progressLayout: ViewGroup) {
+        Matrix.getInstance(progressLayout.context).currentSession?.also { session ->
             val uploadStateTracker = session.contentUploadProgressTracker()
             updateListeners[eventId]?.also {
                 uploadStateTracker.untrack(eventId, it)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt
index 4f509798..6d985ae6 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt
@@ -17,8 +17,10 @@
 package im.vector.riotredesign.features.home.room.detail.timeline.helper
 
 import androidx.recyclerview.widget.RecyclerView
+import im.vector.riotredesign.core.di.ScreenScope
 import javax.inject.Inject
 
+@ScreenScope
 class TimelineMediaSizeProvider @Inject constructor() {
 
     lateinit var recyclerView: RecyclerView
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
index b1c884fd..25eb8bca 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
@@ -50,7 +50,7 @@ abstract class MessageImageVideoItem : AbsMessageItem {
             override fun onSuccess(data: Session) {
-                Matrix.getInstance().currentSession = data
+                Matrix.getInstance(this@LoginActivity).currentSession = data
                 data.open()
                 data.setFilter(FilterService.FilterPreset.RiotFilter)
                 data.startSync()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/media/ImageContentRenderer.kt
index fcd7cab1..e02536a0 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/media/ImageContentRenderer.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/media/ImageContentRenderer.kt
@@ -57,7 +57,7 @@ object ImageContentRenderer {
         val (width, height) = processSize(data, mode)
         imageView.layoutParams.height = height
         imageView.layoutParams.width = width
-        val contentUrlResolver = Matrix.getInstance().currentSession!!.contentUrlResolver()
+        val contentUrlResolver = Matrix.getInstance(imageView.context).currentSession!!.contentUrlResolver()
         val resolvedUrl = when (mode) {
                               Mode.FULL_SIZE -> contentUrlResolver.resolveFullSize(data.url)
                               Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE)
@@ -76,7 +76,7 @@ object ImageContentRenderer {
 
     fun render(data: Data, imageView: BigImageView) {
         val (width, height) = processSize(data, Mode.THUMBNAIL)
-        val contentUrlResolver = Matrix.getInstance().currentSession!!.contentUrlResolver()
+        val contentUrlResolver = Matrix.getInstance(imageView.context).currentSession!!.contentUrlResolver()
         val fullSize = contentUrlResolver.resolveFullSize(data.url)
         val thumbnail = contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE)
         imageView.showImage(
diff --git a/vector/src/main/java/im/vector/riotredesign/features/media/VideoContentRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/media/VideoContentRenderer.kt
index 577b6570..54a91ed5 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/media/VideoContentRenderer.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/media/VideoContentRenderer.kt
@@ -32,7 +32,7 @@ object VideoContentRenderer {
     ) : Parcelable
 
     fun render(data: Data, thumbnailView: ImageView, videoView: VideoView) {
-        val contentUrlResolver = Matrix.getInstance().currentSession!!.contentUrlResolver()
+        val contentUrlResolver = Matrix.getInstance(videoView.context).currentSession!!.contentUrlResolver()
         val resolvedUrl = contentUrlResolver.resolveFullSize(data.videoUrl)
         videoView.setVideoPath(resolvedUrl)
         videoView.start()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReporter.kt
index f755f433..59bf5c0a 100755
--- a/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReporter.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReporter.kt
@@ -195,7 +195,7 @@ object BugReporter {
                 var matrixSdkVersion = "undefined"
                 var olmVersion = "undefined"
 
-                Matrix.getInstance().currentSession?.let { session ->
+                Matrix.getInstance(context).currentSession?.let { session ->
                     userId = session.sessionParams.credentials.userId
                     deviceId = session.sessionParams.credentials.deviceId ?: "undefined"
                     // TODO matrixSdkVersion = session.getVersion(true);
@@ -207,7 +207,7 @@ object BugReporter {
                     val builder = BugReporterMultipartBody.Builder()
                             .addFormDataPart("text", "[RiotX] $bugDescription")
                             .addFormDataPart("app", "riot-android")
-                            .addFormDataPart("user_agent", Matrix.getInstance().getUserAgent())
+                            .addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent())
                             .addFormDataPart("user_id", userId)
                             .addFormDataPart("device_id", deviceId)
                             // TODO .addFormDataPart("version", Matrix.getInstance(context).getVersion(true, false))

From 47968c944784ad8c1f91aa1ea37afea12f43bff9 Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Fri, 21 Jun 2019 10:36:02 +0200
Subject: [PATCH 07/11] Dagger: everything should be injected ok now

---
 .../android/internal/session/DefaultSession.kt     |  5 +++--
 .../vector/riotredesign/core/di/ScreenComponent.kt | 14 +++++++++++---
 .../core/platform/SimpleFragmentActivity.kt        |  2 +-
 .../roomdirectory/RoomDirectoryActivity.kt         |  5 +++++
 .../settings/VectorSettingsPreferencesFragment.kt  |  5 +++++
 5 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
index 0d0d0821..5e3f34f2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
@@ -43,6 +43,7 @@ import javax.inject.Inject
 
 @SessionScope
 internal class DefaultSession @Inject constructor(override val sessionParams: SessionParams,
+                                                  private val liveEntityObservers: Set<@JvmSuppressWildcards LiveEntityObserver>,
                                                   private val monarchy: Monarchy,
                                                   private val sessionListeners: SessionListeners,
                                                   private val roomService: RoomService,
@@ -76,7 +77,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
         if (!monarchy.isMonarchyThreadOpen) {
             monarchy.openManually()
         }
-        //liveEntityObservers.forEach { it.start() }
+        liveEntityObservers.forEach { it.start() }
     }
 
     @MainThread
@@ -95,7 +96,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
     override fun close() {
         assertMainThread()
         assert(isOpen)
-        //liveEntityObservers.forEach { it.dispose() }
+        liveEntityObservers.forEach { it.dispose() }
         cryptoService.close()
         if (monarchy.isMonarchyThreadOpen) {
             monarchy.closeManually()
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
index 1c28b8ef..90194074 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
@@ -21,10 +21,11 @@ import androidx.lifecycle.ViewModelProvider
 import dagger.BindsInstance
 import dagger.Component
 import im.vector.fragments.keysbackup.restore.KeysBackupRestoreFromPassphraseFragment
-import im.vector.riotredesign.core.platform.SimpleFragmentActivity
+import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.features.MainActivity
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreFromKeyFragment
 import im.vector.riotredesign.features.crypto.keysbackup.restore.KeysBackupRestoreSuccessFragment
+import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupManageActivity
 import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupSettingsFragment
 import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupStep1Fragment
 import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupStep2Fragment
@@ -44,18 +45,20 @@ import im.vector.riotredesign.features.home.room.list.RoomListFragment
 import im.vector.riotredesign.features.login.LoginActivity
 import im.vector.riotredesign.features.reactions.EmojiReactionPickerActivity
 import im.vector.riotredesign.features.roomdirectory.PublicRoomsFragment
+import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
 import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomFragment
 import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerFragment
 import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment
 import im.vector.riotredesign.features.settings.VectorSettingsActivity
+import im.vector.riotredesign.features.settings.VectorSettingsPreferencesFragment
 
 @Component(dependencies = [VectorComponent::class], modules = [ViewModelModule::class, HomeModule::class])
 @ScreenScope
 interface ScreenComponent {
 
-    fun viewModelFactory(): ViewModelProvider.Factory
+    fun session(): Session
 
-    fun inject(activity: SimpleFragmentActivity)
+    fun viewModelFactory(): ViewModelProvider.Factory
 
     fun inject(activity: HomeActivity)
 
@@ -85,6 +88,8 @@ interface ScreenComponent {
 
     fun inject(createRoomFragment: CreateRoomFragment)
 
+    fun inject(keysBackupManageActivity: KeysBackupManageActivity)
+
     fun inject(keysBackupRestoreFromKeyFragment: KeysBackupRestoreFromKeyFragment)
 
     fun inject(keysBackupRestoreFromPassphraseFragment: KeysBackupRestoreFromPassphraseFragment)
@@ -109,6 +114,9 @@ interface ScreenComponent {
 
     fun inject(mainActivity: MainActivity)
 
+    fun inject(vectorSettingsPreferencesFragment: VectorSettingsPreferencesFragment)
+
+    fun inject(roomDirectoryActivity: RoomDirectoryActivity)
 
     @Component.Factory
     interface Factory {
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
index 8c9bfbde..b02b2cb8 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/SimpleFragmentActivity.kt
@@ -48,7 +48,7 @@ abstract class SimpleFragmentActivity : VectorBaseActivity() {
     @Inject lateinit var session: Session
 
     override fun injectWith(injector: ScreenComponent) {
-        injector.inject(this)
+        session = injector.session()
     }
 
     override fun initUiAndData() {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryActivity.kt
index 64853b8d..1b99b5a1 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/RoomDirectoryActivity.kt
@@ -19,6 +19,7 @@ package im.vector.riotredesign.features.roomdirectory
 import android.os.Bundle
 import androidx.lifecycle.ViewModelProviders
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.addFragment
 import im.vector.riotredesign.core.extensions.addFragmentToBackstack
 import im.vector.riotredesign.core.extensions.observeEvent
@@ -43,6 +44,10 @@ class RoomDirectoryActivity : VectorBaseActivity() {
 
     override fun getLayoutRes() = R.layout.activity_simple
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         navigationViewModel = ViewModelProviders.of(this, viewModelFactory).get(RoomDirectoryNavigationViewModel::class.java)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
index 1d2371c8..aa067cc5 100755
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
@@ -50,6 +50,7 @@ import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
 import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.DaggerScreenComponent
 import im.vector.riotredesign.core.dialogs.ExportKeysDialog
 import im.vector.riotredesign.core.extensions.showPassword
 import im.vector.riotredesign.core.extensions.withArgs
@@ -96,6 +97,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
     // TODO     }
     // TODO }
 
+
     private var mLoadingView: View? = null
 
     private var mDisplayedEmails = ArrayList()
@@ -809,10 +811,13 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
     }
 
     override fun onAttach(context: Context) {
+        val screenComponent = DaggerScreenComponent.factory().create(vectorActivity.getVectorComponent(), vectorActivity)
         super.onAttach(context)
+        screenComponent.inject(this)
         if (context is VectorSettingsFragmentInteractionListener) {
             interactionListener = context
         }
+
     }
 
     override fun onDetach() {

From 6e7adaec59aeeece702cf6baf23f96fdcbced32c Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Wed, 26 Jun 2019 15:22:44 +0200
Subject: [PATCH 08/11] Dagger: prepare for multi session [WIP]

---
 .../im/vector/matrix/android/api/Matrix.kt    |   7 --
 .../matrix/android/api/auth/Authenticator.kt  |  15 ++-
 .../matrix/android/internal/SessionManager.kt |  34 ++---
 .../android/internal/auth/AuthModule.kt       |   2 +
 .../internal/auth/DefaultAuthenticator.kt     |  25 ++--
 .../internal/auth/SessionParamsStore.kt       |  10 +-
 .../auth/db/RealmSessionParamsStore.kt        |  59 +++++++--
 .../internal/auth/db/SessionParamsEntity.kt   |   2 +
 .../internal/auth/db/SessionParamsMapper.kt   |   2 +-
 .../android/internal/di/AuthQualifiers.kt     |  29 +++++
 .../android/internal/di/MatrixComponent.kt    |   7 +-
 .../android/internal/di/NetworkModule.kt      |  14 +--
 .../network/AccessTokenInterceptor.kt         |  11 +-
 .../internal/network/RetrofitFactory.kt       |  39 ++++++
 .../android/internal/session/SessionModule.kt |  24 +++-
 .../internal/session/content/FileUploader.kt  |   5 +-
 .../membership/SenderRoomMemberExtractor.kt   |   4 +-
 .../session/signout/DefaultSignOutService.kt  |   1 +
 .../internal/session/signout/SignOutTask.kt   |  13 +-
 .../android/internal/session/sync/SyncTask.kt |   4 +-
 .../vector/riotredesign/VectorApplication.kt  |  58 +++++----
 .../core/di/ActiveSessionHolder.kt            |  57 +++++++++
 .../{HasInjector.kt => HasScreenInjector.kt}  |   4 +-
 .../riotredesign/core/di/HasVectorInjector.kt |  25 ++++
 .../riotredesign/core/di/ScreenComponent.kt   |  24 +++-
 .../riotredesign/core/di/VectorComponent.kt   |  14 ++-
 .../riotredesign/core/di/VectorModule.kt      |   4 +-
 .../riotredesign/core/extensions/Session.kt   |  28 +++++
 .../core/platform/VectorBaseActivity.kt       |  29 ++---
 .../core/platform/VectorBaseFragment.kt       |   4 +-
 .../riotredesign/features/MainActivity.kt     |  44 ++++---
 .../autocomplete/user/AutocompleteUserItem.kt |   3 +-
 .../IncomingVerificationRequestHandler.kt     |   7 +-
 .../SASVerificationIncomingFragment.kt        |   6 +-
 .../features/home/AvatarRenderer.kt           |  25 ++--
 .../features/home/HomeActivity.kt             |  13 +-
 .../features/home/HomeDetailFragment.kt       |   3 +-
 .../features/home/HomeDrawerFragment.kt       |   3 +-
 .../home/group/GroupSummaryController.kt      |   4 +-
 .../features/home/group/GroupSummaryItem.kt   |   3 +-
 .../home/room/detail/RoomDetailFragment.kt    |  12 +-
 .../timeline/TimelineEventController.kt       |  29 ++---
 .../action/MessageActionsBottomSheet.kt       |   3 +-
 .../timeline/factory/EncryptedItemFactory.kt  |   5 +-
 .../timeline/factory/EncryptionItemFactory.kt |   5 +-
 .../timeline/factory/MessageItemFactory.kt    | 118 +++++++++---------
 .../timeline/factory/NoticeItemFactory.kt     |   5 +-
 .../helper/ContentUploadStateTrackerBinder.kt |  10 +-
 .../detail/timeline/item/AbsMessageItem.kt    |   4 +-
 .../detail/timeline/item/MergedHeaderItem.kt  |   3 +-
 .../detail/timeline/item/MessageFileItem.kt   |   3 +
 .../timeline/item/MessageImageVideoItem.kt    |  13 +-
 .../detail/timeline/item/MessageTextItem.kt   |   3 +
 .../room/detail/timeline/item/NoticeItem.kt   |   5 +-
 .../timeline/item/RedactedMessageItem.kt      |   3 +
 .../home/room/list/RoomSummaryController.kt   |   5 +-
 .../home/room/list/RoomSummaryItem.kt         |   3 +-
 .../features/html/EventHtmlRenderer.kt        |  34 ++---
 .../features/html/PillImageSpan.kt            |   5 +-
 .../features/invite/VectorInviteView.kt       |   8 +-
 .../features/login/LoginActivity.kt           |  10 +-
 .../features/media/ImageContentRenderer.kt    |  20 +--
 .../media/ImageMediaViewerActivity.kt         |  10 +-
 .../features/media/VideoContentRenderer.kt    |   6 +-
 .../media/VideoMediaViewerActivity.kt         |  11 +-
 .../features/rageshake/BugReportActivity.kt   |  16 ++-
 .../features/rageshake/BugReporter.kt         |  24 ++--
 .../features/rageshake/RageShake.kt           |   7 +-
 .../VectorUncaughtExceptionHandler.kt         |  22 ++--
 .../features/roomdirectory/PublicRoomItem.kt  |   5 +-
 .../roomdirectory/PublicRoomsController.kt    |   3 +
 .../RoomPreviewNoPreviewFragment.kt           |   5 +-
 ...ttingsNotificationsTroubleshootFragment.kt |   3 +-
 .../SignOutBottomSheetDialogFragment.kt       |   2 -
 74 files changed, 727 insertions(+), 358 deletions(-)
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/AuthQualifiers.kt
 create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/RetrofitFactory.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/ActiveSessionHolder.kt
 rename vector/src/main/java/im/vector/riotredesign/core/di/{HasInjector.kt => HasScreenInjector.kt} (90%)
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/di/HasVectorInjector.kt
 create mode 100644 vector/src/main/java/im/vector/riotredesign/core/extensions/Session.kt

diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
index 3ea61119..63fd6a34 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt
@@ -53,7 +53,6 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
     @Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
     @Inject internal lateinit var olmManager: OlmManager
     @Inject internal lateinit var sessionManager: SessionManager
-    var currentSession: Session? = null
 
     init {
         Monarchy.init(context)
@@ -63,12 +62,6 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
         }
         ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
         userAgentHolder.setApplicationFlavor(matrixConfiguration.applicationFlavor)
-        authenticator.getLastActiveSession()?.also {
-            currentSession = it
-            it.open()
-            it.setFilter(FilterService.FilterPreset.RiotFilter)
-            it.startSync()
-        }
     }
 
     fun getUserAgent() = userAgentHolder.userAgent
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/Authenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/Authenticator.kt
index 633d262e..2ca6d0a2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/Authenticator.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/Authenticator.kt
@@ -18,6 +18,7 @@ package im.vector.matrix.android.api.auth
 
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
+import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.util.Cancelable
 
@@ -40,14 +41,24 @@ interface Authenticator {
      * Check if there is an active [Session].
      * @return true if there is at least one active session.
      */
-    fun hasActiveSessions(): Boolean
+    fun hasAuthenticatedSessions(): Boolean
 
     //TODO remove this method. Shouldn't be managed like that.
     /**
      * Get the last active [Session], if there is an active session.
      * @return the lastActive session if any, or null
      */
-    fun getLastActiveSession(): Session?
+    fun getLastAuthenticatedSession(): Session?
+
+    /**
+     * Get an authenticated session. You should at least call authenticate one time before.
+     * If you logout, this session will no longer be valid.
+     *
+     * @param sessionParams the sessionParams to open with.
+     * @return the associated session if any, or null
+     */
+    fun getSession(sessionParams: SessionParams): Session?
+
 
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
index d70052ef..7e0a67a4 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/SessionManager.kt
@@ -20,6 +20,7 @@ package im.vector.matrix.android.internal
 
 import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.api.session.Session
+import im.vector.matrix.android.internal.auth.SessionParamsStore
 import im.vector.matrix.android.internal.di.MatrixComponent
 import im.vector.matrix.android.internal.di.MatrixScope
 import im.vector.matrix.android.internal.session.DaggerSessionComponent
@@ -27,27 +28,18 @@ import im.vector.matrix.android.internal.session.SessionComponent
 import javax.inject.Inject
 
 @MatrixScope
-internal class SessionManager @Inject constructor(private val matrixComponent: MatrixComponent) {
+internal class SessionManager @Inject constructor(private val matrixComponent: MatrixComponent,
+                                                  private val sessionParamsStore: SessionParamsStore) {
 
     private val sessionComponents = HashMap()
 
     fun getSessionComponent(userId: String): SessionComponent? {
-        return sessionComponents[userId]
+        val sessionParams = sessionParamsStore.get(userId) ?: return null
+        return getOrCreateSessionComponent(sessionParams)
     }
 
-    fun createSession(sessionParams: SessionParams): Session {
-        val userId = sessionParams.credentials.userId
-        if (sessionComponents.containsKey(userId)) {
-            throw RuntimeException("You already have a session for the user $userId")
-        }
-        return DaggerSessionComponent
-                .factory()
-                .create(matrixComponent, sessionParams)
-                .also {
-                    sessionComponents[userId] = it
-                }.let {
-                    it.session()
-                }
+    fun getOrCreateSession(sessionParams: SessionParams): Session {
+        return getOrCreateSessionComponent(sessionParams).session()
     }
 
     fun releaseSession(userId: String) {
@@ -59,5 +51,17 @@ internal class SessionManager @Inject constructor(private val matrixComponent: M
         }
     }
 
+    private fun getOrCreateSessionComponent(sessionParams: SessionParams): SessionComponent {
+        val userId = sessionParams.credentials.userId
+        if (sessionComponents.containsKey(userId)) {
+            return sessionComponents[userId]!!
+        }
+        return DaggerSessionComponent
+                .factory()
+                .create(matrixComponent, sessionParams)
+                .also {
+                    sessionComponents[sessionParams.credentials.userId] = it
+                }
+    }
 
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
index 71e7d371..472d653d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthModule.kt
@@ -49,6 +49,8 @@ internal abstract class AuthModule {
         }
     }
 
+
+
     @Binds
     abstract fun bindSessionParamsStore(sessionParamsStore: RealmSessionParamsStore): SessionParamsStore
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
index c19ec005..3eb8f113 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt
@@ -28,32 +28,41 @@ import im.vector.matrix.android.internal.SessionManager
 import im.vector.matrix.android.internal.auth.data.PasswordLoginParams
 import im.vector.matrix.android.internal.auth.data.ThreePidMedium
 import im.vector.matrix.android.internal.di.MatrixScope
+import im.vector.matrix.android.internal.di.Unauthenticated
+import im.vector.matrix.android.internal.network.RetrofitFactory
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.util.CancelableCoroutine
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
+import okhttp3.OkHttpClient
 import retrofit2.Retrofit
 import javax.inject.Inject
 
-internal class DefaultAuthenticator @Inject constructor(private val retrofitBuilder: Retrofit.Builder,
+internal class DefaultAuthenticator @Inject constructor(@Unauthenticated
+                                                        private val okHttpClient: OkHttpClient,
+                                                        private val retrofitFactory: RetrofitFactory,
                                                         private val coroutineDispatchers: MatrixCoroutineDispatchers,
                                                         private val sessionParamsStore: SessionParamsStore,
                                                         private val sessionManager: SessionManager
 ) : Authenticator {
 
-    override fun hasActiveSessions(): Boolean {
-        return sessionParamsStore.get() != null
+    override fun hasAuthenticatedSessions(): Boolean {
+        return sessionParamsStore.getLast() != null
     }
 
-    override fun getLastActiveSession(): Session? {
-        val sessionParams = sessionParamsStore.get()
+    override fun getLastAuthenticatedSession(): Session? {
+        val sessionParams = sessionParamsStore.getLast()
         return sessionParams?.let {
-            sessionManager.createSession(it)
+            sessionManager.getOrCreateSession(it)
         }
     }
 
+    override fun getSession(sessionParams: SessionParams): Session? {
+        return sessionManager.getOrCreateSession(sessionParams)
+    }
+
     override fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig,
                               login: String,
                               password: String,
@@ -84,13 +93,13 @@ internal class DefaultAuthenticator @Inject constructor(private val retrofitBuil
             sessionParamsStore.save(sessionParams)
             sessionParams
         }.map {
-            sessionManager.createSession(it)
+            sessionManager.getOrCreateSession(it)
         }
 
     }
 
     private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {
-        val retrofit = retrofitBuilder.baseUrl(homeServerConnectionConfig.homeServerUri.toString()).build()
+        val retrofit = retrofitFactory.create(okHttpClient, homeServerConnectionConfig.homeServerUri.toString())
         return retrofit.create(AuthAPI::class.java)
     }
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt
index df8b71e4..e7729d37 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt
@@ -21,9 +21,15 @@ import im.vector.matrix.android.api.auth.data.SessionParams
 
 internal interface SessionParamsStore {
 
-    fun get(): SessionParams?
+    fun get(userId: String): SessionParams?
+
+    fun getLast(): SessionParams?
+
+    fun getAll(): List
 
     fun save(sessionParams: SessionParams): Try
 
-    fun delete(): Try
+    fun delete(userId: String): Try
+
+    fun deleteAll(): Try
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
index 4a202e3a..1bb27d20 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt
@@ -20,15 +20,48 @@ import arrow.core.Try
 import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.internal.auth.SessionParamsStore
 import im.vector.matrix.android.internal.di.AuthDatabase
-import im.vector.matrix.android.internal.di.MatrixScope
 import io.realm.Realm
 import io.realm.RealmConfiguration
 import javax.inject.Inject
 
 internal class RealmSessionParamsStore @Inject constructor(private val mapper: SessionParamsMapper,
-                                                           @AuthDatabase private val realmConfiguration: RealmConfiguration
+                                                           @AuthDatabase
+                                                           private val realmConfiguration: RealmConfiguration
 ) : SessionParamsStore {
 
+    override fun getLast(): SessionParams? {
+        val realm = Realm.getInstance(realmConfiguration)
+        val sessionParams = realm
+                .where(SessionParamsEntity::class.java)
+                .findAll()
+                .map { mapper.map(it) }
+                .lastOrNull()
+        realm.close()
+        return sessionParams
+    }
+
+    override fun get(userId: String): SessionParams? {
+        val realm = Realm.getInstance(realmConfiguration)
+        val sessionParams = realm
+                .where(SessionParamsEntity::class.java)
+                .equalTo(SessionParamsEntityFields.USER_ID, userId)
+                .findAll()
+                .map { mapper.map(it) }
+                .firstOrNull()
+        realm.close()
+        return sessionParams
+    }
+
+    override fun getAll(): List {
+        val realm = Realm.getInstance(realmConfiguration)
+        val sessionParams = realm
+                .where(SessionParamsEntity::class.java)
+                .findAll()
+                .mapNotNull { mapper.map(it) }
+        realm.close()
+        return sessionParams
+    }
+
     override fun save(sessionParams: SessionParams): Try {
         return Try {
             val entity = mapper.map(sessionParams)
@@ -43,18 +76,20 @@ internal class RealmSessionParamsStore @Inject constructor(private val mapper: S
         }
     }
 
-    override fun get(): SessionParams? {
-        val realm = Realm.getInstance(realmConfiguration)
-        val sessionParams = realm
-                .where(SessionParamsEntity::class.java)
-                .findAll()
-                .map { mapper.map(it) }
-                .lastOrNull()
-        realm.close()
-        return sessionParams
+    override fun delete(userId: String): Try {
+        return Try {
+            val realm = Realm.getInstance(realmConfiguration)
+            realm.executeTransaction {
+                it.where(SessionParamsEntity::class.java)
+                        .equalTo(SessionParamsEntityFields.USER_ID, userId)
+                        .findAll()
+                        .deleteAllFromRealm()
+            }
+            realm.close()
+        }
     }
 
-    override fun delete(): Try {
+    override fun deleteAll(): Try {
         return Try {
             val realm = Realm.getInstance(realmConfiguration)
             realm.executeTransaction {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsEntity.kt
index 7ebfbcc4..e6569d28 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsEntity.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsEntity.kt
@@ -17,8 +17,10 @@
 package im.vector.matrix.android.internal.auth.db
 
 import io.realm.RealmObject
+import io.realm.annotations.PrimaryKey
 
 internal open class SessionParamsEntity(
+        @PrimaryKey var userId: String = "",
         var credentialsJson: String = "",
         var homeServerConnectionConfigJson: String = ""
 ) : RealmObject()
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
index a8738cb4..64303ea0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/SessionParamsMapper.kt
@@ -49,7 +49,7 @@ internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
         if (credentialsJson == null || homeServerConnectionConfigJson == null) {
             return null
         }
-        return SessionParamsEntity(credentialsJson, homeServerConnectionConfigJson)
+        return SessionParamsEntity(sessionParams.credentials.userId, credentialsJson, homeServerConnectionConfigJson)
     }
 
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/AuthQualifiers.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/AuthQualifiers.kt
new file mode 100644
index 00000000..e89d8b8e
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/AuthQualifiers.kt
@@ -0,0 +1,29 @@
+/*
+ *
+ *  * 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.matrix.android.internal.di
+
+import javax.inject.Qualifier
+
+@Qualifier
+@Retention(AnnotationRetention.RUNTIME)
+annotation class Authenticated
+
+@Qualifier
+@Retention(AnnotationRetention.RUNTIME)
+annotation class Unauthenticated
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
index 30471d57..ad03bbca 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixComponent.kt
@@ -23,9 +23,11 @@ import dagger.BindsInstance
 import dagger.Component
 import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.auth.Authenticator
+import im.vector.matrix.android.internal.SessionManager
 import im.vector.matrix.android.internal.auth.AuthModule
 import im.vector.matrix.android.internal.auth.SessionParamsStore
 import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
+import im.vector.matrix.android.internal.network.RetrofitFactory
 import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
@@ -42,8 +44,7 @@ internal interface MatrixComponent {
 
     fun moshi(): Moshi
 
-    fun retrofitBuilder(): Retrofit.Builder
-
+    @Unauthenticated
     fun okHttpClient(): OkHttpClient
 
     fun authenticator(): Authenticator
@@ -62,6 +63,8 @@ internal interface MatrixComponent {
 
     fun backgroundDetectionObserver(): BackgroundDetectionObserver
 
+    fun sessionManager(): SessionManager
+
     fun inject(matrix: Matrix)
 
     @Component.Factory
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt
index b6a3242d..2f9e8c69 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt
@@ -66,9 +66,9 @@ internal object NetworkModule {
     @MatrixScope
     @Provides
     @JvmStatic
+    @Unauthenticated
     fun providesOkHttpClient(stethoInterceptor: StethoInterceptor,
                              userAgentInterceptor: UserAgentInterceptor,
-                             accessTokenInterceptor: AccessTokenInterceptor,
                              httpLoggingInterceptor: HttpLoggingInterceptor,
                              curlLoggingInterceptor: CurlLoggingInterceptor,
                              okReplayInterceptor: OkReplayInterceptor): OkHttpClient {
@@ -78,7 +78,6 @@ internal object NetworkModule {
                 .writeTimeout(30, TimeUnit.SECONDS)
                 .addNetworkInterceptor(stethoInterceptor)
                 .addInterceptor(userAgentInterceptor)
-                .addInterceptor(accessTokenInterceptor)
                 .addInterceptor(httpLoggingInterceptor)
                 .apply {
                     if (BuildConfig.LOG_PRIVATE_DATA) {
@@ -94,15 +93,4 @@ internal object NetworkModule {
     fun providesMoshi(): Moshi {
         return MoshiProvider.providesMoshi()
     }
-
-    @Provides
-    @JvmStatic
-    fun providesRetrofitBuilder(okHttpClient: OkHttpClient,
-                                moshi: Moshi): Retrofit.Builder {
-        return Retrofit.Builder()
-                .client(okHttpClient)
-                .addConverterFactory(UnitConverterFactory)
-                .addConverterFactory(MoshiConverterFactory.create(moshi))
-    }
-
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/AccessTokenInterceptor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/AccessTokenInterceptor.kt
index 5c2f9d8c..0f723d41 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/AccessTokenInterceptor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/AccessTokenInterceptor.kt
@@ -16,22 +16,19 @@
 
 package im.vector.matrix.android.internal.network
 
-import im.vector.matrix.android.internal.auth.SessionParamsStore
-import im.vector.matrix.android.internal.di.MatrixScope
+import im.vector.matrix.android.api.auth.data.Credentials
+import im.vector.matrix.android.internal.session.SessionScope
 import okhttp3.Interceptor
 import okhttp3.Response
 import javax.inject.Inject
 
-internal class AccessTokenInterceptor @Inject constructor(private val sessionParamsStore: SessionParamsStore) : Interceptor {
+internal class AccessTokenInterceptor @Inject constructor(private val credentials: Credentials) : Interceptor {
 
     override fun intercept(chain: Interceptor.Chain): Response {
         var request = chain.request()
         val newRequestBuilder = request.newBuilder()
         // Add the access token to all requests if it is set
-        val sessionParams = sessionParamsStore.get()
-        sessionParams?.let {
-            newRequestBuilder.addHeader(HttpHeaders.Authorization, "Bearer " + it.credentials.accessToken)
-        }
+        newRequestBuilder.addHeader(HttpHeaders.Authorization, "Bearer " + credentials.accessToken)
         request = newRequestBuilder.build()
         return chain.proceed(request)
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/RetrofitFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/RetrofitFactory.kt
new file mode 100644
index 00000000..1338c36e
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/RetrofitFactory.kt
@@ -0,0 +1,39 @@
+/*
+ *
+ *  * 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.matrix.android.internal.network
+
+import com.squareup.moshi.Moshi
+import okhttp3.Interceptor
+import okhttp3.OkHttpClient
+import retrofit2.Retrofit
+import retrofit2.converter.moshi.MoshiConverterFactory
+import javax.inject.Inject
+
+class RetrofitFactory @Inject constructor(private val moshi: Moshi) {
+
+    fun create(okHttpClient: OkHttpClient, baseUrl: String): Retrofit {
+        return Retrofit.Builder()
+                .baseUrl(baseUrl)
+                .client(okHttpClient)
+                .addConverterFactory(UnitConverterFactory)
+                .addConverterFactory(MoshiConverterFactory.create(moshi))
+                .build()
+    }
+
+}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
index 3ae65b90..cff657ae 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt
@@ -28,13 +28,18 @@ import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.internal.database.LiveEntityObserver
 import im.vector.matrix.android.internal.database.model.SessionRealmModule
+import im.vector.matrix.android.internal.di.Authenticated
 import im.vector.matrix.android.internal.di.SessionDatabase
+import im.vector.matrix.android.internal.di.Unauthenticated
+import im.vector.matrix.android.internal.network.AccessTokenInterceptor
+import im.vector.matrix.android.internal.network.RetrofitFactory
 import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
 import im.vector.matrix.android.internal.session.room.EventRelationsAggregationUpdater
 import im.vector.matrix.android.internal.session.room.prune.EventsPruner
 import im.vector.matrix.android.internal.session.user.UserEntityUpdater
 import im.vector.matrix.android.internal.util.md5
 import io.realm.RealmConfiguration
+import okhttp3.OkHttpClient
 import retrofit2.Retrofit
 import java.io.File
 
@@ -86,13 +91,26 @@ internal abstract class SessionModule {
         @JvmStatic
         @Provides
         @SessionScope
-        fun providesRetrofit(sessionParams: SessionParams, retrofitBuilder: Retrofit.Builder): Retrofit {
-            return retrofitBuilder
-                    .baseUrl(sessionParams.homeServerConnectionConfig.homeServerUri.toString())
+        @Authenticated
+        fun providesOkHttpClient(@Unauthenticated okHttpClient: OkHttpClient,
+                                 accessTokenInterceptor: AccessTokenInterceptor): OkHttpClient {
+            return okHttpClient.newBuilder()
+                    .addInterceptor(accessTokenInterceptor)
                     .build()
         }
+
+        @JvmStatic
+        @Provides
+        @SessionScope
+        fun providesRetrofit(@Authenticated okHttpClient: OkHttpClient,
+                             sessionParams: SessionParams,
+                             retrofitFactory: RetrofitFactory): Retrofit {
+            return retrofitFactory
+                    .create(okHttpClient, sessionParams.homeServerConnectionConfig.homeServerUri.toString())
+        }
     }
 
+
     @Binds
     abstract fun bindSession(session: DefaultSession): Session
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
index 217c06ba..dac85cb2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/FileUploader.kt
@@ -20,7 +20,9 @@ import arrow.core.Try
 import arrow.core.Try.Companion.raise
 import com.squareup.moshi.Moshi
 import im.vector.matrix.android.api.auth.data.SessionParams
+import im.vector.matrix.android.internal.di.Authenticated
 import im.vector.matrix.android.internal.di.MoshiProvider
+import im.vector.matrix.android.internal.di.Unauthenticated
 import im.vector.matrix.android.internal.network.ProgressRequestBody
 import im.vector.matrix.android.internal.session.SessionScope
 import okhttp3.*
@@ -29,7 +31,8 @@ import java.io.IOException
 import javax.inject.Inject
 
 
-internal class FileUploader @Inject constructor(private val okHttpClient: OkHttpClient,
+internal class FileUploader @Inject constructor(@Authenticated
+                                                private val okHttpClient: OkHttpClient,
                                                 private val sessionParams: SessionParams,
                                                 private val moshi: Moshi) {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/SenderRoomMemberExtractor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/SenderRoomMemberExtractor.kt
index 56bf71f5..209e5f38 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/SenderRoomMemberExtractor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/SenderRoomMemberExtractor.kt
@@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.database.query.where
 import io.realm.Realm
 import io.realm.RealmList
 import io.realm.RealmQuery
+import timber.log.Timber
 import javax.inject.Inject
 
 internal class SenderRoomMemberExtractor @Inject constructor(private val roomId: String) {
@@ -46,9 +47,8 @@ internal class SenderRoomMemberExtractor @Inject constructor(private val roomId:
             event.stateIndex <= 0 -> baseQuery(chunkEntity.events, sender, unlinked).next(from = event.stateIndex)?.prevContent
             else                  -> baseQuery(chunkEntity.events, sender, unlinked).prev(since = event.stateIndex)?.content
         }
-
         val fallbackContent = content
-                       ?: baseQuery(roomEntity.untimelinedStateEvents, sender, unlinked).prev(since = event.stateIndex)?.content
+                ?: baseQuery(roomEntity.untimelinedStateEvents, sender, unlinked).prev(since = event.stateIndex)?.content
 
         return ContentMapper.map(fallbackContent).toModel()
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
index 2b240ff9..f24e7b46 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/DefaultSignOutService.kt
@@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.signout
 
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.signout.SignOutService
+import im.vector.matrix.android.internal.SessionManager
 import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.configureWith
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
index b627ebd6..baf67191 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt
@@ -17,6 +17,9 @@
 package im.vector.matrix.android.internal.session.signout
 
 import arrow.core.Try
+import im.vector.matrix.android.api.auth.data.Credentials
+import im.vector.matrix.android.api.auth.data.SessionParams
+import im.vector.matrix.android.internal.SessionManager
 import im.vector.matrix.android.internal.auth.SessionParamsStore
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.SessionScope
@@ -25,14 +28,20 @@ import javax.inject.Inject
 
 internal interface SignOutTask : Task
 
-internal class DefaultSignOutTask @Inject constructor(private val signOutAPI: SignOutAPI,
+internal class DefaultSignOutTask @Inject constructor(private val credentials: Credentials,
+                                                      private val signOutAPI: SignOutAPI,
+                                                      private val sessionManager: SessionManager,
                                                       private val sessionParamsStore: SessionParamsStore) : SignOutTask {
 
     override suspend fun execute(params: Unit): Try {
         return executeRequest {
             apiCall = signOutAPI.signOut()
         }.flatMap {
-            sessionParamsStore.delete()
+            sessionParamsStore.delete(credentials.userId)
+        }.flatMap {
+            Try {
+                sessionManager.releaseSession(credentials.userId)
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
index 6acd82c9..35f0775b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt
@@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.session.sync
 import arrow.core.Try
 import arrow.core.failure
 import arrow.core.recoverWith
+import im.vector.matrix.android.api.auth.data.Credentials
 import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.api.failure.MatrixError
 import im.vector.matrix.android.internal.auth.SessionParamsStore
@@ -36,6 +37,7 @@ internal interface SyncTask : Task {
 }
 
 internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
+                                                   private val credentials: Credentials,
                                                    private val filterRepository: FilterRepository,
                                                    private val syncResponseHandler: SyncResponseHandler,
                                                    private val sessionParamsStore: SessionParamsStore
@@ -58,7 +60,7 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
             // Intercept 401
             if (throwable is Failure.ServerError
                 && throwable.error.code == MatrixError.UNKNOWN_TOKEN) {
-                sessionParamsStore.delete()
+                sessionParamsStore.delete(credentials.userId)
             }
 
             // Transmit the throwable
diff --git a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
index b2ce3c8a..52267e99 100644
--- a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
+++ b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
@@ -32,51 +32,55 @@ import com.github.piasy.biv.loader.glide.GlideImageLoader
 import com.jakewharton.threetenabp.AndroidThreeTen
 import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.MatrixConfiguration
-import im.vector.riotredesign.core.di.DaggerVectorComponent
-import im.vector.riotredesign.core.di.HasInjector
-import im.vector.riotredesign.core.di.VectorComponent
+import im.vector.riotredesign.core.di.*
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.lifecycle.VectorActivityLifecycleCallbacks
 import im.vector.riotredesign.features.rageshake.VectorFileLogger
 import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
 import timber.log.Timber
 import javax.inject.Inject
+import kotlin.system.measureTimeMillis
 
 
-class VectorApplication : Application(), HasInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider {
+class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider {
 
     lateinit var appContext: Context
     //font thread handler
     @Inject lateinit var vectorConfiguration: VectorConfiguration
     @Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
+    @Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler
+    @Inject lateinit var activeSessionHolder: ActiveSessionHolder
     lateinit var vectorComponent: VectorComponent
     private var fontThreadHandler: Handler? = null
 
     override fun onCreate() {
-        super.onCreate()
-        appContext = this
-        vectorComponent = DaggerVectorComponent.factory().create(this)
-        vectorComponent.inject(this)
-        VectorUncaughtExceptionHandler.activate(this)
-        // Log
-        VectorFileLogger.init(this)
-        Timber.plant(Timber.DebugTree(), VectorFileLogger)
-        if (BuildConfig.DEBUG) {
-            Stetho.initializeWithDefaults(this)
+        val time = measureTimeMillis {
+            super.onCreate()
+            appContext = this
+            vectorComponent = DaggerVectorComponent.factory().create(this)
+            vectorComponent.inject(this)
+            vectorUncaughtExceptionHandler.activate(this)
+            // Log
+            VectorFileLogger.init(this)
+            Timber.plant(Timber.DebugTree(), VectorFileLogger)
+            if (BuildConfig.DEBUG) {
+                Stetho.initializeWithDefaults(this)
+            }
+            AndroidThreeTen.init(this)
+            BigImageViewer.initialize(GlideImageLoader.with(applicationContext))
+            EpoxyController.defaultDiffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
+            EpoxyController.defaultModelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
+            registerActivityLifecycleCallbacks(VectorActivityLifecycleCallbacks())
+            val fontRequest = FontRequest(
+                    "com.google.android.gms.fonts",
+                    "com.google.android.gms",
+                    "Noto Color Emoji Compat",
+                    R.array.com_google_android_gms_fonts_certs
+            )
+            FontsContractCompat.requestFont(this, fontRequest, emojiCompatFontProvider, getFontThreadHandler())
+            vectorConfiguration.initConfiguration()
         }
-        AndroidThreeTen.init(this)
-        BigImageViewer.initialize(GlideImageLoader.with(applicationContext))
-        EpoxyController.defaultDiffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
-        EpoxyController.defaultModelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
-        registerActivityLifecycleCallbacks(VectorActivityLifecycleCallbacks())
-        val fontRequest = FontRequest(
-                "com.google.android.gms.fonts",
-                "com.google.android.gms",
-                "Noto Color Emoji Compat",
-                R.array.com_google_android_gms_fonts_certs
-        )
-        FontsContractCompat.requestFont(this, fontRequest, emojiCompatFontProvider, getFontThreadHandler())
-        vectorConfiguration.initConfiguration()
+        Timber.v("On create took $time ms")
     }
 
     override fun providesMatrixConfiguration() = MatrixConfiguration(BuildConfig.FLAVOR_DESCRIPTION)
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ActiveSessionHolder.kt
new file mode 100644
index 00000000..17602126
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ActiveSessionHolder.kt
@@ -0,0 +1,57 @@
+/*
+ *
+ *  * 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.riotredesign.core.di
+
+import im.vector.matrix.android.api.auth.Authenticator
+import im.vector.matrix.android.api.auth.data.SessionParams
+import im.vector.matrix.android.api.session.Session
+import im.vector.matrix.android.api.session.sync.FilterService
+import java.lang.IllegalStateException
+import java.util.concurrent.atomic.AtomicReference
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class ActiveSessionHolder @Inject constructor(private val authenticator: Authenticator) {
+
+    private var activeSession: AtomicReference = AtomicReference()
+
+    fun setActiveSession(session: Session){
+        activeSession.set(session)
+    }
+
+    fun clearActiveSession(){
+        activeSession.set(null)
+    }
+
+    fun hasActiveSession(): Boolean {
+        return activeSession.get() != null
+    }
+
+    fun getActiveSession(): Session {
+        return activeSession.get() ?: throw IllegalStateException("You should authenticate before using this")
+    }
+
+    //TODO: Stop sync ?
+    fun switchToSession(sessionParams: SessionParams) {
+        val newActiveSession = authenticator.getSession(sessionParams)
+        activeSession.set(newActiveSession)
+    }
+
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/HasInjector.kt b/vector/src/main/java/im/vector/riotredesign/core/di/HasScreenInjector.kt
similarity index 90%
rename from vector/src/main/java/im/vector/riotredesign/core/di/HasInjector.kt
rename to vector/src/main/java/im/vector/riotredesign/core/di/HasScreenInjector.kt
index ca2e27ab..746c0c18 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/HasInjector.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/HasScreenInjector.kt
@@ -16,8 +16,8 @@
 
 package im.vector.riotredesign.core.di
 
-interface HasInjector {
+interface HasScreenInjector {
 
-    fun injector(): C
+    fun injector(): ScreenComponent
 
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/HasVectorInjector.kt b/vector/src/main/java/im/vector/riotredesign/core/di/HasVectorInjector.kt
new file mode 100644
index 00000000..e8301c73
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/HasVectorInjector.kt
@@ -0,0 +1,25 @@
+/*
+ *
+ *  * 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.riotredesign.core.di
+
+interface HasVectorInjector {
+
+    fun injector(): VectorComponent
+
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
index 90194074..47b92a9f 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
@@ -31,10 +31,7 @@ import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupSt
 import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupStep2Fragment
 import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupStep3Fragment
 import im.vector.riotredesign.features.crypto.verification.SASVerificationIncomingFragment
-import im.vector.riotredesign.features.home.HomeActivity
-import im.vector.riotredesign.features.home.HomeDetailFragment
-import im.vector.riotredesign.features.home.HomeDrawerFragment
-import im.vector.riotredesign.features.home.HomeModule
+import im.vector.riotredesign.features.home.*
 import im.vector.riotredesign.features.home.group.GroupListFragment
 import im.vector.riotredesign.features.home.room.detail.RoomDetailFragment
 import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageActionsBottomSheet
@@ -42,7 +39,13 @@ import im.vector.riotredesign.features.home.room.detail.timeline.action.MessageM
 import im.vector.riotredesign.features.home.room.detail.timeline.action.QuickReactionFragment
 import im.vector.riotredesign.features.home.room.detail.timeline.action.ViewReactionBottomSheet
 import im.vector.riotredesign.features.home.room.list.RoomListFragment
+import im.vector.riotredesign.features.invite.VectorInviteView
 import im.vector.riotredesign.features.login.LoginActivity
+import im.vector.riotredesign.features.media.ImageMediaViewerActivity
+import im.vector.riotredesign.features.media.VideoMediaViewerActivity
+import im.vector.riotredesign.features.rageshake.BugReportActivity
+import im.vector.riotredesign.features.rageshake.BugReporter
+import im.vector.riotredesign.features.rageshake.RageShake
 import im.vector.riotredesign.features.reactions.EmojiReactionPickerActivity
 import im.vector.riotredesign.features.roomdirectory.PublicRoomsFragment
 import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
@@ -60,6 +63,10 @@ interface ScreenComponent {
 
     fun viewModelFactory(): ViewModelProvider.Factory
 
+    fun bugReporter(): BugReporter
+
+    fun rageShake(): RageShake
+
     fun inject(activity: HomeActivity)
 
     fun inject(roomDetailFragment: RoomDetailFragment)
@@ -118,6 +125,15 @@ interface ScreenComponent {
 
     fun inject(roomDirectoryActivity: RoomDirectoryActivity)
 
+    fun inject(bugReportActivity: BugReportActivity)
+
+    fun inject(imageMediaViewerActivity: ImageMediaViewerActivity)
+
+    fun inject(vectorInviteView: VectorInviteView)
+
+    fun inject(videoMediaViewerActivity: VideoMediaViewerActivity)
+
+
     @Component.Factory
     interface Factory {
         fun create(vectorComponent: VectorComponent,
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
index 3e21cbac..54321160 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
@@ -28,17 +28,23 @@ import im.vector.riotredesign.VectorApplication
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.crypto.keysrequest.KeyRequestHandler
 import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
+import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.HomeNavigator
 import im.vector.riotredesign.features.home.HomeRoomListObservableStore
 import im.vector.riotredesign.features.home.group.SelectedGroupStore
 import im.vector.riotredesign.features.navigation.Navigator
 import im.vector.riotredesign.features.notifications.NotificationDrawerManager
+import im.vector.riotredesign.features.rageshake.BugReporter
+import im.vector.riotredesign.features.rageshake.RageShake
+import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
 import javax.inject.Singleton
 
 @Component(modules = [VectorModule::class])
 @Singleton
 interface VectorComponent {
 
+    fun inject(vectorApplication: VectorApplication)
+
     fun matrix(): Matrix
 
     fun currentSession(): Session
@@ -51,6 +57,8 @@ interface VectorComponent {
 
     fun vectorConfiguration(): VectorConfiguration
 
+    fun activeSessionHolder(): ActiveSessionHolder
+
     fun emojiCompatFontProvider(): EmojiCompatFontProvider
 
     fun navigator(): Navigator
@@ -65,10 +73,12 @@ interface VectorComponent {
 
     fun incomingKeyRequestHandler(): KeyRequestHandler
 
-    fun inject(vectorApplication: VectorApplication)
-
     fun authenticator(): Authenticator
 
+    fun bugReporter(): BugReporter
+
+    fun vectorUncaughtExceptionHandler(): VectorUncaughtExceptionHandler
+
     @Component.Factory
     interface Factory {
         fun create(@BindsInstance context: Context): VectorComponent
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
index ec8db244..b1c6c7e7 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorModule.kt
@@ -55,9 +55,9 @@ abstract class VectorModule {
 
         @Provides
         @JvmStatic
-        fun providesCurrentSession(matrix: Matrix): Session {
+        fun providesCurrentSession(activeSessionHolder: ActiveSessionHolder): Session {
             //TODO: handle session injection better
-            return matrix.currentSession!!
+            return activeSessionHolder.getActiveSession()
         }
 
         @Provides
diff --git a/vector/src/main/java/im/vector/riotredesign/core/extensions/Session.kt b/vector/src/main/java/im/vector/riotredesign/core/extensions/Session.kt
new file mode 100644
index 00000000..03766cf0
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotredesign/core/extensions/Session.kt
@@ -0,0 +1,28 @@
+/*
+ *
+ *  * 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.riotredesign.core.extensions
+
+import im.vector.matrix.android.api.session.Session
+import im.vector.matrix.android.api.session.sync.FilterService
+
+fun Session.openAndStartSync(){
+    open()
+    setFilter(FilterService.FilterPreset.RiotFilter)
+    startSync()
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
index 7296b7d5..440a4eca 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt
@@ -32,40 +32,32 @@ import androidx.appcompat.widget.Toolbar
 import androidx.coordinatorlayout.widget.CoordinatorLayout
 import androidx.core.view.isVisible
 import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.ViewModelProviders
 import butterknife.BindView
 import butterknife.ButterKnife
 import butterknife.Unbinder
 import com.airbnb.mvrx.BaseMvRxActivity
-import com.airbnb.mvrx.MvRxState
 import com.bumptech.glide.util.Util
 import com.google.android.material.snackbar.Snackbar
 import im.vector.riotredesign.BuildConfig
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.di.DaggerScreenComponent
-import im.vector.riotredesign.core.di.HasInjector
-import im.vector.riotredesign.core.di.ScreenComponent
-import im.vector.riotredesign.core.di.VectorComponent
+import im.vector.riotredesign.core.di.*
 import im.vector.riotredesign.core.utils.toast
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.rageshake.BugReportActivity
 import im.vector.riotredesign.features.rageshake.BugReporter
 import im.vector.riotredesign.features.rageshake.RageShake
-import im.vector.riotredesign.features.roomdirectory.PublicRoomsViewState
-import im.vector.riotredesign.features.roomdirectory.RoomDirectoryViewModel
 import im.vector.riotredesign.features.themes.ActivityOtherThemes
 import im.vector.riotredesign.features.themes.ThemeUtils
 import im.vector.riotredesign.receivers.DebugReceiver
 import io.reactivex.disposables.CompositeDisposable
 import io.reactivex.disposables.Disposable
 import timber.log.Timber
-import javax.inject.Provider
-import kotlin.reflect.KClass
+import kotlin.system.measureTimeMillis
 
 
-abstract class VectorBaseActivity : BaseMvRxActivity(), HasInjector {
+abstract class VectorBaseActivity : BaseMvRxActivity(), HasScreenInjector {
     /* ==========================================================================================
      * UI
      * ========================================================================================== */
@@ -81,6 +73,8 @@ abstract class VectorBaseActivity : BaseMvRxActivity(), HasInjector()
 
-    private var rageShake: RageShake? = null
     private lateinit var screenComponent: ScreenComponent
 
     override fun attachBaseContext(base: Context) {
@@ -125,9 +118,14 @@ abstract class VectorBaseActivity : BaseMvRxActivity(), HasInjector).injector()
+        return (application as HasVectorInjector).injector()
     }
 
     /**
diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
index f1fa25f7..d0f8214e 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseFragment.kt
@@ -35,14 +35,14 @@ import com.airbnb.mvrx.BaseMvRxFragment
 import com.airbnb.mvrx.MvRx
 import com.bumptech.glide.util.Util.assertMainThread
 import im.vector.riotredesign.core.di.DaggerScreenComponent
-import im.vector.riotredesign.core.di.HasInjector
+import im.vector.riotredesign.core.di.HasScreenInjector
 import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.features.navigation.Navigator
 import io.reactivex.disposables.CompositeDisposable
 import io.reactivex.disposables.Disposable
 import timber.log.Timber
 
-abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed, HasInjector {
+abstract class VectorBaseFragment : BaseMvRxFragment(), OnBackPressed, HasScreenInjector {
 
     // Butterknife unbinder
     private var mUnBinder: Unbinder? = null
diff --git a/vector/src/main/java/im/vector/riotredesign/features/MainActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/MainActivity.kt
index a87753e6..be5a7d51 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/MainActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/MainActivity.kt
@@ -22,7 +22,9 @@ import android.os.Bundle
 import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.auth.Authenticator
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import im.vector.riotredesign.core.di.ScreenComponent
+import im.vector.riotredesign.core.extensions.openAndStartSync
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import im.vector.riotredesign.features.home.HomeActivity
 import im.vector.riotredesign.features.login.LoginActivity
@@ -49,6 +51,7 @@ class MainActivity : VectorBaseActivity() {
 
     @Inject lateinit var matrix: Matrix
     @Inject lateinit var authenticator: Authenticator
+    @Inject lateinit var sessionHolder: ActiveSessionHolder
 
     override fun injectWith(injector: ScreenComponent) {
         injector.inject(this)
@@ -58,30 +61,31 @@ class MainActivity : VectorBaseActivity() {
         super.onCreate(savedInstanceState)
         val clearCache = intent.getBooleanExtra(EXTRA_CLEAR_CACHE, false)
         val clearCredentials = intent.getBooleanExtra(EXTRA_CLEAR_CREDENTIALS, false)
-        val session = matrix.currentSession
-        if (session == null) {
-            start()
-        } else {
-            // Handle some wanted cleanup
-            when {
-                clearCredentials -> session.signOut(object : MatrixCallback {
-                    override fun onSuccess(data: Unit) {
-                        Timber.w("SIGN_OUT: success, start app")
-                        start()
-                    }
-                })
-                clearCache       -> session.clearCache(object : MatrixCallback {
-                    override fun onSuccess(data: Unit) {
-                        start()
-                    }
-                })
-                else             -> start()
-            }
+        // Handle some wanted cleanup
+        when {
+            clearCredentials -> sessionHolder.getActiveSession().signOut(object : MatrixCallback {
+                override fun onSuccess(data: Unit) {
+                    Timber.w("SIGN_OUT: success, start app")
+                    sessionHolder.clearActiveSession()
+                    start()
+                }
+            })
+            clearCache       -> sessionHolder.getActiveSession().clearCache(object : MatrixCallback {
+                override fun onSuccess(data: Unit) {
+                    start()
+                }
+            })
+            else             -> start()
         }
     }
 
     private fun start() {
-        val intent = if (authenticator.hasActiveSessions()) {
+        val intent = if (authenticator.hasAuthenticatedSessions()) {
+            if (!sessionHolder.hasActiveSession()) {
+                val lastAuthenticatedSession = authenticator.getLastAuthenticatedSession()!!
+                sessionHolder.setActiveSession(lastAuthenticatedSession)
+                lastAuthenticatedSession.openAndStartSync()
+            }
             HomeActivity.newIntent(this)
         } else {
             LoginActivity.newIntent(this)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserItem.kt b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserItem.kt
index 57694725..17cbde66 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/autocomplete/user/AutocompleteUserItem.kt
@@ -29,6 +29,7 @@ import im.vector.riotredesign.features.home.AvatarRenderer
 @EpoxyModelClass(layout = R.layout.item_autocomplete_user)
 abstract class AutocompleteUserItem : VectorEpoxyModel() {
 
+    @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
     @EpoxyAttribute var name: String? = null
     @EpoxyAttribute var userId: String = ""
     @EpoxyAttribute var avatarUrl: String? = null
@@ -37,7 +38,7 @@ abstract class AutocompleteUserItem : VectorEpoxyModel {
                 //Add a notification for every incoming request
-                val session = Matrix.getInstance(context).currentSession!!
+                val session = activeSessionHolder.getActiveSession()
                 val name = session.getUser(tx.otherUserId)?.displayName
                            ?: tx.otherUserId
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
index b8549995..6acbad55 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/verification/SASVerificationIncomingFragment.kt
@@ -27,6 +27,7 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.features.home.AvatarRenderer
+import javax.inject.Inject
 
 class SASVerificationIncomingFragment : VectorBaseFragment() {
 
@@ -48,6 +49,7 @@ class SASVerificationIncomingFragment : VectorBaseFragment() {
 
     override fun getLayoutResId() = R.layout.fragment_sas_verification_incoming_request
 
+    @Inject lateinit var avatarRenderer: AvatarRenderer
     private lateinit var viewModel: SasVerificationViewModel
 
     override fun injectWith(injector: ScreenComponent) {
@@ -66,10 +68,10 @@ class SASVerificationIncomingFragment : VectorBaseFragment() {
         otherDeviceTextView.text = viewModel.otherDeviceId
 
         viewModel.otherUser?.let {
-            AvatarRenderer.render(it, avatarImageView)
+            avatarRenderer.render(it, avatarImageView)
         } ?: run {
             // Fallback to what we know
-            AvatarRenderer.render(null, viewModel.otherUserId ?: "", viewModel.otherUserId, avatarImageView)
+            avatarRenderer.render(null, viewModel.otherUserId ?: "", viewModel.otherUserId, avatarImageView)
         }
 
         viewModel.transactionState.observe(this, Observer {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/AvatarRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/home/AvatarRenderer.kt
index 451a49c2..a9943a6e 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/AvatarRenderer.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/AvatarRenderer.kt
@@ -26,29 +26,32 @@ import com.amulyakhare.textdrawable.TextDrawable
 import com.bumptech.glide.request.RequestOptions
 import com.bumptech.glide.request.target.DrawableImageViewTarget
 import com.bumptech.glide.request.target.Target
-import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.MatrixPatterns
 import im.vector.matrix.android.api.session.content.ContentUrlResolver
 import im.vector.matrix.android.api.session.room.model.RoomSummary
 import im.vector.matrix.android.api.session.user.model.User
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import im.vector.riotredesign.core.glide.GlideApp
 import im.vector.riotredesign.core.glide.GlideRequest
 import im.vector.riotredesign.core.glide.GlideRequests
+import javax.inject.Inject
 
 /**
  * This helper centralise ways to retrieve avatar into ImageView or even generic Target
  */
 
-object AvatarRenderer {
+class AvatarRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder){
 
-    private const val THUMBNAIL_SIZE = 250
+    companion object {
+        private const val THUMBNAIL_SIZE = 250
 
-    private val AVATAR_COLOR_LIST = listOf(
-            R.color.riotx_avatar_fill_1,
-            R.color.riotx_avatar_fill_2,
-            R.color.riotx_avatar_fill_3
-    )
+        private val AVATAR_COLOR_LIST = listOf(
+                R.color.riotx_avatar_fill_1,
+                R.color.riotx_avatar_fill_2,
+                R.color.riotx_avatar_fill_3
+        )
+    }
 
     @UiThread
     fun render(roomSummary: RoomSummary, imageView: ImageView) {
@@ -78,7 +81,7 @@ object AvatarRenderer {
             name
         }
         val placeholder = getPlaceholderDrawable(context, identifier, displayName)
-        buildGlideRequest(context, glideRequest, avatarUrl)
+        buildGlideRequest(glideRequest, avatarUrl)
                 .placeholder(placeholder)
                 .into(target)
     }
@@ -115,8 +118,8 @@ object AvatarRenderer {
 //        return AVATAR_COLOR_LIST[colorIndex.toInt()]
 //    }
 
-    private fun buildGlideRequest(context: Context, glideRequest: GlideRequests, avatarUrl: String?): GlideRequest {
-        val resolvedUrl = Matrix.getInstance(context).currentSession!!.contentUrlResolver()
+    private fun buildGlideRequest(glideRequest: GlideRequests, avatarUrl: String?): GlideRequest {
+        val resolvedUrl = activeSessionHolder.getActiveSession().contentUrlResolver()
                 .resolveThumbnail(avatarUrl, THUMBNAIL_SIZE, THUMBNAIL_SIZE, ContentUrlResolver.ThumbnailMethod.SCALE)
 
         return glideRequest
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
index d0e05f87..ca5c6c52 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeActivity.kt
@@ -31,6 +31,7 @@ import androidx.lifecycle.ViewModelProviders
 import com.airbnb.mvrx.viewModel
 import im.vector.matrix.android.api.Matrix
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.extensions.hideKeyboard
 import im.vector.riotredesign.core.extensions.observeEvent
@@ -57,8 +58,10 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
     private val homeActivityViewModel: HomeActivityViewModel by viewModel()
     private lateinit var navigationViewModel: HomeNavigationViewModel
 
+    @Inject lateinit var activeSessionHolder: ActiveSessionHolder
     @Inject lateinit var homeActivityViewModelFactory: HomeActivityViewModel.Factory
     @Inject lateinit var homeNavigator: HomeNavigator
+    @Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler
     // TODO Move this elsewhere
     @Inject lateinit var incomingVerificationRequestHandler: IncomingVerificationRequestHandler
     // TODO Move this elsewhere
@@ -119,14 +122,14 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
     override fun onResume() {
         super.onResume()
 
-        if (VectorUncaughtExceptionHandler.didAppCrash(this)) {
-            VectorUncaughtExceptionHandler.clearAppCrashStatus(this)
+        if (vectorUncaughtExceptionHandler.didAppCrash(this)) {
+            vectorUncaughtExceptionHandler.clearAppCrashStatus(this)
 
             AlertDialog.Builder(this)
                     .setMessage(R.string.send_bug_report_app_crashed)
                     .setCancelable(false)
-                    .setPositiveButton(R.string.yes) { _, _ -> BugReporter.openBugReportScreen(this) }
-                    .setNegativeButton(R.string.no) { _, _ -> BugReporter.deleteCrashFile(this) }
+                    .setPositiveButton(R.string.yes) { _, _ -> bugReporter.openBugReportScreen(this) }
+                    .setNegativeButton(R.string.no) { _, _ -> bugReporter.deleteCrashFile(this) }
                     .show()
         }
     }
@@ -140,7 +143,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
         when (item.itemId) {
             R.id.sliding_menu_sign_out -> {
-                SignOutUiWorker(this).perform(Matrix.getInstance(this).currentSession!!)
+                SignOutUiWorker(this).perform(activeSessionHolder.getActiveSession())
                 return true
             }
         }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
index 23eb943d..4ea3df5d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDetailFragment.kt
@@ -70,6 +70,7 @@ class HomeDetailFragment : VectorBaseFragment(), KeysBackupBanner.Delegate {
 
     @Inject lateinit var session: Session
     @Inject lateinit var homeDetailViewModelFactory: HomeDetailViewModel.Factory
+    @Inject lateinit var avatarRenderer: AvatarRenderer
 
     override fun getLayoutResId(): Int {
         return R.layout.fragment_home_detail
@@ -138,7 +139,7 @@ class HomeDetailFragment : VectorBaseFragment(), KeysBackupBanner.Delegate {
             parentActivity.configure(groupToolbar)
         }
         groupToolbar.title = ""
-        AvatarRenderer.render(
+        avatarRenderer.render(
                 params.groupAvatar,
                 params.groupId,
                 params.groupName,
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
index 28b8cf20..378b6a1b 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt
@@ -37,6 +37,7 @@ class HomeDrawerFragment : VectorBaseFragment() {
     }
 
     @Inject lateinit var session: Session
+    @Inject lateinit var avatarRenderer: AvatarRenderer
 
     override fun getLayoutResId() = R.layout.fragment_home_drawer
 
@@ -53,7 +54,7 @@ class HomeDrawerFragment : VectorBaseFragment() {
 
         session.observeUser(session.sessionParams.credentials.userId).observeK(this) { user ->
             if (user != null) {
-                AvatarRenderer.render(user.avatarUrl, user.userId, user.displayName, homeDrawerHeaderAvatarView)
+                avatarRenderer.render(user.avatarUrl, user.userId, user.displayName, homeDrawerHeaderAvatarView)
                 homeDrawerUsernameView.text = user.displayName
                 homeDrawerUserIdView.text = user.userId
             }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryController.kt b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryController.kt
index e82afb54..02904be3 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryController.kt
@@ -18,9 +18,10 @@ package im.vector.riotredesign.features.home.group
 
 import com.airbnb.epoxy.TypedEpoxyController
 import im.vector.matrix.android.api.session.group.model.GroupSummary
+import im.vector.riotredesign.features.home.AvatarRenderer
 import javax.inject.Inject
 
-class GroupSummaryController @Inject constructor(): TypedEpoxyController() {
+class GroupSummaryController @Inject constructor(private val avatarRenderer: AvatarRenderer): TypedEpoxyController() {
 
     var callback: Callback? = null
 
@@ -35,6 +36,7 @@ class GroupSummaryController @Inject constructor(): TypedEpoxyController
             val isSelected = groupSummary.groupId == selected?.groupId
             groupSummaryItem {
+                avatarRenderer(avatarRenderer)
                 id(groupSummary.groupId)
                 groupId(groupSummary.groupId)
                 groupName(groupSummary.displayName)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryItem.kt
index 16749849..1abb59bd 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/group/GroupSummaryItem.kt
@@ -29,6 +29,7 @@ import im.vector.riotredesign.features.home.AvatarRenderer
 @EpoxyModelClass(layout = R.layout.item_group)
 abstract class GroupSummaryItem : VectorEpoxyModel() {
 
+    @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
     @EpoxyAttribute lateinit var groupName: CharSequence
     @EpoxyAttribute lateinit var groupId: String
     @EpoxyAttribute var avatarUrl: String? = null
@@ -40,7 +41,7 @@ abstract class GroupSummaryItem : VectorEpoxyModel() {
         holder.rootView.setOnClickListener { listener?.invoke() }
         holder.groupNameView.text = groupName
         holder.rootView.isChecked = selected
-        AvatarRenderer.render(avatarUrl, groupId, groupName.toString(), holder.avatarImageView)
+        avatarRenderer.render(avatarUrl, groupId, groupName.toString(), holder.avatarImageView)
     }
 
     class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
index f2eeaa99..11c4a30d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
@@ -174,6 +174,7 @@ class RoomDetailFragment :
     private val textComposerViewModel: TextComposerViewModel by fragmentViewModel()
 
     @Inject lateinit var session: Session
+    @Inject lateinit var avatarRenderer: AvatarRenderer
     @Inject lateinit var timelineEventController: TimelineEventController
     @Inject lateinit var commandAutocompletePolicy: CommandAutocompletePolicy
     @Inject lateinit var autocompleteCommandPresenter: AutocompleteCommandPresenter
@@ -183,6 +184,7 @@ class RoomDetailFragment :
     @Inject lateinit var textComposerViewModelFactory: TextComposerViewModel.Factory
     private lateinit var scrollOnNewMessageCallback: ScrollOnNewMessageCallback
 
+
     override fun getLayoutResId() = R.layout.fragment_room_detail
 
     private lateinit var actionViewModel: ActionsHandler
@@ -223,7 +225,7 @@ class RoomDetailFragment :
                     commandAutocompletePolicy.enabled = true
                     val uid = session.sessionParams.credentials.userId
                     val meMember = session.getRoom(roomId)?.getRoomMember(uid)
-                    AvatarRenderer.render(meMember?.avatarUrl, uid, meMember?.displayName, composerLayout.composerAvatarImageView)
+                    avatarRenderer.render(meMember?.avatarUrl, uid, meMember?.displayName, composerLayout.composerAvatarImageView)
                     composerLayout.collapse()
                 }
                 SendMode.EDIT,
@@ -270,7 +272,7 @@ class RoomDetailFragment :
                         composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_reply))
                     }
 
-                    AvatarRenderer.render(event.senderAvatar, event.root.sender
+                    avatarRenderer.render(event.senderAvatar, event.root.sender
                                                               ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar)
 
                     composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text.length)
@@ -378,7 +380,7 @@ class RoomDetailFragment :
 
                         // Add the span
                         val user = session.getUser(item.userId)
-                        val span = PillImageSpan(glideRequests, requireContext(), item.userId, user)
+                        val span = PillImageSpan(glideRequests, avatarRenderer, requireContext(), item.userId, user)
                         span.bind(composerLayout.composerEditText)
 
                         editable.setSpan(span, startIndex, startIndex + displayName.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
@@ -487,7 +489,7 @@ class RoomDetailFragment :
 
             val uid = session.sessionParams.credentials.userId
             val meMember = session.getRoom(state.roomId)?.getRoomMember(uid)
-            AvatarRenderer.render(meMember?.avatarUrl, uid, meMember?.displayName, composerLayout.composerAvatarImageView)
+            avatarRenderer.render(meMember?.avatarUrl, uid, meMember?.displayName, composerLayout.composerAvatarImageView)
 
         } else if (summary?.membership == Membership.INVITE && inviter != null) {
             inviteView.visibility = View.VISIBLE
@@ -500,7 +502,7 @@ class RoomDetailFragment :
     private fun renderRoomSummary(state: RoomDetailViewState) {
         state.asyncRoomSummary()?.let {
             roomToolbarTitleView.text = it.displayName
-            AvatarRenderer.render(it, roomToolbarAvatarImageView)
+            avatarRenderer.render(it, roomToolbarAvatarImageView)
             if (it.topic.isNotEmpty()) {
                 roomToolbarSubtitleView.visibility = View.VISIBLE
                 roomToolbarSubtitleView.text = it.topic
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
index d4505b40..d4627232 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt
@@ -25,25 +25,14 @@ import androidx.recyclerview.widget.RecyclerView
 import com.airbnb.epoxy.EpoxyController
 import com.airbnb.epoxy.EpoxyModel
 import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
-import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
-import im.vector.matrix.android.api.session.room.model.message.MessageContent
-import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
-import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
-import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
+import im.vector.matrix.android.api.session.room.model.message.*
 import im.vector.matrix.android.api.session.room.timeline.Timeline
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.core.epoxy.LoadingItem_
 import im.vector.riotredesign.core.extensions.localDateTime
+import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.room.detail.timeline.factory.TimelineItemFactory
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineEventDiffUtilCallback
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineEventVisibilityStateChangedListener
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.canBeMerged
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.nextDisplayableEvent
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.prevSameTypeEvents
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderAvatar
-import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderName
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.*
 import im.vector.riotredesign.features.home.room.detail.timeline.item.DaySeparatorItem
 import im.vector.riotredesign.features.home.room.detail.timeline.item.DaySeparatorItem_
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MergedHeaderItem
@@ -56,7 +45,9 @@ import javax.inject.Inject
 class TimelineEventController @Inject constructor(private val dateFormatter: TimelineDateFormatter,
                                                   private val timelineItemFactory: TimelineItemFactory,
                                                   private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
-                                                  @TimelineEventControllerHandler private val backgroundHandler: Handler
+                                                  private val avatarRenderer: AvatarRenderer,
+                                                  @TimelineEventControllerHandler
+                                                  private val backgroundHandler: Handler
 ) : EpoxyController(backgroundHandler, backgroundHandler), Timeline.Listener {
 
     interface Callback : ReactionPillCallback, AvatarCallback, BaseCallback {
@@ -188,8 +179,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
             // Should be build if not cached or if cached but contains mergedHeader or formattedDay
             // We then are sure we always have items up to date.
             if (modelCache[position] == null
-                || modelCache[position]?.mergedHeaderModel != null
-                || modelCache[position]?.formattedDayModel != null) {
+                    || modelCache[position]?.mergedHeaderModel != null
+                    || modelCache[position]?.formattedDayModel != null) {
                 modelCache[position] = buildItemModels(position, currentSnapshot)
             }
         }
@@ -261,7 +252,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
                 // => handle case where paginating from mergeable events and we get more
                 val previousCollapseStateKey = mergedEventIds.intersect(mergeItemCollapseStates.keys).firstOrNull()
                 val initialCollapseState = mergeItemCollapseStates.remove(previousCollapseStateKey)
-                                           ?: true
+                        ?: true
                 val isCollapsed = mergeItemCollapseStates.getOrPut(event.localId) { initialCollapseState }
                 if (isCollapsed) {
                     collapsedEventIds.addAll(mergedEventIds)
@@ -269,7 +260,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
                     collapsedEventIds.removeAll(mergedEventIds)
                 }
                 val mergeId = mergedEventIds.joinToString(separator = "_") { it }
-                MergedHeaderItem(isCollapsed, mergeId, mergedData) {
+                MergedHeaderItem(isCollapsed, mergeId, mergedData, avatarRenderer) {
                     mergeItemCollapseStates[event.localId] = it
                     requestModelBuild()
                 }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
index d32e83a6..ef440c9e 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
@@ -46,6 +46,7 @@ import javax.inject.Inject
 class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment() {
 
     @Inject lateinit var messageActionViewModelFactory: MessageActionsViewModel.Factory
+    @Inject lateinit var avatarRenderer: AvatarRenderer
     private val viewModel: MessageActionsViewModel by fragmentViewModel(MessageActionsViewModel::class)
 
     private lateinit var actionHandlerModel: ActionsHandler
@@ -127,7 +128,7 @@ class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment() {
             senderNameTextView.text = it.senderName
             messageBodyTextView.text = it.messageBody
             messageTimestampText.text = it.ts
-            AvatarRenderer.render(it.senderAvatarPath, it.userId, it.senderName, senderAvatarImageView)
+            avatarRenderer.render(it.senderAvatarPath, it.userId, it.senderName, senderAvatarImageView)
         } else {
             bottom_sheet_message_preview.isVisible = false
         }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
index 46f5b7eb..fb6c398b 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
@@ -26,6 +26,7 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
 import im.vector.riotredesign.core.resources.StringProvider
+import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderAvatar
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderName
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
@@ -33,7 +34,8 @@ import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem
 import javax.inject.Inject
 
 // This class handles timeline event who haven't been successfully decrypted
-class EncryptedItemFactory @Inject constructor(private val stringProvider: StringProvider) {
+class EncryptedItemFactory @Inject constructor(private val stringProvider: StringProvider,
+                                               private val avatarRenderer: AvatarRenderer) {
 
     fun create(timelineEvent: TimelineEvent): VectorEpoxyModel<*>? {
         return when {
@@ -59,6 +61,7 @@ class EncryptedItemFactory @Inject constructor(private val stringProvider: Strin
                         showInformation = false
                 )
                 return NoticeItem_()
+                        .avatarRenderer(avatarRenderer)
                         .noticeText(spannableStr)
                         .informationData(informationData)
             }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
index cd8f34d5..835dd46b 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
@@ -23,6 +23,7 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.resources.StringProvider
+import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderAvatar
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderName
 import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
@@ -30,7 +31,8 @@ import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem
 import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_
 import javax.inject.Inject
 
-class EncryptionItemFactory @Inject constructor(private val stringProvider: StringProvider) {
+class EncryptionItemFactory @Inject constructor(private val stringProvider: StringProvider,
+                                                private val avatarRenderer: AvatarRenderer) {
 
     fun create(event: TimelineEvent): NoticeItem? {
         val text = buildNoticeText(event.root, event.senderName) ?: return null
@@ -43,6 +45,7 @@ class EncryptionItemFactory @Inject constructor(private val stringProvider: Stri
                 showInformation = false
         )
         return NoticeItem_()
+                .avatarRenderer(avatarRenderer)
                 .noticeText(text)
                 .informationData(informationData)
     }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
index 9ddd4d34..9774a855 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
@@ -29,14 +29,7 @@ import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.events.model.RelationType
 import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
-import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
-import im.vector.matrix.android.api.session.room.model.message.MessageContent
-import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent
-import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
-import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
-import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent
-import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
-import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
+import im.vector.matrix.android.api.session.room.model.message.*
 import im.vector.matrix.android.api.session.room.send.SendState
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.riotredesign.EmojiCompatFontProvider
@@ -47,23 +40,13 @@ import im.vector.riotredesign.core.linkify.VectorLinkify
 import im.vector.riotredesign.core.resources.ColorProvider
 import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.core.utils.DebouncedClickListener
+import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.getColorFromUserId
 import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
+import im.vector.riotredesign.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
-import im.vector.riotredesign.features.home.room.detail.timeline.item.BlankItem_
-import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem
-import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem_
-import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageFileItem
-import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageFileItem_
-import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem
-import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem_
-import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
-import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem
-import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem_
-import im.vector.riotredesign.features.home.room.detail.timeline.item.ReactionInfoData
-import im.vector.riotredesign.features.home.room.detail.timeline.item.RedactedMessageItem
-import im.vector.riotredesign.features.home.room.detail.timeline.item.RedactedMessageItem_
+import im.vector.riotredesign.features.home.room.detail.timeline.item.*
 import im.vector.riotredesign.features.html.EventHtmlRenderer
 import im.vector.riotredesign.features.media.ImageContentRenderer
 import im.vector.riotredesign.features.media.VideoContentRenderer
@@ -71,12 +54,15 @@ import me.gujun.android.span.span
 import javax.inject.Inject
 
 class MessageItemFactory @Inject constructor(
+        private val avatarRenderer: AvatarRenderer,
         private val colorProvider: ColorProvider,
         private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
         private val timelineDateFormatter: TimelineDateFormatter,
         private val htmlRenderer: EventHtmlRenderer,
         private val stringProvider: StringProvider,
-        private val emojiCompatFontProvider: EmojiCompatFontProvider) {
+        private val emojiCompatFontProvider: EmojiCompatFontProvider,
+        private val imageContentRenderer: ImageContentRenderer,
+        private val contentUploadStateTrackerBinder: ContentUploadStateTrackerBinder) {
 
     fun create(event: TimelineEvent,
                nextEvent: TimelineEvent?,
@@ -89,33 +75,33 @@ class MessageItemFactory @Inject constructor(
         val nextDate = nextEvent?.root?.localDateTime()
         val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
         val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60))
-                                                      ?: false
+                ?: false
 
         val showInformation = addDaySeparator
-                              || event.senderAvatar != nextEvent?.senderAvatar
-                              || event.senderName != nextEvent?.senderName
-                              || nextEvent?.root?.getClearType() != EventType.MESSAGE
-                              || isNextMessageReceivedMoreThanOneHourAgo
+                || event.senderAvatar != nextEvent?.senderAvatar
+                || event.senderName != nextEvent?.senderName
+                || nextEvent?.root?.getClearType() != EventType.MESSAGE
+                || isNextMessageReceivedMoreThanOneHourAgo
 
         val time = timelineDateFormatter.formatMessageHour(date)
         val avatarUrl = event.senderAvatar
         val memberName = event.senderName ?: event.root.sender ?: ""
         val formattedMemberName = span(memberName) {
             textColor = colorProvider.getColor(getColorFromUserId(event.root.sender
-                                                                  ?: ""))
+                    ?: ""))
         }
         val hasBeenEdited = event.annotations?.editSummary != null
         val informationData = MessageInformationData(eventId = eventId,
-                                                     senderId = event.root.sender ?: "",
-                                                     sendState = event.sendState,
-                                                     time = time,
-                                                     avatarUrl = avatarUrl,
-                                                     memberName = formattedMemberName,
-                                                     showInformation = showInformation,
-                                                     orderedReactionList = event.annotations?.reactionsSummary?.map {
-                                                         ReactionInfoData(it.key, it.count, it.addedByMe, it.localEchoEvents.isEmpty())
-                                                     },
-                                                     hasBeenEdited = hasBeenEdited
+                senderId = event.root.sender ?: "",
+                sendState = event.sendState,
+                time = time,
+                avatarUrl = avatarUrl,
+                memberName = formattedMemberName,
+                showInformation = showInformation,
+                orderedReactionList = event.annotations?.reactionsSummary?.map {
+                    ReactionInfoData(it.key, it.count, it.addedByMe, it.localEchoEvents.isEmpty())
+                },
+                hasBeenEdited = hasBeenEdited
         )
 
         if (event.root.unsignedData?.redactedEvent != null) {
@@ -125,9 +111,9 @@ class MessageItemFactory @Inject constructor(
 
         val messageContent: MessageContent =
                 event.annotations?.editSummary?.aggregatedContent?.toModel()
-                ?: event.root.getClearContent().toModel()
-                ?: //Malformed content, we should echo something on screen
-                return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
+                        ?: event.root.getClearContent().toModel()
+                        ?: //Malformed content, we should echo something on screen
+                        return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
 
         if (messageContent.relatesTo?.type == RelationType.REPLACE) {
             // ignore replace event, the targeted id is already edited
@@ -137,16 +123,16 @@ class MessageItemFactory @Inject constructor(
 //        val ev = all.toModel()
         return when (messageContent) {
             is MessageEmoteContent  -> buildEmoteMessageItem(messageContent,
-                                                             informationData,
-                                                             hasBeenEdited,
-                                                             event.annotations?.editSummary,
-                                                             callback)
+                    informationData,
+                    hasBeenEdited,
+                    event.annotations?.editSummary,
+                    callback)
             is MessageTextContent   -> buildTextMessageItem(event.sendState,
-                                                            messageContent,
-                                                            informationData,
-                                                            hasBeenEdited,
-                                                            event.annotations?.editSummary,
-                                                            callback
+                    messageContent,
+                    informationData,
+                    hasBeenEdited,
+                    event.annotations?.editSummary,
+                    callback
             )
             is MessageImageContent  -> buildImageMessageItem(messageContent, informationData, callback)
             is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback)
@@ -161,6 +147,7 @@ class MessageItemFactory @Inject constructor(
                                       informationData: MessageInformationData,
                                       callback: TimelineEventController.Callback?): MessageFileItem? {
         return MessageFileItem_()
+                .avatarRenderer(avatarRenderer)
                 .informationData(informationData)
                 .avatarCallback(callback)
                 .filename(messageContent.body)
@@ -177,7 +164,7 @@ class MessageItemFactory @Inject constructor(
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                                             ?: false
+                            ?: false
                 }
     }
 
@@ -185,6 +172,7 @@ class MessageItemFactory @Inject constructor(
                                      informationData: MessageInformationData,
                                      callback: TimelineEventController.Callback?): MessageFileItem? {
         return MessageFileItem_()
+                .avatarRenderer(avatarRenderer)
                 .informationData(informationData)
                 .avatarCallback(callback)
                 .filename(messageContent.body)
@@ -197,7 +185,7 @@ class MessageItemFactory @Inject constructor(
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                                             ?: false
+                            ?: false
                 }
                 .clickListener(
                         DebouncedClickListener(View.OnClickListener { _ ->
@@ -226,6 +214,9 @@ class MessageItemFactory @Inject constructor(
                 rotation = messageContent.info?.rotation
         )
         return MessageImageVideoItem_()
+                .avatarRenderer(avatarRenderer)
+                .imageContentRenderer(imageContentRenderer)
+                .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
                 .playable(messageContent.info?.mimeType == "image/gif")
                 .informationData(informationData)
                 .avatarCallback(callback)
@@ -242,7 +233,7 @@ class MessageItemFactory @Inject constructor(
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                                             ?: false
+                            ?: false
                 }
     }
 
@@ -267,6 +258,9 @@ class MessageItemFactory @Inject constructor(
         )
 
         return MessageImageVideoItem_()
+                .imageContentRenderer(imageContentRenderer)
+                .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
+                .avatarRenderer(avatarRenderer)
                 .playable(true)
                 .informationData(informationData)
                 .avatarCallback(callback)
@@ -280,7 +274,7 @@ class MessageItemFactory @Inject constructor(
                 .clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) }
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                                             ?: false
+                            ?: false
                 }
     }
 
@@ -306,6 +300,7 @@ class MessageItemFactory @Inject constructor(
                         message(linkifiedBody)
                     }
                 }
+                .avatarRenderer(avatarRenderer)
                 .informationData(informationData)
                 .avatarCallback(callback)
                 .reactionPillCallback(callback)
@@ -317,7 +312,7 @@ class MessageItemFactory @Inject constructor(
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                                             ?: false
+                            ?: false
                 }
     }
 
@@ -349,9 +344,9 @@ class MessageItemFactory @Inject constructor(
                 //nop
             }
         },
-                          editStart,
-                          editEnd,
-                          Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
+                editStart,
+                editEnd,
+                Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
         return spannable
     }
 
@@ -368,6 +363,7 @@ class MessageItemFactory @Inject constructor(
             linkifyBody(formattedBody, callback)
         }
         return MessageTextItem_()
+                .avatarRenderer(avatarRenderer)
                 .message(message)
                 .informationData(informationData)
                 .avatarCallback(callback)
@@ -383,7 +379,7 @@ class MessageItemFactory @Inject constructor(
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                                             ?: false
+                            ?: false
                 }
     }
 
@@ -406,6 +402,7 @@ class MessageItemFactory @Inject constructor(
                         message(message)
                     }
                 }
+                .avatarRenderer(avatarRenderer)
                 .informationData(informationData)
                 .avatarCallback(callback)
                 .reactionPillCallback(callback)
@@ -416,13 +413,14 @@ class MessageItemFactory @Inject constructor(
                         }))
                 .longClickListener { view ->
                     return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
-                                             ?: false
+                            ?: false
                 }
     }
 
     private fun buildRedactedItem(informationData: MessageInformationData,
                                   callback: TimelineEventController.Callback?): RedactedMessageItem? {
         return RedactedMessageItem_()
+                .avatarRenderer(avatarRenderer)
                 .informationData(informationData)
                 .avatarCallback(callback)
     }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/NoticeItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/NoticeItemFactory.kt
index 00d8070f..e1349fef 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/NoticeItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/NoticeItemFactory.kt
@@ -17,6 +17,7 @@
 package im.vector.riotredesign.features.home.room.detail.timeline.factory
 
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
+import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
 import im.vector.riotredesign.features.home.room.detail.timeline.format.NoticeEventFormatter
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderAvatar
@@ -26,7 +27,8 @@ import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem
 import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_
 import javax.inject.Inject
 
-class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEventFormatter) {
+class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEventFormatter,
+                                            private val avatarRenderer: AvatarRenderer) {
 
     fun create(event: TimelineEvent,
                callback: TimelineEventController.Callback?): NoticeItem? {
@@ -41,6 +43,7 @@ class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEv
         )
 
         return NoticeItem_()
+                .avatarRenderer(avatarRenderer)
                 .noticeText(formattedText)
                 .informationData(informationData)
                 .baseCallback(callback)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
index 93b567b1..e72dc9dc 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
@@ -25,10 +25,12 @@ import android.widget.TextView
 import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import im.vector.riotredesign.features.media.ImageContentRenderer
 import java.io.File
+import javax.inject.Inject
 
-object ContentUploadStateTrackerBinder {
+class ContentUploadStateTrackerBinder @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) {
 
     private val updateListeners = mutableMapOf()
 
@@ -36,7 +38,7 @@ object ContentUploadStateTrackerBinder {
              mediaData: ImageContentRenderer.Data,
              progressLayout: ViewGroup) {
 
-        Matrix.getInstance(progressLayout.context).currentSession?.also { session ->
+        activeSessionHolder.getActiveSession().also { session ->
             val uploadStateTracker = session.contentUploadProgressTracker()
             val updateListener = ContentMediaProgressUpdater(progressLayout, mediaData)
             updateListeners[eventId] = updateListener
@@ -44,8 +46,8 @@ object ContentUploadStateTrackerBinder {
         }
     }
 
-    fun unbind(eventId: String, progressLayout: ViewGroup) {
-        Matrix.getInstance(progressLayout.context).currentSession?.also { session ->
+    fun unbind(eventId: String) {
+        activeSessionHolder.getActiveSession().also { session ->
             val uploadStateTracker = session.contentUploadProgressTracker()
             updateListeners[eventId]?.also {
                 uploadStateTracker.untrack(eventId, it)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/AbsMessageItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/AbsMessageItem.kt
index 8a323968..ffa62997 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/AbsMessageItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/AbsMessageItem.kt
@@ -40,6 +40,8 @@ abstract class AbsMessageItem : BaseEventItem() {
 
     abstract val informationData: MessageInformationData
 
+    abstract val avatarRenderer: AvatarRenderer
+
     @EpoxyAttribute
     var longClickListener: View.OnLongClickListener? = null
 
@@ -96,7 +98,7 @@ abstract class AbsMessageItem : BaseEventItem() {
             holder.timeView.visibility = View.VISIBLE
             holder.timeView.text = informationData.time
             holder.memberNameView.text = informationData.memberName
-            AvatarRenderer.render(informationData.avatarUrl, informationData.senderId, informationData.memberName?.toString(), holder.avatarImageView)
+            avatarRenderer.render(informationData.avatarUrl, informationData.senderId, informationData.memberName?.toString(), holder.avatarImageView)
             holder.view.setOnClickListener(cellClickListener)
             holder.view.setOnLongClickListener(longClickListener)
             holder.avatarImageView.setOnLongClickListener(longClickListener)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MergedHeaderItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MergedHeaderItem.kt
index 6cdd7e15..bd1a08b2 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MergedHeaderItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MergedHeaderItem.kt
@@ -30,6 +30,7 @@ import im.vector.riotredesign.features.home.AvatarRenderer
 data class MergedHeaderItem(private val isCollapsed: Boolean,
                             private val mergeId: String,
                             private val mergeData: List,
+                            private val avatarRenderer: AvatarRenderer,
                             private val onCollapsedStateChanged: (Boolean) -> Unit
 ) : BaseEventItem() {
 
@@ -63,7 +64,7 @@ data class MergedHeaderItem(private val isCollapsed: Boolean,
                 val data = distinctMergeData.getOrNull(index)
                 if (data != null && view is ImageView) {
                     view.visibility = View.VISIBLE
-                    AvatarRenderer.render(data.avatarUrl, data.userId, data.memberName, view)
+                    avatarRenderer.render(data.avatarUrl, data.userId, data.memberName, view)
                 } else {
                     view.visibility = View.GONE
                 }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageFileItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageFileItem.kt
index 66055984..9ec8d08b 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageFileItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageFileItem.kt
@@ -25,6 +25,7 @@ import androidx.annotation.DrawableRes
 import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
 import im.vector.riotredesign.R
+import im.vector.riotredesign.features.home.AvatarRenderer
 
 @EpoxyModelClass(layout = R.layout.item_timeline_event_base)
 abstract class MessageFileItem : AbsMessageItem() {
@@ -37,6 +38,8 @@ abstract class MessageFileItem : AbsMessageItem() {
     @EpoxyAttribute
     override lateinit var informationData: MessageInformationData
     @EpoxyAttribute
+    override lateinit var avatarRenderer: AvatarRenderer
+    @EpoxyAttribute
     var clickListener: View.OnClickListener? = null
 
     override fun bind(holder: Holder) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
index 25eb8bca..33bf5732 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
@@ -22,6 +22,7 @@ import android.widget.ImageView
 import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
 import im.vector.riotredesign.R
+import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
 import im.vector.riotredesign.features.media.ImageContentRenderer
 
@@ -33,14 +34,20 @@ abstract class MessageImageVideoItem : AbsMessageItem() {
     @EpoxyAttribute
     var message: CharSequence? = null
     @EpoxyAttribute
+    override lateinit var avatarRenderer: AvatarRenderer
+    @EpoxyAttribute
     override lateinit var informationData: MessageInformationData
 
     val mvmtMethod = BetterLinkMovementMethod.newInstance().also {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/NoticeItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/NoticeItem.kt
index d190875f..b5d5acc8 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/NoticeItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/NoticeItem.kt
@@ -28,6 +28,9 @@ import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventCo
 @EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo)
 abstract class NoticeItem : BaseEventItem() {
 
+    @EpoxyAttribute
+    lateinit var avatarRenderer: AvatarRenderer
+
     @EpoxyAttribute
     var noticeText: CharSequence? = null
 
@@ -46,7 +49,7 @@ abstract class NoticeItem : BaseEventItem() {
     override fun bind(holder: Holder) {
         super.bind(holder)
         holder.noticeTextView.text = noticeText
-        AvatarRenderer.render(
+        avatarRenderer.render(
                 informationData.avatarUrl,
                 informationData.senderId,
                 informationData.memberName?.toString()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/RedactedMessageItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/RedactedMessageItem.kt
index 7331a6f3..d690347d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/RedactedMessageItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/RedactedMessageItem.kt
@@ -3,12 +3,15 @@ package im.vector.riotredesign.features.home.room.detail.timeline.item
 import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
 import im.vector.riotredesign.R
+import im.vector.riotredesign.features.home.AvatarRenderer
 
 @EpoxyModelClass(layout = R.layout.item_timeline_event_base)
 abstract class RedactedMessageItem : AbsMessageItem() {
 
     @EpoxyAttribute
     override lateinit var informationData: MessageInformationData
+    @EpoxyAttribute
+    override lateinit var avatarRenderer: AvatarRenderer
 
     override fun getStubType(): Int = STUB_ID
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt
index 08f7fdb3..992b697e 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt
@@ -25,13 +25,15 @@ import im.vector.matrix.android.api.session.room.model.message.MessageContent
 import im.vector.riotredesign.core.extensions.localDateTime
 import im.vector.riotredesign.core.resources.DateProvider
 import im.vector.riotredesign.core.resources.StringProvider
+import im.vector.riotredesign.features.home.AvatarRenderer
 import im.vector.riotredesign.features.home.room.detail.timeline.format.NoticeEventFormatter
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
 import javax.inject.Inject
 
 class RoomSummaryController @Inject constructor(private val stringProvider: StringProvider,
                                                 private val eventFormatter: NoticeEventFormatter,
-                                                private val timelineDateFormatter: TimelineDateFormatter
+                                                private val timelineDateFormatter: TimelineDateFormatter,
+                                                private val avatarRenderer: AvatarRenderer
 ) : TypedEpoxyController() {
 
     var callback: Callback? = null
@@ -110,6 +112,7 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
 
             }
             roomSummaryItem {
+                avatarRenderer(avatarRenderer)
                 id(roomSummary.roomId)
                 roomId(roomSummary.roomId)
                 lastEventTime(lastMessageTime)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryItem.kt
index bf6fbcaa..1207cb13 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryItem.kt
@@ -30,6 +30,7 @@ import im.vector.riotredesign.features.home.AvatarRenderer
 @EpoxyModelClass(layout = R.layout.item_room)
 abstract class RoomSummaryItem : VectorEpoxyModel() {
 
+    @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
     @EpoxyAttribute lateinit var roomName: CharSequence
     @EpoxyAttribute lateinit var roomId: String
     @EpoxyAttribute lateinit var lastFormattedEvent: CharSequence
@@ -47,7 +48,7 @@ abstract class RoomSummaryItem : VectorEpoxyModel() {
         holder.lastEventTimeView.text = lastEventTime
         holder.lastEventView.text = lastFormattedEvent
         holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadCount, showHighlighted))
-        AvatarRenderer.render(avatarUrl, roomId, roomName.toString(), holder.avatarImageView)
+        avatarRenderer.render(avatarUrl, roomId, roomName.toString(), holder.avatarImageView)
     }
 
     class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt
index e57de8d1..6e26be59 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt
@@ -26,37 +26,25 @@ import im.vector.matrix.android.api.permalinks.PermalinkParser
 import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.core.glide.GlideApp
 import im.vector.riotredesign.core.glide.GlideRequests
+import im.vector.riotredesign.features.home.AvatarRenderer
 import org.commonmark.node.BlockQuote
 import org.commonmark.node.HtmlBlock
 import org.commonmark.node.HtmlInline
 import org.commonmark.node.Node
-import ru.noties.markwon.AbstractMarkwonPlugin
-import ru.noties.markwon.Markwon
-import ru.noties.markwon.MarkwonConfiguration
-import ru.noties.markwon.MarkwonVisitor
-import ru.noties.markwon.SpannableBuilder
+import ru.noties.markwon.*
 import ru.noties.markwon.html.HtmlTag
 import ru.noties.markwon.html.MarkwonHtmlParserImpl
 import ru.noties.markwon.html.MarkwonHtmlRenderer
 import ru.noties.markwon.html.TagHandler
-import ru.noties.markwon.html.tag.BlockquoteHandler
-import ru.noties.markwon.html.tag.EmphasisHandler
-import ru.noties.markwon.html.tag.HeadingHandler
-import ru.noties.markwon.html.tag.ImageHandler
-import ru.noties.markwon.html.tag.LinkHandler
-import ru.noties.markwon.html.tag.ListHandler
-import ru.noties.markwon.html.tag.StrikeHandler
-import ru.noties.markwon.html.tag.StrongEmphasisHandler
-import ru.noties.markwon.html.tag.SubScriptHandler
-import ru.noties.markwon.html.tag.SuperScriptHandler
-import ru.noties.markwon.html.tag.UnderlineHandler
+import ru.noties.markwon.html.tag.*
 import java.util.Arrays.asList
 import javax.inject.Inject
 
 class EventHtmlRenderer @Inject constructor(context: AppCompatActivity,
+                                            val avatarRenderer: AvatarRenderer,
                                             session: Session) {
     private val markwon = Markwon.builder(context)
-            .usePlugin(MatrixPlugin.create(GlideApp.with(context), context, session))
+            .usePlugin(MatrixPlugin.create(GlideApp.with(context), context, avatarRenderer, session))
             .build()
 
     fun render(text: String): CharSequence {
@@ -67,6 +55,7 @@ class EventHtmlRenderer @Inject constructor(context: AppCompatActivity,
 
 private class MatrixPlugin private constructor(private val glideRequests: GlideRequests,
                                                private val context: Context,
+                                               private val avatarRenderer: AvatarRenderer,
                                                private val session: Session) : AbstractMarkwonPlugin() {
 
     override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
@@ -80,7 +69,7 @@ private class MatrixPlugin private constructor(private val glideRequests: GlideR
                         ImageHandler.create())
                 .setHandler(
                         "a",
-                        MxLinkHandler(glideRequests, context, session))
+                        MxLinkHandler(glideRequests, context, avatarRenderer, session))
                 .setHandler(
                         "blockquote",
                         BlockquoteHandler())
@@ -112,7 +101,7 @@ private class MatrixPlugin private constructor(private val glideRequests: GlideR
                         asList("h1", "h2", "h3", "h4", "h5", "h6"),
                         HeadingHandler())
                 .setHandler("mx-reply",
-                            MxReplyTagHandler())
+                        MxReplyTagHandler())
 
     }
 
@@ -135,14 +124,15 @@ private class MatrixPlugin private constructor(private val glideRequests: GlideR
 
     companion object {
 
-        fun create(glideRequests: GlideRequests, context: Context, session: Session): MatrixPlugin {
-            return MatrixPlugin(glideRequests, context, session)
+        fun create(glideRequests: GlideRequests, context: Context, avatarRenderer: AvatarRenderer, session: Session): MatrixPlugin {
+            return MatrixPlugin(glideRequests, context, avatarRenderer, session)
         }
     }
 }
 
 private class MxLinkHandler(private val glideRequests: GlideRequests,
                             private val context: Context,
+                            private val avatarRenderer: AvatarRenderer,
                             private val session: Session) : TagHandler() {
 
     private val linkHandler = LinkHandler()
@@ -154,7 +144,7 @@ private class MxLinkHandler(private val glideRequests: GlideRequests,
             when (permalinkData) {
                 is PermalinkData.UserLink -> {
                     val user = session.getUser(permalinkData.userId)
-                    val span = PillImageSpan(glideRequests, context, permalinkData.userId, user)
+                    val span = PillImageSpan(glideRequests, avatarRenderer, context, permalinkData.userId, user)
                     SpannableBuilder.setSpans(
                             visitor.builder(),
                             span,
diff --git a/vector/src/main/java/im/vector/riotredesign/features/html/PillImageSpan.kt b/vector/src/main/java/im/vector/riotredesign/features/html/PillImageSpan.kt
index e83e20e6..c5939e6d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/html/PillImageSpan.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/html/PillImageSpan.kt
@@ -37,6 +37,7 @@ import java.lang.ref.WeakReference
  * It's needed to call [bind] method to start requesting avatar, otherwise only the placeholder icon will be displayed if not already cached.
  */
 class PillImageSpan(private val glideRequests: GlideRequests,
+                    private val avatarRenderer: AvatarRenderer,
                     private val context: Context,
                     private val userId: String,
                     private val user: User?) : ReplacementSpan() {
@@ -52,7 +53,7 @@ class PillImageSpan(private val glideRequests: GlideRequests,
     @UiThread
     fun bind(textView: TextView) {
         tv = WeakReference(textView)
-        AvatarRenderer.render(context, glideRequests, user?.avatarUrl, userId, displayName, target)
+        avatarRenderer.render(context, glideRequests, user?.avatarUrl, userId, displayName, target)
     }
 
     // ReplacementSpan *****************************************************************************
@@ -105,7 +106,7 @@ class PillImageSpan(private val glideRequests: GlideRequests,
             textStartPadding = textPadding
             setChipMinHeightResource(R.dimen.pill_min_height)
             setChipIconSizeResource(R.dimen.pill_avatar_size)
-            chipIcon = AvatarRenderer.getPlaceholderDrawable(context, userId, displayName)
+            chipIcon = avatarRenderer.getPlaceholderDrawable(context, userId, displayName)
             setBounds(0, 0, intrinsicWidth, intrinsicHeight)
         }
     }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/invite/VectorInviteView.kt b/vector/src/main/java/im/vector/riotredesign/features/invite/VectorInviteView.kt
index 54b1476a..ada994df 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/invite/VectorInviteView.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/invite/VectorInviteView.kt
@@ -24,8 +24,10 @@ import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.updateLayoutParams
 import im.vector.matrix.android.api.session.user.model.User
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.HasScreenInjector
 import im.vector.riotredesign.features.home.AvatarRenderer
 import kotlinx.android.synthetic.main.vector_invite_view.view.*
+import javax.inject.Inject
 
 class VectorInviteView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
     : ConstraintLayout(context, attrs, defStyle) {
@@ -40,9 +42,13 @@ class VectorInviteView @JvmOverloads constructor(context: Context, attrs: Attrib
         SMALL
     }
 
+    @Inject lateinit var avatarRenderer: AvatarRenderer
     var callback: Callback? = null
 
     init {
+        if(context is HasScreenInjector){
+            context.injector().inject(this)
+        }
         View.inflate(context, R.layout.vector_invite_view, this)
         setBackgroundColor(Color.WHITE)
         inviteRejectView.setOnClickListener { callback?.onRejectInvite() }
@@ -52,7 +58,7 @@ class VectorInviteView @JvmOverloads constructor(context: Context, attrs: Attrib
     fun render(sender: User, mode: Mode = Mode.LARGE) {
         if (mode == Mode.LARGE) {
             updateLayoutParams { height = LayoutParams.MATCH_CONSTRAINT }
-            AvatarRenderer.render(sender.avatarUrl, sender.userId, sender.displayName, inviteAvatarView)
+            avatarRenderer.render(sender.avatarUrl, sender.userId, sender.displayName, inviteAvatarView)
             inviteIdentifierView.text = sender.userId
             inviteNameView.text = sender.displayName
             inviteLabelView.text = context.getString(R.string.send_you_invite)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/login/LoginActivity.kt
index 5298217c..12b6a240 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/login/LoginActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/login/LoginActivity.kt
@@ -30,7 +30,9 @@ import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.sync.FilterService
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import im.vector.riotredesign.core.di.ScreenComponent
+import im.vector.riotredesign.core.extensions.openAndStartSync
 import im.vector.riotredesign.core.extensions.showPassword
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import im.vector.riotredesign.features.home.HomeActivity
@@ -47,6 +49,7 @@ private const val DEFAULT_ANTIVIRUS_SERVER_URI = "https://matrix.org"
 class LoginActivity : VectorBaseActivity() {
 
     @Inject lateinit var authenticator: Authenticator
+    @Inject lateinit var activeSessionHolder: ActiveSessionHolder
 
     private var passwordShown = false
 
@@ -78,11 +81,8 @@ class LoginActivity : VectorBaseActivity() {
         progressBar.visibility = View.VISIBLE
         authenticator.authenticate(homeServerConnectionConfig, login, password, object : MatrixCallback {
             override fun onSuccess(data: Session) {
-                Matrix.getInstance(this@LoginActivity).currentSession = data
-                data.open()
-                data.setFilter(FilterService.FilterPreset.RiotFilter)
-                data.startSync()
-
+                activeSessionHolder.setActiveSession(data)
+                data.openAndStartSync()
                 goToHome()
             }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/media/ImageContentRenderer.kt
index e02536a0..741ad995 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/media/ImageContentRenderer.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/media/ImageContentRenderer.kt
@@ -24,12 +24,14 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners
 import com.github.piasy.biv.view.BigImageView
 import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.session.content.ContentUrlResolver
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import im.vector.riotredesign.core.glide.GlideApp
 import im.vector.riotredesign.core.utils.DimensionUtils.dpToPx
 import kotlinx.android.parcel.Parcelize
 import java.io.File
+import javax.inject.Inject
 
-object ImageContentRenderer {
+class ImageContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) {
 
     @Parcelize
     data class Data(
@@ -57,26 +59,26 @@ object ImageContentRenderer {
         val (width, height) = processSize(data, mode)
         imageView.layoutParams.height = height
         imageView.layoutParams.width = width
-        val contentUrlResolver = Matrix.getInstance(imageView.context).currentSession!!.contentUrlResolver()
+        val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
         val resolvedUrl = when (mode) {
-                              Mode.FULL_SIZE -> contentUrlResolver.resolveFullSize(data.url)
-                              Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE)
-                          }
-                          //Fallback to base url
-                          ?: data.url
+            Mode.FULL_SIZE -> contentUrlResolver.resolveFullSize(data.url)
+            Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE)
+        }
+        //Fallback to base url
+                ?: data.url
 
         GlideApp
                 .with(imageView)
                 .load(resolvedUrl)
                 .dontAnimate()
-                .transform(RoundedCorners(dpToPx(8,imageView.context)))
+                .transform(RoundedCorners(dpToPx(8, imageView.context)))
                 .thumbnail(0.3f)
                 .into(imageView)
     }
 
     fun render(data: Data, imageView: BigImageView) {
         val (width, height) = processSize(data, Mode.THUMBNAIL)
-        val contentUrlResolver = Matrix.getInstance(imageView.context).currentSession!!.contentUrlResolver()
+        val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
         val fullSize = contentUrlResolver.resolveFullSize(data.url)
         val thumbnail = contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE)
         imageView.showImage(
diff --git a/vector/src/main/java/im/vector/riotredesign/features/media/ImageMediaViewerActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/media/ImageMediaViewerActivity.kt
index 902c2f9b..4b980ccb 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/media/ImageMediaViewerActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/media/ImageMediaViewerActivity.kt
@@ -24,12 +24,20 @@ import android.os.Bundle
 import androidx.appcompat.widget.Toolbar
 import com.github.piasy.biv.indicator.progresspie.ProgressPieIndicator
 import com.github.piasy.biv.view.GlideImageViewFactory
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import kotlinx.android.synthetic.main.activity_image_media_viewer.*
+import javax.inject.Inject
 
 
 class ImageMediaViewerActivity : VectorBaseActivity() {
 
+    @Inject lateinit var imageContentRenderer: ImageContentRenderer
+
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(im.vector.riotredesign.R.layout.activity_image_media_viewer)
@@ -40,7 +48,7 @@ class ImageMediaViewerActivity : VectorBaseActivity() {
             configureToolbar(imageMediaViewerToolbar, mediaData)
             imageMediaViewerImageView.setImageViewFactory(GlideImageViewFactory())
             imageMediaViewerImageView.setProgressIndicator(ProgressPieIndicator())
-            ImageContentRenderer.render(mediaData, imageMediaViewerImageView)
+            imageContentRenderer.render(mediaData, imageMediaViewerImageView)
         }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/media/VideoContentRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/media/VideoContentRenderer.kt
index 54a91ed5..8fd4b43e 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/media/VideoContentRenderer.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/media/VideoContentRenderer.kt
@@ -20,9 +20,11 @@ import android.os.Parcelable
 import android.widget.ImageView
 import android.widget.VideoView
 import im.vector.matrix.android.api.Matrix
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import kotlinx.android.parcel.Parcelize
+import javax.inject.Inject
 
-object VideoContentRenderer {
+class VideoContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder){
 
     @Parcelize
     data class Data(
@@ -32,7 +34,7 @@ object VideoContentRenderer {
     ) : Parcelable
 
     fun render(data: Data, thumbnailView: ImageView, videoView: VideoView) {
-        val contentUrlResolver = Matrix.getInstance(videoView.context).currentSession!!.contentUrlResolver()
+        val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
         val resolvedUrl = contentUrlResolver.resolveFullSize(data.videoUrl)
         videoView.setVideoPath(resolvedUrl)
         videoView.start()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/media/VideoMediaViewerActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/media/VideoMediaViewerActivity.kt
index 0630a2cb..d0b70302 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/media/VideoMediaViewerActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/media/VideoMediaViewerActivity.kt
@@ -20,12 +20,21 @@ import android.content.Context
 import android.content.Intent
 import android.os.Bundle
 import androidx.appcompat.widget.Toolbar
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseActivity
+import im.vector.riotredesign.features.home.AvatarRenderer
 import kotlinx.android.synthetic.main.activity_video_media_viewer.*
+import javax.inject.Inject
 
 
 class VideoMediaViewerActivity : VectorBaseActivity() {
 
+    @Inject lateinit var videoContentRenderer: VideoContentRenderer
+
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(im.vector.riotredesign.R.layout.activity_video_media_viewer)
@@ -34,7 +43,7 @@ class VideoMediaViewerActivity : VectorBaseActivity() {
             finish()
         } else {
             configureToolbar(videoMediaViewerToolbar, mediaData)
-            VideoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerVideoView)
+            videoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerVideoView)
         }
     }
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReportActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReportActivity.kt
index 48f81021..d436013c 100755
--- a/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReportActivity.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReportActivity.kt
@@ -26,9 +26,11 @@ import butterknife.BindView
 import butterknife.OnCheckedChanged
 import butterknife.OnTextChanged
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.platform.VectorBaseActivity
 import kotlinx.android.synthetic.main.activity_bug_report.*
 import timber.log.Timber
+import javax.inject.Inject
 
 /**
  * Form to send a bug report
@@ -66,13 +68,17 @@ class BugReportActivity : VectorBaseActivity() {
     @BindView(R.id.bug_report_mask_view)
     lateinit var mMaskView: View
 
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
     override fun getLayoutRes() = R.layout.activity_bug_report
 
     override fun initUiAndData() {
         configureToolbar(bugReportToolbar)
 
-        if (BugReporter.screenshot != null) {
-            mScreenShotPreview.setImageBitmap(BugReporter.screenshot)
+        if (bugReporter.screenshot != null) {
+            mScreenShotPreview.setImageBitmap(bugReporter.screenshot)
         } else {
             mScreenShotPreview.isVisible = false
             mIncludeScreenShotButton.isChecked = false
@@ -120,7 +126,7 @@ class BugReportActivity : VectorBaseActivity() {
         mProgressBar.isVisible = true
         mProgressBar.progress = 0
 
-        BugReporter.sendBugReport(this,
+        bugReporter.sendBugReport(this,
                 mIncludeLogsButton.isChecked,
                 mIncludeCrashLogsButton.isChecked,
                 mIncludeScreenShotButton.isChecked,
@@ -190,12 +196,12 @@ class BugReportActivity : VectorBaseActivity() {
 
     @OnCheckedChanged(R.id.bug_report_button_include_screenshot)
     internal fun onSendScreenshotChanged() {
-        mScreenShotPreview.isVisible = mIncludeScreenShotButton.isChecked && BugReporter.screenshot != null
+        mScreenShotPreview.isVisible = mIncludeScreenShotButton.isChecked && bugReporter.screenshot != null
     }
 
     override fun onBackPressed() {
         // Ensure there is no crash status remaining, which will be sent later on by mistake
-        BugReporter.deleteCrashFile(this)
+        bugReporter.deleteCrashFile(this)
 
         super.onBackPressed()
     }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReporter.kt
index 59bf5c0a..778ce586 100755
--- a/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReporter.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/rageshake/BugReporter.kt
@@ -30,6 +30,7 @@ import android.view.View
 import im.vector.matrix.android.api.Matrix
 import im.vector.riotredesign.BuildConfig
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import im.vector.riotredesign.core.extensions.toOnOff
 import im.vector.riotredesign.core.utils.getDeviceLocale
 import im.vector.riotredesign.features.settings.VectorLocale
@@ -42,19 +43,26 @@ import java.io.*
 import java.net.HttpURLConnection
 import java.util.*
 import java.util.zip.GZIPOutputStream
+import javax.inject.Inject
+import javax.inject.Singleton
 
 /**
  * BugReporter creates and sends the bug reports.
  */
-object BugReporter {
+@Singleton
+class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSessionHolder){
     var inMultiWindowMode = false
 
-    // filenames
-    private const val LOG_CAT_ERROR_FILENAME = "logcatError.log"
-    private const val LOG_CAT_FILENAME = "logcat.log"
-    private const val LOG_CAT_SCREENSHOT_FILENAME = "screenshot.png"
-    private const val CRASH_FILENAME = "crash.log"
+    companion object {
+        // filenames
+        private const val LOG_CAT_ERROR_FILENAME = "logcatError.log"
+        private const val LOG_CAT_FILENAME = "logcat.log"
+        private const val LOG_CAT_SCREENSHOT_FILENAME = "screenshot.png"
+        private const val CRASH_FILENAME = "crash.log"
 
+        private const val BUFFER_SIZE = 1024 * 1024 * 50
+
+    }
 
     // the http client
     private val mOkHttpClient = OkHttpClient()
@@ -74,8 +82,6 @@ object BugReporter {
     var screenshot: Bitmap? = null
         private set
 
-    private const val BUFFER_SIZE = 1024 * 1024 * 50
-
     private val LOGCAT_CMD_ERROR = arrayOf("logcat", ///< Run 'logcat' command
             "-d", ///< Dump the log rather than continue outputting it
             "-v", // formatting
@@ -195,7 +201,7 @@ object BugReporter {
                 var matrixSdkVersion = "undefined"
                 var olmVersion = "undefined"
 
-                Matrix.getInstance(context).currentSession?.let { session ->
+                activeSessionHolder.getActiveSession().let { session ->
                     userId = session.sessionParams.credentials.userId
                     deviceId = session.sessionParams.credentials.deviceId ?: "undefined"
                     // TODO matrixSdkVersion = session.getVersion(true);
diff --git a/vector/src/main/java/im/vector/riotredesign/features/rageshake/RageShake.kt b/vector/src/main/java/im/vector/riotredesign/features/rageshake/RageShake.kt
index 446d2f48..4125ac20 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/rageshake/RageShake.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/rageshake/RageShake.kt
@@ -16,7 +16,6 @@
 
 package im.vector.riotredesign.features.rageshake
 
-import android.app.Activity
 import android.content.Context
 import android.hardware.Sensor
 import android.hardware.SensorManager
@@ -26,8 +25,10 @@ import androidx.appcompat.app.AppCompatActivity
 import androidx.core.content.edit
 import com.squareup.seismic.ShakeDetector
 import im.vector.riotredesign.R
+import javax.inject.Inject
 
-class RageShake(val activity: Activity) : ShakeDetector.Listener {
+class RageShake @Inject constructor(private val activity: AppCompatActivity,
+                                    private val bugReporter: BugReporter) : ShakeDetector.Listener {
 
     private var shakeDetector: ShakeDetector? = null
 
@@ -94,7 +95,7 @@ class RageShake(val activity: Activity) : ShakeDetector.Listener {
     }
 
     private fun openBugReportScreen() {
-        BugReporter.openBugReportScreen(activity)
+        bugReporter.openBugReportScreen(activity)
     }
 
     companion object {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/rageshake/VectorUncaughtExceptionHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/rageshake/VectorUncaughtExceptionHandler.kt
index 60959029..a7da508e 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/rageshake/VectorUncaughtExceptionHandler.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/rageshake/VectorUncaughtExceptionHandler.kt
@@ -16,7 +16,6 @@
 
 package im.vector.riotredesign.features.rageshake
 
-import android.annotation.SuppressLint
 import android.content.Context
 import android.os.Build
 import androidx.core.content.edit
@@ -25,12 +24,16 @@ import im.vector.riotredesign.BuildConfig
 import timber.log.Timber
 import java.io.PrintWriter
 import java.io.StringWriter
+import javax.inject.Inject
+import javax.inject.Singleton
 
-@SuppressLint("StaticFieldLeak")
-object VectorUncaughtExceptionHandler : Thread.UncaughtExceptionHandler {
+@Singleton
+class VectorUncaughtExceptionHandler @Inject constructor(private val bugReporter: BugReporter) : Thread.UncaughtExceptionHandler {
 
     // key to save the crash status
-    private const val PREFS_CRASH_KEY = "PREFS_CRASH_KEY"
+    companion object {
+        private const val PREFS_CRASH_KEY = "PREFS_CRASH_KEY"
+    }
 
     private var vectorVersion: String = ""
     private var matrixSdkVersion: String = ""
@@ -44,9 +47,7 @@ object VectorUncaughtExceptionHandler : Thread.UncaughtExceptionHandler {
      */
     fun activate(context: Context) {
         this.context = context
-
         previousHandler = Thread.getDefaultUncaughtExceptionHandler()
-
         Thread.setDefaultUncaughtExceptionHandler(this)
     }
 
@@ -58,15 +59,10 @@ object VectorUncaughtExceptionHandler : Thread.UncaughtExceptionHandler {
      * @return the exception description
      */
     override fun uncaughtException(thread: Thread, throwable: Throwable) {
-        if (context == null) {
-            previousHandler?.uncaughtException(thread, throwable)
-            return
-        }
-
+        Timber.v("Uncaught exception: $throwable")
         PreferenceManager.getDefaultSharedPreferences(context).edit {
             putBoolean(PREFS_CRASH_KEY, true)
         }
-
         val b = StringBuilder()
         val appName = "RiotX" // TODO Matrix.getApplicationName()
 
@@ -114,7 +110,7 @@ object VectorUncaughtExceptionHandler : Thread.UncaughtExceptionHandler {
 
         val bugDescription = b.toString()
 
-        BugReporter.saveCrashReport(context, bugDescription)
+        bugReporter.saveCrashReport(context, bugDescription)
 
         // Show the classical system popup
         previousHandler?.uncaughtException(thread, throwable)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomItem.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomItem.kt
index 8e30809f..2f46fbce 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomItem.kt
@@ -31,6 +31,9 @@ import im.vector.riotredesign.features.home.AvatarRenderer
 @EpoxyModelClass(layout = R.layout.item_public_room)
 abstract class PublicRoomItem : VectorEpoxyModel() {
 
+    @EpoxyAttribute
+    lateinit var avatarRenderer: AvatarRenderer
+
     @EpoxyAttribute
     var avatarUrl: String? = null
 
@@ -61,7 +64,7 @@ abstract class PublicRoomItem : VectorEpoxyModel() {
     override fun bind(holder: Holder) {
         holder.rootView.setOnClickListener { globalListener?.invoke() }
 
-        AvatarRenderer.render(avatarUrl, roomId!!, roomName, holder.avatarView)
+        avatarRenderer.render(avatarUrl, roomId!!, roomName, holder.avatarView)
         holder.nameView.text = roomName
         holder.aliasView.setTextOrHide(roomAlias)
         holder.topicView.setTextOrHide(roomTopic)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsController.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsController.kt
index bf395868..b9bf30e7 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsController.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/PublicRoomsController.kt
@@ -28,9 +28,11 @@ import im.vector.riotredesign.core.epoxy.loadingItem
 import im.vector.riotredesign.core.epoxy.noResultItem
 import im.vector.riotredesign.core.error.ErrorFormatter
 import im.vector.riotredesign.core.resources.StringProvider
+import im.vector.riotredesign.features.home.AvatarRenderer
 import javax.inject.Inject
 
 class PublicRoomsController @Inject constructor(private val stringProvider: StringProvider,
+                                                private val avatarRenderer: AvatarRenderer,
                             private val errorFormatter: ErrorFormatter) : TypedEpoxyController() {
 
     var callback: Callback? = null
@@ -79,6 +81,7 @@ class PublicRoomsController @Inject constructor(private val stringProvider: Stri
 
     private fun buildPublicRoom(publicRoom: PublicRoom, viewState: PublicRoomsViewState) {
         publicRoomItem {
+            avatarRenderer(avatarRenderer)
             id(publicRoom.roomId)
             roomId(publicRoom.roomId)
             avatarUrl(publicRoom.avatarUrl)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
index d94503a1..95f9027c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt
@@ -47,6 +47,7 @@ class RoomPreviewNoPreviewFragment : VectorBaseFragment() {
 
     @Inject lateinit var errorFormatter: ErrorFormatter
     @Inject lateinit var roomPreviewViewModelFactory: RoomPreviewViewModel.Factory
+    @Inject lateinit var avatarRenderer: AvatarRenderer
     private val roomPreviewViewModel: RoomPreviewViewModel by fragmentViewModel()
     private val roomPreviewData: RoomPreviewData by args()
 
@@ -65,11 +66,11 @@ class RoomPreviewNoPreviewFragment : VectorBaseFragment() {
         super.onViewCreated(view, savedInstanceState)
 
         // Toolbar
-        AvatarRenderer.render(roomPreviewData.avatarUrl, roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewNoPreviewToolbarAvatar)
+        avatarRenderer.render(roomPreviewData.avatarUrl, roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewNoPreviewToolbarAvatar)
         roomPreviewNoPreviewToolbarTitle.text = roomPreviewData.roomName
 
         // Screen
-        AvatarRenderer.render(roomPreviewData.avatarUrl, roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewNoPreviewAvatar)
+        avatarRenderer.render(roomPreviewData.avatarUrl, roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewNoPreviewAvatar)
         roomPreviewNoPreviewName.text = roomPreviewData.roomName
         roomPreviewNoPreviewTopic.setTextOrHide(roomPreviewData.topic)
 
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt
index b176362a..700fd244 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt
@@ -55,6 +55,7 @@ class VectorSettingsNotificationsTroubleshootFragment : VectorBaseFragment() {
     private var testManager: NotificationTroubleshootTestManager? = null
     // members
     @Inject lateinit var session: Session
+    @Inject lateinit var bugReporter: BugReporter
 
     override fun getLayoutResId() = R.layout.fragment_settings_notifications_troubleshoot
 
@@ -78,7 +79,7 @@ class VectorSettingsNotificationsTroubleshootFragment : VectorBaseFragment() {
 
 
         mSummaryButton.setOnClickListener {
-            BugReporter.openBugReportScreen(activity!!)
+            bugReporter.openBugReportScreen(activity!!)
         }
 
         mRunButton.setOnClickListener {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutBottomSheetDialogFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutBottomSheetDialogFragment.kt
index f420a2ac..ff66800a 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutBottomSheetDialogFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/workers/signout/SignOutBottomSheetDialogFragment.kt
@@ -41,8 +41,6 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
 import im.vector.riotredesign.R
-import im.vector.riotredesign.core.di.HasInjector
-import im.vector.riotredesign.core.di.ScreenComponent
 import im.vector.riotredesign.core.utils.toast
 import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupManageActivity
 import im.vector.riotredesign.features.crypto.keysbackup.setup.KeysBackupSetupActivity

From 1fa7b7367a71d9373b2c1c387c94796ed0783060 Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Thu, 27 Jun 2019 15:25:01 +0200
Subject: [PATCH 09/11] Dagger: merge develop compiling now.

---
 .../java/im/vector/matrix/rx/RxSession.kt     |   5 +
 .../matrix/android/api/session/Session.kt     |   4 +
 .../internal/session/SessionComponent.kt      |  17 +-
 .../notification/DefaultPushRuleService.kt    |   5 +-
 .../internal/session/sync/job/SyncService.kt  |  22 +-
 .../OnApplicationUpgradeOrRebootReceiver.kt   |   8 +-
 .../vector/riotredesign/VectorApplication.kt  |   7 +-
 .../riotredesign/core/di/ScreenComponent.kt   |   3 +
 .../riotredesign/core/di/VectorComponent.kt   |   6 +
 .../riotredesign/core/di/ViewModelModule.kt   |   1 +
 .../core/pushers/PushersManager.kt            |   3 +-
 .../core/resources/AppNameProvider.kt         |   3 +-
 .../services/AlarmSyncBroadcastReceiver.kt    |  16 +-
 .../core/services/EventStreamServiceX.kt      | 587 ------------------
 .../features/home/HomePermalinkHandler.kt     |  57 --
 .../features/home/PermalinkHandler.kt         |   5 +-
 .../timeline/factory/EncryptedItemFactory.kt  |  11 +-
 .../notifications/NotifiableEventResolver.kt  |  27 +-
 .../NotificationBroadcastReceiver.kt          |  12 +-
 .../notifications/OutdatedEventDetector.kt    |   6 +-
 .../VectorSettingsNotificationFragment.kt     |  19 +-
 .../VectorSettingsPreferencesFragment.kt      |  44 +-
 .../settings/push/PushGatewaysFragment.kt     |   3 +-
 .../settings/push/PushGatewaysViewModel.kt    |  46 +-
 .../settings/push/PushRulesViewModel.kt       |   7 +-
 25 files changed, 192 insertions(+), 732 deletions(-)
 delete mode 100644 vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
 delete mode 100644 vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt

diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt
index 4205b049..af149116 100644
--- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt
+++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt
@@ -18,6 +18,7 @@ package im.vector.matrix.rx
 
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.group.model.GroupSummary
+import im.vector.matrix.android.api.session.pushers.Pusher
 import im.vector.matrix.android.api.session.room.model.RoomSummary
 import im.vector.matrix.android.api.session.sync.SyncState
 import io.reactivex.Observable
@@ -36,6 +37,10 @@ class RxSession(private val session: Session) {
         return session.syncState().asObservable()
     }
 
+    fun livePushers(): Observable> {
+        return session.livePushers().asObservable()
+    }
+
 }
 
 fun Session.rx(): RxSession {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt
index ac412678..d947e593 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt
@@ -54,6 +54,10 @@ interface Session :
      */
     val sessionParams: SessionParams
 
+    val myUserId : String
+        get() = sessionParams.credentials.userId
+
+
     /**
      * This method allow to open a session. It does start some service on the background.
      */
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
index 0cb78026..fc23b780 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt
@@ -22,6 +22,7 @@ import im.vector.matrix.android.api.auth.data.SessionParams
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.internal.crypto.CryptoModule
 import im.vector.matrix.android.internal.di.MatrixComponent
+import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
 import im.vector.matrix.android.internal.session.cache.CacheModule
 import im.vector.matrix.android.internal.session.content.ContentModule
 import im.vector.matrix.android.internal.session.content.UploadContentWorker
@@ -37,8 +38,11 @@ import im.vector.matrix.android.internal.session.room.send.RedactEventWorker
 import im.vector.matrix.android.internal.session.room.send.SendEventWorker
 import im.vector.matrix.android.internal.session.signout.SignOutModule
 import im.vector.matrix.android.internal.session.sync.SyncModule
+import im.vector.matrix.android.internal.session.sync.SyncTask
+import im.vector.matrix.android.internal.session.sync.SyncTokenStore
 import im.vector.matrix.android.internal.session.sync.job.SyncWorker
 import im.vector.matrix.android.internal.session.user.UserModule
+import im.vector.matrix.android.internal.task.TaskExecutor
 
 @Component(dependencies = [MatrixComponent::class],
         modules = [
@@ -61,6 +65,14 @@ internal interface SessionComponent {
 
     fun session(): Session
 
+    fun syncTask(): SyncTask
+
+    fun syncTokenStore(): SyncTokenStore
+
+    fun networkConnectivityChecker(): NetworkConnectivityChecker
+
+    fun taskExecutor(): TaskExecutor
+
     fun inject(sendEventWorker: SendEventWorker)
 
     fun inject(sendEventWorker: SendRelationWorker)
@@ -77,7 +89,6 @@ internal interface SessionComponent {
 
     fun inject(addHttpPusherWorker: AddHttpPusherWorker)
 
-
     @Component.Factory
     interface Factory {
         fun create(
@@ -86,4 +97,6 @@ internal interface SessionComponent {
     }
 
 
-}
\ No newline at end of file
+}
+
+
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt
index 9b947829..e8ef2f7d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt
@@ -27,6 +27,7 @@ import im.vector.matrix.android.internal.database.mapper.PushRulesMapper
 import im.vector.matrix.android.internal.database.model.PushRulesEntity
 import im.vector.matrix.android.internal.database.model.PusherEntityFields
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.SessionScope
 import im.vector.matrix.android.internal.session.pushers.GetPushRulesTask
 import im.vector.matrix.android.internal.session.pushers.UpdatePushRuleEnableStatusTask
 import im.vector.matrix.android.internal.task.TaskExecutor
@@ -34,7 +35,7 @@ import im.vector.matrix.android.internal.task.configureWith
 import timber.log.Timber
 import javax.inject.Inject
 
-
+@SessionScope
 internal class DefaultPushRuleService @Inject constructor(
         private val sessionParams: SessionParams,
         private val pushRulesTask: GetPushRulesTask,
@@ -43,10 +44,8 @@ internal class DefaultPushRuleService @Inject constructor(
         private val monarchy: Monarchy
 ) : PushRuleService {
 
-
     private var listeners = ArrayList()
 
-
     override fun fetchPushRules(scope: String) {
         pushRulesTask
                 .configureWith(Unit)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt
index a1872d0a..2fa0d494 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt
@@ -19,7 +19,9 @@ import android.app.Service
 import android.content.Intent
 import android.os.Binder
 import android.os.IBinder
+import androidx.work.ListenableWorker
 import com.squareup.moshi.JsonEncodingException
+import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.failure.Failure
 import im.vector.matrix.android.api.failure.MatrixError
@@ -31,6 +33,7 @@ import im.vector.matrix.android.internal.session.sync.model.SyncResponse
 import im.vector.matrix.android.internal.task.TaskExecutor
 import im.vector.matrix.android.internal.task.TaskThread
 import im.vector.matrix.android.internal.task.configureWith
+import im.vector.matrix.android.internal.worker.getSessionComponent
 import timber.log.Timber
 import java.net.SocketTimeoutException
 import java.util.*
@@ -46,15 +49,15 @@ private const val BACKGROUND_LONG_POOL_TIMEOUT = 0L
  * in order to be able to perform a sync even if the app is not running.
  * The  and  must be declared in the Manifest or the app using the SDK
  */
-internal open class SyncService : Service() {
+open class SyncService : Service() {
 
     private var mIsSelfDestroyed: Boolean = false
     private var cancelableTask: Cancelable? = null
 
-    @Inject lateinit var syncTokenStore: SyncTokenStore
-    @Inject lateinit var syncTask: SyncTask
-    @Inject lateinit var networkConnectivityChecker: NetworkConnectivityChecker
-    @Inject lateinit var taskExecutor: TaskExecutor
+    private lateinit var syncTokenStore: SyncTokenStore
+    private lateinit var syncTask: SyncTask
+    private lateinit var networkConnectivityChecker: NetworkConnectivityChecker
+    private lateinit var taskExecutor: TaskExecutor
 
     private var localBinder = LocalBinder()
 
@@ -68,6 +71,12 @@ internal open class SyncService : Service() {
         nextBatchDelay = 60_000L
         timeout = 0
         intent?.let {
+            val userId = it.getStringExtra(EXTRA_USER_ID)
+            val sessionComponent =  Matrix.getInstance(applicationContext).sessionManager.getSessionComponent(userId) ?: return@let
+            syncTokenStore = sessionComponent.syncTokenStore()
+            syncTask = sessionComponent.syncTask()
+            networkConnectivityChecker = sessionComponent.networkConnectivityChecker()
+            taskExecutor = sessionComponent.taskExecutor()
             if (cancelableTask == null) {
                 timer.cancel()
                 timer = Timer()
@@ -191,7 +200,6 @@ internal open class SyncService : Service() {
         }
 
         internal fun notifySyncFinish() {
-
             listeners.forEach {
                 try {
                     it.onSyncFinsh()
@@ -235,6 +243,8 @@ internal open class SyncService : Service() {
 
     companion object {
 
+        const val EXTRA_USER_ID = "EXTRA_USER_ID"
+
         fun startLongPool(delay: Long) {
 
         }
diff --git a/vector/src/fdroid/java/im/vector/riotredesign/receiver/OnApplicationUpgradeOrRebootReceiver.kt b/vector/src/fdroid/java/im/vector/riotredesign/receiver/OnApplicationUpgradeOrRebootReceiver.kt
index a13bc71a..c8a64e39 100644
--- a/vector/src/fdroid/java/im/vector/riotredesign/receiver/OnApplicationUpgradeOrRebootReceiver.kt
+++ b/vector/src/fdroid/java/im/vector/riotredesign/receiver/OnApplicationUpgradeOrRebootReceiver.kt
@@ -20,6 +20,7 @@ package im.vector.riotredesign.receiver
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
+import im.vector.riotredesign.core.di.HasVectorInjector
 import im.vector.riotredesign.core.services.AlarmSyncBroadcastReceiver
 import timber.log.Timber
 
@@ -27,6 +28,11 @@ class OnApplicationUpgradeOrRebootReceiver : BroadcastReceiver() {
 
     override fun onReceive(context: Context, intent: Intent) {
         Timber.v("## onReceive() ${intent.action}")
-        AlarmSyncBroadcastReceiver.scheduleAlarm(context, 10)
+        if (context is HasVectorInjector) {
+            val activeSession = context.injector().activeSessionHolder().getSafeActiveSession()
+            if (activeSession != null) {
+                AlarmSyncBroadcastReceiver.scheduleAlarm(context, activeSession.myUserId, 10)
+            }
+        }
     }
 }
diff --git a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
index 61754276..e6f65fbc 100644
--- a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
+++ b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt
@@ -114,7 +114,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
             @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
             fun entersForeground() {
                 AlarmSyncBroadcastReceiver.cancelAlarm(appContext)
-                activeSessionHolder.getActiveSession().also {
+                activeSessionHolder.getSafeActiveSession()?.also {
                     it.stopAnyBackgroundSync()
                 }
             }
@@ -128,8 +128,9 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
                 } else {
                     //TODO check if notifications are enabled for this device
                     //We need to use alarm in this mode
-                    if (PreferencesManager.areNotificationEnabledForDevice(applicationContext)) {
-                        AlarmSyncBroadcastReceiver.scheduleAlarm(applicationContext, 4_000L)
+                    val activeSession = activeSessionHolder.getSafeActiveSession()
+                    if (activeSession != null && PreferencesManager.areNotificationEnabledForDevice(applicationContext)) {
+                        AlarmSyncBroadcastReceiver.scheduleAlarm(applicationContext, activeSession.myUserId, 4_000L)
                         Timber.i("Alarm scheduled to restart service")
                     }
                 }
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
index 7bceedc8..8f3a3180 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt
@@ -53,6 +53,7 @@ import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomFragme
 import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerFragment
 import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment
 import im.vector.riotredesign.features.settings.VectorSettingsActivity
+import im.vector.riotredesign.features.settings.VectorSettingsNotificationPreferenceFragment
 import im.vector.riotredesign.features.settings.VectorSettingsPreferencesFragment
 
 @Component(dependencies = [VectorComponent::class], modules = [ViewModelModule::class, HomeModule::class])
@@ -133,6 +134,8 @@ interface ScreenComponent {
 
     fun inject(videoMediaViewerActivity: VideoMediaViewerActivity)
 
+    fun inject(vectorSettingsNotificationPreferenceFragment: VectorSettingsNotificationPreferenceFragment)
+
     @Component.Factory
     interface Factory {
         fun create(vectorComponent: VectorComponent,
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
index 54321160..5be30bb0 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
@@ -33,7 +33,9 @@ import im.vector.riotredesign.features.home.HomeNavigator
 import im.vector.riotredesign.features.home.HomeRoomListObservableStore
 import im.vector.riotredesign.features.home.group.SelectedGroupStore
 import im.vector.riotredesign.features.navigation.Navigator
+import im.vector.riotredesign.features.notifications.NotificationBroadcastReceiver
 import im.vector.riotredesign.features.notifications.NotificationDrawerManager
+import im.vector.riotredesign.features.notifications.PushRuleTriggerListener
 import im.vector.riotredesign.features.rageshake.BugReporter
 import im.vector.riotredesign.features.rageshake.RageShake
 import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
@@ -43,6 +45,8 @@ import javax.inject.Singleton
 @Singleton
 interface VectorComponent {
 
+    fun inject(vectorApplication: NotificationBroadcastReceiver)
+
     fun inject(vectorApplication: VectorApplication)
 
     fun matrix(): Matrix
@@ -79,6 +83,8 @@ interface VectorComponent {
 
     fun vectorUncaughtExceptionHandler(): VectorUncaughtExceptionHandler
 
+    fun pushRuleTriggerListener(): PushRuleTriggerListener
+
     @Component.Factory
     interface Factory {
         fun create(@BindsInstance context: Context): VectorComponent
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
index 34b3e150..df984d23 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt
@@ -57,6 +57,7 @@ import im.vector.riotredesign.features.workers.signout.SignOutViewModel
 
 @Module
 interface ViewModelModule {
+    
 
     @Binds
     fun bindViewModelFactory(factory: VectorViewModelFactory): ViewModelProvider.Factory
diff --git a/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt
index 1182efb1..777e04ca 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt
@@ -6,10 +6,11 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.resources.AppNameProvider
 import im.vector.riotredesign.core.resources.LocaleProvider
 import im.vector.riotredesign.core.resources.StringProvider
+import javax.inject.Inject
 
 private const val DEFAULT_PUSHER_FILE_TAG = "mobile"
 
-class PushersManager(
+class PushersManager @Inject constructor(
         private val currentSession: Session,
         private val localeProvider: LocaleProvider,
         private val stringProvider: StringProvider,
diff --git a/vector/src/main/java/im/vector/riotredesign/core/resources/AppNameProvider.kt b/vector/src/main/java/im/vector/riotredesign/core/resources/AppNameProvider.kt
index 4adfde79..1c7b9225 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/resources/AppNameProvider.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/resources/AppNameProvider.kt
@@ -2,9 +2,10 @@ package im.vector.riotredesign.core.resources
 
 import android.content.Context
 import timber.log.Timber
+import javax.inject.Inject
 
 
-class AppNameProvider(private val context: Context) {
+class AppNameProvider @Inject constructor(private val context: Context) {
 
     fun getAppName(): String {
         try {
diff --git a/vector/src/main/java/im/vector/riotredesign/core/services/AlarmSyncBroadcastReceiver.kt b/vector/src/main/java/im/vector/riotredesign/core/services/AlarmSyncBroadcastReceiver.kt
index f89f39e3..6c6a3f67 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/services/AlarmSyncBroadcastReceiver.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/services/AlarmSyncBroadcastReceiver.kt
@@ -8,6 +8,7 @@ import android.content.Intent
 import android.os.Build
 import android.os.PowerManager
 import androidx.core.content.ContextCompat
+import im.vector.matrix.android.internal.session.sync.job.SyncService
 import timber.log.Timber
 
 class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
@@ -22,11 +23,12 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
             }
         }
 
-
+        val userId = intent.getStringExtra(SyncService.EXTRA_USER_ID)
         // This method is called when the BroadcastReceiver is receiving an Intent broadcast.
         Timber.d("RestartBroadcastReceiver received intent")
         Intent(context, VectorSyncService::class.java).also {
             it.action = "SLOW"
+            it.putExtra(SyncService.EXTRA_USER_ID, userId)
             context.startService(it)
             try {
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -40,7 +42,7 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
             }
         }
 
-        scheduleAlarm(context, 30_000L)
+        scheduleAlarm(context, userId, 30_000L)
 
         Timber.i("Alarm scheduled to restart service")
     }
@@ -48,11 +50,13 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
     companion object {
         const val REQUEST_CODE = 0
 
-        fun scheduleAlarm(context: Context, delay: Long) {
+        fun scheduleAlarm(context: Context, userId: String, delay: Long) {
             //Reschedule
-            val intent = Intent(context, AlarmSyncBroadcastReceiver::class.java)
+            val intent = Intent(context, AlarmSyncBroadcastReceiver::class.java).apply {
+                putExtra(SyncService.EXTRA_USER_ID, userId)
+            }
             val pIntent = PendingIntent.getBroadcast(context, AlarmSyncBroadcastReceiver.REQUEST_CODE,
-                    intent, PendingIntent.FLAG_UPDATE_CURRENT)
+                                                     intent, PendingIntent.FLAG_UPDATE_CURRENT)
             val firstMillis = System.currentTimeMillis() + delay
             val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -65,7 +69,7 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
         fun cancelAlarm(context: Context) {
             val intent = Intent(context, AlarmSyncBroadcastReceiver::class.java)
             val pIntent = PendingIntent.getBroadcast(context, AlarmSyncBroadcastReceiver.REQUEST_CODE,
-                    intent, PendingIntent.FLAG_UPDATE_CURRENT)
+                                                     intent, PendingIntent.FLAG_UPDATE_CURRENT)
             val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
             alarmMgr.cancel(pIntent)
         }
diff --git a/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt b/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
deleted file mode 100644
index 6c4b7043..00000000
--- a/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt
+++ /dev/null
@@ -1,587 +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.riotredesign.core.services
-
-import android.content.Context
-import android.content.Intent
-import androidx.core.content.ContextCompat
-import androidx.work.Constraints
-import androidx.work.NetworkType
-import androidx.work.OneTimeWorkRequestBuilder
-import androidx.work.WorkManager
-import im.vector.matrix.android.api.session.Session
-import im.vector.matrix.android.api.session.events.model.Event
-import im.vector.riotredesign.R
-import im.vector.riotredesign.features.notifications.NotifiableEventResolver
-import im.vector.riotredesign.features.notifications.NotificationUtils
-import timber.log.Timber
-import java.util.concurrent.TimeUnit
-import javax.inject.Inject
-
-/**
- * A service in charge of controlling whether the event stream is running or not.
- *
- * It manages messages notifications displayed to the end user.
- */
-class EventStreamServiceX : VectorService() {
-
-    /**
-     * Managed session (no multi session for Riot)
-     */
-    @Inject lateinit var session: Session
-
-    /**
-     * Set to true to simulate a push immediately when service is destroyed
-     */
-    private var mSimulatePushImmediate = false
-
-    /**
-     * The current state.
-     */
-    private var serviceState = ServiceState.INIT
-        set(newServiceState) {
-            Timber.i("setServiceState from $field to $newServiceState")
-            field = newServiceState
-        }
-
-    /**
-     * Push manager
-     */
-    // TODO private var mPushManager: PushManager? = null
-
-    private var mNotifiableEventResolver: NotifiableEventResolver? = null
-
-    /**
-     * Live events listener
-     */
-    /* TODO
-    private val mEventsListener = object : MXEventListener() {
-        override fun onBingEvent(event: Event, roomState: RoomState, bingRule: BingRule) {
-            if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
-                Timber.i("%%%%%%%%  MXEventListener: the event $event")
-            }
-
-            Timber.i("prepareNotification : " + event.eventId + " in " + roomState.roomId)
-            val session = Matrix.getMXSession(applicationContext, event.matrixId)
-
-            // invalid session ?
-            // should never happen.
-            // But it could be triggered because of multi accounts management.
-            // The dedicated account is removing but some pushes are still received.
-            if (null == session || !session.isAlive) {
-                Timber.i("prepareNotification : don't bing - no session")
-                return
-            }
-
-            if (EventType.CALL_INVITE == event.getClearType()) {
-                handleCallInviteEvent(event)
-                return
-            }
-
-
-            val notifiableEvent = mNotifiableEventResolver!!.resolveEvent(event, roomState, bingRule, session)
-            if (notifiableEvent != null) {
-                VectorApp.getInstance().notificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
-            }
-        }
-
-        override fun onLiveEventsChunkProcessed(fromToken: String, toToken: String) {
-            Timber.i("%%%%%%%%  MXEventListener: onLiveEventsChunkProcessed[$fromToken->$toToken]")
-
-            VectorApp.getInstance().notificationDrawerManager.refreshNotificationDrawer(OutdatedEventDetector(this@EventStreamServiceX))
-
-            // do not suspend the application if there is some active calls
-            if (ServiceState.CATCHUP == serviceState) {
-                val hasActiveCalls = session?.mCallsManager?.hasActiveCalls() == true
-
-                // if there are some active calls, the catchup should not be stopped.
-                // because an user could answer to a call from another device.
-                // there will no push because it is his own message.
-                // so, the client has no choice to catchup until the ring is shutdown
-                if (hasActiveCalls) {
-                    Timber.i("onLiveEventsChunkProcessed : Catchup again because there are active calls")
-                    catchup(false)
-                } else if (ServiceState.CATCHUP == serviceState) {
-                    Timber.i("onLiveEventsChunkProcessed : no Active call")
-                    CallsManager.getSharedInstance().checkDeadCalls()
-                    stop()
-                }
-            }
-        }
-    }    */
-
-    /**
-     * Service internal state
-     */
-    private enum class ServiceState {
-        // Initial state
-        INIT,
-        // Service is started for a Catchup. Once the catchup is finished the service will be stopped
-        CATCHUP,
-        // Service is started, and session is monitored
-        STARTED
-    }
-
-    override fun onCreate() {
-        //setup injector
-        super.onCreate()
-    }
-
-    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
-        // Cancel any previous worker
-        cancelAnySimulatedPushSchedule()
-
-        // no intent : restarted by Android
-        if (null == intent) {
-            // Cannot happen anymore
-            Timber.e("onStartCommand : null intent")
-            myStopSelf()
-            return START_NOT_STICKY
-        }
-
-        val action = intent.action
-
-        Timber.i("onStartCommand with action : $action (current state $serviceState)")
-
-        // Manage foreground notification
-        when (action) {
-            ACTION_BOOT_COMPLETE,
-            ACTION_APPLICATION_UPGRADE,
-            ACTION_SIMULATED_PUSH_RECEIVED -> {
-                // Display foreground notification
-                Timber.i("startForeground")
-                val notification = NotificationUtils.buildForegroundServiceNotification(this, R.string.notification_sync_in_progress)
-                startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification)
-            }
-            ACTION_GO_TO_FOREGROUND        -> {
-                // Stop foreground notification display
-                Timber.i("stopForeground")
-                stopForeground(true)
-            }
-        }
-
-        if (null == session) {
-            Timber.e("onStartCommand : no sessions")
-            myStopSelf()
-            return START_NOT_STICKY
-        }
-
-        when (action) {
-            ACTION_START,
-            ACTION_GO_TO_FOREGROUND        ->
-                when (serviceState) {
-                    ServiceState.INIT    ->
-                        start(false)
-                    ServiceState.CATCHUP ->
-                        // A push has been received before, just change state, to avoid stopping the service when catchup is over
-                        serviceState = ServiceState.STARTED
-                    ServiceState.STARTED -> {
-                        // Nothing to do
-                    }
-                }
-            ACTION_STOP,
-            ACTION_GO_TO_BACKGROUND,
-            ACTION_LOGOUT                  ->
-                stop()
-            ACTION_PUSH_RECEIVED,
-            ACTION_SIMULATED_PUSH_RECEIVED ->
-                when (serviceState) {
-                    ServiceState.INIT    ->
-                        start(true)
-                    ServiceState.CATCHUP ->
-                        catchup(true)
-                    ServiceState.STARTED ->
-                        // Nothing to do
-                        Unit
-                }
-            ACTION_PUSH_UPDATE             -> pushStatusUpdate()
-            ACTION_BOOT_COMPLETE           -> {
-                // No FCM only
-                mSimulatePushImmediate = true
-                stop()
-            }
-            ACTION_APPLICATION_UPGRADE     -> {
-                // FDroid only
-                catchup(true)
-            }
-            else                           -> {
-                // Should not happen
-            }
-        }
-
-        // We don't want the service to be restarted automatically by the System
-        return START_NOT_STICKY
-    }
-
-    override fun onDestroy() {
-        super.onDestroy()
-
-        // Schedule worker?
-        scheduleSimulatedPushIfNeeded()
-    }
-
-    /**
-     * Tell the WorkManager to cancel any schedule of push simulation
-     */
-    private fun cancelAnySimulatedPushSchedule() {
-        WorkManager.getInstance().cancelAllWorkByTag(PUSH_SIMULATOR_REQUEST_TAG)
-    }
-
-    /**
-     * Configure the WorkManager to schedule a simulated push, if necessary
-     */
-    private fun scheduleSimulatedPushIfNeeded() {
-        if (shouldISimulatePush()) {
-            val delay = if (mSimulatePushImmediate) 0 else 60_000 // TODO mPushManager?.backgroundSyncDelay ?: let { 60_000 }
-            Timber.i("## service is schedule to restart in $delay millis, if network is connected")
-
-            val pushSimulatorRequest = OneTimeWorkRequestBuilder()
-                    .setInitialDelay(delay.toLong(), TimeUnit.MILLISECONDS)
-                    .setConstraints(Constraints.Builder()
-                                            .setRequiredNetworkType(NetworkType.CONNECTED)
-                                            .build())
-                    .addTag(PUSH_SIMULATOR_REQUEST_TAG)
-                    .build()
-
-            WorkManager.getInstance().let {
-                // Cancel any previous worker
-                it.cancelAllWorkByTag(PUSH_SIMULATOR_REQUEST_TAG)
-                it.enqueue(pushSimulatorRequest)
-            }
-        }
-    }
-
-    /**
-     * Start the even stream.
-     *
-     * @param session the session
-     */
-    private fun startEventStream(session: Session) {
-        /* TODO
-        // resume if it was only suspended
-        if (null != session.currentSyncToken) {
-            session.resumeEventStream()
-        } else {
-            session.startEventStream(store?.eventStreamToken)
-        }
-        */
-    }
-
-    /**
-     * Monitor the provided session.
-     *
-     * @param session the session
-     */
-    private fun monitorSession(session: Session) {
-        /* TODO
-        session.dataHandler.addListener(mEventsListener)
-        CallsManager.getSharedInstance().addSession(session)
-
-        val store = session.dataHandler.store
-
-        // the store is ready (no data loading in progress...)
-        if (store!!.isReady) {
-            startEventStream(session, store)
-        } else {
-            // wait that the store is ready  before starting the events stream
-            store.addMXStoreListener(object : MXStoreListener() {
-                override fun onStoreReady(accountId: String) {
-                    startEventStream(session, store)
-
-                    store.removeMXStoreListener(this)
-                }
-
-                override fun onStoreCorrupted(accountId: String, description: String) {
-                    // start a new initial sync
-                    if (null == store.eventStreamToken) {
-                        startEventStream(session, store)
-                    } else {
-                        // the data are out of sync
-                        Matrix.getInstance(applicationContext)!!.reloadSessions(applicationContext)
-                    }
-
-                    store.removeMXStoreListener(this)
-                }
-
-                override fun onStoreOOM(accountId: String, description: String) {
-                    val uiHandler = Handler(mainLooper)
-
-                    uiHandler.post {
-                        Toast.makeText(applicationContext, "$accountId : $description", Toast.LENGTH_LONG).show()
-                        Matrix.getInstance(applicationContext)!!.reloadSessions(applicationContext)
-                    }
-                }
-            })
-
-            store.open()
-        }
-        */
-    }
-
-    /**
-     * internal start.
-     */
-    private fun start(forPush: Boolean) {
-        val applicationContext = applicationContext
-        // TODO mPushManager = Matrix.getInstance(applicationContext)!!.pushManager
-        mNotifiableEventResolver = NotifiableEventResolver(applicationContext)
-
-        monitorSession(session!!)
-
-        serviceState = if (forPush) {
-            ServiceState.CATCHUP
-        } else {
-            ServiceState.STARTED
-        }
-    }
-
-    /**
-     * internal stop.
-     */
-    private fun stop() {
-        Timber.i("## stop(): the service is stopped")
-
-        /* TODO
-        if (null != session && session!!.isAlive) {
-            session!!.stopEventStream()
-            session!!.dataHandler.removeListener(mEventsListener)
-            CallsManager.getSharedInstance().removeSession(session)
-        }
-        session = null
-        */
-
-        // Stop the service
-        myStopSelf()
-    }
-
-    /**
-     * internal catchup method.
-     *
-     * @param checkState true to check if the current state allow to perform a catchup
-     */
-    private fun catchup(checkState: Boolean) {
-        var canCatchup = true
-
-        if (!checkState) {
-            Timber.i("catchup  without checking serviceState ")
-        } else {
-            Timber.i("catchup with serviceState " + serviceState + " CurrentActivity ") // TODO + VectorApp.getCurrentActivity())
-
-            /* TODO
-            // the catchup should only be done
-            // 1- the serviceState is in catchup : the event stream might have gone to sleep between two catchups
-            // 2- the thread is suspended
-            // 3- the application has been launched by a push so there is no displayed activity
-            canCatchup = (serviceState == ServiceState.CATCHUP
-                    //|| (serviceState == ServiceState.PAUSE)
-                    || ServiceState.STARTED == serviceState && null == VectorApp.getCurrentActivity())
-                    */
-        }
-
-        if (canCatchup) {
-            if (session != null) {
-                // TODO session!!.catchupEventStream()
-            } else {
-                Timber.i("catchup no session")
-            }
-
-            serviceState = ServiceState.CATCHUP
-        } else {
-            Timber.i("No catchup is triggered because there is already a running event thread")
-        }
-    }
-
-    /**
-     * The push status has been updated (i.e disabled or enabled).
-     * TODO Useless now?
-     */
-    private fun pushStatusUpdate() {
-        Timber.i("## pushStatusUpdate")
-    }
-
-    /* ==========================================================================================
-     * Push simulator
-     * ========================================================================================== */
-
-    /**
-     * @return true if the FCM is disable or not setup, user allowed background sync, user wants notification
-     */
-    private fun shouldISimulatePush(): Boolean {
-        return false
-
-        /* TODO
-
-        if (Matrix.getInstance(applicationContext)?.defaultSession == null) {
-            Timber.i("## shouldISimulatePush: NO: no session")
-
-            return false
-        }
-
-        mPushManager?.let { pushManager ->
-            if (pushManager.useFcm()
-                    && !TextUtils.isEmpty(pushManager.currentRegistrationToken)
-                    && pushManager.isServerRegistered) {
-                // FCM is ok
-                Timber.i("## shouldISimulatePush: NO: FCM is up")
-                return false
-            }
-
-            if (!pushManager.isBackgroundSyncAllowed) {
-                // User has disabled background sync
-                Timber.i("## shouldISimulatePush: NO: background sync not allowed")
-                return false
-            }
-
-            if (!pushManager.areDeviceNotificationsAllowed()) {
-                // User does not want notifications
-                Timber.i("## shouldISimulatePush: NO: user does not want notification")
-                return false
-            }
-        }
-
-        // Lets simulate push
-        Timber.i("## shouldISimulatePush: YES")
-        return true
-        */
-    }
-
-
-    //================================================================================
-    // Call management
-    //================================================================================
-
-    private fun handleCallInviteEvent(event: Event) {
-        /*
-        TODO
-        val session = Matrix.getMXSession(applicationContext, event.matrixId)
-
-        // invalid session ?
-        // should never happen.
-        // But it could be triggered because of multi accounts management.
-        // The dedicated account is removing but some pushes are still received.
-        if (null == session || !session.isAlive) {
-            Timber.v("prepareCallNotification : don't bing - no session")
-            return
-        }
-
-        val room: Room? = session.dataHandler.getRoom(event.roomId)
-
-        // invalid room ?
-        if (null == room) {
-            Timber.i("prepareCallNotification : don't bing - the room does not exist")
-            return
-        }
-
-        var callId: String? = null
-        var isVideo = false
-
-        try {
-            callId = event.contentAsJsonObject?.get("call_id")?.asString
-
-            // Check if it is a video call
-            val offer = event.contentAsJsonObject?.get("offer")?.asJsonObject
-            val sdp = offer?.get("sdp")
-            val sdpValue = sdp?.asString
-
-            isVideo = sdpValue?.contains("m=video") == true
-        } catch (e: Exception) {
-            Timber.e(e, "prepareNotification : getContentAsJsonObject")
-        }
-
-        if (!TextUtils.isEmpty(callId)) {
-            CallService.onIncomingCall(this,
-                    isVideo,
-                    room.getRoomDisplayName(this),
-                    room.roomId,
-                    session.myUserId!!,
-                    callId!!)
-        }
-         */
-    }
-
-    companion object {
-        private const val PUSH_SIMULATOR_REQUEST_TAG = "PUSH_SIMULATOR_REQUEST_TAG"
-
-        private const val ACTION_START = "im.vector.riotredesign.core.services.EventStreamServiceX.START"
-        private const val ACTION_LOGOUT = "im.vector.riotredesign.core.services.EventStreamServiceX.LOGOUT"
-        private const val ACTION_GO_TO_FOREGROUND = "im.vector.riotredesign.core.services.EventStreamServiceX.GO_TO_FOREGROUND"
-        private const val ACTION_GO_TO_BACKGROUND = "im.vector.riotredesign.core.services.EventStreamServiceX.GO_TO_BACKGROUND"
-        private const val ACTION_PUSH_UPDATE = "im.vector.riotredesign.core.services.EventStreamServiceX.PUSH_UPDATE"
-        private const val ACTION_PUSH_RECEIVED = "im.vector.riotredesign.core.services.EventStreamServiceX.PUSH_RECEIVED"
-        private const val ACTION_SIMULATED_PUSH_RECEIVED = "im.vector.riotredesign.core.services.EventStreamServiceX.SIMULATED_PUSH_RECEIVED"
-        private const val ACTION_STOP = "im.vector.riotredesign.core.services.EventStreamServiceX.STOP"
-        private const val ACTION_BOOT_COMPLETE = "im.vector.riotredesign.core.services.EventStreamServiceX.BOOT_COMPLETE"
-        private const val ACTION_APPLICATION_UPGRADE = "im.vector.riotredesign.core.services.EventStreamServiceX.APPLICATION_UPGRADE"
-
-        /* ==========================================================================================
-         * Events sent to the service
-         * ========================================================================================== */
-
-        fun onApplicationStarted(context: Context) {
-            sendAction(context, ACTION_START)
-        }
-
-        fun onLogout(context: Context) {
-            sendAction(context, ACTION_LOGOUT)
-        }
-
-        fun onAppGoingToForeground(context: Context) {
-            sendAction(context, ACTION_GO_TO_FOREGROUND)
-        }
-
-        fun onAppGoingToBackground(context: Context) {
-            sendAction(context, ACTION_GO_TO_BACKGROUND)
-        }
-
-        fun onPushUpdate(context: Context) {
-            sendAction(context, ACTION_PUSH_UPDATE)
-        }
-
-        fun onPushReceived(context: Context) {
-            sendAction(context, ACTION_PUSH_RECEIVED)
-        }
-
-        fun onSimulatedPushReceived(context: Context) {
-            sendAction(context, ACTION_SIMULATED_PUSH_RECEIVED, true)
-        }
-
-        fun onApplicationStopped(context: Context) {
-            sendAction(context, ACTION_STOP)
-        }
-
-        fun onBootComplete(context: Context) {
-            sendAction(context, ACTION_BOOT_COMPLETE, true)
-        }
-
-        fun onApplicationUpgrade(context: Context) {
-            sendAction(context, ACTION_APPLICATION_UPGRADE, true)
-        }
-
-        private fun sendAction(context: Context, action: String, foreground: Boolean = false) {
-            Timber.i("sendAction $action")
-
-            val intent = Intent(context, EventStreamServiceX::class.java)
-            intent.action = action
-
-            if (foreground) {
-                ContextCompat.startForegroundService(context, intent)
-            } else {
-                context.startService(intent)
-            }
-        }
-    }
-}
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt
deleted file mode 100644
index 9041dec1..00000000
--- a/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt
+++ /dev/null
@@ -1,57 +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.riotredesign.features.home
-
-import android.net.Uri
-import im.vector.matrix.android.api.permalinks.PermalinkData
-import im.vector.matrix.android.api.permalinks.PermalinkParser
-import im.vector.riotredesign.features.navigation.Navigator
-import javax.inject.Inject
-
-class HomePermalinkHandler @Inject constructor(private val homeNavigator: HomeNavigator,
-                                               private val navigator: Navigator) {
-
-    fun launch(deepLink: String?) {
-        val uri = deepLink?.let { Uri.parse(it) }
-        launch(uri)
-    }
-
-    fun launch(deepLink: Uri?) {
-        if (deepLink == null) {
-            return
-        }
-        val permalinkData = PermalinkParser.parse(deepLink)
-        when (permalinkData) {
-            is PermalinkData.EventLink    -> {
-                homeNavigator.openRoomDetail(permalinkData.roomIdOrAlias, permalinkData.eventId, navigator)
-            }
-            is PermalinkData.RoomLink     -> {
-                homeNavigator.openRoomDetail(permalinkData.roomIdOrAlias, null, navigator)
-            }
-            is PermalinkData.GroupLink    -> {
-                homeNavigator.openGroupDetail(permalinkData.groupId)
-            }
-            is PermalinkData.UserLink     -> {
-                homeNavigator.openUserDetail(permalinkData.userId)
-            }
-            is PermalinkData.FallbackLink -> {
-
-            }
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/PermalinkHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/home/PermalinkHandler.kt
index 537f7f93..825e9748 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/PermalinkHandler.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/PermalinkHandler.kt
@@ -22,9 +22,10 @@ import im.vector.matrix.android.api.permalinks.PermalinkData
 import im.vector.matrix.android.api.permalinks.PermalinkParser
 import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.features.navigation.Navigator
+import javax.inject.Inject
 
-class PermalinkHandler(private val session: Session,
-                       private val navigator: Navigator) {
+class PermalinkHandler @Inject constructor(private val session: Session,
+                                           private val navigator: Navigator) {
 
     fun launch(context: Context, deepLink: String?, navigateToRoomInterceptor: NavigateToRoomInterceptor? = null): Boolean {
         val uri = deepLink?.let { Uri.parse(it) }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
index c71d4a4c..44b1ed69 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
@@ -31,12 +31,13 @@ import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTex
 import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_
 import im.vector.riotredesign.features.home.room.detail.timeline.util.MessageInformationDataFactory
 import me.gujun.android.span.span
+import javax.inject.Inject
 
 // This class handles timeline events who haven't been successfully decrypted
-class EncryptedItemFactory(private val messageInformationDataFactory: MessageInformationDataFactory,
-                           private val colorProvider: ColorProvider,
-                           private val stringProvider: StringProvider,
-                           private val avatarRenderer: AvatarRenderer) {
+class EncryptedItemFactory @Inject constructor(private val messageInformationDataFactory: MessageInformationDataFactory,
+                                               private val colorProvider: ColorProvider,
+                                               private val stringProvider: StringProvider,
+                                               private val avatarRenderer: AvatarRenderer) {
 
     fun create(event: TimelineEvent,
                nextEvent: TimelineEvent?,
@@ -79,7 +80,7 @@ class EncryptedItemFactory(private val messageInformationDataFactory: MessageInf
                                 }))
                         .longClickListener { view ->
                             return@longClickListener callback?.onEventLongClicked(informationData, null, view)
-                                    ?: false
+                                                     ?: false
                         }
             }
             else                                             -> null
diff --git a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotifiableEventResolver.kt b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotifiableEventResolver.kt
index ca2ec614..821ad181 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotifiableEventResolver.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotifiableEventResolver.kt
@@ -30,6 +30,7 @@ import im.vector.riotredesign.R
 import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.features.home.room.detail.timeline.format.NoticeEventFormatter
 import timber.log.Timber
+import javax.inject.Inject
 
 /**
  * The notifiable event resolver is able to create a NotifiableEvent (view model for notifications) from an sdk Event.
@@ -37,8 +38,8 @@ import timber.log.Timber
  * The NotifiableEventResolver is the only aware of session/store, the NotificationDrawerManager has no knowledge of that,
  * this pattern allow decoupling between the object responsible of displaying notifications and the matrix sdk.
  */
-class NotifiableEventResolver(private val stringProvider: StringProvider,
-                              private val noticeEventFormatter: NoticeEventFormatter) {
+class NotifiableEventResolver @Inject constructor(private val stringProvider: StringProvider,
+                                                  private val noticeEventFormatter: NoticeEventFormatter) {
 
     //private val eventDisplay = RiotEventDisplay(context)
 
@@ -95,8 +96,8 @@ class NotifiableEventResolver(private val stringProvider: StringProvider,
             // Ok room is not known in store, but we can still display something
             val body =
                     event.annotations?.editSummary?.aggregatedContent?.toModel()?.body
-                            ?: event.root.getClearContent().toModel()?.body
-                            ?: stringProvider.getString(R.string.notification_unknown_new_event)
+                    ?: event.root.getClearContent().toModel()?.body
+                    ?: stringProvider.getString(R.string.notification_unknown_new_event)
             val roomName = stringProvider.getString(R.string.notification_unknown_room_name)
             val senderDisplayName = event.senderName
 
@@ -114,8 +115,8 @@ class NotifiableEventResolver(private val stringProvider: StringProvider,
             return notifiableEvent
         } else {
             val body = event.annotations?.editSummary?.aggregatedContent?.toModel()?.body
-                    ?: event.root.getClearContent().toModel()?.body
-                    ?: stringProvider.getString(R.string.notification_unknown_new_event)
+                       ?: event.root.getClearContent().toModel()?.body
+                       ?: stringProvider.getString(R.string.notification_unknown_new_event)
             val roomName = room.roomSummary?.displayName ?: ""
             val senderDisplayName = event.senderName ?: ""
 
@@ -137,15 +138,15 @@ class NotifiableEventResolver(private val stringProvider: StringProvider,
             // TODO They will be not displayed the first time (known limitation)
             notifiableEvent.roomAvatarPath = session.contentUrlResolver()
                     .resolveThumbnail(room.roomSummary?.avatarUrl,
-                            250,
-                            250,
-                            ContentUrlResolver.ThumbnailMethod.SCALE)
+                                      250,
+                                      250,
+                                      ContentUrlResolver.ThumbnailMethod.SCALE)
 
             notifiableEvent.senderAvatarPath = session.contentUrlResolver()
                     .resolveThumbnail(event.senderAvatar,
-                            250,
-                            250,
-                            ContentUrlResolver.ThumbnailMethod.SCALE)
+                                      250,
+                                      250,
+                                      ContentUrlResolver.ThumbnailMethod.SCALE)
 
             return notifiableEvent
         }
@@ -158,7 +159,7 @@ class NotifiableEventResolver(private val stringProvider: StringProvider,
         val dName = event.senderId?.let { session.getUser(it)?.displayName }
         if (Membership.INVITE == content.membership) {
             val body = noticeEventFormatter.format(event, dName)
-                    ?: stringProvider.getString(R.string.notification_new_invitation)
+                       ?: stringProvider.getString(R.string.notification_new_invitation)
             return InviteNotifiableEvent(
                     session.sessionParams.credentials.userId,
                     eventId = event.eventId!!,
diff --git a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt
index b73ee6a6..0c04eba0 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt
@@ -20,12 +20,12 @@ import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
 import androidx.core.app.RemoteInput
-import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.room.Room
 import im.vector.riotredesign.R
 import im.vector.riotredesign.core.di.ActiveSessionHolder
+import im.vector.riotredesign.core.di.HasVectorInjector
 import timber.log.Timber
 import java.util.*
 import javax.inject.Inject
@@ -38,10 +38,14 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
     @Inject lateinit var notificationDrawerManager: NotificationDrawerManager
     @Inject lateinit var activeSessionHolder: ActiveSessionHolder
 
+
     override fun onReceive(context: Context?, intent: Intent?) {
         if (intent == null || context == null) return
         Timber.v("NotificationBroadcastReceiver received : $intent")
-
+        val appContext = context.applicationContext
+        if (appContext is HasVectorInjector) {
+            appContext.injector().inject(this)
+        }
         when (intent.action) {
             NotificationUtils.SMART_REPLY_ACTION        ->
                 handleSmartReply(intent, context)
@@ -60,7 +64,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
     }
 
     private fun handleMarkAsRead(context: Context, roomId: String) {
-       activeSessionHolder.getActiveSession().let { session ->
+        activeSessionHolder.getActiveSession().let { session ->
             session.getRoom(roomId)
                     ?.markAllAsRead(object : MatrixCallback {})
         }
@@ -95,7 +99,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
                 false,
                 System.currentTimeMillis(),
                 session.getUser(session.sessionParams.credentials.userId)?.displayName
-                        ?: context?.getString(R.string.notification_sender_me),
+                ?: context?.getString(R.string.notification_sender_me),
                 session.sessionParams.credentials.userId,
                 message,
                 room.roomId,
diff --git a/vector/src/main/java/im/vector/riotredesign/features/notifications/OutdatedEventDetector.kt b/vector/src/main/java/im/vector/riotredesign/features/notifications/OutdatedEventDetector.kt
index a51178a4..05bbc2ea 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/notifications/OutdatedEventDetector.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/notifications/OutdatedEventDetector.kt
@@ -15,10 +15,10 @@
  */
 package im.vector.riotredesign.features.notifications
 
-import im.vector.matrix.android.api.session.Session
+import im.vector.riotredesign.core.di.ActiveSessionHolder
 import javax.inject.Inject
 
-class OutdatedEventDetector @Inject constructor(private val session: Session) {
+class OutdatedEventDetector @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) {
 
     /**
      * Returns true if the given event is outdated.
@@ -29,7 +29,7 @@ class OutdatedEventDetector @Inject constructor(private val session: Session) {
         if (notifiableEvent is NotifiableMessageEvent) {
             val eventID = notifiableEvent.eventId
             val roomID = notifiableEvent.roomId
-            val room = session.getRoom(roomID) ?: return false
+            val room = activeSessionHolder.getSafeActiveSession()?.getRoom(roomID) ?: return false
             return room.isEventRead(eventID)
         }
         return false
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationFragment.kt
index 1a967db0..7b94dedd 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationFragment.kt
@@ -16,32 +16,43 @@
 
 package im.vector.riotredesign.features.settings
 
+import android.content.Context
 import android.os.Bundle
 import androidx.preference.Preference
 import androidx.preference.SwitchPreference
 import im.vector.matrix.android.api.Matrix
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.di.ActiveSessionHolder
+import im.vector.riotredesign.core.di.DaggerScreenComponent
 import im.vector.riotredesign.core.platform.VectorPreferenceFragment
 import im.vector.riotredesign.core.pushers.PushersManager
 import im.vector.riotredesign.push.fcm.FcmHelper
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
 
 // Referenced in vector_settings_preferences_root.xml
 class VectorSettingsNotificationPreferenceFragment : VectorPreferenceFragment() {
 
+
     override var titleRes: Int = R.string.settings_notifications
 
-    val pushManager: PushersManager by inject()
-
+    @Inject lateinit var pushManager: PushersManager
+    @Inject lateinit var activeSessionHolder: ActiveSessionHolder
 
     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
         addPreferencesFromResource(R.xml.vector_settings_notifications)
     }
 
+    override fun onAttach(context: Context) {
+        val screenComponent = DaggerScreenComponent.factory().create(vectorActivity.getVectorComponent(), vectorActivity)
+        super.onAttach(context)
+        screenComponent.inject(this)
+    }
+
+
     override fun onResume() {
         super.onResume()
-        Matrix.getInstance().currentSession?.refreshPushers()
+        activeSessionHolder.getSafeActiveSession()?.refreshPushers()
     }
 
     override fun onPreferenceTreeClick(preference: Preference?): Boolean {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
index dd53396f..4d9abbe0 100755
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt
@@ -35,12 +35,21 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.view.inputmethod.InputMethodManager
-import android.widget.*
+import android.widget.Button
+import android.widget.CheckedTextView
+import android.widget.EditText
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
 import androidx.appcompat.app.AlertDialog
 import androidx.core.content.ContextCompat
 import androidx.core.content.edit
 import androidx.core.view.isVisible
-import androidx.preference.*
+import androidx.preference.EditTextPreference
+import androidx.preference.Preference
+import androidx.preference.PreferenceCategory
+import androidx.preference.PreferenceManager
+import androidx.preference.SwitchPreference
 import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
 import com.google.android.material.textfield.TextInputEditText
 import com.google.android.material.textfield.TextInputLayout
@@ -68,7 +77,19 @@ import im.vector.riotredesign.core.preference.BingRule
 import im.vector.riotredesign.core.preference.ProgressBarPreference
 import im.vector.riotredesign.core.preference.UserAvatarPreference
 import im.vector.riotredesign.core.preference.VectorPreference
-import im.vector.riotredesign.core.utils.*
+import im.vector.riotredesign.core.utils.PERMISSIONS_FOR_WRITING_FILES
+import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_EXPORT_KEYS
+import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA
+import im.vector.riotredesign.core.utils.allGranted
+import im.vector.riotredesign.core.utils.checkPermissions
+import im.vector.riotredesign.core.utils.copyToClipboard
+import im.vector.riotredesign.core.utils.displayInWebView
+import im.vector.riotredesign.core.utils.getCallRingtoneName
+import im.vector.riotredesign.core.utils.getCallRingtoneUri
+import im.vector.riotredesign.core.utils.openFileSelection
+import im.vector.riotredesign.core.utils.setCallRingtoneUri
+import im.vector.riotredesign.core.utils.setUseRiotDefaultRingtone
+import im.vector.riotredesign.core.utils.toast
 import im.vector.riotredesign.features.MainActivity
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.crypto.keys.KeysExporter
@@ -76,7 +97,6 @@ import im.vector.riotredesign.features.crypto.keys.KeysImporter
 import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupManageActivity
 import im.vector.riotredesign.features.themes.ThemeUtils
 import im.vector.riotredesign.features.version.getVersion
-import org.koin.android.ext.android.inject
 import timber.log.Timber
 import java.lang.ref.WeakReference
 import java.text.DateFormat
@@ -314,7 +334,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
             // It does not work on XML, do it here
             it.icon = activity?.let {
                 ThemeUtils.tintDrawable(it,
-                        ContextCompat.getDrawable(it, R.drawable.ic_add_black)!!, R.attr.vctr_settings_icon_tint_color)
+                                        ContextCompat.getDrawable(it, R.drawable.ic_add_black)!!, R.attr.vctr_settings_icon_tint_color)
             }
 
             // Unfortunately, this is not supported in lib v7
@@ -331,7 +351,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
             // It does not work on XML, do it here
             it.icon = activity?.let {
                 ThemeUtils.tintDrawable(it,
-                        ContextCompat.getDrawable(it, R.drawable.ic_add_black)!!, R.attr.vctr_settings_icon_tint_color)
+                                        ContextCompat.getDrawable(it, R.drawable.ic_add_black)!!, R.attr.vctr_settings_icon_tint_color)
             }
 
             it.setOnPreferenceClickListener {
@@ -713,7 +733,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
                 context?.let { context: Context ->
                     AlertDialog.Builder(context)
                             .setSingleChoiceItems(R.array.media_saving_choice,
-                                    PreferencesManager.getSelectedMediasSavingPeriod(activity)) { d, n ->
+                                                  PreferencesManager.getSelectedMediasSavingPeriod(activity)) { d, n ->
                                 PreferencesManager.setSelectedMediasSavingPeriod(activity, n)
                                 d.cancel()
 
@@ -1773,7 +1793,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
             mDisplayedEmails = newEmailsList
 
             val addEmailBtn = mUserSettingsCategory.findPreference(ADD_EMAIL_PREFERENCE_KEY)
-                    ?: return
+                              ?: return
 
             var order = addEmailBtn.order
 
@@ -2449,7 +2469,9 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
 
             // disable the deletion for our own device
             if (!TextUtils.equals(session.getMyDevice()?.deviceId, aDeviceInfo.deviceId)) {
-                builder.setNegativeButton(R.string.delete) { _, _ -> displayDeviceDeletionDialog(aDeviceInfo) }
+                builder.setNegativeButton(R.string.delete) { _, _ ->
+                    //displayDeviceDeletionDialog(aDeviceInfo)
+                }
             }
             builder.setNeutralButton(R.string.cancel, null)
                     .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event ->
@@ -2746,8 +2768,8 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
 
                                         AlertDialog.Builder(thisActivity)
                                                 .setMessage(getString(R.string.encryption_import_room_keys_success,
-                                                        data.successfullyNumberOfImportedKeys,
-                                                        data.totalNumberOfKeys))
+                                                                      data.successfullyNumberOfImportedKeys,
+                                                                      data.totalNumberOfKeys))
                                                 .setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
                                                 .show()
                                     }
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysFragment.kt
index 1ea57264..b51c131c 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysFragment.kt
@@ -29,14 +29,15 @@ import im.vector.riotredesign.core.platform.VectorBaseFragment
 import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.core.ui.list.genericFooterItem
 import kotlinx.android.synthetic.main.fragment_generic_recycler_epoxy.*
+import javax.inject.Inject
 
 // Referenced in vector_settings_notifications.xml
 class PushGatewaysFragment : VectorBaseFragment() {
 
     override fun getLayoutResId(): Int = R.layout.fragment_generic_recycler_epoxy
 
+    @Inject lateinit var pushGatewaysViewModelFactory: PushGatewaysViewModel.Factory
     private val viewModel: PushGatewaysViewModel by fragmentViewModel(PushGatewaysViewModel::class)
-
     private val epoxyController by lazy { PushGateWayController(StringProvider(requireContext().resources)) }
 
     override fun onResume() {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysViewModel.kt
index edb032a0..70bbd17a 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysViewModel.kt
@@ -16,38 +16,50 @@
 
 package im.vector.riotredesign.features.settings.push
 
-import androidx.lifecycle.Observer
-import com.airbnb.mvrx.*
+import com.airbnb.mvrx.Async
+import com.airbnb.mvrx.FragmentViewModelContext
+import com.airbnb.mvrx.MvRxState
+import com.airbnb.mvrx.MvRxViewModelFactory
+import com.airbnb.mvrx.Uninitialized
+import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.pushers.Pusher
+import im.vector.matrix.rx.RxSession
 import im.vector.riotredesign.core.platform.VectorViewModel
-import org.koin.android.ext.android.get
 
 
 data class PushGatewayViewState(
         val pushGateways: Async> = Uninitialized
 ) : MvRxState
 
-class PushGatewaysViewModel(initialState: PushGatewayViewState) : VectorViewModel(initialState) {
+class PushGatewaysViewModel @AssistedInject constructor(@Assisted initialState: PushGatewayViewState,
+                                                        private val session: Session) : VectorViewModel(initialState) {
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: PushGatewayViewState): PushGatewaysViewModel
+    }
 
     companion object : MvRxViewModelFactory {
 
         override fun create(viewModelContext: ViewModelContext, state: PushGatewayViewState): PushGatewaysViewModel? {
-            val session = viewModelContext.activity.get()
-            val fragment = (viewModelContext as FragmentViewModelContext).fragment
-
-            val livePushers = session.livePushers()
-
-            val viewModel = PushGatewaysViewModel(state)
-
-            livePushers.observe(fragment, Observer {
-                viewModel.setState {
-                    PushGatewayViewState(Success(it))
-                }
-            })
-            return viewModel
+            val fragment: PushGatewaysFragment = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.pushGatewaysViewModelFactory.create(state)
         }
+    }
 
+    init {
+        observePushers()
+    }
+
+    private fun observePushers() {
+        RxSession(session)
+                .livePushers()
+                .execute {
+                    copy(pushGateways = it)
+                }
     }
 
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushRulesViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushRulesViewModel.kt
index 03a2e600..24294353 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushRulesViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushRulesViewModel.kt
@@ -19,23 +19,20 @@ import com.airbnb.mvrx.MvRxState
 import com.airbnb.mvrx.MvRxViewModelFactory
 import com.airbnb.mvrx.ViewModelContext
 import im.vector.matrix.android.api.pushrules.rest.PushRule
-import im.vector.matrix.android.api.session.Session
+import im.vector.riotredesign.core.di.HasScreenInjector
 import im.vector.riotredesign.core.platform.VectorViewModel
-import org.koin.android.ext.android.get
 
 data class PushRulesViewState(
         val rules: List = emptyList()
 ) : MvRxState
 
-
 class PushRulesViewModel(initialState: PushRulesViewState) : VectorViewModel(initialState) {
 
     companion object : MvRxViewModelFactory {
 
         override fun initialState(viewModelContext: ViewModelContext): PushRulesViewState? {
-            val session = viewModelContext.activity.get()
+            val session = (viewModelContext.activity as HasScreenInjector).injector().session()
             val rules = session.getPushRules()
-
             return PushRulesViewState(rules)
         }
 

From f18bc9bd00d6383b69d8b15e083726020526846a Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Thu, 27 Jun 2019 19:12:46 +0200
Subject: [PATCH 10/11] Dagger: fix no session

---
 .../internal/session/pushers/DefaultPusherService.kt   | 10 ++++++++--
 .../gplay/push/fcm/VectorFirebaseMessagingService.kt   |  2 +-
 .../vector/riotredesign/core/pushers/PushersManager.kt |  2 +-
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt
index aafe781f..103bdb71 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt
@@ -15,8 +15,13 @@
  */
 package im.vector.matrix.android.internal.session.pushers
 
+import android.content.Context
 import androidx.lifecycle.LiveData
-import androidx.work.*
+import androidx.work.BackoffPolicy
+import androidx.work.Constraints
+import androidx.work.NetworkType
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkManager
 import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.auth.data.SessionParams
@@ -37,6 +42,7 @@ import javax.inject.Inject
 
 
 internal class DefaultPusherService @Inject constructor(
+        private val context: Context,
         private val monarchy: Monarchy,
         private val sessionParam: SessionParams,
         private val getPusherTask: GetPushersTask,
@@ -93,7 +99,7 @@ internal class DefaultPusherService @Inject constructor(
                 .setInputData(WorkerParamsFactory.toData(params))
                 .setBackoffCriteria(BackoffPolicy.LINEAR, 10_000L, TimeUnit.MILLISECONDS)
                 .build()
-        WorkManager.getInstance().enqueue(request)
+        WorkManager.getInstance(context).enqueue(request)
         return request.id
     }
 
diff --git a/vector/src/gplay/java/im/vector/riotredesign/gplay/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/gplay/java/im/vector/riotredesign/gplay/push/fcm/VectorFirebaseMessagingService.kt
index bd30e5c9..6386cb5a 100755
--- a/vector/src/gplay/java/im/vector/riotredesign/gplay/push/fcm/VectorFirebaseMessagingService.kt
+++ b/vector/src/gplay/java/im/vector/riotredesign/gplay/push/fcm/VectorFirebaseMessagingService.kt
@@ -105,7 +105,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
         if (refreshedToken == null) {
             Timber.w("onNewToken:received null token")
         } else {
-            if (PreferencesManager.areNotificationEnabledForDevice(applicationContext)) {
+            if (PreferencesManager.areNotificationEnabledForDevice(applicationContext) && activeSessionHolder.hasActiveSession()) {
                 pusherManager.registerPusherWithFcmKey(refreshedToken)
             }
         }
diff --git a/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt
index 5d2ee895..cfc77576 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt
@@ -36,7 +36,7 @@ class PushersManager @Inject constructor(
     }
 
     fun unregisterPusher(pushKey: String, callback: MatrixCallback) {
-        val currentSession = activeSessionHolder.getActiveSession()
+        val currentSession = activeSessionHolder.getSafeActiveSession() ?: return
         currentSession.removeHttpPusher(pushKey, stringProvider.getString(R.string.pusher_app_id), callback)
     }
 }
\ No newline at end of file

From 604de7eebc608c9808b948c13f124c4f78409856 Mon Sep 17 00:00:00 2001
From: ganfra 
Date: Fri, 28 Jun 2019 09:35:34 +0200
Subject: [PATCH 11/11] Dagger: fix some merging issues

---
 .../troubleshoot/TestAutoStartBoot.kt         | 15 +++---
 .../TestBackgroundRestrictions.kt             | 21 ++++----
 ...ificationTroubleshootTestManagerFactory.kt | 36 ++++++-------
 .../fcm/VectorFirebaseMessagingService.kt     | 13 +++--
 .../riotredesign/core/di/VectorComponent.kt   | 10 ++--
 .../timeline/action/MessageMenuViewModel.kt   |  1 -
 .../timeline/action/ViewReactionViewModel.kt  | 50 +++++++++++--------
 7 files changed, 80 insertions(+), 66 deletions(-)

diff --git a/vector/src/fdroid/java/im/vector/riotredesign/fdroid/features/settings/troubleshoot/TestAutoStartBoot.kt b/vector/src/fdroid/java/im/vector/riotredesign/fdroid/features/settings/troubleshoot/TestAutoStartBoot.kt
index 211f7337..adc2d00c 100644
--- a/vector/src/fdroid/java/im/vector/riotredesign/fdroid/features/settings/troubleshoot/TestAutoStartBoot.kt
+++ b/vector/src/fdroid/java/im/vector/riotredesign/fdroid/features/settings/troubleshoot/TestAutoStartBoot.kt
@@ -15,26 +15,29 @@
  */
 package im.vector.riotredesign.fdroid.features.settings.troubleshoot
 
-import androidx.fragment.app.Fragment
+import androidx.appcompat.app.AppCompatActivity
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.features.settings.PreferencesManager
 import im.vector.riotredesign.features.settings.troubleshoot.TroubleshootTest
+import javax.inject.Inject
 
 /**
  * Test that the application is started on boot
  */
-class TestAutoStartBoot(val fragment: Fragment) : TroubleshootTest(R.string.settings_troubleshoot_test_service_boot_title) {
+class TestAutoStartBoot @Inject constructor(private val context: AppCompatActivity,
+                                            private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_service_boot_title) {
 
     override fun perform() {
-        if (PreferencesManager.autoStartOnBoot(fragment.context)) {
-            description = fragment.getString(R.string.settings_troubleshoot_test_service_boot_success)
+        if (PreferencesManager.autoStartOnBoot(context)) {
+            description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_success)
             status = TestStatus.SUCCESS
             quickFix = null
         } else {
-            description = fragment.getString(R.string.settings_troubleshoot_test_service_boot_failed)
+            description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_failed)
             quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_service_boot_quickfix) {
                 override fun doFix() {
-                    PreferencesManager.setAutoStartOnBoot(fragment.context, true)
+                    PreferencesManager.setAutoStartOnBoot(context, true)
                     manager?.retry()
                 }
             }
diff --git a/vector/src/fdroid/java/im/vector/riotredesign/fdroid/features/settings/troubleshoot/TestBackgroundRestrictions.kt b/vector/src/fdroid/java/im/vector/riotredesign/fdroid/features/settings/troubleshoot/TestBackgroundRestrictions.kt
index 72c0b433..c124864a 100644
--- a/vector/src/fdroid/java/im/vector/riotredesign/fdroid/features/settings/troubleshoot/TestBackgroundRestrictions.kt
+++ b/vector/src/fdroid/java/im/vector/riotredesign/fdroid/features/settings/troubleshoot/TestBackgroundRestrictions.kt
@@ -17,24 +17,27 @@ package im.vector.riotredesign.fdroid.features.settings.troubleshoot
 
 import android.content.Context
 import android.net.ConnectivityManager
+import androidx.appcompat.app.AppCompatActivity
 import androidx.core.net.ConnectivityManagerCompat
-import androidx.fragment.app.Fragment
 import im.vector.riotredesign.R
+import im.vector.riotredesign.core.resources.StringProvider
 import im.vector.riotredesign.features.settings.troubleshoot.TroubleshootTest
+import javax.inject.Inject
 
-class TestBackgroundRestrictions(val fragment: Fragment) : TroubleshootTest(R.string.settings_troubleshoot_test_bg_restricted_title) {
+class TestBackgroundRestrictions @Inject constructor(private val context: AppCompatActivity,
+                                                     private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_bg_restricted_title) {
 
     override fun perform() {
-        (fragment.context!!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {
+        (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {
             // Checks if the device is on a metered network
             if (isActiveNetworkMetered) {
                 // Checks user’s Data Saver settings.
                 val restrictBackgroundStatus = ConnectivityManagerCompat.getRestrictBackgroundStatus(this)
                 when (restrictBackgroundStatus) {
-                    ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED -> {
+                    ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED     -> {
                         // Background data usage is blocked for this app. Wherever possible,
                         // the app should also use less data in the foreground.
-                        description = fragment.getString(R.string.settings_troubleshoot_test_bg_restricted_failed,
+                        description = stringProvider.getString(R.string.settings_troubleshoot_test_bg_restricted_failed,
                                 "RESTRICT_BACKGROUND_STATUS_ENABLED")
                         status = TestStatus.FAILED
                         quickFix = null
@@ -42,15 +45,15 @@ class TestBackgroundRestrictions(val fragment: Fragment) : TroubleshootTest(R.st
                     ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED -> {
                         // The app is whitelisted. Wherever possible,
                         // the app should use less data in the foreground and background.
-                        description = fragment.getString(R.string.settings_troubleshoot_test_bg_restricted_success,
+                        description = stringProvider.getString(R.string.settings_troubleshoot_test_bg_restricted_success,
                                 "RESTRICT_BACKGROUND_STATUS_WHITELISTED")
                         status = TestStatus.SUCCESS
                         quickFix = null
                     }
-                    ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED -> {
+                    ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED    -> {
                         // Data Saver is disabled. Since the device is connected to a
                         // metered network, the app should use less data wherever possible.
-                        description = fragment.getString(R.string.settings_troubleshoot_test_bg_restricted_success,
+                        description = stringProvider.getString(R.string.settings_troubleshoot_test_bg_restricted_success,
                                 "RESTRICT_BACKGROUND_STATUS_DISABLED")
                         status = TestStatus.SUCCESS
                         quickFix = null
@@ -61,7 +64,7 @@ class TestBackgroundRestrictions(val fragment: Fragment) : TroubleshootTest(R.st
             } else {
                 // The device is not on a metered network.
                 // Use data as required to perform syncs, downloads, and updates.
-                description = fragment.getString(R.string.settings_troubleshoot_test_bg_restricted_success, "")
+                description = stringProvider.getString(R.string.settings_troubleshoot_test_bg_restricted_success, "")
                 status = TestStatus.SUCCESS
                 quickFix = null
             }
diff --git a/vector/src/fdroid/java/im/vector/riotredesign/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/fdroid/java/im/vector/riotredesign/push/fcm/NotificationTroubleshootTestManagerFactory.kt
index 9a5ada35..f55d9b8e 100644
--- a/vector/src/fdroid/java/im/vector/riotredesign/push/fcm/NotificationTroubleshootTestManagerFactory.kt
+++ b/vector/src/fdroid/java/im/vector/riotredesign/push/fcm/NotificationTroubleshootTestManagerFactory.kt
@@ -16,31 +16,27 @@
 package im.vector.riotredesign.push.fcm
 
 import androidx.fragment.app.Fragment
-import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.fdroid.features.settings.troubleshoot.TestAutoStartBoot
 import im.vector.riotredesign.fdroid.features.settings.troubleshoot.TestBackgroundRestrictions
 import im.vector.riotredesign.features.settings.troubleshoot.*
+import javax.inject.Inject
 
-class NotificationTroubleshootTestManagerFactory {
+class NotificationTroubleshootTestManagerFactory @Inject constructor(private val testSystemSettings: TestSystemSettings,
+                                                                     private val testAccountSettings: TestAccountSettings,
+                                                                     private val testDeviceSettings: TestDeviceSettings,
+                                                                     private val testBingRulesSettings: TestBingRulesSettings,
+                                                                     private val testAutoStartBoot: TestAutoStartBoot,
+                                                                     private val testBackgroundRestrictions: TestBackgroundRestrictions) {
 
-    companion object {
-        fun createTestManager(fragment: Fragment, session: Session?): NotificationTroubleshootTestManager {
-            val mgr = NotificationTroubleshootTestManager(fragment)
-            mgr.addTest(TestSystemSettings(fragment))
-            if (session != null) {
-                mgr.addTest(TestAccountSettings(fragment, session))
-            }
-            mgr.addTest(TestDeviceSettings(fragment))
-            if (session != null) {
-                mgr.addTest(TestBingRulesSettings(fragment, session))
-            }
-            // mgr.addTest(TestNotificationServiceRunning(fragment))
-            // mgr.addTest(TestServiceRestart(fragment))
-            mgr.addTest(TestAutoStartBoot(fragment))
-            mgr.addTest(TestBackgroundRestrictions(fragment))
-            // mgr.addTest(TestBatteryOptimization(fragment))
-            return mgr
-        }
+    fun create(fragment: Fragment): NotificationTroubleshootTestManager {
+        val mgr = NotificationTroubleshootTestManager(fragment)
+        mgr.addTest(testSystemSettings)
+        mgr.addTest(testAccountSettings)
+        mgr.addTest(testDeviceSettings)
+        mgr.addTest(testBingRulesSettings)
+        mgr.addTest(testAutoStartBoot)
+        mgr.addTest(testBackgroundRestrictions)
+        return mgr
     }
 
 }
\ No newline at end of file
diff --git a/vector/src/gplay/java/im/vector/riotredesign/gplay/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/gplay/java/im/vector/riotredesign/gplay/push/fcm/VectorFirebaseMessagingService.kt
index 6386cb5a..177b2346 100755
--- a/vector/src/gplay/java/im/vector/riotredesign/gplay/push/fcm/VectorFirebaseMessagingService.kt
+++ b/vector/src/gplay/java/im/vector/riotredesign/gplay/push/fcm/VectorFirebaseMessagingService.kt
@@ -49,10 +49,10 @@ import javax.inject.Inject
  */
 class VectorFirebaseMessagingService : FirebaseMessagingService() {
 
-    @Inject lateinit var notificationDrawerManager: NotificationDrawerManager
-    @Inject lateinit var notifiableEventResolver: NotifiableEventResolver
-    @Inject lateinit var pusherManager: PushersManager
-    @Inject lateinit var activeSessionHolder: ActiveSessionHolder
+    private lateinit var notificationDrawerManager: NotificationDrawerManager
+    private lateinit var notifiableEventResolver: NotifiableEventResolver
+    private lateinit var pusherManager: PushersManager
+    private lateinit var activeSessionHolder: ActiveSessionHolder
 
     // UI handler
     private val mUIHandler by lazy {
@@ -61,7 +61,10 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
 
     override fun onCreate() {
         super.onCreate()
-        vectorComponent().inject(this)
+        notificationDrawerManager = vectorComponent().notificationDrawerManager()
+        notifiableEventResolver = vectorComponent().notifiableEventResolver()
+        pusherManager = vectorComponent().pusherManager()
+        activeSessionHolder = vectorComponent().activeSessionHolder()
     }
 
     /**
diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
index c32d2d9a..ffc3a126 100644
--- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
+++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt
@@ -25,6 +25,7 @@ import im.vector.matrix.android.api.auth.Authenticator
 import im.vector.matrix.android.api.session.Session
 import im.vector.riotredesign.EmojiCompatFontProvider
 import im.vector.riotredesign.VectorApplication
+import im.vector.riotredesign.core.pushers.PushersManager
 import im.vector.riotredesign.features.configuration.VectorConfiguration
 import im.vector.riotredesign.features.crypto.keysrequest.KeyRequestHandler
 import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
@@ -33,13 +34,12 @@ import im.vector.riotredesign.features.home.HomeNavigator
 import im.vector.riotredesign.features.home.HomeRoomListObservableStore
 import im.vector.riotredesign.features.home.group.SelectedGroupStore
 import im.vector.riotredesign.features.navigation.Navigator
+import im.vector.riotredesign.features.notifications.NotifiableEventResolver
 import im.vector.riotredesign.features.notifications.NotificationBroadcastReceiver
 import im.vector.riotredesign.features.notifications.NotificationDrawerManager
 import im.vector.riotredesign.features.notifications.PushRuleTriggerListener
 import im.vector.riotredesign.features.rageshake.BugReporter
-import im.vector.riotredesign.features.rageshake.RageShake
 import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
-import im.vector.riotredesign.gplay.push.fcm.VectorFirebaseMessagingService
 import javax.inject.Singleton
 
 @Component(modules = [VectorModule::class])
@@ -50,8 +50,6 @@ interface VectorComponent {
 
     fun inject(vectorApplication: VectorApplication)
 
-    fun inject(vectorFirebaseMessagingService: VectorFirebaseMessagingService)
-
     fun matrix(): Matrix
 
     fun currentSession(): Session
@@ -90,6 +88,10 @@ interface VectorComponent {
 
     fun pushRuleTriggerListener(): PushRuleTriggerListener
 
+    fun pusherManager(): PushersManager
+
+    fun notifiableEventResolver(): NotifiableEventResolver
+
     @Component.Factory
     interface Factory {
         fun create(@BindsInstance context: Context): VectorComponent
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuViewModel.kt
index 421f0f40..fcd73e82 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageMenuViewModel.kt
@@ -160,7 +160,6 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M
 
                 this.add(SimpleAction(VIEW_SOURCE, R.string.view_source, R.drawable.ic_view_source, JSONObject(event.root.toContent()).toString(4)))
                 if (event.isEncrypted()) {
-                    this.add(SimpleAction(VIEW_DECRYPTED_SOURCE, R.string.view_decrypted_source, R.drawable.ic_view_source, state.eventId))
                     val decryptedContent = event.root.mClearEvent?.toContent()?.let {
                         JSONObject(it).toString(4)
                     } ?: stringProvider.getString(R.string.encryption_information_decryption_error)
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionViewModel.kt
index 8404faca..cdcebd55 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/ViewReactionViewModel.kt
@@ -4,11 +4,13 @@ import com.airbnb.mvrx.*
 import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import im.vector.matrix.android.api.session.Session
+import im.vector.matrix.android.api.session.room.model.ReactionAggregatedSummary
 import im.vector.matrix.rx.RxRoom
 import im.vector.riotredesign.core.extensions.localDateTime
 import im.vector.riotredesign.core.platform.VectorViewModel
 import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
 import io.reactivex.Observable
+import io.reactivex.Single
 
 
 data class DisplayReactionsViewState(
@@ -46,19 +48,17 @@ class ViewReactionViewModel @AssistedInject constructor(@Assisted
     @AssistedInject.Factory
     interface Factory {
         fun create(initialState: DisplayReactionsViewState): ViewReactionViewModel
+    }
 
-        companion object : MvRxViewModelFactory {
-
-            override fun create(viewModelContext: ViewModelContext, state: DisplayReactionsViewState): ViewReactionViewModel? {
-                val fragment: ViewReactionBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
-                return fragment.viewReactionViewModelFactory.create(state)
-            }
+    companion object : MvRxViewModelFactory {
 
+        override fun create(viewModelContext: ViewModelContext, state: DisplayReactionsViewState): ViewReactionViewModel? {
+            val fragment: ViewReactionBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
+            return fragment.viewReactionViewModelFactory.create(state)
         }
 
     }
 
-
     init {
         observeEventAnnotationSummaries()
     }
@@ -69,23 +69,31 @@ class ViewReactionViewModel @AssistedInject constructor(@Assisted
                 .flatMapSingle { summaries ->
                     Observable
                             .fromIterable(summaries)
-                            .flatMapIterable { it.reactionsSummary }
-                            .map {
-                                val event = room.getTimeLineEvent(eventId)
-                                        ?: throw RuntimeException("Your eventId is not valid")
-                                val localDate = event.root.localDateTime()
-                                ReactionInfo(
-                                        event.root.eventId!!,
-                                        it.key,
-                                        event.root.senderId ?: "",
-                                        event.senderName,
-                                        timelineDateFormatter.formatMessageHour(localDate)
-                                )
-                            }
-                            .toList()
+                            .flatMapIterable {it.reactionsSummary}
+                            .toReactionInfoList()
                 }
                 .execute {
                     copy(mapReactionKeyToMemberList = it)
                 }
     }
+
+    private fun Observable.toReactionInfoList(): Single> {
+        return flatMap { summary ->
+            Observable
+                    .fromIterable(summary.sourceEvents)
+                    .map {
+                        val event = room.getTimeLineEvent(it)
+                                ?: throw RuntimeException("Your eventId is not valid")
+                        val localDate = event.root.localDateTime()
+                        ReactionInfo(
+                                event.root.eventId!!,
+                                summary.key,
+                                event.root.senderId ?: "",
+                                event.getDisambiguatedDisplayName(),
+                                timelineDateFormatter.formatMessageHour(localDate)
+                        )
+                    }
+        }
+                .toList()
+    }
 }
\ No newline at end of file