Merge pull request #5887 from vector-im/feature/bma/Matrix

Improve Matrix class
This commit is contained in:
Benoit Marty 2022-05-16 13:08:15 +02:00 committed by GitHub
commit 955f366690
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 93 additions and 103 deletions

View file

@ -14,6 +14,16 @@ jobs:
- name: Run code quality check suite - name: Run code quality check suite
run: ./tools/check/check_code_quality.sh run: ./tools/check/check_code_quality.sh
# Knit for all the modules (https://github.com/Kotlin/kotlinx-knit)
knit:
name: Knit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run knit
run: |
./gradlew knit
# ktlint for all the modules # ktlint for all the modules
ktlint: ktlint:
name: Kotlin Linter name: Kotlin Linter

View file

@ -30,6 +30,7 @@ buildscript {
classpath "com.likethesalad.android:stem-plugin:2.0.0" classpath "com.likethesalad.android:stem-plugin:2.0.0"
classpath 'org.owasp:dependency-check-gradle:7.1.0.1' classpath 'org.owasp:dependency-check-gradle:7.1.0.1'
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.21" classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.21"
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }

1
changelog.d/5887.sdk Normal file
View file

@ -0,0 +1 @@
Small change in the Matrix class: deprecated methods have been removed and the constructor is now public. Also the fun `workerFactory()` has been renamed to `getWorkerFactory()`

View file

@ -37,9 +37,9 @@ Wording: "We've sent you an email to verify your address. Please follow the inst
} }
``` ```
## User receive an e-mail ## User receives an e-mail
> [homeserver.org] Validate your email > `homeserver.org` Validate your email
> >
> A request to add an email address to your Matrix account has been received. If this was you, please click the link below to confirm adding this email: > A request to add an email address to your Matrix account has been received. If this was you, please click the link below to confirm adding this email:
https://homeserver.org/_matrix/client/unstable/add_threepid/email/submit_token?token=WUnEhQAmJrXupdEbXgdWvnVIKaGYZFsU&client_secret=TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh&sid=bxyDHuJKsdkjMlTJ https://homeserver.org/_matrix/client/unstable/add_threepid/email/submit_token?token=WUnEhQAmJrXupdEbXgdWvnVIKaGYZFsU&client_secret=TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh&sid=bxyDHuJKsdkjMlTJ

View file

@ -116,7 +116,7 @@ Review such PR is the same recipe than for PR from Dependabot
##### Sync analytics plan ##### Sync analytics plan
This tools imports any update in the analytics plan. See instruction in the PR itself to handle it. This tools imports any update in the analytics plan. See instruction in the PR itself to handle it.
More info can be found in the file [analytics.md] More info can be found in the file [analytics.md](./analytics.md)
## Reviewing PR ## Reviewing PR

View file

