Merge branch 'develop' into feature/ons/poll

* develop: (129 commits)
  Improve Rx sequence regarding listener
  adding changelog entry
  using correct license for matrix-sdk test
  extending the room name resolved to create a dedicated room name data class which contains a normalized version of the room name
  Remove shortcut as soon as a PIN code is set
  ensuring the store migration class is always equal to other store migration instances - is needed as realm will throw if multiple migration instances are created and they don't match
  removing extra query definition by chaining the query creation with modifiers
  removing noisy log which duplicates a type clause and fixing when casing formatting to have a case per line
  documenting the different query cases
  making the isNormalized function an extension and internal to the sdk
  Cache immutable value
  Do not show shortcuts if a PIN code is set
  Remove (disable) shortcut if a room is left
  Ensure ShortcutsHandler get all the joined rooms #4168
  Add `sortOrder: RoomSortOrder` parameter, with no API break
  Clean code
  adding normalised room display name field and making use of it when filtering rooms by name - fixes non latin-1 character set room names from being ignored when searching with inexact casing
  adding normalisation to the query string cases
  making value processing an injectable class, it will need to have its own dependencies to support normalisation
  porting QueryStringValue to sealed interface with a sub category for the content based values - allows for handling those cases separately for normalisation
  ...

# Conflicts:
#	vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
This commit is contained in:
Onuray Sahin 2021-10-28 18:05:10 +03:00
commit a5a3a817e1
372 changed files with 4414 additions and 3801 deletions

View file

