Browse Source

Analytics : add analytics on read status and favorite toggles

pull/2416/head
ganfra 7 months ago
parent
commit
66030aeb64
  1. 1
      features/roomdetails/impl/build.gradle.kts
  2. 17
      features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt
  3. 12
      features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt
  4. 1
      features/roomlist/impl/build.gradle.kts
  5. 62
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt
  6. 21
      features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt
  7. 2
      gradle/libs.versions.toml
  8. 5
      services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/trackers/AnalyticsTracker.kt

1
features/roomdetails/impl/build.gradle.kts

@ -70,6 +70,7 @@ dependencies {
testImplementation(projects.tests.testutils) testImplementation(projects.tests.testutils)
testImplementation(projects.features.leaveroom.test) testImplementation(projects.features.leaveroom.test)
testImplementation(projects.features.createroom.test) testImplementation(projects.features.createroom.test)
testImplementation(projects.services.analytics.test)
ksp(libs.showkase.processor) ksp(libs.showkase.processor)
} }

17
features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt

@ -27,6 +27,7 @@ import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.leaveroom.api.LeaveRoomPresenter
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
@ -46,6 +47,8 @@ import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
import io.element.android.libraries.matrix.api.room.powerlevels.canSendState import io.element.android.libraries.matrix.api.room.powerlevels.canSendState
import io.element.android.libraries.matrix.api.room.roomNotificationSettings import io.element.android.libraries.matrix.api.room.roomNotificationSettings
import io.element.android.libraries.matrix.ui.room.getDirectRoomMember import io.element.android.libraries.matrix.ui.room.getDirectRoomMember
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -60,6 +63,7 @@ class RoomDetailsPresenter @Inject constructor(
private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory, private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory,
private val leaveRoomPresenter: LeaveRoomPresenter, private val leaveRoomPresenter: LeaveRoomPresenter,
private val dispatchers: CoroutineDispatchers, private val dispatchers: CoroutineDispatchers,
private val analyticsService: AnalyticsService,
) : Presenter<RoomDetailsState> { ) : Presenter<RoomDetailsState> {
@Composable @Composable
override fun present(): RoomDetailsState { override fun present(): RoomDetailsState {
@ -124,11 +128,7 @@ class RoomDetailsPresenter @Inject constructor(
client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.isOneToOne) client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.isOneToOne)
} }
} }
is RoomDetailsEvent.SetFavorite -> { is RoomDetailsEvent.SetFavorite -> scope.setFavorite(event.isFavorite)
scope.launch {
room.setIsFavorite(event.isFavorite)
}
}
} }
} }
@ -187,4 +187,11 @@ class RoomDetailsPresenter @Inject constructor(
room.updateRoomNotificationSettings() room.updateRoomNotificationSettings()
}.launchIn(this) }.launchIn(this)
} }
private fun CoroutineScope.setFavorite(isFavorite: Boolean) = launch {
room.setIsFavorite(isFavorite)
.onSuccess {
analyticsService.captureInteraction(Interaction.Name.MobileRoomFavouriteToggle)
}
}
} }

12
features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt

