From 89657e0a35831f717dc34e42093b2d6c5c12d8c4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 16 Mar 2023 15:06:04 +0100 Subject: [PATCH] Add `:services:analytics` modules. For now import the current plan. This will allow to import existing class from EA and not break compatibility with existing analytics call. --- .../kotlin/extension/DependencyHandleScope.kt | 1 + services/analytics/api/build.gradle.kts | 27 + .../analytics/api/AnalyticsTracker.kt | 36 ++ .../analytics/api/VectorAnalyticsEvent.kt | 22 + .../analytics/api/VectorAnalyticsScreen.kt | 22 + .../services/analytics/api/plan/CallEnded.kt | 56 +++ .../services/analytics/api/plan/CallError.kt | 51 ++ .../analytics/api/plan/CallStarted.kt | 51 ++ .../services/analytics/api/plan/Composer.kt | 58 +++ .../analytics/api/plan/CreatedRoom.kt | 41 ++ .../services/analytics/api/plan/Error.kt | 82 +++ .../analytics/api/plan/Interaction.kt | 468 ++++++++++++++++++ .../services/analytics/api/plan/JoinedRoom.kt | 107 ++++ .../analytics/api/plan/MobileScreen.kt | 327 ++++++++++++ .../analytics/api/plan/PerformanceTimer.kt | 109 ++++ .../analytics/api/plan/PermissionChanged.kt | 53 ++ .../services/analytics/api/plan/Signup.kt | 84 ++++ .../analytics/api/plan/SlashCommand.kt | 46 ++ .../api/plan/UnauthenticatedError.kt | 66 +++ .../analytics/api/plan/UserProperties.kt | 98 ++++ .../services/analytics/api/plan/ViewRoom.kt | 306 ++++++++++++ services/analytics/noop/build.gradle.kts | 34 ++ .../analytics/noop/NoopAnalyticsTracker.kt | 35 ++ settings.gradle.kts | 2 + 24 files changed, 2182 insertions(+) create mode 100644 services/analytics/api/build.gradle.kts create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsTracker.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/VectorAnalyticsEvent.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/VectorAnalyticsScreen.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallEnded.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallError.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallStarted.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Composer.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CreatedRoom.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Error.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Interaction.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/JoinedRoom.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/MobileScreen.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/PerformanceTimer.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/PermissionChanged.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Signup.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/SlashCommand.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/UnauthenticatedError.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/UserProperties.kt create mode 100644 services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/ViewRoom.kt create mode 100644 services/analytics/noop/build.gradle.kts create mode 100644 services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsTracker.kt diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 3d134bcab4..1474ab72d2 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -66,6 +66,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { fun DependencyHandlerScope.allServicesImpl() { implementation(project(":services:appnavstate:impl")) + implementation(project(":services:analytics:noop")) } fun DependencyHandlerScope.allFeaturesApi() { diff --git a/services/analytics/api/build.gradle.kts b/services/analytics/api/build.gradle.kts new file mode 100644 index 0000000000..b82dbabf93 --- /dev/null +++ b/services/analytics/api/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.services.analytics.api" +} + +dependencies { + // implementation(libs.coroutines.core) +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsTracker.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsTracker.kt new file mode 100644 index 0000000000..90c2b5cfd4 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsTracker.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api + +import io.element.android.services.analytics.api.plan.UserProperties + +interface AnalyticsTracker { + /** + * Capture an Event. + */ + fun capture(event: VectorAnalyticsEvent) + + /** + * Track a displayed screen. + */ + fun screen(screen: VectorAnalyticsScreen) + + /** + * Update user specific properties. + */ + fun updateUserProperties(userProperties: UserProperties) +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/VectorAnalyticsEvent.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/VectorAnalyticsEvent.kt new file mode 100644 index 0000000000..49534505c5 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/VectorAnalyticsEvent.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api + +interface VectorAnalyticsEvent { + fun getName(): String + fun getProperties(): Map? +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/VectorAnalyticsScreen.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/VectorAnalyticsScreen.kt new file mode 100644 index 0000000000..7720158e20 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/VectorAnalyticsScreen.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api + +interface VectorAnalyticsScreen { + fun getName(): String + fun getProperties(): Map? +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallEnded.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallEnded.kt new file mode 100644 index 0000000000..63adbaff12 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallEnded.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when a call has ended. + */ +data class CallEnded( + /** + * The duration of the call in milliseconds. + */ + val durationMs: Int, + /** + * Whether its a video call or not. + */ + val isVideo: Boolean, + /** + * Number of participants in the call. + */ + val numParticipants: Int, + /** + * Whether this user placed it. + */ + val placed: Boolean, +) : VectorAnalyticsEvent { + + override fun getName() = "CallEnded" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("durationMs", durationMs) + put("isVideo", isVideo) + put("numParticipants", numParticipants) + put("placed", placed) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallError.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallError.kt new file mode 100644 index 0000000000..10225e25c2 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallError.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when an error occurred in a call. + */ +data class CallError( + /** + * Whether its a video call or not. + */ + val isVideo: Boolean, + /** + * Number of participants in the call. + */ + val numParticipants: Int, + /** + * Whether this user placed it. + */ + val placed: Boolean, +) : VectorAnalyticsEvent { + + override fun getName() = "CallError" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("isVideo", isVideo) + put("numParticipants", numParticipants) + put("placed", placed) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallStarted.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallStarted.kt new file mode 100644 index 0000000000..1ee9db0d1b --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CallStarted.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when a call is started. + */ +data class CallStarted( + /** + * Whether its a video call or not. + */ + val isVideo: Boolean, + /** + * Number of participants in the call. + */ + val numParticipants: Int, + /** + * Whether this user placed it. + */ + val placed: Boolean, +) : VectorAnalyticsEvent { + + override fun getName() = "CallStarted" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("isVideo", isVideo) + put("numParticipants", numParticipants) + put("placed", placed) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Composer.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Composer.kt new file mode 100644 index 0000000000..00a827a166 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Composer.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user sends a message via the composer. + */ +data class Composer( + /** + * Whether the user was using the composer inside of a thread. + */ + val inThread: Boolean, + /** + * Whether the user's composer interaction was editing a previously sent + * event. + */ + val isEditing: Boolean, + /** + * Whether the user's composer interaction was a reply to a previously + * sent event. + */ + val isReply: Boolean, + /** + * Whether this message begins a new thread or not. + */ + val startsThread: Boolean? = null, +) : VectorAnalyticsEvent { + + override fun getName() = "Composer" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("inThread", inThread) + put("isEditing", isEditing) + put("isReply", isReply) + startsThread?.let { put("startsThread", it) } + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CreatedRoom.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CreatedRoom.kt new file mode 100644 index 0000000000..1112e732ed --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/CreatedRoom.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user creates a room. + */ +data class CreatedRoom( + /** + * Whether the room is a DM. + */ + val isDM: Boolean, +) : VectorAnalyticsEvent { + + override fun getName() = "CreatedRoom" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("isDM", isDM) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Error.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Error.kt new file mode 100644 index 0000000000..a10fc46ced --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Error.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when an error occurred. + */ +data class Error( + /** + * Context - client defined, can be used for debugging. + */ + val context: String? = null, + /** + * Which crypto module is the client currently using. + */ + val cryptoModule: CryptoModule? = null, + val domain: Domain, + val name: Name, +) : VectorAnalyticsEvent { + + enum class Domain { + E2EE, + TO_DEVICE, + VOIP, + } + + enum class Name { + OlmIndexError, + OlmKeysNotSentError, + OlmUnspecifiedError, + ToDeviceFailedToDecrypt, + UnknownError, + VoipIceFailed, + VoipIceTimeout, + VoipInviteTimeout, + VoipUserHangup, + VoipUserMediaFailed, + } + + enum class CryptoModule { + + /** + * Native / legacy crypto module specific to each platform. + */ + Native, + + /** + * Shared / cross-platform crypto module written in Rust. + */ + Rust, + } + + override fun getName() = "Error" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + context?.let { put("context", it) } + cryptoModule?.let { put("cryptoModule", it.name) } + put("domain", domain.name) + put("name", name.name) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Interaction.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Interaction.kt new file mode 100644 index 0000000000..f0d0a47d85 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Interaction.kt @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user clicks/taps/activates a UI element. + */ +data class Interaction( + /** + * The index of the element, if its in a list of elements. + */ + val index: Int? = null, + /** + * The manner with which the user activated the UI element. + */ + val interactionType: InteractionType? = null, + /** + * The unique name of this element. + */ + val name: Name, +) : VectorAnalyticsEvent { + + enum class Name { + /** + * User tapped the All filter in the All Chats filter tab. + */ + MobileAllChatsFilterAll, + + /** + * User tapped the Favourites filter in the All Chats filter tab. + */ + MobileAllChatsFilterFavourites, + + /** + * User tapped the People filter in the All Chats filter tab. + */ + MobileAllChatsFilterPeople, + + /** + * User tapped the Unreads filter in the All Chats filter tab. + */ + MobileAllChatsFilterUnreads, + + /** + * User disabled filters from the all chats layout settings. + */ + MobileAllChatsFiltersDisabled, + + /** + * User enabled filters from the all chats layout settings. + */ + MobileAllChatsFiltersEnabled, + + /** + * User disabled recents from the all chats layout settings. + */ + MobileAllChatsRecentsDisabled, + + /** + * User enabled recents from the all chats layout settings. + */ + MobileAllChatsRecentsEnabled, + + /** + * User tapped on Add to Home button on Room Details screen. + */ + MobileRoomAddHome, + + /** + * User tapped on Leave Room button on Room Details screen. + */ + MobileRoomLeave, + + /** + * User tapped on Threads button on Room screen. + */ + MobileRoomThreadListButton, + + /** + * User tapped on a thread summary item on Room screen. + */ + MobileRoomThreadSummaryItem, + + /** + * User validated the creation of a new space. + */ + MobileSpaceCreationValidated, + + /** + * User tapped on the filter button on ThreadList screen. + */ + MobileThreadListFilterItem, + + /** + * User selected a thread on ThreadList screen. + */ + MobileThreadListThreadItem, + + /** + * User tapped the already selected space from the space list. + */ + SpacePanelSelectedSpace, + + /** + * User tapped an unselected space from the space list -> space + * switching should occur. + */ + SpacePanelSwitchSpace, + + /** + * User tapped an unselected sub space from the space list -> space + * switching should occur. + */ + SpacePanelSwitchSubSpace, + + /** + * User clicked the create room button in the add existing room to space + * dialog in Element Web/Desktop. + */ + WebAddExistingToSpaceDialogCreateRoomButton, + + /** + * User clicked the create DM button in the home page of Element + * Web/Desktop. + */ + WebHomeCreateChatButton, + + /** + * User clicked the create room button in the home page of Element + * Web/Desktop. + */ + WebHomeCreateRoomButton, + + /** + * User clicked the explore rooms button in the home page of Element + * Web/Desktop. + */ + WebHomeExploreRoomsButton, + + /** + * User clicked on the mini avatar uploader in the home page of Element + * Web/Desktop. + */ + WebHomeMiniAvatarUploadButton, + + /** + * User clicked the explore rooms button next to the search field at the + * top of the left panel in Element Web/Desktop. + */ + WebLeftPanelExploreRoomsButton, + + /** + * User clicked on the avatar uploader in the profile settings of + * Element Web/Desktop. + */ + WebProfileSettingsAvatarUploadButton, + + /** + * User interacted with pin to sidebar checkboxes in the quick settings + * menu of Element Web/Desktop. + */ + WebQuickSettingsPinToSidebarCheckbox, + + /** + * User interacted with the theme dropdown in the quick settings menu of + * Element Web/Desktop. + */ + WebQuickSettingsThemeDropdown, + + /** + * User accessed the room invite flow using the button at the top of the + * room member list in the right panel of Element Web/Desktop. + */ + WebRightPanelMemberListInviteButton, + + /** + * User accessed room member list using the 'People' button in the right + * panel room summary card of Element Web/Desktop. + */ + WebRightPanelRoomInfoPeopleButton, + + /** + * User accessed room settings using the 'Settings' button in the right + * panel room summary card of Element Web/Desktop. + */ + WebRightPanelRoomInfoSettingsButton, + + /** + * User accessed room member list using the back button in the right + * panel user info card of Element Web/Desktop. + */ + WebRightPanelRoomUserInfoBackButton, + + /** + * User invited someone to room by clicking invite on the right panel + * user info card in Element Web/Desktop. + */ + WebRightPanelRoomUserInfoInviteButton, + + /** + * User clicked the threads 'show' filter dropdown in the threads panel + * in Element Web/Desktop. + */ + WebRightPanelThreadPanelFilterDropdown, + + /** + * User clicked the create room button in the room directory of Element + * Web/Desktop. + */ + WebRoomDirectoryCreateRoomButton, + + /** + * User clicked the Threads button in the top right of a room in Element + * Web/Desktop. + */ + WebRoomHeaderButtonsThreadsButton, + + /** + * User adjusted their favourites using the context menu on the header + * of a room in Element Web/Desktop. + */ + WebRoomHeaderContextMenuFavouriteToggle, + + /** + * User accessed the room invite flow using the context menu on the + * header of a room in Element Web/Desktop. + */ + WebRoomHeaderContextMenuInviteItem, + + /** + * User interacted with leave action in the context menu on the header + * of a room in Element Web/Desktop. + */ + WebRoomHeaderContextMenuLeaveItem, + + /** + * User accessed their room notification settings via the context menu + * on the header of a room in Element Web/Desktop. + */ + WebRoomHeaderContextMenuNotificationsItem, + + /** + * User accessed room member list using the context menu on the header + * of a room in Element Web/Desktop. + */ + WebRoomHeaderContextMenuPeopleItem, + + /** + * User accessed room settings using the context menu on the header of a + * room in Element Web/Desktop. + */ + WebRoomHeaderContextMenuSettingsItem, + + /** + * User clicked the create DM button in the + context menu of the room + * list header in Element Web/Desktop. + */ + WebRoomListHeaderPlusMenuCreateChatItem, + + /** + * User clicked the create room button in the + context menu of the room + * list header in Element Web/Desktop. + */ + WebRoomListHeaderPlusMenuCreateRoomItem, + + /** + * User clicked the explore rooms button in the + context menu of the + * room list header in Element Web/Desktop. + */ + WebRoomListHeaderPlusMenuExploreRoomsItem, + + /** + * User adjusted their favourites using the context menu on a room tile + * in the room list in Element Web/Desktop. + */ + WebRoomListRoomTileContextMenuFavouriteToggle, + + /** + * User accessed the room invite flow using the context menu on a room + * tile in the room list in Element Web/Desktop. + */ + WebRoomListRoomTileContextMenuInviteItem, + + /** + * User interacted with leave action in the context menu on a room tile + * in the room list in Element Web/Desktop. + */ + WebRoomListRoomTileContextMenuLeaveItem, + + /** + * User accessed room settings using the context menu on a room tile in + * the room list in Element Web/Desktop. + */ + WebRoomListRoomTileContextMenuSettingsItem, + + /** + * User accessed their room notification settings via the context menu + * on a room tile in the room list in Element Web/Desktop. + */ + WebRoomListRoomTileNotificationsMenu, + + /** + * User clicked the create DM button in the + context menu of the rooms + * sublist in Element Web/Desktop. + */ + WebRoomListRoomsSublistPlusMenuCreateChatItem, + + /** + * User clicked the create room button in the + context menu of the + * rooms sublist in Element Web/Desktop. + */ + WebRoomListRoomsSublistPlusMenuCreateRoomItem, + + /** + * User clicked the explore rooms button in the + context menu of the + * rooms sublist in Element Web/Desktop. + */ + WebRoomListRoomsSublistPlusMenuExploreRoomsItem, + + /** + * User clicked on the button to return to the user onboarding list in + * the room list in Element Web/Desktop. + */ + WebRoomListUserOnboardingButton, + + /** + * User clicked on the button to close the user onboarding button in the + * room list in Element Web/Desktop. + */ + WebRoomListUserOnboardingIgnoreButton, + + /** + * User interacted with leave action in the general tab of the room + * settings dialog in Element Web/Desktop. + */ + WebRoomSettingsLeaveButton, + + /** + * User interacted with the prompt to create a new room when adjusting + * security settings in an existing room in Element Web/Desktop. + */ + WebRoomSettingsSecurityTabCreateNewRoomButton, + + /** + * User clicked a thread summary in the timeline of a room in Element + * Web/Desktop. + */ + WebRoomTimelineThreadSummaryButton, + + /** + * User interacted with the theme radio selector in the Appearance tab + * of Settings in Element Web/Desktop. + */ + WebSettingsAppearanceTabThemeSelector, + + /** + * User interacted with the pre-built space checkboxes in the Sidebar + * tab of Settings in Element Web/Desktop. + */ + WebSettingsSidebarTabSpacesCheckbox, + + /** + * User clicked the explore rooms button in the context menu of a space + * in Element Web/Desktop. + */ + WebSpaceContextMenuExploreRoomsItem, + + /** + * User clicked the home button in the context menu of a space in + * Element Web/Desktop. + */ + WebSpaceContextMenuHomeItem, + + /** + * User clicked the new room button in the context menu of a space in + * Element Web/Desktop. + */ + WebSpaceContextMenuNewRoomItem, + + /** + * User clicked the new room button in the context menu on the space + * home in Element Web/Desktop. + */ + WebSpaceHomeCreateRoomButton, + + /** + * User clicked the back button on a Thread view going back to the + * Threads Panel of Element Web/Desktop. + */ + WebThreadViewBackButton, + + /** + * User selected a thread in the Threads panel in Element Web/Desktop. + */ + WebThreadsPanelThreadItem, + + /** + * User clicked the theme toggle button in the user menu of Element + * Web/Desktop. + */ + WebUserMenuThemeToggleButton, + + /** + * User clicked on the send DM CTA in the header of the new user + * onboarding page in Element Web/Desktop. + */ + WebUserOnboardingHeaderSendDm, + + /** + * User clicked on the action of the download apps task on the new user + * onboarding page in Element Web/Desktop. + */ + WebUserOnboardingTaskDownloadApps, + + /** + * User clicked on the action of the enable notifications task on the + * new user onboarding page in Element Web/Desktop. + */ + WebUserOnboardingTaskEnableNotifications, + + /** + * User clicked on the action of the find people task on the new user + * onboarding page in Element Web/Desktop. + */ + WebUserOnboardingTaskSendDm, + + /** + * User clicked on the action of the your profile task on the new user + * onboarding page in Element Web/Desktop. + */ + WebUserOnboardingTaskSetupProfile, + } + + enum class InteractionType { + Keyboard, + Pointer, + Touch, + } + + override fun getName() = "Interaction" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + index?.let { put("index", it) } + interactionType?.let { put("interactionType", it.name) } + put("name", name.name) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/JoinedRoom.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/JoinedRoom.kt new file mode 100644 index 0000000000..d7c86629c7 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/JoinedRoom.kt @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user joins a room. + */ +data class JoinedRoom( + /** + * Whether the room is a DM. + */ + val isDM: Boolean, + /** + * Whether the room is a Space. + */ + val isSpace: Boolean, + /** + * The size of the room. + */ + val roomSize: RoomSize, + /** + * The trigger for a room being joined if known. + */ + val trigger: Trigger? = null, +) : VectorAnalyticsEvent { + + enum class Trigger { + /** + * Room joined via an invite. + */ + Invite, + + /** + * Room joined via link. + */ + MobilePermalink, + + /** + * Room joined via a push/desktop notification. + */ + Notification, + + /** + * Room joined via the public rooms directory. + */ + RoomDirectory, + + /** + * Room joined via its preview. + */ + RoomPreview, + + /** + * Room joined via the /join slash command. + */ + SlashCommand, + + /** + * Room joined via the space hierarchy view. + */ + SpaceHierarchy, + + /** + * Room joined via a timeline pill or link in another room. + */ + Timeline, + } + + enum class RoomSize { + ElevenToOneHundred, + MoreThanAThousand, + One, + OneHundredAndOneToAThousand, + ThreeToTen, + Two, + } + + override fun getName() = "JoinedRoom" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("isDM", isDM) + put("isSpace", isSpace) + put("roomSize", roomSize.name) + trigger?.let { put("trigger", it.name) } + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/MobileScreen.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/MobileScreen.kt new file mode 100644 index 0000000000..69e637b01e --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/MobileScreen.kt @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsScreen + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user changed screen on Element Android/iOS. + */ +data class MobileScreen( + /** + * How long the screen was displayed for in milliseconds. + */ + val durationMs: Int? = null, + val screenName: ScreenName, +) : VectorAnalyticsScreen { + + enum class ScreenName { + /** + * The screen that displays the user's breadcrumbs. + */ + Breadcrumbs, + + /** + * The screen shown to create a new (non-direct) room. + */ + CreateRoom, + + /** + * The screen shown to create a new space. + */ + CreateSpace, + + /** + * The confirmation screen shown before deactivating an account. + */ + DeactivateAccount, + + /** + * The tab on mobile that displays the dialpad. + */ + Dialpad, + + /** + * The Favourites tab on mobile that lists your favourite people/rooms. + */ + Favourites, + + /** + * The form for the forgot password use case. + */ + ForgotPassword, + + /** + * Legacy: The screen that shows information about a specific group. + */ + Group, + + /** + * The Home tab on iOS | possibly the same on Android? + */ + Home, + + /** + * The screen shown to share a link to download the app. + */ + InviteFriends, + + /** + * Room accessed via space bottom sheet list. + */ + Invites, + + /** + * The screen that displays the login flow (when the user already has an + * account). + */ + Login, + + /** + * Legacy: The screen that shows all groups/communities you have joined. + */ + MyGroups, + + /** + * The People tab on mobile that lists all the DM rooms you have joined. + */ + People, + + /** + * The screen that displays the registration flow (when the user wants + * to create an account). + */ + Register, + + /** + * The screen that displays the messages and events received in a room. + */ + Room, + + /** + * The room addresses screen shown from the Room Details screen. + */ + RoomAddresses, + + /** + * The screen shown when tapping the name of a room from the Room + * screen. + */ + RoomDetails, + + /** + * The screen that lists public rooms for you to discover. + */ + RoomDirectory, + + /** + * The screen that lists all the user's rooms and let them filter the + * rooms. + */ + RoomFilter, + + /** + * The screen that displays the list of members that are part of a room. + */ + RoomMembers, + + /** + * The notifications settings screen shown from the Room Details screen. + */ + RoomNotifications, + + /** + * The roles permissions screen shown from the Room Details screen. + */ + RoomPermissions, + + /** + * Screen that displays room preview if user hasn't joined yet. + */ + RoomPreview, + + /** + * The screen that allows you to search for messages/files in a specific + * room. + */ + RoomSearch, + + /** + * The settings screen shown from the Room Details screen. + */ + RoomSettings, + + /** + * The screen that allows you to see all of the files sent in a specific + * room. + */ + RoomUploads, + + /** + * The Rooms tab on mobile that lists all the (non-direct) rooms you've + * joined. + */ + Rooms, + + /** + * The Files tab shown in the global search screen on Mobile. + */ + SearchFiles, + + /** + * The Messages tab shown in the global search screen on Mobile. + */ + SearchMessages, + + /** + * The People tab shown in the global search screen on Mobile. + */ + SearchPeople, + + /** + * The Rooms tab shown in the global search screen on Mobile. + */ + SearchRooms, + + /** + * The global settings screen shown in the app. + */ + Settings, + + /** + * The advanced settings screen (developer mode, rageshake, push + * notification rules). + */ + SettingsAdvanced, + + /** + * The settings screen to change the default notification options. + */ + SettingsDefaultNotifications, + + /** + * The settings screen with general profile settings. + */ + SettingsGeneral, + + /** + * The Help and About screen. + */ + SettingsHelp, + + /** + * The settings screen with list of the ignored users. + */ + SettingsIgnoredUsers, + + /** + * The experimental features settings screen. + */ + SettingsLabs, + + /** + * The settings screen with legals information. + */ + SettingsLegals, + + /** + * The settings screen to manage notification mentions and keywords. + */ + SettingsMentionsAndKeywords, + + /** + * The notifications settings screen. + */ + SettingsNotifications, + + /** + * The preferences screen (theme, language, editor preferences, etc. + */ + SettingsPreferences, + + /** + * The global security settings screen. + */ + SettingsSecurity, + + /** + * The calls settings screen. + */ + SettingsVoiceVideo, + + /** + * The sidebar shown on mobile with spaces, settings etc. + */ + Sidebar, + + /** + * Room accessed via space bottom sheet list. + */ + SpaceBottomSheet, + + /** + * Screen that displays the list of rooms and spaces of a space. + */ + SpaceExploreRooms, + + /** + * Screen that displays the list of members of a space. + */ + SpaceMembers, + + /** + * The bottom sheet that list all space options. + */ + SpaceMenu, + + /** + * The screen shown to create a new direct room. + */ + StartChat, + + /** + * The screen shown to select which room directory you'd like to use. + */ + SwitchDirectory, + + /** + * Screen that displays list of threads for a room. + */ + ThreadList, + + /** + * A screen that shows information about a room member. + */ + User, + + /** + * The splash screen. + */ + Welcome, + } + + override fun getName() = screenName.name + + override fun getProperties(): Map? { + return mutableMapOf().apply { + durationMs?.let { put("durationMs", it) } + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/PerformanceTimer.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/PerformanceTimer.kt new file mode 100644 index 0000000000..8296ae783f --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/PerformanceTimer.kt @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered after timing an operation in the app. + */ +data class PerformanceTimer( + /** + * Client defined, can be used for debugging. + */ + val context: String? = null, + /** + * Client defined, an optional value to indicate how many items were + * handled during the operation. + */ + val itemCount: Int? = null, + /** + * The timer that is being reported. + */ + val name: Name, + /** + * The time reported by the timer in milliseconds. + */ + val timeMs: Int, +) : VectorAnalyticsEvent { + + enum class Name { + /** + * The time spent parsing the response from an initial /sync request. In + * this case, `itemCount` should contain the number of joined rooms. + */ + InitialSyncParsing, + + /** + * The time spent waiting for a response to an initial /sync request. In + * this case, `itemCount` should contain the number of joined rooms. + */ + InitialSyncRequest, + + /** + * The time taken to display an event in the timeline that was opened + * from a notification. + */ + NotificationsOpenEvent, + + /** + * The duration of a regular /sync request when resuming the app. In + * this case, `itemCount` should contain the number of joined rooms in + * the response. + */ + StartupIncrementalSync, + + /** + * The duration of an initial /sync request during startup (if the store + * has been wiped). In this case, `itemCount` should contain the number + * of joined rooms. + */ + StartupInitialSync, + + /** + * How long the app launch screen is displayed for. + */ + StartupLaunchScreen, + + /** + * The time to preload data in the MXStore on iOS. In this case, + * `itemCount` should contain the number of rooms in the store. + */ + StartupStorePreload, + + /** + * The time to load all data from the store (including + * StartupStorePreload time). In this case, `itemCount` should contain + * the number of rooms loaded into the session + */ + StartupStoreReady, + } + + override fun getName() = "PerformanceTimer" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + context?.let { put("context", it) } + itemCount?.let { put("itemCount", it) } + put("name", name.name) + put("timeMs", timeMs) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/PermissionChanged.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/PermissionChanged.kt new file mode 100644 index 0000000000..9f93078f26 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/PermissionChanged.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user changes a permission status. + */ +data class PermissionChanged( + /** + * Whether the permission has been granted by the user. + */ + val granted: Boolean, + /** + * The name of the permission. + */ + val permission: Permission, +) : VectorAnalyticsEvent { + + enum class Permission { + /** + * Permissions related to sending notifications have changed. + */ + Notification, + } + + override fun getName() = "PermissionChanged" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("granted", granted) + put("permission", permission.name) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Signup.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Signup.kt new file mode 100644 index 0000000000..00b7ef7b60 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/Signup.kt @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered once onboarding has completed, but only if the user registered a + * new account. + */ +data class Signup( + /** + * The type of authentication that was used to sign up. + */ + val authenticationType: AuthenticationType, +) : VectorAnalyticsEvent { + + enum class AuthenticationType { + /** + * Social login using Apple. + */ + Apple, + + /** + * Social login using Facebook. + */ + Facebook, + + /** + * Social login using GitHub. + */ + GitHub, + + /** + * Social login using GitLab. + */ + GitLab, + + /** + * Social login using Google. + */ + Google, + + /** + * Registration using some other mechanism such as fallback. + */ + Other, + + /** + * Registration with a username and password. + */ + Password, + + /** + * Registration using another SSO provider. + */ + SSO, + } + + override fun getName() = "Signup" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("authenticationType", authenticationType.name) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/SlashCommand.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/SlashCommand.kt new file mode 100644 index 0000000000..de0af607b0 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/SlashCommand.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user runs a slash command in their composer. + */ +data class SlashCommand( + /** + * The name of this command. + */ + val command: Command, +) : VectorAnalyticsEvent { + + enum class Command { + Invite, + Part, + } + + override fun getName() = "SlashCommand" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("command", command.name) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/UnauthenticatedError.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/UnauthenticatedError.kt new file mode 100644 index 0000000000..e235fa994c --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/UnauthenticatedError.kt @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user becomes unauthenticated without actually clicking + * sign out(E.g. Due to expiry of an access token without a way to refresh). + */ +data class UnauthenticatedError( + /** + * The error code as defined in matrix spec. The source of this error is + * from the homeserver. + */ + val errorCode: ErrorCode, + /** + * The reason for the error. The source of this error is from the + * homeserver, the reason can vary and is subject to change so there is + * no enum of possible values. + */ + val errorReason: String, + /** + * Whether the auth mechanism is refresh-token-based. + */ + val refreshTokenAuth: Boolean, + /** + * Whether a soft logout or hard logout was triggered. + */ + val softLogout: Boolean, +) : VectorAnalyticsEvent { + + enum class ErrorCode { + M_FORBIDDEN, + M_UNKNOWN, + M_UNKNOWN_TOKEN, + } + + override fun getName() = "UnauthenticatedError" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + put("errorCode", errorCode.name) + put("errorReason", errorReason) + put("refreshTokenAuth", refreshTokenAuth) + put("softLogout", softLogout) + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/UserProperties.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/UserProperties.kt new file mode 100644 index 0000000000..cd72f05af1 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/UserProperties.kt @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * The user properties to apply when identifying. This is not an event + * definition. These properties must all be device independent. + */ +data class UserProperties( + /** + * The active filter in the All Chats screen. + */ + val allChatsActiveFilter: AllChatsActiveFilter? = null, + /** + * The selected messaging use case during the onboarding flow. + */ + val ftueUseCaseSelection: FtueUseCaseSelection? = null, + /** + * Number of joined rooms the user has favourited. + */ + val numFavouriteRooms: Int? = null, + /** + * Number of spaces (and sub-spaces) the user is joined to. + */ + val numSpaces: Int? = null, +) { + + enum class FtueUseCaseSelection { + /** + * The third option, Communities. + */ + CommunityMessaging, + + /** + * The first option, Friends and family. + */ + PersonalMessaging, + + /** + * The footer option to skip the question. + */ + Skip, + + /** + * The second option, Teams. + */ + WorkMessaging, + } + + enum class AllChatsActiveFilter { + + /** + * Filters are activated and All is selected. + */ + All, + + /** + * Filters are activated and Favourites is selected. + */ + Favourites, + + /** + * Filters are activated and People is selected. + */ + People, + + /** + * Filters are activated and Unreads is selected. + */ + Unreads, + } + + fun getProperties(): Map? { + return mutableMapOf().apply { + allChatsActiveFilter?.let { put("allChatsActiveFilter", it.name) } + ftueUseCaseSelection?.let { put("ftueUseCaseSelection", it.name) } + numFavouriteRooms?.let { put("numFavouriteRooms", it) } + numSpaces?.let { put("numSpaces", it) } + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/ViewRoom.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/ViewRoom.kt new file mode 100644 index 0000000000..7477b83b13 --- /dev/null +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/plan/ViewRoom.kt @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.api.plan + +import io.element.android.services.analytics.api.VectorAnalyticsEvent + +// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT +// https://github.com/matrix-org/matrix-analytics-events/ + +/** + * Triggered when the user changes rooms. + */ +data class ViewRoom( + /** + * active space when user navigated to the room. + */ + val activeSpace: ActiveSpace? = null, + /** + * Whether the room is a DM. + */ + val isDM: Boolean? = null, + /** + * Whether the room is a Space. + */ + val isSpace: Boolean? = null, + /** + * The reason for the room change if known. + */ + val trigger: Trigger? = null, + /** + * Whether the interaction was performed via the keyboard input. + */ + val viaKeyboard: Boolean? = null, +) : VectorAnalyticsEvent { + + enum class Trigger { + /** + * Room accessed due to being just created. + */ + Created, + + /** + * Room switched due to user interacting with a message search result. + */ + MessageSearch, + + /** + * Room switched due to user selecting a user to go to a DM with. + */ + MessageUser, + + /** + * Room accessed via space explore. + */ + MobileExploreRooms, + + /** + * Room switched due to user interacting with a file search result. + */ + MobileFileSearch, + + /** + * Room accessed via interacting with the incall screen. + */ + MobileInCall, + + /** + * Room accessed during external sharing. + */ + MobileLinkShare, + + /** + * Room accessed via link. + */ + MobilePermalink, + + /** + * Room accessed via interacting with direct chat item in the room + * contact detail screen. + */ + MobileRoomMemberDetail, + + /** + * Room accessed via preview. + */ + MobileRoomPreview, + + /** + * Room switched due to user interacting with a room search result. + */ + MobileRoomSearch, + + /** + * Room accessed via interacting with direct chat item in the search + * contact detail screen. + */ + MobileSearchContactDetail, + + /** + * Room accessed via space bottom sheet list. + */ + MobileSpaceBottomSheet, + + /** + * Room accessed via interacting with direct chat item in the space + * contact detail screen. + */ + MobileSpaceMemberDetail, + + /** + * Room accessed via space members list. + */ + MobileSpaceMembers, + + /** + * Space accessed via interacting with the space menu. + */ + MobileSpaceMenu, + + /** + * Space accessed via interacting with a space settings menu item. + */ + MobileSpaceSettings, + + /** + * Room accessed via a push/desktop notification. + */ + Notification, + + /** + * Room accessed via the predecessor link at the top of the upgraded + * room. + */ + Predecessor, + + /** + * Room accessed via the public rooms directory. + */ + RoomDirectory, + + /** + * Room accessed via the room list. + */ + RoomList, + + /** + * Room accessed via a shortcut. + */ + Shortcut, + + /** + * Room accessed via a slash command in Element Web/Desktop like /goto. + */ + SlashCommand, + + /** + * Room accessed via the space hierarchy view. + */ + SpaceHierarchy, + + /** + * Room accessed via a timeline pill or link in another room. + */ + Timeline, + + /** + * Room accessed via a tombstone at the bottom of a predecessor room. + */ + Tombstone, + + /** + * Room switched due to user interacting with incoming verification + * request. + */ + VerificationRequest, + + /** + * Room switched due to accepting a call in a different room in Element + * Web/Desktop. + */ + WebAcceptCall, + + /** + * Room switched due to making a call via the dial pad in Element + * Web/Desktop. + */ + WebDialPad, + + /** + * Room accessed via interacting with the floating call or Jitsi PIP in + * Element Web/Desktop. + */ + WebFloatingCallWindow, + + /** + * Room accessed via the shortcut in Element Web/Desktop's forward + * modal. + */ + WebForwardShortcut, + + /** + * Room accessed via the Element Web/Desktop horizontal breadcrumbs at + * the top of the room list. + */ + WebHorizontalBreadcrumbs, + + /** + * Room accessed via an Element Web/Desktop keyboard shortcut like go to + * next room with unread messages. + */ + WebKeyboardShortcut, + + /** + * Room accessed via Element Web/Desktop's notification panel. + */ + WebNotificationPanel, + + /** + * Room accessed via the predecessor link in Settings > Advanced in + * Element Web/Desktop. + */ + WebPredecessorSettings, + + /** + * Room accessed via clicking on a notifications badge on a room list + * sublist in Element Web/Desktop. + */ + WebRoomListNotificationBadge, + + /** + * Room switched due to the user changing space in Element Web/Desktop. + */ + WebSpaceContextSwitch, + + /** + * Room accessed via clicking on the notifications badge on the + * currently selected space in Element Web/Desktop. + */ + WebSpacePanelNotificationBadge, + + /** + * Room accessed via Element Web/Desktop's Unified Search modal. + */ + WebUnifiedSearch, + + /** + * Room accessed via the Element Web/Desktop vertical breadcrumb hover + * menu. + */ + WebVerticalBreadcrumbs, + + /** + * Room switched due to widget interaction. + */ + Widget, + } + + enum class ActiveSpace { + + /** + * Active space is Home. + */ + Home, + + /** + * Active space is a meta space. + */ + Meta, + + /** + * Active space is a private space. + */ + Private, + + /** + * Active space is a public space. + */ + Public, + } + + override fun getName() = "ViewRoom" + + override fun getProperties(): Map? { + return mutableMapOf().apply { + activeSpace?.let { put("activeSpace", it.name) } + isDM?.let { put("isDM", it) } + isSpace?.let { put("isSpace", it) } + trigger?.let { put("trigger", it.name) } + viaKeyboard?.let { put("viaKeyboard", it) } + }.takeIf { it.isNotEmpty() } + } +} diff --git a/services/analytics/noop/build.gradle.kts b/services/analytics/noop/build.gradle.kts new file mode 100644 index 0000000000..fca489c3d3 --- /dev/null +++ b/services/analytics/noop/build.gradle.kts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-library") + alias(libs.plugins.anvil) +} + +android { + namespace = "io.element.android.services.analytics.impl" +} + +anvil { + generateDaggerFactories.set(true) +} + +dependencies { + implementation(libs.dagger) + implementation(projects.libraries.di) + api(projects.services.analytics.api) +} diff --git a/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsTracker.kt b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsTracker.kt new file mode 100644 index 0000000000..1448a06591 --- /dev/null +++ b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsTracker.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.noop + +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.services.analytics.api.AnalyticsTracker +import io.element.android.services.analytics.api.VectorAnalyticsEvent +import io.element.android.services.analytics.api.VectorAnalyticsScreen +import io.element.android.services.analytics.api.plan.UserProperties +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class NoopAnalyticsTracker @Inject constructor() : AnalyticsTracker { + + override fun capture(event: VectorAnalyticsEvent) = Unit + + override fun screen(screen: VectorAnalyticsScreen) = Unit + + override fun updateUserProperties(userProperties: UserProperties) = Unit +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 7a534a5778..85939a4eea 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -66,6 +66,8 @@ include(":libraries:session-storage:api") include(":libraries:session-storage:impl") include(":libraries:session-storage:impl-memory") +include(":services:analytics:api") +include(":services:analytics:noop") include(":services:appnavstate:api") include(":services:appnavstate:impl")