From 71bfffe58f635e2a3530842c0db95d70c78d9cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 27 Nov 2025 12:13:16 +0100 Subject: [PATCH] Move analytic watchers to `:services:analytics` --- .../android/appnav/LoggedInFlowNode.kt | 2 +- .../android/appnav/NotLoggedInFlowNode.kt | 2 +- .../io/element/android/appnav/RootFlowNode.kt | 1 + features/home/impl/build.gradle.kts | 1 - .../home/impl/roomlist/RoomListPresenter.kt | 2 +- .../impl/roomlist/RoomListPresenterTest.kt | 10 +------ .../api/watchers/AnalyticsColdStartWatcher.kt | 18 ++++++++++++ .../watchers/AnalyticsRoomListStateWatcher.kt | 17 +++++++++++ services/analytics/impl/build.gradle.kts | 4 +++ .../DefaultAnalyticsColdStartWatcher.kt | 21 ++++---------- .../DefaultAnalyticsRoomListStateWatcher.kt | 29 +++++++++---------- .../DefaultAnalyticsColdStartWatcherTest.kt | 2 +- ...efaultAnalyticsRoomListStateWatcherTest.kt | 6 ++-- .../watchers/FakeAnalyticsColdStartWatcher.kt | 16 ++++++++++ 14 files changed, 84 insertions(+), 47 deletions(-) create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/watchers/AnalyticsColdStartWatcher.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/watchers/AnalyticsRoomListStateWatcher.kt rename appnav/src/main/kotlin/io/element/android/appnav/analytics/AnalyticsColdStartWatcher.kt => services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt (73%) rename appnav/src/main/kotlin/io/element/android/appnav/analytics/AnalyticsRoomListStateWatcher.kt => services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsRoomListStateWatcher.kt (77%) rename {appnav/src/test/kotlin/io/element/android/appnav/analytics => services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/watchers}/DefaultAnalyticsColdStartWatcherTest.kt (98%) rename appnav/src/test/kotlin/io/element/android/appnav/analytics/AnalyticsRoomListStateWatcherTest.kt => services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsRoomListStateWatcherTest.kt (97%) create mode 100644 services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/watchers/FakeAnalyticsColdStartWatcher.kt diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index 310913e0ac..7e782c7cc4 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -41,7 +41,6 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.annotations.ContributesNode -import io.element.android.appnav.analytics.AnalyticsRoomListStateWatcher import io.element.android.appnav.loggedin.LoggedInNode import io.element.android.appnav.loggedin.MediaPreviewConfigMigration import io.element.android.appnav.loggedin.SendQueues @@ -93,6 +92,7 @@ import io.element.android.libraries.push.api.notifications.conversations.Notific import io.element.android.libraries.ui.common.nodes.emptyNode import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.analytics.api.watchers.AnalyticsRoomListStateWatcher import io.element.android.services.appnavstate.api.AppNavigationStateService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.first diff --git a/appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt index b1d371b4c0..080f3c1d77 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt @@ -24,7 +24,6 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode -import io.element.android.appnav.analytics.AnalyticsColdStartWatcher import io.element.android.features.login.api.LoginEntryPoint import io.element.android.features.login.api.LoginParams import io.element.android.libraries.architecture.BackstackView @@ -35,6 +34,7 @@ import io.element.android.libraries.architecture.inputs import io.element.android.libraries.designsystem.utils.ForceOrientationInMobileDevices import io.element.android.libraries.designsystem.utils.ScreenOrientation import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder +import io.element.android.services.analytics.api.watchers.AnalyticsColdStartWatcher import kotlinx.parcelize.Parcelize @ContributesNode(AppScope::class) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt index 52788fc992..838804a055 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt @@ -65,6 +65,7 @@ import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.ui.common.nodes.emptyNode import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.analytics.api.watchers.AnalyticsColdStartWatcher import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/features/home/impl/build.gradle.kts b/features/home/impl/build.gradle.kts index 9362702a1a..b36ee6aed2 100644 --- a/features/home/impl/build.gradle.kts +++ b/features/home/impl/build.gradle.kts @@ -28,7 +28,6 @@ setupDependencyInjection() dependencies { implementation(projects.appconfig) - implementation(projects.appnav) implementation(projects.libraries.core) implementation(projects.libraries.androidutils) implementation(projects.libraries.architecture) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt index ce1197f9ca..5fc07ab21c 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt @@ -25,7 +25,6 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import dev.zacsweers.metro.Inject import im.vector.app.features.analytics.plan.Interaction -import io.element.android.appnav.analytics.AnalyticsColdStartWatcher import io.element.android.features.announcement.api.Announcement import io.element.android.features.announcement.api.AnnouncementService import io.element.android.features.home.impl.datasource.RoomListDataSource @@ -52,6 +51,7 @@ import io.element.android.libraries.preferences.api.store.SessionPreferencesStor import io.element.android.libraries.push.api.battery.BatteryOptimizationState import io.element.android.libraries.push.api.notifications.NotificationCleaner import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.analytics.api.watchers.AnalyticsColdStartWatcher import io.element.android.services.analyticsproviders.api.trackers.captureInteraction import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableSet diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt index a3be896f40..acc68db018 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt @@ -13,7 +13,6 @@ import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.Interaction -import io.element.android.appnav.analytics.AnalyticsColdStartWatcher import io.element.android.features.announcement.api.Announcement import io.element.android.features.announcement.api.AnnouncementService import io.element.android.features.home.impl.FakeDateTimeObserver @@ -71,6 +70,7 @@ import io.element.android.libraries.push.api.notifications.NotificationCleaner import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.services.analytics.test.watchers.FakeAnalyticsColdStartWatcher import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate @@ -677,11 +677,3 @@ class RoomListPresenterTest { coldStartWatcher = FakeAnalyticsColdStartWatcher(), ) } - -private class FakeAnalyticsColdStartWatcher : AnalyticsColdStartWatcher { - override fun start() {} - - override fun whenLoggingIn() {} - - override fun onRoomListVisible() {} -} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/watchers/AnalyticsColdStartWatcher.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/watchers/AnalyticsColdStartWatcher.kt new file mode 100644 index 0000000000..67d3c5498b --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/watchers/AnalyticsColdStartWatcher.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.services.analytics.api.watchers + +/** + * Adds a performance check transaction measuring the time between a cold start (or, after we read the user consent after a cold start) + * until the cached room list is displayed. This check only takes place in a cold app start after the user is authenticated. + */ +interface AnalyticsColdStartWatcher { + fun start() + fun whenLoggingIn() + fun onRoomListVisible() +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/watchers/AnalyticsRoomListStateWatcher.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/watchers/AnalyticsRoomListStateWatcher.kt new file mode 100644 index 0000000000..2f6d4723a3 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/watchers/AnalyticsRoomListStateWatcher.kt @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.services.analytics.api.watchers + +/** + * This component is used to check how long it takes for the room list to be up to date after opening the app while it's on a 'warm' state: + * the app was previously running and we just returned to it. + */ +interface AnalyticsRoomListStateWatcher { + fun start() + fun stop() +} diff --git a/services/analytics/impl/build.gradle.kts b/services/analytics/impl/build.gradle.kts index 8aa542f60a..6ba2963853 100644 --- a/services/analytics/impl/build.gradle.kts +++ b/services/analytics/impl/build.gradle.kts @@ -25,16 +25,20 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.architecture) implementation(projects.libraries.designsystem) + implementation(projects.libraries.matrix.api) implementation(projects.libraries.preferences.api) implementation(projects.libraries.sessionStorage.api) + implementation(projects.services.appnavstate.api) api(projects.services.analyticsproviders.api) api(projects.services.analytics.api) implementation(libs.androidx.datastore.preferences) testCommonDependencies(libs) + testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.analyticsproviders.test) + testImplementation(projects.services.appnavstate.test) testImplementation(projects.services.toolbox.test) } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/analytics/AnalyticsColdStartWatcher.kt b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt similarity index 73% rename from appnav/src/main/kotlin/io/element/android/appnav/analytics/AnalyticsColdStartWatcher.kt rename to services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt index 8b9efa94bf..f5ef72ba8d 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/analytics/AnalyticsColdStartWatcher.kt +++ b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt @@ -5,14 +5,15 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.appnav.analytics +package io.element.android.services.analytics.impl.watchers import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction.ColdStartUntilCachedRoomList +import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.analytics.api.watchers.AnalyticsColdStartWatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn @@ -20,16 +21,6 @@ import kotlinx.coroutines.flow.onEach import timber.log.Timber import java.util.concurrent.atomic.AtomicBoolean -/** - * Adds a performance check transaction measuring the time between a cold start (or, after we read the user consent after a cold start) - * until the cached room list is displayed. This check only takes place in a cold app start after the user is authenticated. - */ -interface AnalyticsColdStartWatcher { - fun start() - fun whenLoggingIn() - fun onRoomListVisible() -} - @SingleIn(AppScope::class) @ContributesBinding(AppScope::class) class DefaultAnalyticsColdStartWatcher( @@ -44,7 +35,7 @@ class DefaultAnalyticsColdStartWatcher( if (hasConsent) { if (isColdStart.get()) { Timber.d("Starting cold start check") - analyticsService.startLongRunningTransaction(ColdStartUntilCachedRoomList) + analyticsService.startLongRunningTransaction(AnalyticsLongRunningTransaction.ColdStartUntilCachedRoomList) } else { error("The app is no longer in a cold start state") } @@ -56,7 +47,7 @@ class DefaultAnalyticsColdStartWatcher( override fun whenLoggingIn() { if (isColdStart.getAndSet(false)) { - analyticsService.removeLongRunningTransaction(ColdStartUntilCachedRoomList) + analyticsService.removeLongRunningTransaction(AnalyticsLongRunningTransaction.ColdStartUntilCachedRoomList) Timber.d("Canceled cold start check: user is logging in") } } @@ -64,7 +55,7 @@ class DefaultAnalyticsColdStartWatcher( override fun onRoomListVisible() { if (isColdStart.getAndSet(false)) { Timber.d("Room list is visible, finishing cold start check") - analyticsService.removeLongRunningTransaction(ColdStartUntilCachedRoomList)?.finish() + analyticsService.removeLongRunningTransaction(AnalyticsLongRunningTransaction.ColdStartUntilCachedRoomList)?.finish() } } } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/analytics/AnalyticsRoomListStateWatcher.kt b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsRoomListStateWatcher.kt similarity index 77% rename from appnav/src/main/kotlin/io/element/android/appnav/analytics/AnalyticsRoomListStateWatcher.kt rename to services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsRoomListStateWatcher.kt index 91efa0bf92..c2a82eb49b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/analytics/AnalyticsRoomListStateWatcher.kt +++ b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsRoomListStateWatcher.kt @@ -5,15 +5,18 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.appnav.analytics +package io.element.android.services.analytics.impl.watchers -import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.core.coroutine.childScope import io.element.android.libraries.core.coroutine.withPreviousValue +import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.roomlist.RoomListService -import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction.ResumeAppUntilNewRoomsReceived +import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.analytics.api.watchers.AnalyticsRoomListStateWatcher import io.element.android.services.appnavstate.api.AppNavigationStateService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel @@ -24,35 +27,31 @@ import kotlinx.coroutines.flow.onEach import timber.log.Timber import java.util.concurrent.atomic.AtomicBoolean -/** - * This component is used to check how long it takes for the room list to be up to date after opening the app while it's on a 'warm' state: - * the app was previously running and we just returned to it. - */ -@Inject -class AnalyticsRoomListStateWatcher( +@ContributesBinding(SessionScope::class) +class DefaultAnalyticsRoomListStateWatcher( private val appNavigationStateService: AppNavigationStateService, private val roomListService: RoomListService, private val analyticsService: AnalyticsService, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val dispatchers: CoroutineDispatchers, -) { +) : AnalyticsRoomListStateWatcher { private var currentCoroutineScope: CoroutineScope? = null private val isWarmState = AtomicBoolean(false) - fun start() { + override fun start() { if (currentCoroutineScope != null) { Timber.w("Can't start RoomListStateWatcher, it's already running.") return } - val coroutineScope = CoroutineScope(sessionCoroutineScope.coroutineContext + dispatchers.computation) + val coroutineScope = sessionCoroutineScope.childScope(dispatchers.computation, "AnalyticsRoomListStateWatcher") appNavigationStateService.appNavigationState .map { it.isInForeground } .distinctUntilChanged() .withPreviousValue() .onEach { (wasInForeground, isInForeground) -> if (isInForeground && roomListService.state.value != RoomListService.State.Running) { - analyticsService.startLongRunningTransaction(ResumeAppUntilNewRoomsReceived) + analyticsService.startLongRunningTransaction(AnalyticsLongRunningTransaction.ResumeAppUntilNewRoomsReceived) } if (wasInForeground == false && isInForeground) { @@ -64,7 +63,7 @@ class AnalyticsRoomListStateWatcher( roomListService.state .onEach { state -> if (state == RoomListService.State.Running && isWarmState.get()) { - analyticsService.removeLongRunningTransaction(ResumeAppUntilNewRoomsReceived)?.finish() + analyticsService.removeLongRunningTransaction(AnalyticsLongRunningTransaction.ResumeAppUntilNewRoomsReceived)?.finish() } } .launchIn(coroutineScope) @@ -72,7 +71,7 @@ class AnalyticsRoomListStateWatcher( currentCoroutineScope = coroutineScope } - fun stop() { + override fun stop() { currentCoroutineScope?.cancel() currentCoroutineScope = null } diff --git a/appnav/src/test/kotlin/io/element/android/appnav/analytics/DefaultAnalyticsColdStartWatcherTest.kt b/services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcherTest.kt similarity index 98% rename from appnav/src/test/kotlin/io/element/android/appnav/analytics/DefaultAnalyticsColdStartWatcherTest.kt rename to services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcherTest.kt index d71d51faba..325316b45c 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/analytics/DefaultAnalyticsColdStartWatcherTest.kt +++ b/services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcherTest.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.appnav.analytics +package io.element.android.services.analytics.impl.watchers import com.google.common.truth.Truth.assertThat import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction.ColdStartUntilCachedRoomList diff --git a/appnav/src/test/kotlin/io/element/android/appnav/analytics/AnalyticsRoomListStateWatcherTest.kt b/services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsRoomListStateWatcherTest.kt similarity index 97% rename from appnav/src/test/kotlin/io/element/android/appnav/analytics/AnalyticsRoomListStateWatcherTest.kt rename to services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsRoomListStateWatcherTest.kt index f05190acc7..3b1f562c67 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/analytics/AnalyticsRoomListStateWatcherTest.kt +++ b/services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsRoomListStateWatcherTest.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.appnav.analytics +package io.element.android.services.analytics.impl.watchers import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.roomlist.RoomListService @@ -23,7 +23,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) -class AnalyticsRoomListStateWatcherTest { +class DefaultAnalyticsRoomListStateWatcherTest { @Test fun `Opening the app in a warm state tracks the time until the room list is synced`() = runTest { val navigationStateService = FakeAppNavigationStateService() @@ -160,7 +160,7 @@ class AnalyticsRoomListStateWatcherTest { appNavigationStateService: FakeAppNavigationStateService = FakeAppNavigationStateService(), roomListService: FakeRoomListService = FakeRoomListService(), analyticsService: FakeAnalyticsService = FakeAnalyticsService(), - ) = AnalyticsRoomListStateWatcher( + ) = DefaultAnalyticsRoomListStateWatcher( appNavigationStateService = appNavigationStateService, roomListService = roomListService, analyticsService = analyticsService, diff --git a/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/watchers/FakeAnalyticsColdStartWatcher.kt b/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/watchers/FakeAnalyticsColdStartWatcher.kt new file mode 100644 index 0000000000..ad13c8422d --- /dev/null +++ b/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/watchers/FakeAnalyticsColdStartWatcher.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.services.analytics.test.watchers + +import io.element.android.services.analytics.api.watchers.AnalyticsColdStartWatcher + +class FakeAnalyticsColdStartWatcher : AnalyticsColdStartWatcher { + override fun start() {} + override fun whenLoggingIn() {} + override fun onRoomListVisible() {} +}