@ -22,6 +22,7 @@ import app.cash.molecule.moleculeFlow
import app.cash.turbine.TurbineTestContext import app.cash.turbine.TurbineTestContext
import app.cash.turbine.test import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.createroom.test.FakeStartDMAction import io.element.android.features.createroom.test.FakeStartDMAction
import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.leaveroom.api.LeaveRoomPresenter
@ -50,6 +51,8 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.FakeLifecycleOwner import io.element.android.tests.testutils.FakeLifecycleOwner
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.consumeItemsUntilPredicate
@ -77,6 +80,7 @@ class RoomDetailsPresenterTests {
leaveRoomPresenter: LeaveRoomPresenter = FakeLeaveRoomPresenter(), leaveRoomPresenter: LeaveRoomPresenter = FakeLeaveRoomPresenter(),
dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
analyticsService: AnalyticsService = FakeAnalyticsService(),
): RoomDetailsPresenter { ): RoomDetailsPresenter {
val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService) val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService)
val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory { val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory {
@ -95,6 +99,7 @@ class RoomDetailsPresenterTests {
roomMembersDetailsPresenterFactory = roomMemberDetailsPresenterFactory, roomMembersDetailsPresenterFactory = roomMemberDetailsPresenterFactory,
leaveRoomPresenter = leaveRoomPresenter, leaveRoomPresenter = leaveRoomPresenter,
dispatchers = dispatchers, dispatchers = dispatchers,
analyticsService = analyticsService,
) )
} }
@ -435,13 +440,18 @@ class RoomDetailsPresenterTests {
@Test @Test
fun `present - when set is favorite event is emitted, then the action is called`() = runTest { fun `present - when set is favorite event is emitted, then the action is called`() = runTest {
val room = FakeMatrixRoom() val room = FakeMatrixRoom()
val presenter = createRoomDetailsPresenter(room = room) val analyticsService = FakeAnalyticsService()
val presenter = createRoomDetailsPresenter(room = room, analyticsService = analyticsService)
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(RoomDetailsEvent.SetFavorite(true)) initialState.eventSink(RoomDetailsEvent.SetFavorite(true))
assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true)) assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true))
initialState.eventSink(RoomDetailsEvent.SetFavorite(false)) initialState.eventSink(RoomDetailsEvent.SetFavorite(false))
assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false)) assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false))
assertThat(analyticsService.capturedEvents).containsExactly(
Interaction(name = Interaction.Name.MobileRoomFavouriteToggle),
Interaction(name = Interaction.Name.MobileRoomFavouriteToggle)
)
cancelAndIgnoreRemainingEvents() cancelAndIgnoreRemainingEvents()
} }
} }

1
features/roomlist/impl/build.gradle.kts

@ -76,6 +76,7 @@ dependencies {
testImplementation(projects.libraries.permissions.noop) testImplementation(projects.libraries.permissions.noop)
testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.preferences.test)
testImplementation(projects.features.invitelist.test) testImplementation(projects.features.invitelist.test)
testImplementation(projects.services.analytics.test)
testImplementation(projects.features.networkmonitor.test) testImplementation(projects.features.networkmonitor.test)
testImplementation(projects.tests.testutils) testImplementation(projects.tests.testutils)
testImplementation(projects.features.leaveroom.test) testImplementation(projects.features.leaveroom.test)

62
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt

@ -29,6 +29,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.snapshotFlow
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.leaveroom.api.LeaveRoomPresenter
import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkMonitor
@ -45,12 +46,15 @@ import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.indicator.api.IndicatorService import io.element.android.libraries.indicator.api.IndicatorService
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.api.user.getCurrentUser import io.element.android.libraries.matrix.api.user.getCurrentUser
import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
@ -78,6 +82,7 @@ class RoomListPresenter @Inject constructor(
private val indicatorService: IndicatorService, private val indicatorService: IndicatorService,
private val migrationScreenPresenter: MigrationScreenPresenter, private val migrationScreenPresenter: MigrationScreenPresenter,
private val sessionPreferencesStore: SessionPreferencesStore, private val sessionPreferencesStore: SessionPreferencesStore,
private val analyticsService: AnalyticsService,
) : Presenter<RoomListState> { ) : Presenter<RoomListState> {
@Composable @Composable
override fun present(): RoomListState { override fun present(): RoomListState {
@ -145,27 +150,9 @@ class RoomListPresenter @Inject constructor(
} }
is RoomListEvents.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(event.roomId)) is RoomListEvents.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(event.roomId))
is RoomListEvents.SetRoomIsFavorite -> coroutineScope.launch { is RoomListEvents.SetRoomIsFavorite -> coroutineScope.setRoomIsFavorite(event.roomId, event.isFavorite)
client.getRoom(event.roomId)?.use { room -> is RoomListEvents.MarkAsRead -> coroutineScope.markAsRead(event.roomId)
room.setIsFavorite(event.isFavorite) is RoomListEvents.MarkAsUnread -> coroutineScope.markAsUnread(event.roomId)
}
}
is RoomListEvents.MarkAsRead -> coroutineScope.launch {
client.getRoom(event.roomId)?.use { room ->
room.setUnreadFlag(isUnread = false)
val receiptType = if (sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first()) {
ReceiptType.READ
} else {
ReceiptType.READ_PRIVATE
}
room.markAsRead(receiptType)
}
}
is RoomListEvents.MarkAsUnread -> coroutineScope.launch {
client.getRoom(event.roomId)?.use { room ->
room.setUnreadFlag(isUnread = true)
}
}
} }
} }
@ -225,6 +212,39 @@ class RoomListPresenter @Inject constructor(
} }
} }
private fun CoroutineScope.setRoomIsFavorite(roomId: RoomId, isFavorite: Boolean) = launch {
client.getRoom(roomId)?.use { room ->
room.setIsFavorite(isFavorite)
.onSuccess {
analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuFavouriteToggle)
}
}
}
private fun CoroutineScope.markAsRead(roomId: RoomId) = launch {
client.getRoom(roomId)?.use { room ->
room.setUnreadFlag(isUnread = false)
val receiptType = if (sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first()) {
ReceiptType.READ
} else {
ReceiptType.READ_PRIVATE
}
room.markAsRead(receiptType)
.onSuccess {
analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle)
}
}
}
private fun CoroutineScope.markAsUnread(roomId: RoomId) = launch {
client.getRoom(roomId)?.use { room ->
room.setUnreadFlag(isUnread = true)
.onSuccess {
analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle)
}
}
}
private fun updateVisibleRange(range: IntRange) { private fun updateVisibleRange(range: IntRange) {
if (range.isEmpty()) return if (range.isEmpty()) return
val midExtendedRangeSize = EXTENDED_RANGE_SIZE / 2 val midExtendedRangeSize = EXTENDED_RANGE_SIZE / 2

21
features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt

@ -20,6 +20,7 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow import app.cash.molecule.moleculeFlow
import app.cash.turbine.test import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.leaveroom.api.LeaveRoomPresenter
import io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter import io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter
@ -66,6 +67,8 @@ import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.consumeItemsUntilPredicate
import io.element.android.tests.testutils.testCoroutineDispatchers import io.element.android.tests.testutils.testCoroutineDispatchers
@ -474,10 +477,11 @@ class RoomListPresenterTests {
fun `present - when set is favorite event is emitted, then the action is called`() = runTest { fun `present - when set is favorite event is emitted, then the action is called`() = runTest {
val scope = CoroutineScope(coroutineContext + SupervisorJob()) val scope = CoroutineScope(coroutineContext + SupervisorJob())
val room = FakeMatrixRoom() val room = FakeMatrixRoom()
val analyticsService = FakeAnalyticsService()
val client = FakeMatrixClient().apply { val client = FakeMatrixClient().apply {
givenGetRoomResult(A_ROOM_ID, room) givenGetRoomResult(A_ROOM_ID, room)
} }
val presenter = createRoomListPresenter(client = client, coroutineScope = scope) val presenter = createRoomListPresenter(client = client, coroutineScope = scope, analyticsService = analyticsService)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
}.test { }.test {
@ -486,6 +490,10 @@ class RoomListPresenterTests {
assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true)) assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true))
initialState.eventSink(RoomListEvents.SetRoomIsFavorite(A_ROOM_ID, false)) initialState.eventSink(RoomListEvents.SetRoomIsFavorite(A_ROOM_ID, false))
assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false)) assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false))
assertThat(analyticsService.capturedEvents).containsExactly(
Interaction(name = Interaction.Name.MobileRoomListRoomContextMenuFavouriteToggle),
Interaction(name = Interaction.Name.MobileRoomListRoomContextMenuFavouriteToggle)
)
cancelAndIgnoreRemainingEvents() cancelAndIgnoreRemainingEvents()
scope.cancel() scope.cancel()
} }
@ -527,11 +535,13 @@ class RoomListPresenterTests {
val matrixClient = FakeMatrixClient().apply { val matrixClient = FakeMatrixClient().apply {
givenGetRoomResult(A_ROOM_ID, room) givenGetRoomResult(A_ROOM_ID, room)
} }
val analyticsService = FakeAnalyticsService()
val scope = CoroutineScope(coroutineContext + SupervisorJob()) val scope = CoroutineScope(coroutineContext + SupervisorJob())
val presenter = createRoomListPresenter( val presenter = createRoomListPresenter(
client = matrixClient, client = matrixClient,
coroutineScope = scope, coroutineScope = scope,
sessionPreferencesStore = sessionPreferencesStore, sessionPreferencesStore = sessionPreferencesStore,
analyticsService = analyticsService,
) )
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
@ -550,6 +560,11 @@ class RoomListPresenterTests {
initialState.eventSink.invoke(RoomListEvents.MarkAsRead(A_ROOM_ID)) initialState.eventSink.invoke(RoomListEvents.MarkAsRead(A_ROOM_ID))
assertThat(room.markAsReadCalls).isEqualTo(listOf(ReceiptType.READ, ReceiptType.READ_PRIVATE)) assertThat(room.markAsReadCalls).isEqualTo(listOf(ReceiptType.READ, ReceiptType.READ_PRIVATE))
assertThat(room.setUnreadFlagCalls).isEqualTo(listOf(false, true, false)) assertThat(room.setUnreadFlagCalls).isEqualTo(listOf(false, true, false))
assertThat(analyticsService.capturedEvents).containsExactly(
Interaction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle),
Interaction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle),
Interaction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle),
)
cancelAndIgnoreRemainingEvents() cancelAndIgnoreRemainingEvents()
scope.cancel() scope.cancel()
} }
@ -572,7 +587,8 @@ class RoomListPresenterTests {
migrationScreenPresenter: MigrationScreenPresenter = MigrationScreenPresenter( migrationScreenPresenter: MigrationScreenPresenter = MigrationScreenPresenter(
matrixClient = client, matrixClient = client,
migrationScreenStore = InMemoryMigrationScreenStore(), migrationScreenStore = InMemoryMigrationScreenStore(),
) ),
analyticsService: AnalyticsService = FakeAnalyticsService(),
) = RoomListPresenter( ) = RoomListPresenter(
client = client, client = client,
sessionVerificationService = sessionVerificationService, sessionVerificationService = sessionVerificationService,
@ -599,5 +615,6 @@ class RoomListPresenterTests {
), ),
migrationScreenPresenter = migrationScreenPresenter, migrationScreenPresenter = migrationScreenPresenter,
sessionPreferencesStore = sessionPreferencesStore, sessionPreferencesStore = sessionPreferencesStore,
analyticsService = analyticsService,
) )
} }