@ -1,3 +1,24 @@
Changes in Element v1.3.6 (2021-10-26)
======================================
Bugfixes 🐛
----------
- Correctly handle url of type https://mobile.element.io/?hs_url=…&is_url=…
Skip the choose server screen when such URL are open when Element ([#2684](https://github.com/vector-im/element-android/issues/2684))
Changes in Element v1.3.5 (2021-10-25)
======================================
Bugfixes 🐛
----------
- Fixing malformed link pop up when tapping on notifications ([#4267](https://github.com/vector-im/element-android/issues/4267))
- Fix Broken EditText when using FromEditTextItem ([#4276](https://github.com/vector-im/element-android/issues/4276))
- Fix crash when clicking on ViewEvent source actions ([#4279](https://github.com/vector-im/element-android/issues/4279))
- Fix voice message record button wrong visibility ([#4283](https://github.com/vector-im/element-android/issues/4283))
- Fix unread marker not showing ([#4313](https://github.com/vector-im/element-android/issues/4313))
Changes in Element v1.3.4 (2021-10-20)
======================================
@ -5,6 +26,7 @@ Features ✨
----------
- Implement /part command, with or without parameter ([#2909](https://github.com/vector-im/element-android/issues/2909))
- Handle Presence support, for Direct Message room ([#4090](https://github.com/vector-im/element-android/issues/4090))
- Priority conversations for Android 11+ ([#3313](https://github.com/vector-im/element-android/issues/3313))
Bugfixes 🐛
----------

View file

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

1
changelog.d/1491.bugfix Normal file
View file

@ -0,0 +1 @@
Stops showing a dedicated redacted event notification, the message notifications will update accordingly

1
changelog.d/3395.bugfix Normal file
View file

@ -0,0 +1 @@
Fixes marking individual notifications as read causing other notifications to be dismissed

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

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

1
changelog.d/3968.bugfix Normal file
View file

@ -0,0 +1 @@
Fixing room search needing exact casing for non latin-1 character named rooms

1
changelog.d/4152.bugfix Normal file
View file

@ -0,0 +1 @@
Tentatively fixing the doubled notifications by updating the group summary at specific points in the notification rendering cycle

1
changelog.d/4170.bugfix Normal file
View file

@ -0,0 +1 @@
Do not show shortcuts if a PIN code is set

1
changelog.d/4192.misc Normal file
View file

@ -0,0 +1 @@
Limit supported TLS versions and cipher suites

1
changelog.d/4255.bugfix Normal file
View file

@ -0,0 +1 @@
Fixes being unable to join rooms by name

1
changelog.d/4266.removal Normal file
View file

@ -0,0 +1 @@
Add API `LoginWizard.loginCustom(data: JsonDict): Session` to be able to login to a homeserver using arbitrary request content

View file

@ -1 +0,0 @@
Fix voice message record button wrong visibility

1
changelog.d/4334.removal Normal file
View file

@ -0,0 +1 @@
Add optional deviceId to the login API

1
changelog.d/582.feature Normal file
View file

@ -0,0 +1 @@
Adding the room name to the invitation notification (if the room summary is available)

View file

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

33
docs/hilt_migration.md Normal file
View file

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

View file

@ -1,2 +1,2 @@
Main changes in this version: Add Presence support, for Direct Message room (note: presence is disabled on matrix.org. Add again Android Auto support.
Main changes in this version: Add Presence support, for Direct Message room (note: presence is disabled on matrix.org). Add again Android Auto support.
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View file

@ -0,0 +1,2 @@
Main changes in this version: Add Presence support, for Direct Message room (note: presence is disabled on matrix.org). Add again Android Auto support.
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.5

View file

@ -0,0 +1,2 @@
Main changes in this version: Add Presence support, for Direct Message room (note: presence is disabled on matrix.org). Add again Android Auto support.
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.6

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version: Affiche le(s) politique(s) des serveurs didentité dans les réglages. Retrait temporaire du support dAndroid Auto
Liste de tous les changements: https://github.com/vector-im/element-android/releases/tag/v1.3.3

View file

@ -37,3 +37,6 @@ Messagerie instantannée, appels audio et vidéo, partage de fichier, partage d
<b>Reprenez où vous vous êtes arrêté</b>
Restez en contact où que vous soyez grâce à lhistorique des messages synchronisé entre tous vos appareils et sur le web sur https://app.element.io
<b>Open source</b>
Element Adroid est un projet libre, hébergé par GitHub. Veuillez signaler tous les problèmes et / ou contribuer à son développement sur https://github.com/vector-im/element-android

View file

@ -31,7 +31,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
buildConfigField "String", "SDK_VERSION", "\"1.3.5\""
buildConfigField "String", "SDK_VERSION", "\"1.3.7\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
resValue "string", "git_sdk_revision", "\"${gitRevision()}\""
@ -156,7 +156,7 @@ dependencies {
implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.35'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.36'
testImplementation libs.tests.junit
testImplementation 'org.robolectric:robolectric:4.6.1'

View file

@ -16,6 +16,7 @@
package org.matrix.android.sdk.api
import okhttp3.ConnectionSpec
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import java.net.Proxy
@ -44,6 +45,10 @@ data class MatrixConfiguration(
* You can create one using for instance Proxy(proxyType, InetSocketAddress.createUnresolved(hostname, port).
*/
val proxy: Proxy? = null,
/**
* TLS versions and cipher suites limitation for unauthenticated requests
*/
val connectionSpec: ConnectionSpec = ConnectionSpec.RESTRICTED_TLS,
/**
* True to advertise support for call transfers to other parties on Matrix calls.
*/

View file

@ -105,9 +105,15 @@ interface AuthenticationService {
/**
* Authenticate with a matrixId and a password
* Usually call this after a successful call to getWellKnownData()
* @param homeServerConnectionConfig the information about the homeserver and other configuration
* @param matrixId the matrixId of the user
* @param password the password of the account
* @param initialDeviceName the initial device name
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
*/
suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
matrixId: String,
password: String,
initialDeviceName: String): Session
initialDeviceName: String,
deviceId: String? = null): Session
}

View file

@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.auth.data
import android.net.Uri
import com.squareup.moshi.JsonClass
import okhttp3.CipherSuite
import okhttp3.ConnectionSpec
import okhttp3.TlsVersion
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder
import org.matrix.android.sdk.internal.network.ssl.Fingerprint
@ -191,32 +192,25 @@ data class HomeServerConnectionConfig(
/**
* Convenient method to limit the TLS versions and cipher suites for this Builder
* Ref:
* - https://www.ssi.gouv.fr/uploads/2017/02/security-recommendations-for-tls_v1.1.pdf
* - https://www.ssi.gouv.fr/uploads/2017/07/anssi-guide-recommandations_de_securite_relatives_a_tls-v1.2.pdf
* - https://developer.android.com/reference/javax/net/ssl/SSLEngine
*
* @param tlsLimitations true to use Tls limitations
* @param enableCompatibilityMode set to true for Android < 20
* @return this builder
*/
@Deprecated("TLS versions and cipher suites are limited by default")
fun withTlsLimitations(tlsLimitations: Boolean, enableCompatibilityMode: Boolean): Builder {
if (tlsLimitations) {
withShouldAcceptTlsExtensions(false)
// Tls versions
addAcceptedTlsVersion(TlsVersion.TLS_1_2)
addAcceptedTlsVersion(TlsVersion.TLS_1_3)
// TlS versions
ConnectionSpec.RESTRICTED_TLS.tlsVersions?.let { this.tlsVersions.addAll(it) }
forceUsageOfTlsVersions(enableCompatibilityMode)
// Cipher suites
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)
ConnectionSpec.RESTRICTED_TLS.cipherSuites?.let { this.tlsCipherSuites.addAll(it) }
if (enableCompatibilityMode) {
// Adopt some preceding cipher suites for Android < 20 to be able to negotiate

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.api.auth.login
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.util.JsonDict
/**
* Set of methods to be able to login to an existing account on a homeserver.
@ -34,12 +35,14 @@ interface LoginWizard {
*
* @param login the login field. Can be a user name, or a msisdn (email or phone number) associated to the account
* @param password the password of the account
* @param deviceName the initial device name
* @param initialDeviceName the initial device name
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
* @return a [Session] if the login is successful
*/
suspend fun login(login: String,
password: String,
deviceName: String): Session
initialDeviceName: String,
deviceId: String? = null): Session
/**
* Exchange a login token to an access token.
@ -49,6 +52,12 @@ interface LoginWizard {
*/
suspend fun loginWithToken(loginToken: String): Session
/**
* Login to the homeserver by sending a custom JsonDict.
* The data should contain at least one entry "type" with a String value.
*/
suspend fun loginCustom(data: JsonDict): Session
/**
* Ask the homeserver to reset the user password. The password will not be reset until
* [resetPasswordMailConfirmed] is successfully called.

View file

@ -19,17 +19,41 @@ package org.matrix.android.sdk.api.query
/**
* Basic query language. All these cases are mutually exclusive.
*/
sealed class QueryStringValue {
object NoCondition : QueryStringValue()
object IsNull : QueryStringValue()
object IsNotNull : QueryStringValue()
object IsEmpty : QueryStringValue()
object IsNotEmpty : QueryStringValue()
data class Equals(val string: String, val case: Case = Case.SENSITIVE) : QueryStringValue()
data class Contains(val string: String, val case: Case = Case.SENSITIVE) : QueryStringValue()
sealed interface QueryStringValue {
sealed interface ContentQueryStringValue : QueryStringValue {
val string: String
val case: Case
}
object NoCondition : QueryStringValue
object IsNull : QueryStringValue
object IsNotNull : QueryStringValue
object IsEmpty : QueryStringValue
object IsNotEmpty : QueryStringValue
data class Equals(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
data class Contains(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
enum class Case {
/**
* Match query sensitive to case
*/
SENSITIVE,
INSENSITIVE
/**
* Match query insensitive to case, this only works for Latin-1 character sets
*/
INSENSITIVE,
/**
* Match query with input normalized (case insensitive)
* Works around Realms inability to sort or filter by case for non Latin-1 character sets
* Expects the target field to contain normalized data
*
* @see org.matrix.android.sdk.internal.util.Normalizer.normalize
*/
NORMALIZED
}
}
internal fun QueryStringValue.isNormalized() = this is QueryStringValue.ContentQueryStringValue && case == QueryStringValue.Case.NORMALIZED

View file

@ -22,6 +22,8 @@ import org.json.JSONObject
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
@ -310,3 +312,6 @@ fun Event.isEdition(): Boolean {
fun Event.getPresenceContent(): PresenceContent? {
return content.toModel<PresenceContent>()
}
fun Event.isInvitation(): Boolean = type == EventType.STATE_ROOM_MEMBER &&
content?.toModel<RoomMemberContent>()?.membership == Membership.INVITE

View file

@ -94,13 +94,15 @@ interface RoomService {
* Get a snapshot list of room summaries.
* @return the immutable list of [RoomSummary]
*/
fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary>
fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary>
/**
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of List[RoomSummary]
*/
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>>
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): LiveData<List<RoomSummary>>
/**
* Get a snapshot list of Breadcrumbs

View file

@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.session.space
import android.net.Uri
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult
@ -74,9 +75,11 @@ interface SpaceService {
* Get a live list of space summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of List[SpaceSummary]
*/
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>>
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>>
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary>
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary>
suspend fun joinSpace(spaceIdOrAlias: String,
reason: String? = null,

View file

@ -121,6 +121,10 @@ internal interface AuthAPI {
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
suspend fun login(@Body loginParams: TokenLoginParams): Credentials
@Headers("CONNECT_TIMEOUT:60000", "READ_TIMEOUT:60000", "WRITE_TIMEOUT:60000")
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
suspend fun login(@Body loginParams: JsonDict): Credentials
/**
* Ask the homeserver to reset the password associated with the provided email.
*/

View file

@ -388,8 +388,15 @@ internal class DefaultAuthenticationService @Inject constructor(
override suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
matrixId: String,
password: String,
initialDeviceName: String): Session {
return directLoginTask.execute(DirectLoginTask.Params(homeServerConnectionConfig, matrixId, password, initialDeviceName))
initialDeviceName: String,
deviceId: String?): Session {
return directLoginTask.execute(DirectLoginTask.Params(
homeServerConnectionConfig = homeServerConnectionConfig,
userId = matrixId,
password = password,
deviceName = initialDeviceName,
deviceId = deviceId
))
}
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {

View file

@ -49,51 +49,54 @@ internal data class PasswordLoginParams(
fun userIdentifier(user: String,
password: String,
deviceDisplayName: String? = null,
deviceId: String? = null): PasswordLoginParams {
deviceDisplayName: String?,
deviceId: String?): PasswordLoginParams {
return PasswordLoginParams(
mapOf(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_USER,
IDENTIFIER_KEY_USER to user
),
password,
LoginFlowTypes.PASSWORD,
deviceDisplayName,
deviceId)
password = password,
type = LoginFlowTypes.PASSWORD,
deviceDisplayName = deviceDisplayName,
deviceId = deviceId
)
}
fun thirdPartyIdentifier(medium: String,
address: String,
password: String,
deviceDisplayName: String? = null,
deviceId: String? = null): PasswordLoginParams {
deviceDisplayName: String?,
deviceId: String?): PasswordLoginParams {
return PasswordLoginParams(
mapOf(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_THIRD_PARTY,
IDENTIFIER_KEY_MEDIUM to medium,
IDENTIFIER_KEY_ADDRESS to address
),
password,
LoginFlowTypes.PASSWORD,
deviceDisplayName,
deviceId)
password = password,
type = LoginFlowTypes.PASSWORD,
deviceDisplayName = deviceDisplayName,
deviceId = deviceId
)
}
fun phoneIdentifier(country: String,
phone: String,
password: String,
deviceDisplayName: String? = null,
deviceId: String? = null): PasswordLoginParams {
deviceDisplayName: String?,
deviceId: String?): PasswordLoginParams {
return PasswordLoginParams(
mapOf(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_PHONE,
IDENTIFIER_KEY_COUNTRY to country,
IDENTIFIER_KEY_PHONE to phone
),
password,
LoginFlowTypes.PASSWORD,
deviceDisplayName,
deviceId)
password = password,
type = LoginFlowTypes.PASSWORD,
deviceDisplayName = deviceDisplayName,
deviceId = deviceId
)
}
}
}

View file

@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.auth.login.LoginProfileInfo
import org.matrix.android.sdk.api.auth.login.LoginWizard
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.auth.AuthAPI
import org.matrix.android.sdk.internal.auth.PendingSessionStore
import org.matrix.android.sdk.internal.auth.SessionCreator
@ -52,11 +53,23 @@ internal class DefaultLoginWizard(
override suspend fun login(login: String,
password: String,
deviceName: String): Session {
initialDeviceName: String,
deviceId: String?): Session {
val loginParams = if (Patterns.EMAIL_ADDRESS.matcher(login).matches()) {
PasswordLoginParams.thirdPartyIdentifier(ThreePidMedium.EMAIL, login, password, deviceName)
PasswordLoginParams.thirdPartyIdentifier(
medium = ThreePidMedium.EMAIL,
address = login,
password = password,
deviceDisplayName = initialDeviceName,
deviceId = deviceId
)
} else {
PasswordLoginParams.userIdentifier(login, password, deviceName)
PasswordLoginParams.userIdentifier(
user = login,
password = password,
deviceDisplayName = initialDeviceName,
deviceId = deviceId
)
}
val credentials = executeRequest(null) {
authAPI.login(loginParams)
@ -79,6 +92,14 @@ internal class DefaultLoginWizard(
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
}
override suspend fun loginCustom(data: JsonDict): Session {
val credentials = executeRequest(null) {
authAPI.login(data)
}
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
}
override suspend fun resetPassword(email: String, newPassword: String) {
val param = RegisterAddThreePidTask.Params(
RegisterThreePid.Email(email),

View file

@ -37,7 +37,8 @@ internal interface DirectLoginTask : Task<DirectLoginTask.Params, Session> {
val homeServerConnectionConfig: HomeServerConnectionConfig,
val userId: String,
val password: String,
val deviceName: String
val deviceName: String,
val deviceId: String?
)
}
@ -55,7 +56,12 @@ internal class DefaultDirectLoginTask @Inject constructor(
val authAPI = retrofitFactory.create(client, homeServerUrl)
.create(AuthAPI::class.java)
val loginParams = PasswordLoginParams.userIdentifier(params.userId, params.password, params.deviceName)
val loginParams = PasswordLoginParams.userIdentifier(
user = params.userId,
password = params.password,
deviceDisplayName = params.deviceName,
deviceId = params.deviceId
)
val credentials = try {
executeRequest(null) {

View file

@ -34,7 +34,7 @@ internal interface SendEventTask : Task<SendEventTask.Params, String> {
internal class DefaultSendEventTask @Inject constructor(
private val localEchoRepository: LocalEchoRepository,
private val encryptEventTask: DefaultEncryptEventTask,
private val encryptEventTask: EncryptEventTask,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val roomAPI: RoomAPI,
private val globalErrorReceiver: GlobalErrorReceiver) : SendEventTask {

View file

@ -34,7 +34,7 @@ internal interface SendVerificationMessageTask : Task<SendVerificationMessageTas
internal class DefaultSendVerificationMessageTask @Inject constructor(
private val localEchoRepository: LocalEchoRepository,
private val encryptEventTask: DefaultEncryptEventTask,
private val encryptEventTask: EncryptEventTask,
private val roomAPI: RoomAPI,
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
private val globalErrorReceiver: GlobalErrorReceiver) : SendVerificationMessageTask {

View file

@ -45,11 +45,24 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntityFields
import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.util.Normalizer
import timber.log.Timber
import javax.inject.Inject
internal object RealmSessionStoreMigration : RealmMigration {
internal class RealmSessionStoreMigration @Inject constructor(
private val normalizer: Normalizer
) : RealmMigration {
const val SESSION_STORE_SCHEMA_VERSION = 18L
companion object {
const val SESSION_STORE_SCHEMA_VERSION = 19L
}
/**
* Forces all RealmSessionStoreMigration instances to be equal
* Avoids Realm throwing when multiple instances of the migration are set
*/
override fun equals(other: Any?) = other is RealmSessionStoreMigration
override fun hashCode() = 1000
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
@ -72,6 +85,7 @@ internal object RealmSessionStoreMigration : RealmMigration {
if (oldVersion <= 15) migrateTo16(realm)
if (oldVersion <= 16) migrateTo17(realm)
if (oldVersion <= 17) migrateTo18(realm)
if (oldVersion <= 18) migrateTo19(realm)
}
private fun migrateTo1(realm: DynamicRealm) {
@ -364,4 +378,16 @@ internal object RealmSessionStoreMigration : RealmMigration {
realm.schema.get("RoomMemberSummaryEntity")
?.addRealmObjectField(RoomMemberSummaryEntityFields.USER_PRESENCE_ENTITY.`$`, userPresenceEntity)
}
private fun migrateTo19(realm: DynamicRealm) {
Timber.d("Step 18 -> 19")
realm.schema.get("RoomSummaryEntity")
?.addField(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, String::class.java)
?.transform {
it.getString(RoomSummaryEntityFields.DISPLAY_NAME)?.let { displayName ->
val normalised = normalizer.normalize(displayName)
it.set(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, normalised)
}
}
}
}

View file

@ -40,6 +40,7 @@ private const val REALM_NAME = "disk_store.realm"
*/
internal class SessionRealmConfigurationFactory @Inject constructor(
private val realmKeysUtils: RealmKeysUtils,
private val realmSessionStoreMigration: RealmSessionStoreMigration,
@SessionFilesDirectory val directory: File,
@SessionId val sessionId: String,
@UserMd5 val userMd5: String,
@ -71,7 +72,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
.allowWritesOnUiThread(true)
.modules(SessionRealmModule())
.schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION)
.migration(RealmSessionStoreMigration)
.migration(realmSessionStoreMigration)
.build()
// Try creating a realm instance and if it succeeds we can clear the flag

View file

@ -21,13 +21,13 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
import org.matrix.android.sdk.api.session.room.model.SpaceParentInfo
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
import org.matrix.android.sdk.api.session.typing.TypingUsersTracker
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
import org.matrix.android.sdk.internal.database.model.presence.toUserPresence
import org.matrix.android.sdk.internal.session.typing.DefaultTypingUsersTracker
import javax.inject.Inject
internal class RoomSummaryMapper @Inject constructor(private val timelineEventMapper: TimelineEventMapper,
private val typingUsersTracker: DefaultTypingUsersTracker) {
private val typingUsersTracker: TypingUsersTracker) {
fun map(roomSummaryEntity: RoomSummaryEntity): RoomSummary {
val tags = roomSummaryEntity.tags().map {
@ -42,7 +42,7 @@ internal class RoomSummaryMapper @Inject constructor(private val timelineEventMa
return RoomSummary(
roomId = roomSummaryEntity.roomId,
displayName = roomSummaryEntity.displayName ?: "",
displayName = roomSummaryEntity.displayName() ?: "",
name = roomSummaryEntity.name ?: "",
topic = roomSummaryEntity.topic ?: "",
avatarUrl = roomSummaryEntity.avatarUrl ?: "",

View file

@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.VersioningState
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntity
import org.matrix.android.sdk.internal.session.room.membership.RoomName
internal open class RoomSummaryEntity(
@PrimaryKey var roomId: String = "",
@ -36,10 +37,24 @@ internal open class RoomSummaryEntity(
var children: RealmList<SpaceChildSummaryEntity> = RealmList()
) : RealmObject() {
var displayName: String? = ""
set(value) {
if (value != field) field = value
private var displayName: String? = ""
fun displayName() = displayName
fun setDisplayName(roomName: RoomName) {
if (roomName.name != displayName) {
displayName = roomName.name
normalizedDisplayName = roomName.normalizedName
}
}
/**
* Workaround for Realm only supporting Latin-1 character sets when sorting
* or filtering by case
* See https://github.com/realm/realm-core/issues/777
*/
private var normalizedDisplayName: String? = ""
var avatarUrl: String? = ""
set(value) {
if (value != field) field = value
@ -284,5 +299,6 @@ internal open class RoomSummaryEntity(
roomEncryptionTrustLevelStr = value?.name
}
}
companion object
}

View file

@ -20,6 +20,7 @@ import com.facebook.stetho.okhttp3.StethoInterceptor
import com.squareup.moshi.Moshi
import dagger.Module
import dagger.Provides
import okhttp3.ConnectionSpec
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.matrix.android.sdk.BuildConfig
@ -29,6 +30,7 @@ import org.matrix.android.sdk.internal.network.TimeOutInterceptor
import org.matrix.android.sdk.internal.network.UserAgentInterceptor
import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor
import org.matrix.android.sdk.internal.network.interceptors.FormattedJsonHttpLogger
import java.util.Collections
import java.util.concurrent.TimeUnit
@Module
@ -66,6 +68,8 @@ internal object NetworkModule {
httpLoggingInterceptor: HttpLoggingInterceptor,
curlLoggingInterceptor: CurlLoggingInterceptor,
apiInterceptor: ApiInterceptor): OkHttpClient {
val spec = ConnectionSpec.Builder(matrixConfiguration.connectionSpec).build()
return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
@ -87,6 +91,7 @@ internal object NetworkModule {
proxy(it)
}
}
.connectionSpecs(Collections.singletonList(spec))
.build()
}

View file

@ -177,15 +177,13 @@ internal object CertUtil {
val trustPinned = arrayOf<TrustManager>(PinnedTrustManagerProvider.provide(hsConfig.allowedFingerprints, defaultTrustManager))
val sslSocketFactory: SSLSocketFactory
if (hsConfig.forceUsageTlsVersions && hsConfig.tlsVersions != null) {
val sslSocketFactory = if (hsConfig.forceUsageTlsVersions && !hsConfig.tlsVersions.isNullOrEmpty()) {
// Force usage of accepted Tls Versions for Android < 20
sslSocketFactory = TLSSocketFactory(trustPinned, hsConfig.tlsVersions)
TLSSocketFactory(trustPinned, hsConfig.tlsVersions)
} else {
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustPinned, java.security.SecureRandom())
sslSocketFactory = sslContext.socketFactory
sslContext.socketFactory
}
return PinnedSSLSocketFactory(sslSocketFactory, defaultTrustManager!!)
@ -237,14 +235,14 @@ internal object CertUtil {
* @return a list of accepted TLS specifications.
*/
fun newConnectionSpecs(hsConfig: HomeServerConnectionConfig): List<ConnectionSpec> {
val builder = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
val builder = ConnectionSpec.Builder(ConnectionSpec.RESTRICTED_TLS)
val tlsVersions = hsConfig.tlsVersions
if (null != tlsVersions && tlsVersions.isNotEmpty()) {
if (!tlsVersions.isNullOrEmpty()) {
builder.tlsVersions(*tlsVersions.toTypedArray())
}
val tlsCipherSuites = hsConfig.tlsCipherSuites
if (null != tlsCipherSuites && tlsCipherSuites.isNotEmpty()) {
if (!tlsCipherSuites.isNullOrEmpty()) {
builder.cipherSuites(*tlsCipherSuites.toTypedArray())
}

View file

@ -20,24 +20,41 @@ import io.realm.Case
import io.realm.RealmObject
import io.realm.RealmQuery
import org.matrix.android.sdk.api.query.QueryStringValue
import timber.log.Timber
import org.matrix.android.sdk.api.query.QueryStringValue.ContentQueryStringValue
import org.matrix.android.sdk.internal.util.Normalizer
import javax.inject.Inject
fun <T : RealmObject> RealmQuery<T>.process(field: String, queryStringValue: QueryStringValue): RealmQuery<T> {
when (queryStringValue) {
is QueryStringValue.NoCondition -> Timber.v("No condition to process")
is QueryStringValue.IsNotNull -> isNotNull(field)
is QueryStringValue.IsNull -> isNull(field)
is QueryStringValue.IsEmpty -> isEmpty(field)
is QueryStringValue.IsNotEmpty -> isNotEmpty(field)
is QueryStringValue.Equals -> equalTo(field, queryStringValue.string, queryStringValue.case.toRealmCase())
is QueryStringValue.Contains -> contains(field, queryStringValue.string, queryStringValue.case.toRealmCase())
class QueryStringValueProcessor @Inject constructor(
private val normalizer: Normalizer
) {
fun <T : RealmObject> RealmQuery<T>.process(field: String, queryStringValue: QueryStringValue): RealmQuery<T> {
return when (queryStringValue) {
is QueryStringValue.NoCondition -> this
is QueryStringValue.IsNotNull -> isNotNull(field)
is QueryStringValue.IsNull -> isNull(field)
is QueryStringValue.IsEmpty -> isEmpty(field)
is QueryStringValue.IsNotEmpty -> isNotEmpty(field)
is ContentQueryStringValue -> when (queryStringValue) {
is QueryStringValue.Equals -> equalTo(field, queryStringValue.toRealmValue(), queryStringValue.case.toRealmCase())
is QueryStringValue.Contains -> contains(field, queryStringValue.toRealmValue(), queryStringValue.case.toRealmCase())
}
}
}
private fun ContentQueryStringValue.toRealmValue(): String {
return when (case) {
QueryStringValue.Case.NORMALIZED -> normalizer.normalize(string)
QueryStringValue.Case.SENSITIVE,
QueryStringValue.Case.INSENSITIVE -> string
}
}
return this
}
private fun QueryStringValue.Case.toRealmCase(): Case {
return when (this) {
QueryStringValue.Case.INSENSITIVE -> Case.INSENSITIVE
QueryStringValue.Case.SENSITIVE -> Case.SENSITIVE
QueryStringValue.Case.SENSITIVE,
QueryStringValue.Case.NORMALIZED -> Case.SENSITIVE
}
}

View file

@ -41,6 +41,7 @@ import org.matrix.android.sdk.api.session.file.ContentDownloadStateTracker
import org.matrix.android.sdk.api.session.file.FileService
import org.matrix.android.sdk.api.session.group.GroupService
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.api.session.identity.IdentityService
import org.matrix.android.sdk.api.session.initsync.SyncStatusService
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
import org.matrix.android.sdk.api.session.media.MediaService
@ -72,7 +73,6 @@ import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
import org.matrix.android.sdk.internal.di.WorkManagerProvider
import org.matrix.android.sdk.internal.network.GlobalErrorHandler
import org.matrix.android.sdk.internal.session.identity.DefaultIdentityService
import org.matrix.android.sdk.internal.session.sync.SyncTokenStore
import org.matrix.android.sdk.internal.session.sync.job.SyncThread
import org.matrix.android.sdk.internal.session.sync.job.SyncWorker
@ -124,7 +124,7 @@ internal class DefaultSession @Inject constructor(
private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>,
private val accountService: Lazy<AccountService>,
private val eventService: Lazy<EventService>,
private val defaultIdentityService: DefaultIdentityService,
private val identityService: IdentityService,
private val integrationManagerService: IntegrationManagerService,
private val thirdPartyService: Lazy<ThirdPartyService>,
private val callSignalingService: Lazy<CallSignalingService>,
@ -275,7 +275,7 @@ internal class DefaultSession @Inject constructor(
override fun cryptoService(): CryptoService = cryptoService.get()
override fun identityService() = defaultIdentityService
override fun identityService() = identityService
override fun fileService(): FileService = defaultFileService.get()

View file

@ -35,12 +35,12 @@ import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.content.ContentUrlResolver
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.internal.di.Authenticated
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.ProgressRequestBody
import org.matrix.android.sdk.internal.network.awaitResponse
import org.matrix.android.sdk.internal.network.toFailure
import org.matrix.android.sdk.internal.session.homeserver.DefaultHomeServerCapabilitiesService
import org.matrix.android.sdk.internal.util.TemporaryFileCreator
import java.io.File
import java.io.FileNotFoundException
@ -50,7 +50,7 @@ import javax.inject.Inject
internal class FileUploader @Inject constructor(
@Authenticated private val okHttpClient: OkHttpClient,
private val globalErrorReceiver: GlobalErrorReceiver,
private val homeServerCapabilitiesService: DefaultHomeServerCapabilitiesService,
private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
private val context: Context,
private val temporaryFileCreator: TemporaryFileCreator,
contentUrlResolver: ContentUrlResolver,

View file

@ -30,12 +30,16 @@ import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity
import org.matrix.android.sdk.internal.database.model.GroupSummaryEntityFields
import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.util.fetchCopyMap
import javax.inject.Inject
internal class DefaultGroupService @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val groupFactory: GroupFactory) : GroupService {
internal class DefaultGroupService @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val groupFactory: GroupFactory,
private val queryStringValueProcessor: QueryStringValueProcessor,
) : GroupService {
override fun getGroup(groupId: String): Group? {
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
@ -67,8 +71,10 @@ internal class DefaultGroupService @Inject constructor(@SessionDatabase private
}
private fun groupSummariesQuery(realm: Realm, queryParams: GroupSummaryQueryParams): RealmQuery<GroupSummaryEntity> {
return GroupSummaryEntity.where(realm)
.process(GroupSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
.process(GroupSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
return with(queryStringValueProcessor) {
GroupSummaryEntity.where(realm)
.process(GroupSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
.process(GroupSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
}
}
}

View file

@ -80,7 +80,7 @@ internal class DefaultIdentityService @Inject constructor(
private val identityApiProvider: IdentityApiProvider,
private val accountDataDataSource: UserAccountDataDataSource,
private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
private val sign3pidInvitationTask: DefaultSign3pidInvitationTask,
private val sign3pidInvitationTask: Sign3pidInvitationTask,
private val sessionParams: SessionParams
) : IdentityService, SessionLifecycleObserver {

View file

@ -21,6 +21,7 @@ import dagger.Module
import dagger.Provides
import io.realm.RealmConfiguration
import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.session.identity.IdentityService
import org.matrix.android.sdk.internal.database.RealmKeysUtils
import org.matrix.android.sdk.internal.di.AuthenticatedIdentity
import org.matrix.android.sdk.internal.di.IdentityDatabase
@ -75,6 +76,9 @@ internal abstract class IdentityModule {
}
}
@Binds
abstract fun bindIdentityService(service: DefaultIdentityService): IdentityService
@Binds
@AuthenticatedIdentity
abstract fun bindAccessTokenProvider(provider: IdentityAccessTokenProvider): AccessTokenProvider

View file

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.notification
import org.matrix.android.sdk.api.pushrules.rest.PushRule
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.isInvitation
import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.task.Task
@ -48,14 +49,18 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
}
val newJoinEvents = params.syncResponse.join
.mapNotNull { (key, value) ->
value.timeline?.events?.map { it.copy(roomId = key) }
value.timeline?.events?.mapNotNull {
it.takeIf { !it.isInvitation() }?.copy(roomId = key)
}
}
.flatten()
val inviteEvents = params.syncResponse.invite
.mapNotNull { (key, value) ->
value.inviteState?.events?.map { it.copy(roomId = key) }
}
.flatten()
val allEvents = (newJoinEvents + inviteEvents).filter { event ->
when (event.type) {
EventType.MESSAGE,

View file

@ -85,12 +85,14 @@ internal class DefaultRoomService @Inject constructor(
return roomSummaryDataSource.getRoomSummary(roomIdOrAlias)
}
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
return roomSummaryDataSource.getRoomSummaries(queryParams)
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder): List<RoomSummary> {
return roomSummaryDataSource.getRoomSummaries(queryParams, sortOrder)
}
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getRoomSummariesLive(queryParams)
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getRoomSummariesLive(queryParams, sortOrder)
}
override fun getPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,

View file

@ -33,6 +33,7 @@ import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.session.room.membership.admin.MembershipAdminTask
import org.matrix.android.sdk.internal.session.room.membership.joining.InviteTask
@ -51,7 +52,8 @@ internal class DefaultMembershipService @AssistedInject constructor(
private val leaveRoomTask: LeaveRoomTask,
private val membershipAdminTask: MembershipAdminTask,
@UserId
private val userId: String
private val userId: String,
private val queryStringValueProcessor: QueryStringValueProcessor
) : MembershipService {
@AssistedFactory
@ -94,15 +96,17 @@ internal class DefaultMembershipService @AssistedInject constructor(
}
private fun roomMembersQuery(realm: Realm, queryParams: RoomMemberQueryParams): RealmQuery<RoomMemberSummaryEntity> {
return RoomMemberHelper(realm, roomId).queryRoomMembersEvent()
.process(RoomMemberSummaryEntityFields.USER_ID, queryParams.userId)
.process(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
.process(RoomMemberSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
.apply {
if (queryParams.excludeSelf) {
notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
return with(queryStringValueProcessor) {
RoomMemberHelper(realm, roomId).queryRoomMembersEvent()
.process(RoomMemberSummaryEntityFields.USER_ID, queryParams.userId)
.process(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
.process(RoomMemberSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
.apply {
if (queryParams.excludeSelf) {
notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
}
}
}
}
}
override fun getNumberOfJoinedMembers(): Int {

View file

@ -34,6 +34,7 @@ import org.matrix.android.sdk.internal.database.query.getOrNull
import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.displayname.DisplayNameResolver
import org.matrix.android.sdk.internal.util.Normalizer
import javax.inject.Inject
/**
@ -42,6 +43,7 @@ import javax.inject.Inject
internal class RoomDisplayNameResolver @Inject constructor(
matrixConfiguration: MatrixConfiguration,
private val displayNameResolver: DisplayNameResolver,
private val normalizer: Normalizer,
@UserId private val userId: String
) {
@ -54,7 +56,7 @@ internal class RoomDisplayNameResolver @Inject constructor(
* @param roomId: the roomId to resolve the name of.
* @return the room display name
*/
fun resolve(realm: Realm, roomId: String): String {
fun resolve(realm: Realm, roomId: String): RoomName {
// this algorithm is the one defined in
// https://github.com/matrix-org/matrix-js-sdk/blob/develop/lib/models/room.js#L617
// calculateRoomName(room, userId)
@ -66,12 +68,12 @@ internal class RoomDisplayNameResolver @Inject constructor(
val roomName = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_NAME, stateKey = "")?.root
name = ContentMapper.map(roomName?.content).toModel<RoomNameContent>()?.name
if (!name.isNullOrEmpty()) {
return name
return name.toRoomName()
}
val canonicalAlias = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_CANONICAL_ALIAS, stateKey = "")?.root
name = ContentMapper.map(canonicalAlias?.content).toModel<RoomCanonicalAliasContent>()?.canonicalAlias
if (!name.isNullOrEmpty()) {
return name
return name.toRoomName()
}
val roomMembers = RoomMemberHelper(realm, roomId)
@ -152,7 +154,7 @@ internal class RoomDisplayNameResolver @Inject constructor(
}
}
}
return name ?: roomId
return (name ?: roomId).toRoomName()
}
/** See [org.matrix.android.sdk.api.session.room.sender.SenderInfo.disambiguatedDisplayName] */
@ -165,4 +167,8 @@ internal class RoomDisplayNameResolver @Inject constructor(
"${roomMemberSummary.displayName} (${roomMemberSummary.userId})"
}
}
private fun String.toRoomName() = RoomName(this, normalizedName = normalizer.normalize(this))
}
internal data class RoomName(val name: String, val normalizedName: String)

View file

@ -31,11 +31,15 @@ import org.matrix.android.sdk.internal.database.mapper.asDomain
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
import org.matrix.android.sdk.internal.query.process
import javax.inject.Inject
internal class StateEventDataSource @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val realmSessionProvider: RealmSessionProvider) {
internal class StateEventDataSource @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val realmSessionProvider: RealmSessionProvider,
private val queryStringValueProcessor: QueryStringValueProcessor
) {
fun getStateEvent(roomId: String, eventType: String, stateKey: QueryStringValue): Event? {
return realmSessionProvider.withRealm { realm ->
@ -78,13 +82,15 @@ internal class StateEventDataSource @Inject constructor(@SessionDatabase private
eventTypes: Set<String>,
stateKey: QueryStringValue
): RealmQuery<CurrentStateEventEntity> {
return realm.where<CurrentStateEventEntity>()
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.apply {
if (eventTypes.isNotEmpty()) {
`in`(CurrentStateEventEntityFields.TYPE, eventTypes.toTypedArray())
return with(queryStringValueProcessor) {
realm.where<CurrentStateEventEntity>()
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.apply {
if (eventTypes.isNotEmpty()) {
`in`(CurrentStateEventEntityFields.TYPE, eventTypes.toTypedArray())
}
}
}
.process(CurrentStateEventEntityFields.STATE_KEY, stateKey)
.process(CurrentStateEventEntityFields.STATE_KEY, stateKey)
}
}
}

View file

@ -25,10 +25,10 @@ import androidx.paging.PagedList
import com.zhuinden.monarchy.Monarchy
import io.realm.Realm
import io.realm.RealmQuery
import io.realm.Sort
import io.realm.kotlin.where
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
import org.matrix.android.sdk.api.query.RoomCategoryFilter
import org.matrix.android.sdk.api.query.isNormalized
import org.matrix.android.sdk.api.session.room.ResultBoundaries
import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
@ -48,12 +48,16 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
import org.matrix.android.sdk.internal.database.query.findByAlias
import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.util.fetchCopyMap
import javax.inject.Inject
internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper) {
internal class RoomSummaryDataSource @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val queryStringValueProcessor: QueryStringValueProcessor
) {
fun getRoomSummary(roomIdOrAlias: String): RoomSummary? {
return monarchy
@ -80,25 +84,27 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
}
}
fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary> {
return monarchy.fetchAllMappedSync(
{ roomSummariesQuery(it, queryParams) },
{ roomSummariesQuery(it, queryParams).process(sortOrder) },
{ roomSummaryMapper.map(it) }
)
}
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{
roomSummariesQuery(it, queryParams)
.sort(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, Sort.DESCENDING)
roomSummariesQuery(it, queryParams).process(sortOrder)
},
{ roomSummaryMapper.map(it) }
)
}
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> {
return getRoomSummariesLive(queryParams)
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>> {
return getRoomSummariesLive(queryParams, sortOrder)
}
fun getSpaceSummary(roomIdOrAlias: String): RoomSummary? {
@ -122,8 +128,9 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
}
}
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> {
return getRoomSummaries(spaceSummaryQueryParams)
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary> {
return getRoomSummaries(spaceSummaryQueryParams, sortOrder)
}
fun getRootSpaceSummaries(): List<RoomSummary> {
@ -238,12 +245,20 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
}
private fun roomSummariesQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> {
val query = RoomSummaryEntity.where(realm)
query.process(RoomSummaryEntityFields.ROOM_ID, queryParams.roomId)
query.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
query.process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias)
query.process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
query.equalTo(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, false)
val query = with(queryStringValueProcessor) {
RoomSummaryEntity.where(realm)
.process(RoomSummaryEntityFields.ROOM_ID, queryParams.roomId)
.let {
if (queryParams.displayName.isNormalized()) {
it.process(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, queryParams.displayName)
} else {
it.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
}
}
.process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias)
.process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
.equalTo(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, false)
}
queryParams.roomCategoryFilter?.let {
when (it) {

View file

@ -65,6 +65,7 @@ import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataD
import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
import org.matrix.android.sdk.internal.session.room.relationship.RoomChildRelationInfo
import org.matrix.android.sdk.internal.util.Normalizer
import timber.log.Timber
import javax.inject.Inject
import kotlin.system.measureTimeMillis
@ -75,7 +76,8 @@ internal class RoomSummaryUpdater @Inject constructor(
private val roomAvatarResolver: RoomAvatarResolver,
private val eventDecryptor: EventDecryptor,
private val crossSigningService: DefaultCrossSigningService,
private val roomAccountDataDataSource: RoomAccountDataDataSource) {
private val roomAccountDataDataSource: RoomAccountDataDataSource,
private val normalizer: Normalizer) {
fun update(realm: Realm,
roomId: String,
@ -136,7 +138,7 @@ internal class RoomSummaryUpdater @Inject constructor(
// avoid this call if we are sure there are unread events
!isEventRead(realm.configuration, userId, roomId, latestPreviewableEvent?.eventId)
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(realm, roomId)
roomSummaryEntity.setDisplayName(roomDisplayNameResolver.resolve(realm, roomId))
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId)
roomSummaryEntity.name = ContentMapper.map(lastNameEvent?.content).toModel<RoomNameContent>()?.name
roomSummaryEntity.topic = ContentMapper.map(lastTopicEvent?.content).toModel<RoomTopicContent>()?.topic

View file

@ -42,11 +42,12 @@ internal class DefaultSignInAgainTask @Inject constructor(
signOutAPI.loginAgain(
PasswordLoginParams.userIdentifier(
// Reuse the same userId
sessionParams.userId,
params.password,
user = sessionParams.userId,
password = params.password,
// The spec says the initial device name will be ignored
// https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-login
// but https://github.com/matrix-org/synapse/issues/6525
deviceDisplayName = null,
// Reuse the same deviceId
deviceId = sessionParams.deviceId
)

View file

@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.model.GuestAccess
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
@ -94,12 +95,14 @@ internal class DefaultSpaceService @Inject constructor(
return spaceGetter.get(spaceId)
}
override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getSpaceSummariesLive(queryParams)
override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getSpaceSummariesLive(queryParams, sortOrder)
}
override fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> {
return roomSummaryDataSource.getSpaceSummaries(spaceSummaryQueryParams)
override fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder): List<RoomSummary> {
return roomSummaryDataSource.getSpaceSummaries(spaceSummaryQueryParams, sortOrder)
}
override fun getRootSpaceSummaries(): List<RoomSummary> {

View file

@ -166,7 +166,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
roomSummaryEntity.directUserId = userId
// Also update the avatar and displayname, there is a specific treatment for DMs
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId)
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(realm, roomId)
roomSummaryEntity.setDisplayName(roomDisplayNameResolver.resolve(realm, roomId))
}
}
}
@ -178,7 +178,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
it.directUserId = null
// Also update the avatar and displayname, there was a specific treatment for DMs
it.avatarUrl = roomAvatarResolver.resolve(realm, it.roomId)
it.displayName = roomDisplayNameResolver.resolve(realm, it.roomId)
it.setDisplayName(roomDisplayNameResolver.resolve(realm, it.roomId))
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2019 New Vector Ltd
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,14 +14,14 @@
* limitations under the License.
*/
package im.vector.app.features.home.room.list
package org.matrix.android.sdk.internal.util
import dagger.Binds
import dagger.Module
import java.text.Normalizer
import javax.inject.Inject
@Module
abstract class RoomListModule {
class Normalizer @Inject constructor() {
@Binds
abstract fun providesRoomListViewModelFactory(factory: RoomListViewModelFactory): RoomListViewModel.Factory
fun normalize(input: String): String {
return Normalizer.normalize(input.lowercase(), Normalizer.Form.NFD)
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2021 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.internal.database
import io.mockk.mockk
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test
class RealmSessionStoreMigrationTest {
@Test
fun `when creating multiple migration instances then they are equal`() {
RealmSessionStoreMigration(normalizer = mockk()) shouldBeEqualTo RealmSessionStoreMigration(normalizer = mockk())
}
}

View file

@ -1 +0,0 @@
Priority conversations for Android 11+

View file

@ -160,7 +160,7 @@ Formatter\.formatShortFileSize===1
# android\.text\.TextUtils
### This is not a rule, but a warning: the number of "enum class" has changed. For Json classes, it is mandatory that they have `@JsonClass(generateAdapter = false)`. If the enum is not used as a Json class, change the value in file forbidden_strings_in_code.txt
enum class===106
enum class===107
### Do not import temporary legacy classes
import org.matrix.android.sdk.internal.legacy.riot===3

View file

@ -6,6 +6,7 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt'
apply plugin: 'placeholder-resolver'
apply plugin: 'dagger.hilt.android.plugin'
kapt {
correctErrorTypes = true
@ -14,7 +15,7 @@ kapt {
// Note: 2 digits max for each value
ext.versionMajor = 1
ext.versionMinor = 3
ext.versionPatch = 5
ext.versionPatch = 7
static def getGitTimestamp() {
def cmd = 'git show -s --format=%ct'
@ -371,7 +372,7 @@ dependencies {
implementation 'com.facebook.stetho:stetho:1.6.0'
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.35'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.36'
// rx
implementation libs.rx.rxKotlin
@ -456,8 +457,8 @@ dependencies {
implementation 'nl.dionsegijn:konfetti:1.3.2'
implementation 'com.github.jetradarmobile:android-snowfall:1.2.1'
// DI
implementation libs.dagger.dagger
kapt libs.dagger.daggerCompiler
implementation libs.dagger.hilt
kapt libs.dagger.hiltCompiler
// gplay flavor only
gplayImplementation('com.google.firebase:firebase-messaging:22.0.0') {
@ -470,10 +471,7 @@ dependencies {
gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
implementation "androidx.emoji:emoji-appcompat:1.1.0"
implementation ('com.github.BillCarsonFr:JsonViewer:0.6'){
exclude group: 'com.airbnb.android'
}
implementation ('com.github.BillCarsonFr:JsonViewer:0.7')
// WebRTC
// org.webrtc:google-webrtc is for development purposes only

View file

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

View file

@ -22,6 +22,7 @@ import android.os.Build
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.checkPermissions
@ -31,6 +32,7 @@ import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.databinding.ActivityDebugPermissionBinding
import timber.log.Timber
@AndroidEntryPoint
class DebugPermissionActivity : VectorBaseActivity<ActivityDebugPermissionBinding>() {
override fun getBinding() = ActivityDebugPermissionBinding.inflate(layoutInflater)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -27,18 +27,15 @@ import androidx.lifecycle.ProcessLifecycleOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.vectorComponent
import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.PushersManager
import im.vector.app.features.badge.BadgeProxy
import im.vector.app.features.notifications.NotifiableEventResolver
import im.vector.app.features.notifications.NotifiableMessageEvent
import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.notifications.SimpleNotifiableEvent
import im.vector.app.features.settings.VectorDataStore
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.push.fcm.FcmHelper
@ -48,25 +45,25 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.logger.LoggerTag
import org.matrix.android.sdk.api.pushrules.Action
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.Event
import timber.log.Timber
import javax.inject.Inject
private val loggerTag = LoggerTag("Push", LoggerTag.SYNC)
/**
* Class extending FirebaseMessagingService.
*/
@AndroidEntryPoint
class VectorFirebaseMessagingService : FirebaseMessagingService() {
private lateinit var notificationDrawerManager: NotificationDrawerManager
private lateinit var notifiableEventResolver: NotifiableEventResolver
private lateinit var pusherManager: PushersManager
private lateinit var activeSessionHolder: ActiveSessionHolder
private lateinit var vectorPreferences: VectorPreferences
private lateinit var vectorDataStore: VectorDataStore
private lateinit var wifiDetector: WifiDetector
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
@Inject lateinit var notifiableEventResolver: NotifiableEventResolver
@Inject lateinit var pusherManager: PushersManager
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var vectorDataStore: VectorDataStore
@Inject lateinit var wifiDetector: WifiDetector
private val coroutineScope = CoroutineScope(SupervisorJob())
@ -75,19 +72,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
Handler(Looper.getMainLooper())
}
override fun onCreate() {
super.onCreate()
with(vectorComponent()) {
notificationDrawerManager = notificationDrawerManager()
notifiableEventResolver = notifiableEventResolver()
pusherManager = pusherManager()
activeSessionHolder = activeSessionHolder()
vectorPreferences = vectorPreferences()
vectorDataStore = vectorDataStore()
wifiDetector = wifiDetector()
}
}
/**
* Called when message is received.
*
@ -212,12 +196,11 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
Timber.tag(loggerTag.value).d("Fast lane: start request")
val event = tryOrNull { session.getEvent(roomId, eventId) } ?: return@launch
val resolvedEvent = notifiableEventResolver.resolveInMemoryEvent(session, event)
val resolvedEvent = notifiableEventResolver.resolveInMemoryEvent(session, event, canBeReplaced = true)
resolvedEvent
?.also { Timber.tag(loggerTag.value).d("Fast lane: notify drawer") }
?.let {
it.isPushGatewayEvent = true
notificationDrawerManager.onNotifiableEventReceived(it)
notificationDrawerManager.refreshNotificationDrawer()
}
@ -238,87 +221,4 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
}
return false
}
private fun handleNotificationWithoutSyncingMode(data: Map<String, String>, session: Session?) {
if (session == null) {
Timber.tag(loggerTag.value).e("## handleNotificationWithoutSyncingMode cannot find session")
return
}
// The Matrix event ID of the event being notified about.
// This is required if the notification is about a particular Matrix event.
// It may be omitted for notifications that only contain updated badge counts.
// This ID can and should be used to detect duplicate notification requests.
val eventId = data["event_id"] ?: return // Just ignore
val eventType = data["type"]
if (eventType == null) {
// Just add a generic unknown event
val simpleNotifiableEvent = SimpleNotifiableEvent(
session.myUserId,
eventId,
null,
true, // It's an issue in this case, all event will bing even if expected to be silent.
title = getString(R.string.notification_unknown_new_event),
description = "",
type = null,
timestamp = System.currentTimeMillis(),
soundName = Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT,
isPushGatewayEvent = true
)
notificationDrawerManager.onNotifiableEventReceived(simpleNotifiableEvent)
notificationDrawerManager.refreshNotificationDrawer()
} else {
val event = parseEvent(data) ?: return
val notifiableEvent = notifiableEventResolver.resolveEvent(event, session)
if (notifiableEvent == null) {
Timber.tag(loggerTag.value).e("Unsupported notifiable event $eventId")
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
Timber.tag(loggerTag.value).e("--> $event")
}
} else {
if (notifiableEvent is NotifiableMessageEvent) {
if (notifiableEvent.senderName.isNullOrEmpty()) {
notifiableEvent.senderName = data["sender_display_name"] ?: data["sender"] ?: ""
}
if (notifiableEvent.roomName.isNullOrEmpty()) {
notifiableEvent.roomName = findRoomNameBestEffort(data, session) ?: ""
}
}
notifiableEvent.isPushGatewayEvent = true
notifiableEvent.matrixID = session.myUserId
notificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
notificationDrawerManager.refreshNotificationDrawer()
}
}
}
private fun findRoomNameBestEffort(data: Map<String, String>, session: Session?): String? {
var roomName: String? = data["room_name"]
val roomId = data["room_id"]
if (null == roomName && null != roomId) {
// Try to get the room name from our store
roomName = session?.getRoom(roomId)?.roomSummary()?.displayName
}
return roomName
}
/**
* Try to create an event from the FCM data
*
* @param data the FCM data
* @return the event or null if required data are missing
*/
private fun parseEvent(data: Map<String, String>?): Event? {
return Event(
eventId = data?.get("event_id") ?: return null,
senderId = data["sender"],
roomId = data["room_id"] ?: return null,
type = data["type"] ?: return null,
originServerTs = System.currentTimeMillis()
)
}
}

View file

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

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.di
import androidx.fragment.app.FragmentFactory
import androidx.lifecycle.ViewModelProvider
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
@InstallIn(ActivityComponent::class)
@EntryPoint
interface ActivityEntryPoint {
fun fragmentFactory(): FragmentFactory
fun viewModelFactory(): ViewModelProvider.Factory
}

View file

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

View file

@ -0,0 +1,92 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.di
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.MavericksViewModel
import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import dagger.hilt.DefineComponent
import dagger.hilt.EntryPoint
import dagger.hilt.EntryPoints
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
/**
* To connect Mavericks ViewModel creation with Hilt's dependency injection, add the following Factory and companion object to your MavericksViewModel.
*
* Example:
*
* class MyViewModel @AssistedInject constructor(...): MavericksViewModel<MyState>(...) {
*
* @AssistedFactory
* interface Factory : AssistedViewModelFactory<MyViewModel, MyState> {
* ...
* }
*
* companion object : MavericksViewModelFactory<MyViewModel, MyState> by hiltMavericksViewModelFactory()
* }
*/
inline fun <reified VM : MavericksViewModel<S>, S : MavericksState> hiltMavericksViewModelFactory() = HiltMavericksViewModelFactory<VM, S>(VM::class.java)
class HiltMavericksViewModelFactory<VM : MavericksViewModel<S>, S : MavericksState>(
private val viewModelClass: Class<out MavericksViewModel<S>>
) : MavericksViewModelFactory<VM, S> {
override fun create(viewModelContext: ViewModelContext, state: S): VM {
// We want to create the ViewModelComponent. In order to do that, we need to get its parent: ActivityComponent.
val componentBuilder = EntryPoints.get(viewModelContext.app(), CreateMavericksViewModelComponent::class.java).mavericksViewModelComponentBuilder()
val viewModelComponent = componentBuilder.build()
val viewModelFactoryMap = EntryPoints.get(viewModelComponent, HiltMavericksEntryPoint::class.java).viewModelFactories
val viewModelFactory = viewModelFactoryMap[viewModelClass]
@Suppress("UNCHECKED_CAST")
val castedViewModelFactory = viewModelFactory as? MavericksAssistedViewModelFactory<VM, S>
return castedViewModelFactory?.create(state) as VM
}
override fun initialState(viewModelContext: ViewModelContext): S? {
return super.initialState(viewModelContext)
}
}
/**
* Hilt's ViewModelComponent's parent is ActivityRetainedComponent but there is no easy way to access it. SingletonComponent should be sufficient
* because the ViewModel that gets created is the only object with a reference to the created component so the lifecycle of it will
* still be correct.
*/
@MavericksViewModelScoped
@DefineComponent(parent = SingletonComponent::class)
interface MavericksViewModelComponent
@DefineComponent.Builder
interface MavericksViewModelComponentBuilder {
fun build(): MavericksViewModelComponent
}
@EntryPoint
@InstallIn(SingletonComponent::class)
interface CreateMavericksViewModelComponent {
fun mavericksViewModelComponentBuilder(): MavericksViewModelComponentBuilder
}
@EntryPoint
@InstallIn(MavericksViewModelComponent::class)
interface HiltMavericksEntryPoint {
val viewModelFactories: Map<Class<out MavericksViewModel<*>>, MavericksAssistedViewModelFactory<*, *>>
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.di
import android.os.Handler
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import im.vector.app.features.home.room.detail.timeline.TimelineEventControllerHandler
import im.vector.app.features.home.room.detail.timeline.helper.TimelineAsyncHelper
@Module
@InstallIn(ActivityComponent::class)
object HomeModule {
@Provides
@JvmStatic
@TimelineEventControllerHandler
fun providesTimelineBackgroundHandler(): Handler {
return TimelineAsyncHelper.getBackgroundHandler()
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.di
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.MavericksViewModel
/**
* This factory allows Mavericks to supply the initial or restored [MavericksState] to Hilt.
*
* Add this interface inside of your [MavericksViewModel] class then create the following Hilt module:
*
* @Module
* @InstallIn(MavericksViewModelComponent::class)
* interface ViewModelsModule {
* @Binds
* @IntoMap
* @ViewModelKey(MyViewModel::class)
* fun myViewModelFactory(factory: MyViewModel.Factory): AssistedViewModelFactory<*, *>
* }
*
* If you already have a ViewModelsModule then all you have to do is add the multibinding entry for your new [MavericksViewModel].
*/
interface MavericksAssistedViewModelFactory<VM : MavericksViewModel<S>, S : MavericksState> {
fun create(initialState: S): VM
}

View file

@ -0,0 +1,549 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.di
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.multibindings.IntoMap
import im.vector.app.features.auth.ReAuthViewModel
import im.vector.app.features.call.VectorCallViewModel
import im.vector.app.features.call.conference.JitsiCallViewModel
import im.vector.app.features.call.transfer.CallTransferViewModel
import im.vector.app.features.contactsbook.ContactsBookViewModel
import im.vector.app.features.createdirect.CreateDirectRoomViewModel
import im.vector.app.features.createpoll.CreatePollViewModel
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel
import im.vector.app.features.crypto.quads.SharedSecureStorageViewModel
import im.vector.app.features.crypto.recover.BootstrapSharedViewModel
import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel
import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodViewModel
import im.vector.app.features.crypto.verification.emoji.VerificationEmojiCodeViewModel
import im.vector.app.features.devtools.RoomDevToolViewModel
import im.vector.app.features.discovery.DiscoverySettingsViewModel
import im.vector.app.features.discovery.change.SetIdentityServerViewModel
import im.vector.app.features.home.HomeActivityViewModel
import im.vector.app.features.home.HomeDetailViewModel
import im.vector.app.features.home.PromoteRestrictedViewModel
import im.vector.app.features.home.UnknownDeviceDetectorSharedViewModel
import im.vector.app.features.home.UnreadMessagesSharedViewModel
import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsViewModel
import im.vector.app.features.home.room.detail.composer.TextComposerViewModel
import im.vector.app.features.home.room.detail.search.SearchViewModel
import im.vector.app.features.home.room.detail.timeline.action.MessageActionsViewModel
import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryViewModel
import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsViewModel
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomViewModel
import im.vector.app.features.home.room.list.RoomListViewModel
import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel
import im.vector.app.features.invite.InviteUsersToRoomViewModel
import im.vector.app.features.login.LoginViewModel
import im.vector.app.features.login2.LoginViewModel2
import im.vector.app.features.login2.created.AccountCreatedViewModel
import im.vector.app.features.matrixto.MatrixToBottomSheetViewModel
import im.vector.app.features.rageshake.BugReportViewModel
import im.vector.app.features.reactions.EmojiSearchResultViewModel
import im.vector.app.features.room.RequireActiveMembershipViewModel
import im.vector.app.features.roomdirectory.RoomDirectoryViewModel
import im.vector.app.features.roomdirectory.createroom.CreateRoomViewModel
import im.vector.app.features.roomdirectory.picker.RoomDirectoryPickerViewModel
import im.vector.app.features.roomdirectory.roompreview.RoomPreviewViewModel
import im.vector.app.features.roommemberprofile.RoomMemberProfileViewModel
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheetViewModel
import im.vector.app.features.roomprofile.RoomProfileViewModel
import im.vector.app.features.roomprofile.alias.RoomAliasViewModel
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetViewModel
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListViewModel
import im.vector.app.features.roomprofile.members.RoomMemberListViewModel
import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewModel
import im.vector.app.features.roomprofile.permissions.RoomPermissionsViewModel
import im.vector.app.features.roomprofile.settings.RoomSettingsViewModel
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel
import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel
import im.vector.app.features.settings.account.deactivation.DeactivateAccountViewModel
import im.vector.app.features.settings.crosssigning.CrossSigningSettingsViewModel
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheetViewModel
import im.vector.app.features.settings.devices.DevicesViewModel
import im.vector.app.features.settings.devtools.AccountDataViewModel
import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel
import im.vector.app.features.settings.devtools.KeyRequestListViewModel
import im.vector.app.features.settings.homeserver.HomeserverSettingsViewModel
import im.vector.app.features.settings.ignored.IgnoredUsersViewModel
import im.vector.app.features.settings.locale.LocalePickerViewModel
import im.vector.app.features.settings.push.PushGatewaysViewModel
import im.vector.app.features.settings.threepids.ThreePidsSettingsViewModel
import im.vector.app.features.share.IncomingShareViewModel
import im.vector.app.features.signout.soft.SoftLogoutViewModel
import im.vector.app.features.spaces.SpaceListViewModel
import im.vector.app.features.spaces.SpaceMenuViewModel
import im.vector.app.features.spaces.create.CreateSpaceViewModel
import im.vector.app.features.spaces.explore.SpaceDirectoryViewModel
import im.vector.app.features.spaces.invite.SpaceInviteBottomSheetViewModel
import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedViewModel
import im.vector.app.features.spaces.manage.SpaceAddRoomsViewModel
import im.vector.app.features.spaces.manage.SpaceManageRoomsViewModel
import im.vector.app.features.spaces.manage.SpaceManageSharedViewModel
import im.vector.app.features.spaces.people.SpacePeopleViewModel
import im.vector.app.features.spaces.preview.SpacePreviewViewModel
import im.vector.app.features.spaces.share.ShareSpaceViewModel
import im.vector.app.features.terms.ReviewTermsViewModel
import im.vector.app.features.usercode.UserCodeSharedViewModel
import im.vector.app.features.userdirectory.UserListViewModel
import im.vector.app.features.widgets.WidgetViewModel
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewModel
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import im.vector.app.features.workers.signout.SignoutCheckViewModel
@InstallIn(MavericksViewModelComponent::class)
@Module
interface MavericksViewModelModule {
@Binds
@IntoMap
@MavericksViewModelKey(RoomListViewModel::class)
fun roomListViewModelFactory(factory: RoomListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceManageRoomsViewModel::class)
fun spaceManageRoomsViewModelFactory(factory: SpaceManageRoomsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceManageSharedViewModel::class)
fun spaceManageSharedViewModelFactory(factory: SpaceManageSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceListViewModel::class)
fun spaceListViewModelFactory(factory: SpaceListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ReAuthViewModel::class)
fun reAuthViewModelFactory(factory: ReAuthViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VectorCallViewModel::class)
fun vectorCallViewModelFactory(factory: VectorCallViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(JitsiCallViewModel::class)
fun jitsiCallViewModelFactory(factory: JitsiCallViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomDirectoryViewModel::class)
fun roomDirectoryViewModelFactory(factory: RoomDirectoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ViewReactionsViewModel::class)
fun viewReactionsViewModelFactory(factory: ViewReactionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomWidgetPermissionViewModel::class)
fun roomWidgetPermissionViewModelFactory(factory: RoomWidgetPermissionViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(WidgetViewModel::class)
fun widgetViewModelFactory(factory: WidgetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ServerBackupStatusViewModel::class)
fun serverBackupStatusViewModelFactory(factory: ServerBackupStatusViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SignoutCheckViewModel::class)
fun signoutCheckViewModelFactory(factory: SignoutCheckViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomDirectoryPickerViewModel::class)
fun roomDirectoryPickerViewModelFactory(factory: RoomDirectoryPickerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomDevToolViewModel::class)
fun roomDevToolViewModelFactory(factory: RoomDevToolViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(MigrateRoomViewModel::class)
fun migrateRoomViewModelFactory(factory: MigrateRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(IgnoredUsersViewModel::class)
fun ignoredUsersViewModelFactory(factory: IgnoredUsersViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CallTransferViewModel::class)
fun callTransferViewModelFactory(factory: CallTransferViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ContactsBookViewModel::class)
fun contactsBookViewModelFactory(factory: ContactsBookViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CreateDirectRoomViewModel::class)
fun createDirectRoomViewModelFactory(factory: CreateDirectRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomNotificationSettingsViewModel::class)
fun roomNotificationSettingsViewModelFactory(factory: RoomNotificationSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(KeysBackupSettingsViewModel::class)
fun keysBackupSettingsViewModelFactory(factory: KeysBackupSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SharedSecureStorageViewModel::class)
fun sharedSecureStorageViewModelFactory(factory: SharedSecureStorageViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(PromoteRestrictedViewModel::class)
fun promoteRestrictedViewModelFactory(factory: PromoteRestrictedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(UserListViewModel::class)
fun userListViewModelFactory(factory: UserListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(UserCodeSharedViewModel::class)
fun userCodeSharedViewModelFactory(factory: UserCodeSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ReviewTermsViewModel::class)
fun reviewTermsViewModelFactory(factory: ReviewTermsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ShareSpaceViewModel::class)
fun shareSpaceViewModelFactory(factory: ShareSpaceViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpacePreviewViewModel::class)
fun spacePreviewViewModelFactory(factory: SpacePreviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpacePeopleViewModel::class)
fun spacePeopleViewModelFactory(factory: SpacePeopleViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceAddRoomsViewModel::class)
fun spaceAddRoomsViewModelFactory(factory: SpaceAddRoomsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceLeaveAdvancedViewModel::class)
fun spaceLeaveAdvancedViewModelFactory(factory: SpaceLeaveAdvancedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceInviteBottomSheetViewModel::class)
fun spaceInviteBottomSheetViewModelFactory(factory: SpaceInviteBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceDirectoryViewModel::class)
fun spaceDirectoryViewModelFactory(factory: SpaceDirectoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CreateSpaceViewModel::class)
fun createSpaceViewModelFactory(factory: CreateSpaceViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SpaceMenuViewModel::class)
fun spaceMenuViewModelFactory(factory: SpaceMenuViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SoftLogoutViewModel::class)
fun softLogoutViewModelFactory(factory: SoftLogoutViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(IncomingShareViewModel::class)
fun incomingShareViewModelFactory(factory: IncomingShareViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ThreePidsSettingsViewModel::class)
fun threePidsSettingsViewModelFactory(factory: ThreePidsSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(PushGatewaysViewModel::class)
fun pushGatewaysViewModelFactory(factory: PushGatewaysViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(HomeserverSettingsViewModel::class)
fun homeserverSettingsViewModelFactory(factory: HomeserverSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(LocalePickerViewModel::class)
fun localePickerViewModelFactory(factory: LocalePickerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(GossipingEventsPaperTrailViewModel::class)
fun gossipingEventsPaperTrailViewModelFactory(factory: GossipingEventsPaperTrailViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(AccountDataViewModel::class)
fun accountDataViewModelFactory(factory: AccountDataViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DevicesViewModel::class)
fun devicesViewModelFactory(factory: DevicesViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(KeyRequestListViewModel::class)
fun keyRequestListViewModelFactory(factory: KeyRequestListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CrossSigningSettingsViewModel::class)
fun crossSigningSettingsViewModelFactory(factory: CrossSigningSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DeactivateAccountViewModel::class)
fun deactivateAccountViewModelFactory(factory: DeactivateAccountViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomUploadsViewModel::class)
fun roomUploadsViewModelFactory(factory: RoomUploadsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomJoinRuleChooseRestrictedViewModel::class)
fun roomJoinRuleChooseRestrictedViewModelFactory(factory: RoomJoinRuleChooseRestrictedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomSettingsViewModel::class)
fun roomSettingsViewModelFactory(factory: RoomSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomPermissionsViewModel::class)
fun roomPermissionsViewModelFactory(factory: RoomPermissionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomMemberListViewModel::class)
fun roomMemberListViewModelFactory(factory: RoomMemberListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomBannedMemberListViewModel::class)
fun roomBannedMemberListViewModelFactory(factory: RoomBannedMemberListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomAliasViewModel::class)
fun roomAliasViewModelFactory(factory: RoomAliasViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomAliasBottomSheetViewModel::class)
fun roomAliasBottomSheetViewModelFactory(factory: RoomAliasBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomProfileViewModel::class)
fun roomProfileViewModelFactory(factory: RoomProfileViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomMemberProfileViewModel::class)
fun roomMemberProfileViewModelFactory(factory: RoomMemberProfileViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RoomPreviewViewModel::class)
fun roomPreviewViewModelFactory(factory: RoomPreviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CreateRoomViewModel::class)
fun createRoomViewModelFactory(factory: CreateRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(RequireActiveMembershipViewModel::class)
fun requireActiveMembershipViewModelFactory(factory: RequireActiveMembershipViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(EmojiSearchResultViewModel::class)
fun emojiSearchResultViewModelFactory(factory: EmojiSearchResultViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(BugReportViewModel::class)
fun bugReportViewModelFactory(factory: BugReportViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(MatrixToBottomSheetViewModel::class)
fun matrixToBottomSheetViewModelFactory(factory: MatrixToBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(AccountCreatedViewModel::class)
fun accountCreatedViewModelFactory(factory: AccountCreatedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(LoginViewModel2::class)
fun loginViewModel2Factory(factory: LoginViewModel2.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(LoginViewModel::class)
fun loginViewModelFactory(factory: LoginViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(HomeServerCapabilitiesViewModel::class)
fun homeServerCapabilitiesViewModelFactory(factory: HomeServerCapabilitiesViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(InviteUsersToRoomViewModel::class)
fun inviteUsersToRoomViewModelFactory(factory: InviteUsersToRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(ViewEditHistoryViewModel::class)
fun viewEditHistoryViewModelFactory(factory: ViewEditHistoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(MessageActionsViewModel::class)
fun messageActionsViewModelFactory(factory: MessageActionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VerificationChooseMethodViewModel::class)
fun verificationChooseMethodViewModelFactory(factory: VerificationChooseMethodViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VerificationEmojiCodeViewModel::class)
fun verificationEmojiCodeViewModelFactory(factory: VerificationEmojiCodeViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SearchViewModel::class)
fun searchViewModelFactory(factory: SearchViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(UnreadMessagesSharedViewModel::class)
fun unreadMessagesSharedViewModelFactory(factory: UnreadMessagesSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(UnknownDeviceDetectorSharedViewModel::class)
fun unknownDeviceDetectorSharedViewModelFactory(factory: UnknownDeviceDetectorSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DiscoverySettingsViewModel::class)
fun discoverySettingsViewModelFactory(factory: DiscoverySettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(TextComposerViewModel::class)
fun textComposerViewModelFactory(factory: TextComposerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SetIdentityServerViewModel::class)
fun setIdentityServerViewModelFactory(factory: SetIdentityServerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(BreadcrumbsViewModel::class)
fun breadcrumbsViewModelFactory(factory: BreadcrumbsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(HomeDetailViewModel::class)
fun homeDetailViewModelFactory(factory: HomeDetailViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DeviceVerificationInfoBottomSheetViewModel::class)
fun deviceVerificationInfoBottomSheetViewModelFactory(factory: DeviceVerificationInfoBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(DeviceListBottomSheetViewModel::class)
fun deviceListBottomSheetViewModelFactory(factory: DeviceListBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(HomeActivityViewModel::class)
fun homeActivityViewModelFactory(factory: HomeActivityViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(BootstrapSharedViewModel::class)
fun bootstrapSharedViewModelFactory(factory: BootstrapSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VerificationBottomSheetViewModel::class)
fun verificationBottomSheetViewModelFactory(factory: VerificationBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(CreatePollViewModel::class)
fun createPollViewModelFactory(factory: CreatePollViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
}

View file

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

View file

@ -1,227 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.di
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentFactory
import androidx.lifecycle.ViewModelProvider
import dagger.BindsInstance
import dagger.Component
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.preference.UserAvatarPreference
import im.vector.app.features.MainActivity
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.call.CallControlsBottomSheet
import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.conference.VectorJitsiActivity
import im.vector.app.features.call.transfer.CallTransferActivity
import im.vector.app.features.createdirect.CreateDirectRoomActivity
import im.vector.app.features.createpoll.CreatePollActivity
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity
import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity
import im.vector.app.features.crypto.quads.SharedSecureStorageActivity
import im.vector.app.features.crypto.recover.BootstrapBottomSheet
import im.vector.app.features.crypto.verification.VerificationBottomSheet
import im.vector.app.features.debug.DebugMenuActivity
import im.vector.app.features.devtools.RoomDevToolActivity
import im.vector.app.features.home.HomeActivity
import im.vector.app.features.home.HomeModule
import im.vector.app.features.home.room.detail.JoinReplacementRoomBottomSheet
import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
import im.vector.app.features.home.room.detail.search.SearchActivity
import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBottomSheet
import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
import im.vector.app.features.home.room.detail.widget.RoomWidgetsBottomSheet
import im.vector.app.features.home.room.filtered.FilteredRoomsActivity
import im.vector.app.features.home.room.list.RoomListModule
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.invite.InviteUsersToRoomActivity
import im.vector.app.features.invite.VectorInviteView
import im.vector.app.features.link.LinkHandlerActivity
import im.vector.app.features.login.LoginActivity
import im.vector.app.features.login2.LoginActivity2
import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.media.BigImageViewerActivity
import im.vector.app.features.media.VectorAttachmentViewerActivity
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.qrcode.QrCodeScannerActivity
import im.vector.app.features.rageshake.BugReportActivity
import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.rageshake.RageShake
import im.vector.app.features.reactions.EmojiReactionPickerActivity
import im.vector.app.features.reactions.widget.ReactionButton
import im.vector.app.features.roomdirectory.RoomDirectoryActivity
import im.vector.app.features.roomdirectory.createroom.CreateRoomActivity
import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet
import im.vector.app.features.roomprofile.RoomProfileActivity
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet
import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilityBottomSheet
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleActivity
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleBottomSheet
import im.vector.app.features.settings.VectorSettingsActivity
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet
import im.vector.app.features.share.IncomingShareActivity
import im.vector.app.features.signout.soft.SoftLogoutActivity
import im.vector.app.features.spaces.InviteRoomSpaceChooserBottomSheet
import im.vector.app.features.spaces.LeaveSpaceBottomSheet
import im.vector.app.features.spaces.SpaceCreationActivity
import im.vector.app.features.spaces.SpaceExploreActivity
import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet
import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedActivity
import im.vector.app.features.spaces.manage.SpaceManageActivity
import im.vector.app.features.spaces.share.ShareSpaceBottomSheet
import im.vector.app.features.terms.ReviewTermsActivity
import im.vector.app.features.ui.UiStateRepository
import im.vector.app.features.usercode.UserCodeActivity
import im.vector.app.features.widgets.WidgetActivity
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet
import im.vector.app.features.workers.signout.SignOutBottomSheetDialogFragment
import kotlinx.coroutines.CoroutineScope
@Component(
dependencies = [
VectorComponent::class
],
modules = [
ViewModelModule::class,
FragmentModule::class,
HomeModule::class,
RoomListModule::class,
ScreenModule::class
]
)
@ScreenScope
interface ScreenComponent {
/* ==========================================================================================
* Shortcut to VectorComponent elements
* ========================================================================================== */
fun activeSessionHolder(): ActiveSessionHolder
fun fragmentFactory(): FragmentFactory
fun viewModelFactory(): ViewModelProvider.Factory
fun bugReporter(): BugReporter
fun rageShake(): RageShake
fun navigator(): Navigator
fun pinLocker(): PinLocker
fun errorFormatter(): ErrorFormatter
fun uiStateRepository(): UiStateRepository
fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
fun autoAcceptInvites(): AutoAcceptInvites
fun appCoroutineScope(): CoroutineScope
/* ==========================================================================================
* Activities
* ========================================================================================== */
fun inject(activity: HomeActivity)
fun inject(activity: RoomDetailActivity)
fun inject(activity: RoomProfileActivity)
fun inject(activity: RoomMemberProfileActivity)
fun inject(activity: VectorSettingsActivity)
fun inject(activity: KeysBackupManageActivity)
fun inject(activity: EmojiReactionPickerActivity)
fun inject(activity: LoginActivity)
fun inject(activity: LoginActivity2)
fun inject(activity: LinkHandlerActivity)
fun inject(activity: MainActivity)
fun inject(activity: RoomDirectoryActivity)
fun inject(activity: KeysBackupSetupActivity)
fun inject(activity: BugReportActivity)
fun inject(activity: FilteredRoomsActivity)
fun inject(activity: CreateRoomActivity)
fun inject(activity: CreateDirectRoomActivity)
fun inject(activity: IncomingShareActivity)
fun inject(activity: SoftLogoutActivity)
fun inject(activity: QrCodeScannerActivity)
fun inject(activity: DebugMenuActivity)
fun inject(activity: SharedSecureStorageActivity)
fun inject(activity: BigImageViewerActivity)
fun inject(activity: InviteUsersToRoomActivity)
fun inject(activity: ReviewTermsActivity)
fun inject(activity: WidgetActivity)
fun inject(activity: VectorCallActivity)
fun inject(activity: VectorAttachmentViewerActivity)
fun inject(activity: VectorJitsiActivity)
fun inject(activity: SearchActivity)
fun inject(activity: UserCodeActivity)
fun inject(activity: CallTransferActivity)
fun inject(activity: ReAuthActivity)
fun inject(activity: RoomDevToolActivity)
fun inject(activity: SpaceCreationActivity)
fun inject(activity: SpaceExploreActivity)
fun inject(activity: SpaceManageActivity)
fun inject(activity: RoomJoinRuleActivity)
fun inject(activity: SpaceLeaveAdvancedActivity)
fun inject(activity: CreatePollActivity)
/* ==========================================================================================
* BottomSheets
* ========================================================================================== */
fun inject(bottomSheet: MessageActionsBottomSheet)
fun inject(bottomSheet: ViewReactionsBottomSheet)
fun inject(bottomSheet: ViewEditHistoryBottomSheet)
fun inject(bottomSheet: DisplayReadReceiptsBottomSheet)
fun inject(bottomSheet: RoomListQuickActionsBottomSheet)
fun inject(bottomSheet: RoomAliasBottomSheet)
fun inject(bottomSheet: RoomHistoryVisibilityBottomSheet)
fun inject(bottomSheet: RoomJoinRuleBottomSheet)
fun inject(bottomSheet: VerificationBottomSheet)
fun inject(bottomSheet: DeviceVerificationInfoBottomSheet)
fun inject(bottomSheet: DeviceListBottomSheet)
fun inject(bottomSheet: BootstrapBottomSheet)
fun inject(bottomSheet: RoomWidgetPermissionBottomSheet)
fun inject(bottomSheet: RoomWidgetsBottomSheet)
fun inject(bottomSheet: CallControlsBottomSheet)
fun inject(bottomSheet: SignOutBottomSheetDialogFragment)
fun inject(bottomSheet: MatrixToBottomSheet)
fun inject(bottomSheet: ShareSpaceBottomSheet)
fun inject(bottomSheet: SpaceSettingsMenuBottomSheet)
fun inject(bottomSheet: InviteRoomSpaceChooserBottomSheet)
fun inject(bottomSheet: SpaceInviteBottomSheet)
fun inject(bottomSheet: JoinReplacementRoomBottomSheet)
fun inject(bottomSheet: MigrateRoomBottomSheet)
fun inject(bottomSheet: LeaveSpaceBottomSheet)
/* ==========================================================================================
* Others
* ========================================================================================== */
fun inject(view: VectorInviteView)
fun inject(preference: UserAvatarPreference)
fun inject(button: ReactionButton)
/* ==========================================================================================
* Factory
* ========================================================================================== */
@Component.Factory
interface Factory {
fun create(vectorComponent: VectorComponent,
@BindsInstance context: AppCompatActivity
): ScreenComponent
}
}

View file

@ -1,11 +1,11 @@
/*
* Copyright 2019 New Vector Ltd
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@ -20,9 +20,13 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.scopes.ActivityScoped
import im.vector.app.core.glide.GlideApp
@Module
@InstallIn(ActivityComponent::class)
object ScreenModule {
@Provides
@ -31,6 +35,6 @@ object ScreenModule {
@Provides
@JvmStatic
@ScreenScope
@ActivityScoped
fun providesSharedViewPool() = RecyclerView.RecycledViewPool()
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.di
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.session.SessionListener
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.ui.UiStateRepository
import kotlinx.coroutines.CoroutineScope
@InstallIn(SingletonComponent::class)
@EntryPoint
interface SingletonEntryPoint {
fun sessionListener(): SessionListener
fun avatarRenderer(): AvatarRenderer
fun activeSessionHolder(): ActiveSessionHolder
fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
fun navigator(): Navigator
fun errorFormatter(): ErrorFormatter
fun bugReporter(): BugReporter
fun vectorPreferences(): VectorPreferences
fun uiStateRepository(): UiStateRepository
fun pinLocker(): PinLocker
fun webRtcCallManager(): WebRtcCallManager
fun appCoroutineScope(): CoroutineScope
}

View file

@ -16,6 +16,7 @@
package im.vector.app.core.di
import android.app.Application
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.SharedPreferences
@ -23,6 +24,8 @@ import android.content.res.Resources
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.error.DefaultErrorFormatter
import im.vector.app.core.error.ErrorFormatter
@ -45,74 +48,9 @@ import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session
import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@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(context: Context): Matrix {
return Matrix.getInstance(context)
}
@Provides
@JvmStatic
fun providesCurrentSession(activeSessionHolder: ActiveSessionHolder): Session {
// TODO: handle session injection better
return activeSessionHolder.getActiveSession()
}
@Provides
@JvmStatic
fun providesLegacySessionImporter(matrix: Matrix): LegacySessionImporter {
return matrix.legacySessionImporter()
}
@Provides
@JvmStatic
fun providesAuthenticationService(matrix: Matrix): AuthenticationService {
return matrix.authenticationService()
}
@Provides
@JvmStatic
fun providesRawService(matrix: Matrix): RawService {
return matrix.rawService()
}
@Provides
@JvmStatic
fun providesHomeServerHistoryService(matrix: Matrix): HomeServerHistoryService {
return matrix.homeServerHistoryService()
}
@Provides
@JvmStatic
@Singleton
fun providesApplicationCoroutineScope(): CoroutineScope {
return CoroutineScope(SupervisorJob() + Dispatchers.Main)
}
@Provides
@JvmStatic
fun providesCoroutineDispatchers(): CoroutineDispatchers {
return CoroutineDispatchers(io = Dispatchers.IO)
}
}
abstract class VectorBindModule {
@Binds
abstract fun bindNavigator(navigator: DefaultNavigator): Navigator
@ -129,3 +67,76 @@ abstract class VectorModule {
@Binds
abstract fun bindAutoAcceptInvites(autoAcceptInvites: CompileTimeAutoAcceptInvites): AutoAcceptInvites
}
@InstallIn(SingletonComponent::class)
@Module
object VectorStaticModule {
@Provides
@JvmStatic
fun providesContext(application: Application): Context {
return application.applicationContext
}
@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(context: Context): Matrix {
return Matrix.getInstance(context)
}
@Provides
@JvmStatic
fun providesCurrentSession(activeSessionHolder: ActiveSessionHolder): Session {
// TODO: handle session injection better
return activeSessionHolder.getActiveSession()
}
@Provides
@JvmStatic
fun providesLegacySessionImporter(matrix: Matrix): LegacySessionImporter {
return matrix.legacySessionImporter()
}
@Provides
@JvmStatic
fun providesAuthenticationService(matrix: Matrix): AuthenticationService {
return matrix.authenticationService()
}
@Provides
@JvmStatic
fun providesRawService(matrix: Matrix): RawService {
return matrix.rawService()
}
@Provides
@JvmStatic
fun providesHomeServerHistoryService(matrix: Matrix): HomeServerHistoryService {
return matrix.homeServerHistoryService()
}
@Provides
@JvmStatic
@Singleton
fun providesApplicationCoroutineScope(): CoroutineScope {
return CoroutineScope(SupervisorJob() + Dispatchers.Main)
}
@Provides
@JvmStatic
fun providesCoroutineDispatchers(): CoroutineDispatchers {
return CoroutineDispatchers(io = Dispatchers.IO)
}
}

View file

@ -1,183 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.di
import android.content.Context
import android.content.res.Resources
import dagger.BindsInstance
import dagger.Component
import im.vector.app.ActiveSessionDataSource
import im.vector.app.AppStateHandler
import im.vector.app.EmojiCompatFontProvider
import im.vector.app.EmojiCompatWrapper
import im.vector.app.VectorApplication
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.utils.AssetReader
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.call.conference.JitsiActiveConferenceHolder
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.configuration.VectorConfiguration
import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.CurrentSpaceSuggestedRoomListDataSource
import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.html.VectorHtmlCompressor
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.notifications.NotifiableEventResolver
import im.vector.app.features.notifications.NotificationBroadcastReceiver
import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.notifications.PushRuleTriggerListener
import im.vector.app.features.pin.PinCodeStore
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.rageshake.VectorFileLogger
import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.app.features.reactions.data.EmojiDataSource
import im.vector.app.features.session.SessionListener
import im.vector.app.features.settings.VectorDataStore
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.ui.UiStateRepository
import kotlinx.coroutines.CoroutineScope
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session
import javax.inject.Singleton
@Component(modules = [VectorModule::class])
@Singleton
interface VectorComponent {
fun inject(notificationBroadcastReceiver: NotificationBroadcastReceiver)
fun inject(vectorApplication: VectorApplication)
fun matrix(): Matrix
fun matrixItemColorProvider(): MatrixItemColorProvider
fun sessionListener(): SessionListener
fun currentSession(): Session
fun notificationUtils(): NotificationUtils
fun notificationDrawerManager(): NotificationDrawerManager
fun appContext(): Context
fun resources(): Resources
fun assetReader(): AssetReader
fun dimensionConverter(): DimensionConverter
fun vectorConfiguration(): VectorConfiguration
fun avatarRenderer(): AvatarRenderer
fun activeSessionHolder(): ActiveSessionHolder
fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
fun emojiCompatFontProvider(): EmojiCompatFontProvider
fun emojiCompatWrapper(): EmojiCompatWrapper
fun eventHtmlRenderer(): EventHtmlRenderer
fun vectorHtmlCompressor(): VectorHtmlCompressor
fun navigator(): Navigator
fun errorFormatter(): ErrorFormatter
fun appStateHandler(): AppStateHandler
fun currentSpaceSuggestedRoomListDataSource(): CurrentSpaceSuggestedRoomListDataSource
fun roomDetailPendingActionStore(): RoomDetailPendingActionStore
fun activeSessionObservableStore(): ActiveSessionDataSource
fun incomingVerificationRequestHandler(): IncomingVerificationRequestHandler
fun incomingKeyRequestHandler(): KeyRequestHandler
fun authenticationService(): AuthenticationService
fun rawService(): RawService
fun homeServerHistoryService(): HomeServerHistoryService
fun bugReporter(): BugReporter
fun vectorUncaughtExceptionHandler(): VectorUncaughtExceptionHandler
fun pushRuleTriggerListener(): PushRuleTriggerListener
fun pusherManager(): PushersManager
fun notifiableEventResolver(): NotifiableEventResolver
fun vectorPreferences(): VectorPreferences
fun vectorDataStore(): VectorDataStore
fun wifiDetector(): WifiDetector
fun vectorFileLogger(): VectorFileLogger
fun uiStateRepository(): UiStateRepository
fun pinCodeStore(): PinCodeStore
fun emojiDataSource(): EmojiDataSource
fun alertManager(): PopupAlertManager
fun reAuthHelper(): ReAuthHelper
fun pinLocker(): PinLocker
fun autoAcceptInvites(): AutoAcceptInvites
fun webRtcCallManager(): WebRtcCallManager
fun appCoroutineScope(): CoroutineScope
fun coroutineDispatchers(): CoroutineDispatchers
fun jitsiActiveConferenceHolder(): JitsiActiveConferenceHolder
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): VectorComponent
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,11 +1,11 @@
/*
* Copyright 2019 New Vector Ltd
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,11 +14,12 @@
* limitations under the License.
*/
package im.vector.app.core.di
package im.vector.app.core.extensions
import javax.inject.Scope
import android.net.Uri
@Scope
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class ScreenScope
const val IGNORED_SCHEMA = "ignored"
fun Uri.isIgnored() = scheme == IGNORED_SCHEMA
fun createIgnoredUri(path: String): Uri = Uri.parse("$IGNORED_SCHEMA://$path")

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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