Sync notifications using WorkManager (#5545)

* Initial implementation of notification sync using `WorkManager`

* Use custom `MetroWorkerFactory` to allow assisted injection in WorkManager Workers

* Add tests for `FetchNotificationWorker`. Create `FakeNotificationResolverQueue` to help testing.

* Add more tests, fix Konsist checks

* Add tests for `SyncNotificationWorkManagerRequest`

* Simplify `FakeNotificationResolverQueue`
This commit is contained in:
Jorge Martin Espinosa 2025-10-17 11:51:27 +02:00 committed by GitHub
parent f3d75ee85c
commit ebe94f873e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 968 additions and 98 deletions

View file

@ -34,10 +34,17 @@
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false">
android:exported="false"
tools:node="merge">
<meta-data
android:name='androidx.lifecycle.ProcessLifecycleInitializer'
android:value='androidx.startup' />
<!-- Remove to use Application workManagerConfiguration -->
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
<!--
@ -175,7 +182,6 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_providers" />
</provider>
</application>
</manifest>

View file

@ -9,17 +9,23 @@ package io.element.android.x
import android.app.Application
import androidx.startup.AppInitializer
import androidx.work.Configuration
import dev.zacsweers.metro.createGraphFactory
import io.element.android.features.cachecleaner.api.CacheCleanerInitializer
import io.element.android.libraries.di.DependencyInjectionGraphOwner
import io.element.android.libraries.workmanager.api.di.MetroWorkerFactory
import io.element.android.x.di.AppGraph
import io.element.android.x.info.logApplicationInfo
import io.element.android.x.initializer.CrashInitializer
import io.element.android.x.initializer.PlatformInitializer
class ElementXApplication : Application(), DependencyInjectionGraphOwner {
class ElementXApplication : Application(), DependencyInjectionGraphOwner, Configuration.Provider {
override val graph: AppGraph = createGraphFactory<AppGraph.Factory>().create(this)
override val workManagerConfiguration: Configuration = Configuration.Builder()
.setWorkerFactory(MetroWorkerFactory(graph.workerProviders))
.build()
override fun onCreate() {
super.onCreate()
AppInitializer.getInstance(this).apply {
@ -27,6 +33,7 @@ class ElementXApplication : Application(), DependencyInjectionGraphOwner {
initializeComponent(PlatformInitializer::class.java)
initializeComponent(CacheCleanerInitializer::class.java)
}
logApplicationInfo(this)
}
}

View file

@ -8,16 +8,24 @@
package io.element.android.x.di
import android.content.Context
import androidx.work.ListenableWorker
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.DependencyGraph
import dev.zacsweers.metro.Multibinds
import dev.zacsweers.metro.Provides
import io.element.android.libraries.architecture.NodeFactoriesBindings
import io.element.android.libraries.di.annotations.ApplicationContext
import io.element.android.libraries.workmanager.api.di.MetroWorkerFactory
import kotlin.reflect.KClass
@DependencyGraph(AppScope::class)
interface AppGraph : NodeFactoriesBindings {
val sessionGraphFactory: SessionGraph.Factory
@Multibinds
val workerProviders:
Map<KClass<out ListenableWorker>, MetroWorkerFactory.WorkerInstanceFactory<*>>
@DependencyGraph.Factory
interface Factory {
fun create(