@ -21,7 +21,7 @@ dokkaHtml {
dokkaSourceSets { dokkaSourceSets {
configureEach { configureEach {
// Emit warnings about not documented members. // Emit warnings about not documented members.
reportUndocumented.set(true) // reportUndocumented.set(true)
// Suppress legacy Riot's packages. // Suppress legacy Riot's packages.
perPackageOption { perPackageOption {
matchingRegex.set("org.matrix.android.sdk.internal.legacy.riot") matchingRegex.set("org.matrix.android.sdk.internal.legacy.riot")

View file

@ -11,11 +11,11 @@ This pages list the complete API that this SDK is exposing to a client applicati
A few entry points: A few entry points:
- **Matrix**: The app will have to create and manage a Matrix object. - **[Matrix](org.matrix.android.sdk.api.Matrix)**: The app will have to create and manage a **[Matrix](org.matrix.android.sdk.api.Matrix)** object.
- From this **Matrix** object, you will be able to get various services, including the **AuthenticationService**. - From this **[Matrix](org.matrix.android.sdk.api.Matrix)** object, you will be able to get various services, including the **[AuthenticationService](org.matrix.android.sdk.api.auth.AuthenticationService)**.
- With this **AuthenticationService** you will be able to get an existing **Session**, or create one using a **LoginWizard** or a **RegistrationWizard**, which will finally give you a **Session**. - With this **[AuthenticationService](org.matrix.android.sdk.api.auth.AuthenticationService)** you will be able to get an existing **[Session](org.matrix.android.sdk.api.session.Session)**, or create one using a **[LoginWizard](org.matrix.android.sdk.api.auth.login.LoginWizard)** or a **[RegistrationWizard](org.matrix.android.sdk.api.auth.registration.RegistrationWizard)**, which will finally give you a **[Session](org.matrix.android.sdk.api.session.Session)**.
- From the **Session**, you will be able to retrieve many Services, including the **RoomService**. - From the **[Session](org.matrix.android.sdk.api.session.Session)**, you will be able to retrieve many Services, including the **[RoomService](org.matrix.android.sdk.api.session.room.RoomService)**.
- From the **RoomService**, you will be able to list the rooms, create a **Room**, and get a specific **Room**. - From the **[RoomService](org.matrix.android.sdk.api.session.room.RoomService)**, you will be able to list the rooms, create a **[Room](org.matrix.android.sdk.api.session.room.Room)**, and get a specific **[Room](org.matrix.android.sdk.api.session.room.Room)**.
- And from a **Room**, you will be able to do many things, including get a **Timeline**, send messages, etc. - And from a **[Room](org.matrix.android.sdk.api.session.room.Room)**, you will be able to do many things, including get a **[Timeline](org.matrix.android.sdk.api.session.room.timeline.Timeline)**, send messages, etc.
Please read the whole documentation to learn more! Please read the whole documentation to learn more!

View file

@ -63,8 +63,9 @@ class CommonTestHelper(context: Context) {
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
init { init {
var _matrix: TestMatrix? = null
UiThreadStatement.runOnUiThread { UiThreadStatement.runOnUiThread {
TestMatrix.initialize( _matrix = TestMatrix(
context, context,
MatrixConfiguration( MatrixConfiguration(
applicationFlavor = "TestFlavor", applicationFlavor = "TestFlavor",
@ -72,7 +73,7 @@ class CommonTestHelper(context: Context) {
) )
) )
} }
matrix = TestMatrix.getInstance() matrix = _matrix!!
} }
fun createAccount(userNamePrefix: String, testParams: SessionTestParams): Session { fun createAccount(userNamePrefix: String, testParams: SessionTestParams): Session {

View file

@ -38,13 +38,12 @@ import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory
import org.matrix.olm.OlmManager import org.matrix.olm.OlmManager
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject import javax.inject.Inject
/** /**
* This mimics the Matrix class but using TestMatrixComponent internally instead of regular MatrixComponent. * This mimics the Matrix class but using TestMatrixComponent internally instead of regular MatrixComponent.
*/ */
internal class TestMatrix constructor(context: Context, matrixConfiguration: MatrixConfiguration) { internal class TestMatrix(context: Context, matrixConfiguration: MatrixConfiguration) {
@Inject internal lateinit var legacySessionImporter: LegacySessionImporter @Inject internal lateinit var legacySessionImporter: LegacySessionImporter
@Inject internal lateinit var authenticationService: AuthenticationService @Inject internal lateinit var authenticationService: AuthenticationService
@ -60,13 +59,14 @@ internal class TestMatrix constructor(context: Context, matrixConfiguration: Mat
private val uiHandler = Handler(Looper.getMainLooper()) private val uiHandler = Handler(Looper.getMainLooper())
init { init {
Monarchy.init(context) val appContext = context.applicationContext
DaggerTestMatrixComponent.factory().create(context, matrixConfiguration).inject(this) Monarchy.init(appContext)
DaggerTestMatrixComponent.factory().create(appContext, matrixConfiguration).inject(this)
val configuration = Configuration.Builder() val configuration = Configuration.Builder()
.setExecutor(Executors.newCachedThreadPool()) .setExecutor(Executors.newCachedThreadPool())
.setWorkerFactory(matrixWorkerFactory) .setWorkerFactory(matrixWorkerFactory)
.build() .build()
WorkManager.initialize(context, configuration) WorkManager.initialize(appContext, configuration)
uiHandler.post { uiHandler.post {
ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver) ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
} }
@ -95,23 +95,6 @@ internal class TestMatrix constructor(context: Context, matrixConfiguration: Mat
} }
companion object { companion object {
private lateinit var instance: TestMatrix
private val isInit = AtomicBoolean(false)
fun initialize(context: Context, matrixConfiguration: MatrixConfiguration) {
if (isInit.compareAndSet(false, true)) {
instance = TestMatrix(context.applicationContext, matrixConfiguration)
}
}
fun getInstance(): TestMatrix {
if (isInit.compareAndSet(false, false)) {
throw IllegalStateException("Matrix is not initialized properly. You should call TestMatrix.initialize first")
}
return instance
}
fun getSdkVersion(): String { fun getSdkVersion(): String {
return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")" return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")"
} }

View file

@ -38,15 +38,18 @@ import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory
import org.matrix.olm.OlmManager import org.matrix.olm.OlmManager
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject import javax.inject.Inject
/** /**
* This is the main entry point to the matrix sdk. * This is the main entry point to the matrix sdk.
* <br/> * <br/>
* See [Companion.createInstance] to create an instance. The app should create and manage the instance itself. *
* The constructor creates a new instance of Matrix, it's recommended to manage this instance as a singleton.
*
* @param context the application context
* @param matrixConfiguration global configuration that will be used for every [org.matrix.android.sdk.api.session.Session]
*/ */
class Matrix private constructor(context: Context, matrixConfiguration: MatrixConfiguration) { class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
@Inject internal lateinit var legacySessionImporter: LegacySessionImporter @Inject internal lateinit var legacySessionImporter: LegacySessionImporter
@Inject internal lateinit var authenticationService: AuthenticationService @Inject internal lateinit var authenticationService: AuthenticationService
@ -61,89 +64,72 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
@Inject internal lateinit var lightweightSettingsStorage: LightweightSettingsStorage @Inject internal lateinit var lightweightSettingsStorage: LightweightSettingsStorage
init { init {
Monarchy.init(context) val appContext = context.applicationContext
DaggerMatrixComponent.factory().create(context, matrixConfiguration).inject(this) Monarchy.init(appContext)
if (context.applicationContext !is Configuration.Provider) { DaggerMatrixComponent.factory().create(appContext, matrixConfiguration).inject(this)
if (appContext !is Configuration.Provider) {
val configuration = Configuration.Builder() val configuration = Configuration.Builder()
.setExecutor(Executors.newCachedThreadPool()) .setExecutor(Executors.newCachedThreadPool())
.setWorkerFactory(matrixWorkerFactory) .setWorkerFactory(matrixWorkerFactory)
.build() .build()
WorkManager.initialize(context, configuration) WorkManager.initialize(appContext, configuration)
} }
ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver) ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
} }
/**
* Return the User Agent used for any request that the SDK is making to the homeserver.
* There is no way to change the user agent at the moment.
*/
fun getUserAgent() = userAgentHolder.userAgent fun getUserAgent() = userAgentHolder.userAgent
/**
* Return the AuthenticationService.
*/
fun authenticationService() = authenticationService fun authenticationService() = authenticationService
/**
* Return the RawService.
*/
fun rawService() = rawService fun rawService() = rawService
/**
* Return the LightweightSettingsStorage.
*/
fun lightweightSettingsStorage() = lightweightSettingsStorage fun lightweightSettingsStorage() = lightweightSettingsStorage
/**
* Return the HomeServerHistoryService.
*/
fun homeServerHistoryService() = homeServerHistoryService fun homeServerHistoryService() = homeServerHistoryService
/**
* Return the legacy session importer, useful if you want to migrate an app, which was using the legacy Matrix Android Sdk.
*/
fun legacySessionImporter() = legacySessionImporter fun legacySessionImporter() = legacySessionImporter
fun workerFactory(): WorkerFactory = matrixWorkerFactory /**
* Get the worker factory. The returned value has to be provided to `WorkConfiguration.Builder()`.
*/
fun getWorkerFactory(): WorkerFactory = matrixWorkerFactory
/**
* Register an API interceptor, to be able to be notified when the specified API got a response.
*/
fun registerApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) { fun registerApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) {
apiInterceptor.addListener(path, listener) apiInterceptor.addListener(path, listener)
} }
/**
* Un-register an API interceptor.
*/
fun unregisterApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) { fun unregisterApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) {
apiInterceptor.removeListener(path, listener) apiInterceptor.removeListener(path, listener)
} }
companion object { companion object {
private lateinit var instance: Matrix
private val isInit = AtomicBoolean(false)
/** /**
* Creates a new instance of Matrix, it's recommended to manage this instance as a singleton. * @return a String with details about the Matrix SDK version.
* To make use of the built in singleton use Matrix.initialize() and/or Matrix.getInstance(context) instead
**/
fun createInstance(context: Context, matrixConfiguration: MatrixConfiguration): Matrix {
return Matrix(context.applicationContext, matrixConfiguration)
}
/**
* Initializes a singleton instance of Matrix for the given MatrixConfiguration
* This instance will be returned by Matrix.getInstance(context)
*/
@Deprecated("Use Matrix.createInstance and manage the instance manually")
fun initialize(context: Context, matrixConfiguration: MatrixConfiguration) {
if (isInit.compareAndSet(false, true)) {
instance = Matrix(context.applicationContext, matrixConfiguration)
}
}
/**
* Either provides an already initialized singleton Matrix instance or queries the application context for a MatrixConfiguration.Provider
* to lazily create and store the instance.
*/
@Suppress("deprecation") // suppressing warning as this method is unused but is still provided for SDK clients
@Deprecated("Use Matrix.createInstance and manage the instance manually")
fun getInstance(context: Context): Matrix {
if (isInit.compareAndSet(false, true)) {
val appContext = context.applicationContext
if (appContext is MatrixConfiguration.Provider) {
val matrixConfiguration = (appContext as MatrixConfiguration.Provider).providesMatrixConfiguration()
instance = Matrix(appContext, matrixConfiguration)
} else {
throw IllegalStateException(
"Matrix is not initialized properly." +
" If you want to manage your own Matrix instance use Matrix.createInstance" +
" otherwise you should call Matrix.initialize or let your application implement MatrixConfiguration.Provider."
)
}
}
return instance
}
/**
* @return a String with details about the Matrix SDK version
*/ */
fun getSdkVersion(): String { fun getSdkVersion(): String {
return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")" return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")"

View file

@ -65,13 +65,4 @@ data class MatrixConfiguration(
* Thread messages default enable/disabled value * Thread messages default enable/disabled value
*/ */
val threadMessagesEnabledDefault: Boolean = false, val threadMessagesEnabledDefault: Boolean = false,
) { )
/**
* Can be implemented by your Application class.
*/
@Deprecated("Use Matrix.createInstance and manage the instance manually instead of Matrix.getInstance")
interface Provider {
fun providesMatrixConfiguration(): MatrixConfiguration
}
}

View file

@ -7,11 +7,24 @@ apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'com.likethesalad.stem' apply plugin: 'com.likethesalad.stem'
apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlinx-knit'
kapt { kapt {
correctErrorTypes = true correctErrorTypes = true
} }
knit {
files = fileTree(project.rootDir) {
include '**/*.md'
include '**/*.kt'
include '**/*.kts'
exclude '**/build/**'
exclude '**/.gradle/**'
exclude '**/towncrier/template.md'
exclude '**/CHANGES.md'
}
}
// Note: 2 digits max for each value // Note: 2 digits max for each value
ext.versionMajor = 1 ext.versionMajor = 1
ext.versionMinor = 4 ext.versionMinor = 4

View file

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<lint> <lint>
<!-- Ensure this file does not contain unknown Ids -->
<issue id="UnknownIssueId" severity="error" />
<!-- Modify some severity --> <!-- Modify some severity -->
<!-- Resource --> <!-- Resource -->

View file

@ -26,5 +26,5 @@ fun getMatrixInstance(): Matrix {
val configuration = MatrixConfiguration( val configuration = MatrixConfiguration(
roomDisplayNameFallbackProvider = VectorRoomDisplayNameFallbackProvider(context) roomDisplayNameFallbackProvider = VectorRoomDisplayNameFallbackProvider(context)
) )
return Matrix.createInstance(context, configuration) return Matrix(context, configuration)
} }

View file

@ -224,7 +224,7 @@ class VectorApplication :
override fun getWorkManagerConfiguration(): WorkConfiguration { override fun getWorkManagerConfiguration(): WorkConfiguration {
return WorkConfiguration.Builder() return WorkConfiguration.Builder()
.setWorkerFactory(matrix.workerFactory()) .setWorkerFactory(matrix.getWorkerFactory())
.setExecutor(Executors.newCachedThreadPool()) .setExecutor(Executors.newCachedThreadPool())
.build() .build()
} }

View file

@ -129,7 +129,7 @@ object VectorStaticModule {
@Provides @Provides
@Singleton @Singleton
fun providesMatrix(context: Context, configuration: MatrixConfiguration): Matrix { fun providesMatrix(context: Context, configuration: MatrixConfiguration): Matrix {
return Matrix.createInstance(context, configuration) return Matrix(context, configuration)
} }
@Provides @Provides