2
gradle/libs.versions.toml

@ -174,7 +174,7 @@ kotlinpoet = "com.squareup:kotlinpoet:1.16.0"
# Analytics # Analytics
posthog = "com.posthog:posthog-android:3.1.7" posthog = "com.posthog:posthog-android:3.1.7"
sentry = "io.sentry:sentry-android:7.3.0" sentry = "io.sentry:sentry-android:7.3.0"
matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:aa14cbcdf81af2746d20a71779ec751f971e1d7f" matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.11.0"
# Emojibase # Emojibase
matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.1.3" matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.1.3"

5
services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/trackers/AnalyticsTracker.kt

@ -18,6 +18,7 @@ package io.element.android.services.analyticsproviders.api.trackers
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
import im.vector.app.features.analytics.plan.Interaction
import im.vector.app.features.analytics.plan.UserProperties import im.vector.app.features.analytics.plan.UserProperties
interface AnalyticsTracker { interface AnalyticsTracker {
@ -36,3 +37,7 @@ interface AnalyticsTracker {
*/ */
fun updateUserProperties(userProperties: UserProperties) fun updateUserProperties(userProperties: UserProperties)
} }
fun AnalyticsTracker.captureInteraction(name: Interaction.Name, type: Interaction.InteractionType? = null) {
capture(Interaction(interactionType = type, name = name))
}

Loading…
Cancel
Save