Polls analytics (#1285)
Send poll analytics event (creation, vote, end) where appropriate.
This commit is contained in:
parent
05a3b64c05
commit
8abaee8708
8 changed files with 90 additions and 20 deletions
|
|
@ -30,6 +30,7 @@ import androidx.compose.runtime.setValue
|
|||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.features.analytics.plan.PollEnd
|
||||
import io.element.android.features.messages.impl.actionlist.ActionListEvents
|
||||
import io.element.android.features.messages.impl.actionlist.ActionListPresenter
|
||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
|
||||
|
|
@ -74,6 +75,7 @@ import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
|
|||
import io.element.android.libraries.matrix.ui.room.canRedactAsState
|
||||
import io.element.android.libraries.matrix.ui.room.canSendMessageAsState
|
||||
import io.element.android.libraries.textcomposer.MessageComposerMode
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -92,6 +94,7 @@ class MessagesPresenter @AssistedInject constructor(
|
|||
private val messageSummaryFormatter: MessageSummaryFormatter,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
private val clipboardHelper: ClipboardHelper,
|
||||
private val analyticsService: AnalyticsService,
|
||||
@Assisted private val navigator: MessagesNavigator,
|
||||
) : Presenter<MessagesState> {
|
||||
|
||||
|
|
@ -321,8 +324,10 @@ class MessagesPresenter @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private suspend fun handleEndPollAction(event: TimelineItem.Event) {
|
||||
event.eventId?.let { room.endPoll(it, "The poll with event id: $it has ended.") }
|
||||
// TODO Polls: Send poll end analytic
|
||||
event.eventId?.let {
|
||||
room.endPoll(it, "The poll with event id: $it has ended.")
|
||||
analyticsService.capture(PollEnd())
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleCopyContents(event: TimelineItem.Event) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import im.vector.app.features.analytics.plan.PollVote
|
||||
import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
|
|
@ -35,6 +36,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom
|
|||
import io.element.android.libraries.matrix.api.room.MessageEventType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin
|
||||
import io.element.android.libraries.matrix.ui.room.canSendMessageAsState
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
|
@ -51,6 +53,7 @@ class TimelinePresenter @Inject constructor(
|
|||
private val room: MatrixRoom,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
private val appScope: CoroutineScope,
|
||||
private val analyticsService: AnalyticsService,
|
||||
) : Presenter<TimelineState> {
|
||||
|
||||
private val timeline = room.timeline
|
||||
|
|
@ -93,7 +96,7 @@ class TimelinePresenter @Inject constructor(
|
|||
pollStartId = event.pollStartId,
|
||||
answers = listOf(event.answerId),
|
||||
)
|
||||
// TODO Polls: Send poll vote analytic
|
||||
analyticsService.capture(PollVote())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import app.cash.molecule.RecompositionMode
|
|||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.PollEnd
|
||||
import io.element.android.features.messages.fixtures.aMessageEvent
|
||||
import io.element.android.features.messages.fixtures.aTimelineItemsFactory
|
||||
import io.element.android.features.messages.impl.InviteDialogAction
|
||||
|
|
@ -575,7 +576,11 @@ class MessagesPresenterTest {
|
|||
@Test
|
||||
fun `present - handle poll end`() = runTest {
|
||||
val room = FakeMatrixRoom()
|
||||
val presenter = createMessagePresenter(matrixRoom = room)
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val presenter = createMessagePresenter(
|
||||
matrixRoom = room,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -586,7 +591,8 @@ class MessagesPresenterTest {
|
|||
assertThat(room.endPollInvocations.size).isEqualTo(1)
|
||||
assertThat(room.endPollInvocations.first().pollStartId).isEqualTo(AN_EVENT_ID)
|
||||
assertThat(room.endPollInvocations.first().text).isEqualTo("The poll with event id: \$anEventId has ended.")
|
||||
// TODO Polls: Test poll end analytic
|
||||
assertThat(analyticsService.capturedEvents.size).isEqualTo(1)
|
||||
assertThat(analyticsService.capturedEvents.last()).isEqualTo(PollEnd())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -595,6 +601,7 @@ class MessagesPresenterTest {
|
|||
matrixRoom: MatrixRoom = FakeMatrixRoom(),
|
||||
navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
|
||||
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
|
||||
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
|
||||
): MessagesPresenter {
|
||||
val messageComposerPresenter = MessageComposerPresenter(
|
||||
appCoroutineScope = this,
|
||||
|
|
@ -604,7 +611,7 @@ class MessagesPresenterTest {
|
|||
localMediaFactory = FakeLocalMediaFactory(mockMediaUrl),
|
||||
mediaSender = MediaSender(FakeMediaPreProcessor(), matrixRoom),
|
||||
snackbarDispatcher = SnackbarDispatcher(),
|
||||
analyticsService = FakeAnalyticsService(),
|
||||
analyticsService = analyticsService,
|
||||
messageComposerContext = MessageComposerContextImpl(),
|
||||
richTextEditorStateFactory = TestRichTextEditorStateFactory(),
|
||||
|
||||
|
|
@ -613,7 +620,8 @@ class MessagesPresenterTest {
|
|||
timelineItemsFactory = aTimelineItemsFactory(),
|
||||
room = matrixRoom,
|
||||
dispatchers = coroutineDispatchers,
|
||||
appScope = this
|
||||
appScope = this,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
val buildMeta = aBuildMeta()
|
||||
val actionListPresenter = ActionListPresenter(buildMeta = buildMeta)
|
||||
|
|
@ -633,6 +641,7 @@ class MessagesPresenterTest {
|
|||
messageSummaryFormatter = FakeMessageSummaryFormatter(),
|
||||
navigator = navigator,
|
||||
clipboardHelper = clipboardHelper,
|
||||
analyticsService = analyticsService,
|
||||
dispatchers = coroutineDispatchers,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import app.cash.molecule.RecompositionMode
|
|||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.PollVote
|
||||
import io.element.android.features.messages.fixtures.aTimelineItemsFactory
|
||||
import io.element.android.features.messages.impl.timeline.TimelineEvents
|
||||
import io.element.android.features.messages.impl.timeline.TimelinePresenter
|
||||
|
|
@ -37,6 +38,7 @@ import io.element.android.libraries.matrix.test.room.aMessageContent
|
|||
import io.element.android.libraries.matrix.test.room.anEventTimelineItem
|
||||
import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import io.element.android.tests.testutils.awaitWithLatch
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
|
|
@ -260,7 +262,11 @@ class TimelinePresenterTest {
|
|||
@Test
|
||||
fun `present - PollAnswerSelected event calls into rust room api and analytics`() = runTest {
|
||||
val room = FakeMatrixRoom()
|
||||
val presenter = createTimelinePresenter(room)
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val presenter = createTimelinePresenter(
|
||||
room = room,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -271,7 +277,8 @@ class TimelinePresenterTest {
|
|||
assertThat(room.sendPollResponseInvocations.size).isEqualTo(1)
|
||||
assertThat(room.sendPollResponseInvocations.first().answers).isEqualTo(listOf("anAnswerId"))
|
||||
assertThat(room.sendPollResponseInvocations.first().pollStartId).isEqualTo(AN_EVENT_ID)
|
||||
// TODO Polls: Test poll vote analytic
|
||||
assertThat(analyticsService.capturedEvents.size).isEqualTo(1)
|
||||
assertThat(analyticsService.capturedEvents.last()).isEqualTo(PollVote())
|
||||
}
|
||||
|
||||
private fun TestScope.createTimelinePresenter(
|
||||
|
|
@ -282,18 +289,21 @@ class TimelinePresenterTest {
|
|||
timelineItemsFactory = timelineItemsFactory,
|
||||
room = FakeMatrixRoom(matrixTimeline = timeline),
|
||||
dispatchers = testCoroutineDispatchers(),
|
||||
appScope = this
|
||||
appScope = this,
|
||||
analyticsService = FakeAnalyticsService(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun TestScope.createTimelinePresenter(
|
||||
room: MatrixRoom,
|
||||
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
|
||||
): TimelinePresenter {
|
||||
return TimelinePresenter(
|
||||
timelineItemsFactory = aTimelineItemsFactory(),
|
||||
room = room,
|
||||
dispatchers = testCoroutineDispatchers(),
|
||||
appScope = this
|
||||
appScope = this,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue