Init analytics modules (#350)
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -40,6 +40,7 @@ captures/
|
||||
.idea/.name
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/compiler.xml
|
||||
.idea/deploymentTargetDropDown.xml
|
||||
.idea/gradle.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/misc.xml
|
||||
@@ -54,6 +55,7 @@ captures/
|
||||
.idea/inspectionProfiles
|
||||
# Shelved changes in the IDE
|
||||
.idea/shelf
|
||||
.idea/sonarlint
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||
@@ -88,7 +90,6 @@ lint/generated/
|
||||
lint/outputs/
|
||||
lint/tmp/
|
||||
# lint/reports/
|
||||
/.idea/deploymentTargetDropDown.xml
|
||||
|
||||
/tmp
|
||||
.DS_Store
|
||||
|
||||
@@ -21,4 +21,6 @@ appId: ${APP_ID}
|
||||
- inputText: ${PASSWORD}
|
||||
- pressKey: Enter
|
||||
- tapOn: "Continue"
|
||||
- runFlow: ../assertions/assertAnalyticsDisplayed.yaml
|
||||
- tapOn: "Not now"
|
||||
- runFlow: ../assertions/assertHomeDisplayed.yaml
|
||||
|
||||
5
.maestro/tests/assertions/assertAnalyticsDisplayed.yaml
Normal file
5
.maestro/tests/assertions/assertAnalyticsDisplayed.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
appId: ${APP_ID}
|
||||
---
|
||||
- extendedWaitUntil:
|
||||
visible: "Help improve ElementX dbg"
|
||||
timeout: 10_000
|
||||
@@ -51,13 +51,12 @@ dependencies {
|
||||
implementation(projects.libraries.permissions.api)
|
||||
implementation(projects.libraries.permissions.noop)
|
||||
|
||||
implementation(projects.features.verifysession.api)
|
||||
implementation(projects.features.roomdetails.api)
|
||||
implementation(projects.tests.uitests)
|
||||
implementation(libs.coil)
|
||||
|
||||
implementation(projects.services.apperror.impl)
|
||||
implementation(projects.services.appnavstate.api)
|
||||
implementation(projects.services.analytics.api)
|
||||
|
||||
testImplementation(libs.test.junit)
|
||||
testImplementation(libs.coroutines.test)
|
||||
|
||||
@@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import coil.Coil
|
||||
import com.bumble.appyx.core.composable.Children
|
||||
import com.bumble.appyx.core.lifecycle.subscribe
|
||||
@@ -39,6 +40,7 @@ import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.appnav.loggedin.LoggedInNode
|
||||
import io.element.android.features.analytics.api.AnalyticsEntryPoint
|
||||
import io.element.android.features.createroom.api.CreateRoomEntryPoint
|
||||
import io.element.android.features.invitelist.api.InviteListEntryPoint
|
||||
import io.element.android.features.preferences.api.PreferencesEntryPoint
|
||||
@@ -50,6 +52,7 @@ import io.element.android.libraries.architecture.animation.rememberDefaultTransi
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.AppScope
|
||||
@@ -57,8 +60,13 @@ import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.MAIN_SPACE
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.ui.di.MatrixUIBindings
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@ContributesNode(AppScope::class)
|
||||
@@ -68,20 +76,43 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
private val roomListEntryPoint: RoomListEntryPoint,
|
||||
private val preferencesEntryPoint: PreferencesEntryPoint,
|
||||
private val createRoomEntryPoint: CreateRoomEntryPoint,
|
||||
private val analyticsOptInEntryPoint: AnalyticsEntryPoint,
|
||||
private val appNavigationStateService: AppNavigationStateService,
|
||||
private val verifySessionEntryPoint: VerifySessionEntryPoint,
|
||||
private val inviteListEntryPoint: InviteListEntryPoint,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
snackbarDispatcher: SnackbarDispatcher,
|
||||
) : BackstackNode<LoggedInFlowNode.NavTarget>(
|
||||
backstack = BackStack(
|
||||
initialElement = NavTarget.RoomList,
|
||||
initialElement = NavTarget.SplashScreen,
|
||||
savedStateMap = buildContext.savedStateMap,
|
||||
),
|
||||
buildContext = buildContext,
|
||||
plugins = plugins
|
||||
) {
|
||||
|
||||
private fun observeAnalyticsState() {
|
||||
analyticsService.didAskUserConsent()
|
||||
.distinctUntilChanged()
|
||||
.onEach { isConsentAsked ->
|
||||
if (isConsentAsked) {
|
||||
switchToRoomList()
|
||||
} else {
|
||||
switchToAnalytics()
|
||||
}
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
private fun switchToRoomList() {
|
||||
backstack.safeRoot(NavTarget.RoomList)
|
||||
}
|
||||
|
||||
private fun switchToAnalytics() {
|
||||
backstack.safeRoot(NavTarget.AnalyticsSettings)
|
||||
}
|
||||
|
||||
interface Callback : Plugin {
|
||||
fun onOpenBugReport() = Unit
|
||||
}
|
||||
@@ -105,6 +136,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
|
||||
override fun onBuilt() {
|
||||
super.onBuilt()
|
||||
observeAnalyticsState()
|
||||
lifecycle.subscribe(
|
||||
onCreate = {
|
||||
plugins<LifecycleCallback>().forEach { it.onFlowCreated(inputs.matrixClient) }
|
||||
@@ -128,6 +160,9 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
}
|
||||
|
||||
sealed interface NavTarget : Parcelable {
|
||||
@Parcelize
|
||||
object SplashScreen : NavTarget
|
||||
|
||||
@Parcelize
|
||||
object Permanent : NavTarget
|
||||
|
||||
@@ -150,11 +185,15 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
object VerifySession : NavTarget
|
||||
|
||||
@Parcelize
|
||||
object InviteList: NavTarget
|
||||
object InviteList : NavTarget
|
||||
|
||||
@Parcelize
|
||||
object AnalyticsSettings : NavTarget
|
||||
}
|
||||
|
||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||
return when (navTarget) {
|
||||
NavTarget.SplashScreen -> splashNode(buildContext)
|
||||
NavTarget.Permanent -> {
|
||||
createNode<LoggedInNode>(buildContext)
|
||||
}
|
||||
@@ -244,6 +283,9 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
.callback(callback)
|
||||
.build()
|
||||
}
|
||||
NavTarget.AnalyticsSettings -> {
|
||||
analyticsOptInEntryPoint.createNode(this, buildContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +302,12 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun splashNode(buildContext: BuildContext) = node(buildContext) {
|
||||
Box(modifier = it.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
Box(modifier = modifier) {
|
||||
|
||||
@@ -25,8 +25,8 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
||||
import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.push.providers.api.Distributor
|
||||
import io.element.android.libraries.push.providers.api.PushProvider
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
32
features/analytics/api/build.gradle.kts
Normal file
32
features/analytics/api/build.gradle.kts
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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-compose-library")
|
||||
alias(libs.plugins.ksp)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.features.analytics.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.libraries.architecture)
|
||||
implementation(projects.libraries.designsystem)
|
||||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.libraries.uiStrings)
|
||||
|
||||
ksp(libs.showkase.processor)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.features.analytics.api
|
||||
|
||||
import io.element.android.libraries.architecture.SimpleFeatureEntryPoint
|
||||
|
||||
interface AnalyticsEntryPoint : SimpleFeatureEntryPoint
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.features.analytics.api
|
||||
|
||||
sealed interface AnalyticsOptInEvents {
|
||||
data class EnableAnalytics(val isEnabled: Boolean) : AnalyticsOptInEvents
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.features.analytics.api.preferences
|
||||
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
|
||||
interface AnalyticsPreferencesPresenter : Presenter<AnalyticsPreferencesState>
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.features.analytics.api.preferences
|
||||
|
||||
import io.element.android.features.analytics.api.AnalyticsOptInEvents
|
||||
|
||||
data class AnalyticsPreferencesState(
|
||||
val applicationName: String,
|
||||
val isEnabled: Boolean,
|
||||
val eventSink: (AnalyticsOptInEvents) -> Unit,
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.features.analytics.api.preferences
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
|
||||
open class AnalyticsPreferencesStateProvider : PreviewParameterProvider<AnalyticsPreferencesState> {
|
||||
override val values: Sequence<AnalyticsPreferencesState>
|
||||
get() = sequenceOf(
|
||||
aAnalyticsPreferencesState().copy(isEnabled = true),
|
||||
)
|
||||
}
|
||||
|
||||
fun aAnalyticsPreferencesState() = AnalyticsPreferencesState(
|
||||
applicationName = "ElementX",
|
||||
isEnabled = false,
|
||||
eventSink = {}
|
||||
)
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.features.analytics.api.preferences
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.features.analytics.api.AnalyticsOptInEvents
|
||||
import io.element.android.libraries.designsystem.LinkColor
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
fun AnalyticsPreferencesView(
|
||||
state: AnalyticsPreferencesState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
fun onEnabledChanged(isEnabled: Boolean) {
|
||||
state.eventSink(AnalyticsOptInEvents.EnableAnalytics(isEnabled = isEnabled))
|
||||
}
|
||||
|
||||
PreferenceCategory(title = stringResource(id = StringR.string.screen_analytics_settings_share_data)) {
|
||||
val firstPart = stringResource(id = StringR.string.screen_analytics_settings_help_us_improve, state.applicationName)
|
||||
val secondPart = buildAnnotatedStringWithColoredPart(
|
||||
StringR.string.screen_analytics_settings_read_terms,
|
||||
StringR.string.screen_analytics_settings_read_terms_content_link
|
||||
)
|
||||
val title = "$firstPart\n\n$secondPart"
|
||||
|
||||
PreferenceSwitch(
|
||||
title = title,
|
||||
isChecked = state.isEnabled,
|
||||
onCheckedChange = ::onEnabledChanged
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun buildAnnotatedStringWithColoredPart(
|
||||
@StringRes fullTextRes: Int,
|
||||
@StringRes coloredTextRes: Int,
|
||||
color: Color = LinkColor,
|
||||
underline: Boolean = true,
|
||||
) = buildAnnotatedString {
|
||||
val coloredPart = stringResource(coloredTextRes)
|
||||
val fullText = stringResource(fullTextRes, coloredPart)
|
||||
val startIndex = fullText.indexOf(coloredPart)
|
||||
append(fullText)
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
color = color,
|
||||
textDecoration = if (underline) TextDecoration.Underline else null
|
||||
), start = startIndex, end = startIndex + coloredPart.length
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AnalyticsPreferencesViewLightPreview(@PreviewParameter(AnalyticsPreferencesStateProvider::class) state: AnalyticsPreferencesState) =
|
||||
ElementPreviewLight { ContentToPreview(state) }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AnalyticsPreferencesViewDarkPreview(@PreviewParameter(AnalyticsPreferencesStateProvider::class) state: AnalyticsPreferencesState) =
|
||||
ElementPreviewDark { ContentToPreview(state) }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview(state: AnalyticsPreferencesState) {
|
||||
AnalyticsPreferencesView(state)
|
||||
}
|
||||
57
features/analytics/impl/build.gradle.kts
Normal file
57
features/analytics/impl/build.gradle.kts
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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-compose-library")
|
||||
alias(libs.plugins.anvil)
|
||||
alias(libs.plugins.ksp)
|
||||
id("kotlin-parcelize")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.features.analytics.impl"
|
||||
}
|
||||
|
||||
anvil {
|
||||
generateDaggerFactories.set(true)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.anvilannotations)
|
||||
anvil(projects.anvilcodegen)
|
||||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.libraries.core)
|
||||
implementation(projects.libraries.architecture)
|
||||
implementation(projects.libraries.designsystem)
|
||||
implementation(projects.libraries.elementresources)
|
||||
implementation(projects.libraries.uiStrings)
|
||||
api(projects.features.analytics.api)
|
||||
api(projects.services.analytics.api)
|
||||
implementation(libs.androidx.datastore.preferences)
|
||||
ksp(libs.showkase.processor)
|
||||
|
||||
testImplementation(libs.test.junit)
|
||||
testImplementation(libs.coroutines.test)
|
||||
testImplementation(libs.molecule.runtime)
|
||||
testImplementation(libs.test.truth)
|
||||
testImplementation(libs.test.turbine)
|
||||
testImplementation(libs.test.mockk)
|
||||
testImplementation(projects.libraries.matrix.test)
|
||||
testImplementation(projects.features.analytics.test)
|
||||
testImplementation(projects.features.analytics.impl)
|
||||
|
||||
androidTestImplementation(libs.test.junitext)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.features.analytics.impl
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.bumble.appyx.core.modality.BuildContext
|
||||
import com.bumble.appyx.core.node.Node
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.libraries.di.AppScope
|
||||
|
||||
@ContributesNode(AppScope::class)
|
||||
class AnalyticsOptInNode @AssistedInject constructor(
|
||||
@Assisted buildContext: BuildContext,
|
||||
@Assisted plugins: List<Plugin>,
|
||||
private val presenter: AnalyticsOptInPresenter,
|
||||
) : Node(buildContext, plugins = plugins) {
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val state = presenter.present()
|
||||
AnalyticsOptInView(
|
||||
state = state,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.features.analytics.impl
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import io.element.android.features.analytics.api.AnalyticsOptInEvents
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class AnalyticsOptInPresenter @Inject constructor(
|
||||
private val buildMeta: BuildMeta,
|
||||
private val analyticsService: AnalyticsService,
|
||||
) : Presenter<AnalyticsOptInState> {
|
||||
|
||||
@Composable
|
||||
override fun present(): AnalyticsOptInState {
|
||||
val localCoroutineScope = rememberCoroutineScope()
|
||||
|
||||
fun handleEvents(event: AnalyticsOptInEvents) {
|
||||
when (event) {
|
||||
is AnalyticsOptInEvents.EnableAnalytics -> localCoroutineScope.setIsEnabled(event.isEnabled)
|
||||
}
|
||||
localCoroutineScope.launch {
|
||||
analyticsService.setDidAskUserConsent()
|
||||
}
|
||||
}
|
||||
|
||||
return AnalyticsOptInState(
|
||||
applicationName = buildMeta.applicationName,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.setIsEnabled(enabled: Boolean) = launch {
|
||||
analyticsService.setUserConsent(enabled)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.features.analytics.impl
|
||||
|
||||
import io.element.android.features.analytics.api.AnalyticsOptInEvents
|
||||
|
||||
data class AnalyticsOptInState(
|
||||
val applicationName: String,
|
||||
val eventSink: (AnalyticsOptInEvents) -> Unit
|
||||
)
|
||||
@@ -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.features.analytics.impl
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import javax.inject.Inject
|
||||
|
||||
open class AnalyticsOptInStateProvider @Inject constructor(
|
||||
) : PreviewParameterProvider<AnalyticsOptInState> {
|
||||
override val values: Sequence<AnalyticsOptInState>
|
||||
get() = sequenceOf(
|
||||
aAnalyticsOptInState(),
|
||||
)
|
||||
}
|
||||
|
||||
fun aAnalyticsOptInState() = AnalyticsOptInState(
|
||||
applicationName = "ElementX",
|
||||
eventSink = {}
|
||||
)
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* 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.features.analytics.impl
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.text.SpannableString
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.text.style.StyleSpan
|
||||
import android.text.style.UnderlineSpan
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.CheckCircle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.features.analytics.api.AnalyticsOptInEvents
|
||||
import io.element.android.libraries.designsystem.LinkColor
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
fun AnalyticsOptInView(
|
||||
state: AnalyticsOptInState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
LogCompositions(tag = "Analytics", msg = "Root")
|
||||
val eventSink = state.eventSink
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.imePadding()
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Image(
|
||||
painterResource(id = R.drawable.element_logo_stars),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(16.dp)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_analytics_prompt_title, state.applicationName),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_analytics_prompt_help_us_improve, state.applicationName),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 16.sp,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
|
||||
Text(
|
||||
text = buildAnnotatedStringWithColoredPart(
|
||||
R.string.screen_analytics_prompt_read_terms,
|
||||
R.string.screen_analytics_prompt_read_terms_content_link
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 16.sp,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(imageVector = Icons.Outlined.CheckCircle,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.secondary)
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_analytics_prompt_data_usage).toAnnotatedString(),
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(imageVector = Icons.Outlined.CheckCircle,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.secondary)
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_analytics_prompt_third_party_sharing).toAnnotatedString(),
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(imageVector = Icons.Outlined.CheckCircle,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.secondary)
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_analytics_prompt_settings),
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Button(
|
||||
onClick = { eventSink(AnalyticsOptInEvents.EnableAnalytics(true)) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text(text = stringResource(id = StringR.string.action_enable))
|
||||
}
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
TextButton(
|
||||
onClick = { eventSink(AnalyticsOptInEvents.EnableAnalytics(false)) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text(text = stringResource(id = StringR.string.action_not_now))
|
||||
}
|
||||
Spacer(Modifier.height(40.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun String.toAnnotatedString(): AnnotatedString = buildAnnotatedString {
|
||||
append(this@toAnnotatedString)
|
||||
val spannable = SpannableString(this@toAnnotatedString)
|
||||
spannable.getSpans(0, spannable.length, Any::class.java).forEach { span ->
|
||||
val start = spannable.getSpanStart(span)
|
||||
val end = spannable.getSpanEnd(span)
|
||||
when (span) {
|
||||
is StyleSpan -> when (span.style) {
|
||||
Typeface.BOLD -> addStyle(SpanStyle(fontWeight = FontWeight.Bold), start, end)
|
||||
Typeface.ITALIC -> addStyle(SpanStyle(fontStyle = FontStyle.Italic), start, end)
|
||||
Typeface.BOLD_ITALIC -> addStyle(SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Italic), start, end)
|
||||
}
|
||||
is UnderlineSpan -> addStyle(SpanStyle(textDecoration = TextDecoration.Underline), start, end)
|
||||
is ForegroundColorSpan -> addStyle(SpanStyle(color = Color(span.foregroundColor)), start, end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun buildAnnotatedStringWithColoredPart(
|
||||
@StringRes fullTextRes: Int,
|
||||
@StringRes coloredTextRes: Int,
|
||||
color: Color = LinkColor,
|
||||
underline: Boolean = true,
|
||||
) = buildAnnotatedString {
|
||||
val coloredPart = stringResource(coloredTextRes)
|
||||
val fullText = stringResource(fullTextRes, coloredPart)
|
||||
val startIndex = fullText.indexOf(coloredPart)
|
||||
append(fullText)
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
color = color,
|
||||
textDecoration = if (underline) TextDecoration.Underline else null
|
||||
), start = startIndex, end = startIndex + coloredPart.length
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AnalyticsOptInViewLightPreview(@PreviewParameter(AnalyticsOptInStateProvider::class) state: AnalyticsOptInState) = ElementPreviewLight {
|
||||
ContentToPreview(state)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AnalyticsOptInViewDarkPreview(@PreviewParameter(AnalyticsOptInStateProvider::class) state: AnalyticsOptInState) = ElementPreviewDark {
|
||||
ContentToPreview(state)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview(state: AnalyticsOptInState) {
|
||||
AnalyticsOptInView(state = state)
|
||||
}
|
||||
@@ -14,22 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.services.analytics.noop
|
||||
package io.element.android.features.analytics.impl
|
||||
|
||||
import com.bumble.appyx.core.modality.BuildContext
|
||||
import com.bumble.appyx.core.node.Node
|
||||
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.features.analytics.api.AnalyticsEntryPoint
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
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
|
||||
class DefaultAnalyticsEntryPoint @Inject constructor() : AnalyticsEntryPoint {
|
||||
override fun createNode(parentNode: Node, buildContext: BuildContext): Node {
|
||||
return parentNode.createNode<AnalyticsOptInNode>(buildContext)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.features.analytics.impl.preferences
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.features.analytics.api.AnalyticsOptInEvents
|
||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesPresenter
|
||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesState
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultAnalyticsPreferencesPresenter @Inject constructor(
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val buildMeta: BuildMeta,
|
||||
) : AnalyticsPreferencesPresenter {
|
||||
|
||||
@Composable
|
||||
override fun present(): AnalyticsPreferencesState {
|
||||
val localCoroutineScope = rememberCoroutineScope()
|
||||
val isEnabled = analyticsService.getUserConsent()
|
||||
.collectAsState(initial = false)
|
||||
|
||||
fun handleEvents(event: AnalyticsOptInEvents) {
|
||||
when (event) {
|
||||
is AnalyticsOptInEvents.EnableAnalytics -> localCoroutineScope.setIsEnabled(event.isEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
return AnalyticsPreferencesState(
|
||||
applicationName = buildMeta.applicationName,
|
||||
isEnabled = isEnabled.value,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.setIsEnabled(enabled: Boolean) = launch {
|
||||
analyticsService.setUserConsent(enabled)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="120dp"
|
||||
android:height="94dp"
|
||||
android:viewportWidth="120"
|
||||
android:viewportHeight="94">
|
||||
<path
|
||||
android:pathData="M60.396,4.958L60.604,4.958A44.521,44.521 0,0 1,105.125 49.479L105.125,49.479A44.521,44.521 0,0 1,60.604 94L60.396,94A44.521,44.521 0,0 1,15.875 49.479L15.875,49.479A44.521,44.521 0,0 1,60.396 4.958z"
|
||||
android:fillColor="#0DBD8B"/>
|
||||
<path
|
||||
android:pathData="M53.228,26.676C53.228,24.958 54.623,23.566 56.344,23.566C67.82,23.566 77.123,32.847 77.123,44.296C77.123,46.014 75.727,47.406 74.006,47.406C72.285,47.406 70.889,46.014 70.889,44.296C70.889,36.282 64.377,29.785 56.344,29.785C54.623,29.785 53.228,28.393 53.228,26.676Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M67.772,72.282C67.772,73.999 66.377,75.391 64.655,75.391C53.18,75.391 43.877,66.11 43.877,54.661C43.877,52.944 45.272,51.552 46.994,51.552C48.715,51.552 50.111,52.944 50.111,54.661C50.111,62.675 56.623,69.172 64.655,69.172C66.377,69.172 67.772,70.564 67.772,72.282Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M37.644,56.734C35.922,56.734 34.527,55.342 34.527,53.625C34.527,42.176 43.83,32.895 55.305,32.895C57.027,32.895 58.422,34.287 58.422,36.004C58.422,37.722 57.027,39.114 55.305,39.114C47.272,39.114 40.76,45.611 40.76,53.625C40.76,55.342 39.365,56.734 37.644,56.734Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M83.356,42.223C85.078,42.223 86.473,43.615 86.473,45.332C86.473,56.781 77.17,66.063 65.695,66.063C63.973,66.063 62.578,64.671 62.578,62.953C62.578,61.236 63.973,59.844 65.695,59.844C73.728,59.844 80.24,53.347 80.24,45.332C80.24,43.615 81.635,42.223 83.356,42.223Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M39.571,77.305C40.181,77.305 40.683,76.856 40.769,76.227C41.7,69.687 42.587,68.79 48.918,68.076C49.56,68.001 50.041,67.478 50.041,66.87C50.041,66.251 49.57,65.75 48.929,65.664C42.63,64.843 41.817,64.043 40.769,57.502C40.662,56.873 40.181,56.435 39.571,56.435C38.972,56.435 38.47,56.873 38.374,57.513C37.454,64.053 36.566,64.95 30.235,65.664C29.594,65.739 29.123,66.251 29.123,66.87C29.123,67.478 29.583,67.99 30.235,68.076C36.534,68.951 37.315,69.697 38.374,76.238C38.491,76.867 38.983,77.305 39.571,77.305Z"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#0DBD8B"/>
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M82.194,35.392C82.697,35.392 83.111,35.019 83.182,34.494C83.949,29.044 84.682,28.297 89.905,27.701C90.434,27.639 90.831,27.203 90.831,26.697C90.831,26.181 90.443,25.763 89.913,25.692C84.717,25.007 84.046,24.34 83.182,18.89C83.093,18.365 82.697,18.001 82.194,18.001C81.7,18.001 81.285,18.365 81.205,18.899C80.447,24.349 79.714,25.096 74.491,25.692C73.962,25.754 73.574,26.181 73.574,26.697C73.574,27.203 73.953,27.63 74.491,27.701C79.688,28.43 80.332,29.053 81.205,34.503C81.302,35.028 81.708,35.392 82.194,35.392Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#0DBD8B"/>
|
||||
<path
|
||||
android:pathData="M113.846,18.87C114.174,18.87 114.444,18.631 114.49,18.296C114.991,14.807 115.468,14.329 118.873,13.948C119.218,13.908 119.477,13.63 119.477,13.305C119.477,12.975 119.224,12.708 118.879,12.662C115.491,12.224 115.054,11.797 114.49,8.309C114.433,7.973 114.174,7.74 113.846,7.74C113.524,7.74 113.254,7.973 113.202,8.315C112.707,11.803 112.23,12.281 108.825,12.662C108.48,12.702 108.227,12.975 108.227,13.305C108.227,13.63 108.474,13.903 108.825,13.948C112.213,14.415 112.633,14.813 113.202,18.301C113.265,18.637 113.53,18.87 113.846,18.87Z"
|
||||
android:fillColor="#0DBD8B"/>
|
||||
<path
|
||||
android:pathData="M107.169,9.131C107.354,9.131 107.506,8.997 107.531,8.808C107.813,6.846 108.081,6.577 109.997,6.363C110.191,6.34 110.336,6.183 110.336,6.001C110.336,5.815 110.194,5.665 110,5.639C108.094,5.393 107.849,5.153 107.531,3.191C107.499,3.002 107.354,2.871 107.169,2.871C106.988,2.871 106.836,3.002 106.807,3.194C106.529,5.156 106.26,5.425 104.345,5.639C104.151,5.662 104.008,5.815 104.008,6.001C104.008,6.183 104.147,6.337 104.345,6.363C106.25,6.625 106.486,6.849 106.807,8.811C106.842,9 106.991,9.131 107.169,9.131Z"
|
||||
android:fillColor="#0DBD8B"/>
|
||||
<path
|
||||
android:pathData="M108.575,24.435C108.8,24.435 108.986,24.271 109.018,24.04C109.362,21.642 109.69,21.314 112.031,21.052C112.268,21.024 112.446,20.833 112.446,20.61C112.446,20.383 112.272,20.199 112.035,20.167C109.706,19.866 109.405,19.573 109.018,17.175C108.978,16.944 108.8,16.783 108.575,16.783C108.353,16.783 108.167,16.944 108.132,17.179C107.792,19.577 107.464,19.905 105.123,20.167C104.885,20.195 104.711,20.383 104.711,20.61C104.711,20.833 104.881,21.02 105.123,21.052C107.452,21.372 107.74,21.646 108.132,24.044C108.175,24.275 108.357,24.435 108.575,24.435Z"
|
||||
android:fillColor="#0DBD8B"/>
|
||||
<path
|
||||
android:pathData="M6.197,15.392C6.504,15.392 6.758,15.168 6.801,14.853C7.27,11.583 7.718,11.135 10.91,10.778C11.233,10.74 11.476,10.479 11.476,10.175C11.476,9.865 11.239,9.615 10.915,9.572C7.739,9.161 7.329,8.761 6.801,5.491C6.747,5.176 6.504,4.958 6.197,4.958C5.895,4.958 5.642,5.176 5.593,5.496C5.129,8.767 4.682,9.215 1.49,9.572C1.166,9.609 0.929,9.865 0.929,10.175C0.929,10.479 1.161,10.735 1.49,10.778C4.666,11.215 5.059,11.589 5.593,14.859C5.652,15.174 5.9,15.392 6.197,15.392Z"
|
||||
android:fillColor="#0DBD8B"/>
|
||||
<path
|
||||
android:pathData="M13.231,5.653C13.375,5.653 13.493,5.549 13.513,5.402C13.732,3.876 13.941,3.667 15.431,3.5C15.582,3.482 15.695,3.36 15.695,3.218C15.695,3.074 15.584,2.957 15.433,2.937C13.951,2.745 13.76,2.559 13.513,1.033C13.488,0.886 13.375,0.784 13.231,0.784C13.09,0.784 12.972,0.886 12.95,1.035C12.733,2.561 12.524,2.77 11.035,2.937C10.884,2.955 10.773,3.074 10.773,3.218C10.773,3.36 10.881,3.48 11.035,3.5C12.517,3.704 12.7,3.878 12.95,5.404C12.977,5.551 13.093,5.653 13.231,5.653Z"
|
||||
android:strokeAlpha="0.4"
|
||||
android:fillColor="#0DBD8B"
|
||||
android:fillAlpha="0.4"/>
|
||||
<path
|
||||
android:pathData="M16.747,11.914C16.89,11.914 17.009,11.809 17.029,11.663C17.248,10.136 17.457,9.927 18.946,9.761C19.097,9.743 19.21,9.621 19.21,9.479C19.21,9.335 19.1,9.218 18.949,9.198C17.467,9.006 17.275,8.819 17.029,7.293C17.004,7.147 16.89,7.044 16.747,7.044C16.606,7.044 16.488,7.147 16.465,7.296C16.249,8.822 16.04,9.031 14.55,9.198C14.399,9.215 14.289,9.335 14.289,9.479C14.289,9.621 14.397,9.741 14.55,9.761C16.032,9.965 16.216,10.139 16.465,11.665C16.493,11.812 16.609,11.914 16.747,11.914Z"
|
||||
android:strokeAlpha="0.4"
|
||||
android:fillColor="#0DBD8B"
|
||||
android:fillAlpha="0.4"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_analytics_prompt_data_usage">"Wir erfassen und analysieren "<b>"keine"</b>" Account-Daten"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Helfen Sie uns, Probleme zu identifizieren und %1$s zu verbessern, indem Sie anonyme Nutzungsdaten weitergeben."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"Sie können alle unsere Nutzerbedingungen %1$s lesen."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"hier"</string>
|
||||
<string name="screen_analytics_prompt_settings">"Sie können die Analyse jederzeit in den Einstellungen deaktivieren"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing">"Wir geben "<b>"keine"</b>" Informationen an Dritte weiter"</string>
|
||||
<string name="screen_analytics_prompt_title">"Helfen Sie %1$s zu verbessern"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_analytics_prompt_data_usage"><b>"Nu"</b>" înregistrăm sau profilăm datele contului"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Ajutați-ne să identificăm problemele și să îmbunătățim %1$s prin partajarea datelor de utilizare anonime."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"Puteți citi toate condițiile noastre %1$s."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"aici"</string>
|
||||
<string name="screen_analytics_prompt_settings">"Puteți dezactiva această opțiune oricând din setări"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing"><b>"Nu"</b>" împărtășim informații cu terți"</string>
|
||||
<string name="screen_analytics_prompt_title">"Ajutați la îmbunătățirea %1$s"</string>
|
||||
</resources>
|
||||
10
features/analytics/impl/src/main/res/values/localazy.xml
Normal file
10
features/analytics/impl/src/main/res/values/localazy.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_analytics_prompt_data_usage">"We "<b>"don\'t"</b>" record or profile any account data"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Help us identify issues and improve %1$s by sharing anonymous usage data."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"You can read all our terms %1$s."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"here"</string>
|
||||
<string name="screen_analytics_prompt_settings">"You can turn this off anytime in settings"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing">"We "<b>"don\'t"</b>" share information with third parties"</string>
|
||||
<string name="screen_analytics_prompt_title">"Help improve %1$s"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.features.analytics.impl
|
||||
|
||||
import app.cash.molecule.RecompositionClock
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.analytics.api.AnalyticsOptInEvents
|
||||
import io.element.android.features.analytics.impl.preferences.DefaultAnalyticsPreferencesPresenter
|
||||
import io.element.android.features.analytics.test.A_BUILD_META
|
||||
import io.element.android.features.analytics.test.FakeAnalyticsService
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class AnalyticsOptInPresenterTest {
|
||||
@Test
|
||||
fun `present - enable`() = runTest {
|
||||
val analyticsService = FakeAnalyticsService(isEnabled = false)
|
||||
val presenter = AnalyticsOptInPresenter(
|
||||
A_BUILD_META,
|
||||
analyticsService
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(analyticsService.didAskUserConsent().first()).isFalse()
|
||||
initialState.eventSink.invoke(AnalyticsOptInEvents.EnableAnalytics(true))
|
||||
assertThat(analyticsService.didAskUserConsent().first()).isTrue()
|
||||
assertThat(analyticsService.getUserConsent().first()).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - not now`() = runTest {
|
||||
val analyticsService = FakeAnalyticsService(isEnabled = false)
|
||||
val presenter = AnalyticsOptInPresenter(
|
||||
A_BUILD_META,
|
||||
analyticsService
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(analyticsService.didAskUserConsent().first()).isFalse()
|
||||
initialState.eventSink.invoke(AnalyticsOptInEvents.EnableAnalytics(false))
|
||||
assertThat(analyticsService.didAskUserConsent().first()).isTrue()
|
||||
assertThat(analyticsService.getUserConsent().first()).isFalse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.features.analytics.impl.preferences
|
||||
|
||||
import app.cash.molecule.RecompositionClock
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.analytics.api.AnalyticsOptInEvents
|
||||
import io.element.android.features.analytics.test.A_BUILD_META
|
||||
import io.element.android.features.analytics.test.FakeAnalyticsService
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class AnalyticsPreferencesPresenterTest {
|
||||
@Test
|
||||
fun `present - initial state available`() = runTest {
|
||||
val presenter = DefaultAnalyticsPreferencesPresenter(
|
||||
FakeAnalyticsService(isEnabled = true, didAskUserConsent = true),
|
||||
A_BUILD_META
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.isEnabled).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - initial state not available`() = runTest {
|
||||
val presenter = DefaultAnalyticsPreferencesPresenter(
|
||||
FakeAnalyticsService(isEnabled = false, didAskUserConsent = false),
|
||||
A_BUILD_META
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.isEnabled).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - enable and disable`() = runTest {
|
||||
val presenter = DefaultAnalyticsPreferencesPresenter(
|
||||
FakeAnalyticsService(isEnabled = true, didAskUserConsent = true),
|
||||
A_BUILD_META
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.isEnabled).isTrue()
|
||||
initialState.eventSink.invoke(AnalyticsOptInEvents.EnableAnalytics(false))
|
||||
assertThat(awaitItem().isEnabled).isFalse()
|
||||
initialState.eventSink.invoke(AnalyticsOptInEvents.EnableAnalytics(true))
|
||||
assertThat(awaitItem().isEnabled).isTrue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
features/analytics/test/build.gradle.kts
Normal file
28
features/analytics/test/build.gradle.kts
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.features.analytics.test"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.services.analytics.api)
|
||||
implementation(projects.libraries.core)
|
||||
implementation(libs.coroutines.core)
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.features.analytics.test
|
||||
|
||||
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
|
||||
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
|
||||
import im.vector.app.features.analytics.plan.UserProperties
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analyticsproviders.api.AnalyticsProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class FakeAnalyticsService(
|
||||
isEnabled: Boolean = false,
|
||||
didAskUserConsent: Boolean = false
|
||||
): AnalyticsService {
|
||||
|
||||
private var isEnabledFlow = MutableStateFlow(isEnabled)
|
||||
private var didAskUserConsentFlow = MutableStateFlow(didAskUserConsent)
|
||||
|
||||
override fun getAvailableAnalyticsProviders(): List<AnalyticsProvider> = emptyList()
|
||||
|
||||
override fun getUserConsent(): Flow<Boolean> = isEnabledFlow
|
||||
|
||||
override suspend fun setUserConsent(userConsent: Boolean) {
|
||||
isEnabledFlow.value = userConsent
|
||||
}
|
||||
|
||||
override fun didAskUserConsent(): Flow<Boolean> = didAskUserConsentFlow
|
||||
|
||||
override suspend fun setDidAskUserConsent() {
|
||||
didAskUserConsentFlow.value = true
|
||||
}
|
||||
|
||||
override fun getAnalyticsId(): Flow<String> = MutableStateFlow("")
|
||||
|
||||
override suspend fun setAnalyticsId(analyticsId: String) {
|
||||
}
|
||||
|
||||
override suspend fun onSignOut() {
|
||||
}
|
||||
|
||||
override fun capture(event: VectorAnalyticsEvent) {
|
||||
}
|
||||
|
||||
override fun screen(screen: VectorAnalyticsScreen) {
|
||||
}
|
||||
|
||||
override fun updateUserProperties(userProperties: UserProperties) {
|
||||
}
|
||||
|
||||
override fun trackError(throwable: Throwable) {
|
||||
}
|
||||
}
|
||||
@@ -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.features.analytics.test
|
||||
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
|
||||
val A_BUILD_META = BuildMeta(
|
||||
isDebuggable = true,
|
||||
buildType = BuildType.DEBUG,
|
||||
applicationName = "Element X test",
|
||||
applicationId = "",
|
||||
lowPrivacyLoggingEnabled = false,
|
||||
versionName = "",
|
||||
gitRevision = "",
|
||||
gitRevisionDate = "",
|
||||
gitBranchName = "",
|
||||
flavorDescription = "",
|
||||
flavorShortDescription = "",
|
||||
)
|
||||
|
||||
@@ -42,6 +42,7 @@ dependencies {
|
||||
implementation(projects.libraries.testtags)
|
||||
implementation(projects.libraries.uiStrings)
|
||||
implementation(projects.features.rageshake.api)
|
||||
implementation(projects.features.analytics.api)
|
||||
implementation(projects.libraries.matrixui)
|
||||
implementation(projects.features.logout.api)
|
||||
implementation(libs.datetime)
|
||||
@@ -59,6 +60,8 @@ dependencies {
|
||||
testImplementation(projects.features.rageshake.test)
|
||||
testImplementation(projects.features.rageshake.impl)
|
||||
testImplementation(projects.features.logout.impl)
|
||||
testImplementation(projects.features.analytics.test)
|
||||
testImplementation(projects.features.analytics.impl)
|
||||
|
||||
androidTestImplementation(libs.test.junitext)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package io.element.android.features.preferences.impl.root
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesPresenter
|
||||
import io.element.android.features.logout.api.LogoutPreferencePresenter
|
||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter
|
||||
import io.element.android.libraries.architecture.Async
|
||||
@@ -27,6 +28,7 @@ import javax.inject.Inject
|
||||
class PreferencesRootPresenter @Inject constructor(
|
||||
private val logoutPresenter: LogoutPreferencePresenter,
|
||||
private val rageshakePresenter: RageshakePreferencesPresenter,
|
||||
private val analyticsPresenter: AnalyticsPreferencesPresenter,
|
||||
private val buildType: BuildType,
|
||||
) : Presenter<PreferencesRootState> {
|
||||
|
||||
@@ -34,10 +36,12 @@ class PreferencesRootPresenter @Inject constructor(
|
||||
override fun present(): PreferencesRootState {
|
||||
val logoutState = logoutPresenter.present()
|
||||
val rageshakeState = rageshakePresenter.present()
|
||||
val analyticsState = analyticsPresenter.present()
|
||||
val showDeveloperSettings = buildType != BuildType.RELEASE
|
||||
return PreferencesRootState(
|
||||
logoutState = logoutState,
|
||||
rageshakeState = rageshakeState,
|
||||
analyticsState = analyticsState,
|
||||
myUser = Async.Uninitialized,
|
||||
showDeveloperSettings = showDeveloperSettings
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package io.element.android.features.preferences.impl.root
|
||||
|
||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesState
|
||||
import io.element.android.features.logout.api.LogoutPreferenceState
|
||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState
|
||||
import io.element.android.libraries.architecture.Async
|
||||
@@ -24,6 +25,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
data class PreferencesRootState(
|
||||
val logoutState: LogoutPreferenceState,
|
||||
val rageshakeState: RageshakePreferencesState,
|
||||
val analyticsState: AnalyticsPreferencesState,
|
||||
val myUser: Async<MatrixUser>,
|
||||
val showDeveloperSettings: Boolean
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package io.element.android.features.preferences.impl.root
|
||||
|
||||
import io.element.android.features.analytics.api.preferences.aAnalyticsPreferencesState
|
||||
import io.element.android.features.logout.api.aLogoutPreferenceState
|
||||
import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState
|
||||
import io.element.android.libraries.architecture.Async
|
||||
@@ -23,6 +24,7 @@ import io.element.android.libraries.architecture.Async
|
||||
fun aPreferencesRootState() = PreferencesRootState(
|
||||
logoutState = aLogoutPreferenceState(),
|
||||
rageshakeState = aRageshakePreferencesState(),
|
||||
analyticsState = aAnalyticsPreferencesState(),
|
||||
myUser = Async.Uninitialized,
|
||||
showDeveloperSettings = true
|
||||
)
|
||||
|
||||
@@ -24,6 +24,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.features.logout.api.LogoutPreferenceView
|
||||
import io.element.android.features.preferences.impl.user.UserPreferences
|
||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesView
|
||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
@@ -52,6 +53,9 @@ fun PreferencesRootView(
|
||||
title = stringResource(id = StringR.string.common_settings)
|
||||
) {
|
||||
UserPreferences(state.myUser)
|
||||
AnalyticsPreferencesView(
|
||||
state = state.analyticsState,
|
||||
)
|
||||
RageshakePreferencesView(
|
||||
state = state.rageshakeState,
|
||||
onOpenRageshake = onOpenRageShake,
|
||||
|
||||
@@ -20,12 +20,14 @@ import app.cash.molecule.RecompositionClock
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.analytics.impl.preferences.DefaultAnalyticsPreferencesPresenter
|
||||
import io.element.android.features.analytics.test.A_BUILD_META
|
||||
import io.element.android.features.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.features.logout.impl.DefaultLogoutPreferencePresenter
|
||||
import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePreferencesPresenter
|
||||
import io.element.android.features.rageshake.test.rageshake.FakeRageShake
|
||||
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
@@ -35,10 +37,12 @@ class PreferencesRootPresenterTest {
|
||||
fun `present - initial state`() = runTest {
|
||||
val logoutPresenter = DefaultLogoutPreferencePresenter(FakeMatrixClient())
|
||||
val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore())
|
||||
val analyticsPresenter = DefaultAnalyticsPreferencesPresenter(FakeAnalyticsService(), A_BUILD_META)
|
||||
val presenter = PreferencesRootPresenter(
|
||||
logoutPresenter,
|
||||
rageshakePresenter,
|
||||
BuildType.DEBUG
|
||||
analyticsPresenter,
|
||||
A_BUILD_META.buildType
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
@@ -46,6 +50,7 @@ class PreferencesRootPresenterTest {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.logoutState.logoutAction).isEqualTo(Async.Uninitialized)
|
||||
assertThat(initialState.analyticsState.isEnabled).isFalse()
|
||||
assertThat(initialState.rageshakeState.isEnabled).isTrue()
|
||||
assertThat(initialState.rageshakeState.isSupported).isTrue()
|
||||
assertThat(initialState.rageshakeState.sensitivity).isEqualTo(1.0f)
|
||||
|
||||
@@ -41,6 +41,7 @@ showkase = "1.0.0-beta18"
|
||||
jsoup = "1.16.1"
|
||||
appyx = "1.2.0"
|
||||
dependencycheck = "8.2.1"
|
||||
dependencyanalysis = "1.20.0"
|
||||
stem = "2.3.0"
|
||||
sqldelight = "1.5.5"
|
||||
telephoto = "0.4.0"
|
||||
@@ -148,6 +149,11 @@ otaliastudios_transcoder = "com.otaliastudios:transcoder:0.10.5"
|
||||
vanniktech_blurhash = "com.vanniktech:blurhash:0.1.0"
|
||||
telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "telephoto" }
|
||||
|
||||
# Analytics
|
||||
posthog = "com.posthog.android:posthog:2.0.3"
|
||||
sentry_android = "io.sentry:sentry-android:6.17.0"
|
||||
matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:main-SNAPSHOT"
|
||||
|
||||
# Di
|
||||
inject = "javax.inject:javax.inject:1"
|
||||
dagger = { module = "com.google.dagger:dagger", version.ref = "dagger" }
|
||||
@@ -178,6 +184,7 @@ detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
|
||||
ktlint = "org.jlleitschuh.gradle.ktlint:11.3.2"
|
||||
dependencygraph = { id = "com.savvasdalkitsis.module-dependency-graph", version.ref = "dependencygraph" }
|
||||
dependencycheck = { id = "org.owasp.dependencycheck", version.ref = "dependencycheck" }
|
||||
dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyanalysis" }
|
||||
paparazzi = "app.cash.paparazzi:1.2.0"
|
||||
sonarqube = "org.sonarqube:4.2.0.3129"
|
||||
kover = "org.jetbrains.kotlinx.kover:0.6.1"
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
package io.element.android.libraries.push.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.providers.api.Distributor
|
||||
import io.element.android.libraries.push.providers.api.PushProvider
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
|
||||
interface PushService {
|
||||
// TODO Move away
|
||||
|
||||
@@ -22,8 +22,8 @@ import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
|
||||
import io.element.android.libraries.push.providers.api.Distributor
|
||||
import io.element.android.libraries.push.providers.api.PushProvider
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData
|
||||
import io.element.android.libraries.push.impl.config.PushConfig
|
||||
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
||||
import io.element.android.libraries.push.impl.pushgateway.PushGatewayNotifyRequest
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushproviders.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import io.element.android.services.toolbox.api.appname.AppNameProvider
|
||||
|
||||
@@ -26,7 +26,6 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.push.impl.log.notificationLoggerTag
|
||||
import io.element.android.services.analytics.api.AnalyticsTracker
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
@@ -41,7 +40,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
|
||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
||||
|
||||
//@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||
@Inject lateinit var analyticsTracker: AnalyticsTracker
|
||||
//@Inject lateinit var analyticsTracker: AnalyticsTracker
|
||||
@Inject lateinit var clock: SystemClock
|
||||
@Inject lateinit var actionIds: NotificationActionIds
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ import io.element.android.libraries.push.impl.notifications.NotifiableEventResol
|
||||
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
|
||||
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
|
||||
import io.element.android.libraries.push.impl.store.DefaultPushDataStore
|
||||
import io.element.android.libraries.push.providers.api.PushData
|
||||
import io.element.android.libraries.push.providers.api.PushHandler
|
||||
import io.element.android.libraries.pushproviders.api.PushData
|
||||
import io.element.android.libraries.pushproviders.api.PushHandler
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@@ -18,7 +18,7 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.libraries.push.providers.api"
|
||||
namespace = "io.element.android.libraries.pushproviders.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.api
|
||||
package io.element.android.libraries.pushproviders.api
|
||||
|
||||
data class Distributor(
|
||||
val value: String,
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.api
|
||||
package io.element.android.libraries.pushproviders.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.api
|
||||
package io.element.android.libraries.pushproviders.api
|
||||
|
||||
interface PushHandler {
|
||||
suspend fun handle(pushData: PushData)
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.api
|
||||
package io.element.android.libraries.pushproviders.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.api
|
||||
package io.element.android.libraries.pushproviders.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
|
||||
@@ -19,7 +19,7 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.libraries.push.providers.firebase"
|
||||
namespace = "io.element.android.libraries.pushproviders.firebase"
|
||||
}
|
||||
|
||||
anvil {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
android:name="firebase_analytics_collection_deactivated"
|
||||
android:value="true" />
|
||||
<service
|
||||
android:name="io.element.android.libraries.push.providers.firebase.VectorFirebaseMessagingService"
|
||||
android:name="io.element.android.libraries.pushproviders.firebase.VectorFirebaseMessagingService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
object FirebaseConfig {
|
||||
/**
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushproviders.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.sessionstorage.api.toUserList
|
||||
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import io.element.android.libraries.push.providers.api.PushData
|
||||
import io.element.android.libraries.pushproviders.api.PushData
|
||||
import javax.inject.Inject
|
||||
|
||||
class FirebasePushParser @Inject constructor() {
|
||||
@@ -14,15 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesMultibinding
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.providers.api.Distributor
|
||||
import io.element.android.libraries.push.providers.api.PushProvider
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import io.element.android.libraries.pushproviders.api.PusherSubscriber
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import android.content.Context
|
||||
import com.google.android.gms.common.ConnectionResult
|
||||
@@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.push.providers.api.PushData
|
||||
import io.element.android.libraries.pushproviders.api.PushData
|
||||
|
||||
/**
|
||||
* In this case, the format is:
|
||||
@@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import com.google.firebase.messaging.FirebaseMessagingService
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.push.providers.api.PushHandler
|
||||
import io.element.android.libraries.pushproviders.api.PushHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesTo
|
||||
import io.element.android.libraries.di.AppScope
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.firebase
|
||||
package io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.push.providers.api.PushData
|
||||
import io.element.android.libraries.pushproviders.api.PushData
|
||||
import io.element.android.tests.testutils.assertThrowsInDebug
|
||||
import org.junit.Test
|
||||
|
||||
@@ -20,7 +20,7 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.libraries.push.providers.unifiedpush"
|
||||
namespace = "io.element.android.libraries.pushproviders.unifiedpush"
|
||||
}
|
||||
|
||||
anvil {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.di.AppScope
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
@@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.push.providers.api.PushData
|
||||
import io.element.android.libraries.pushproviders.api.PushData
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import android.content.Context
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.providers.api.Distributor
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PusherSubscriber
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
object UnifiedPushConfig {
|
||||
/**
|
||||
@@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.network.RetrofitFactory
|
||||
import io.element.android.libraries.push.providers.unifiedpush.network.UnifiedPushApi
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.network.UnifiedPushApi
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
@@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushproviders.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import timber.log.Timber
|
||||
@@ -14,10 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.push.providers.api.PushData
|
||||
import io.element.android.libraries.pushproviders.api.PushData
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import javax.inject.Inject
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import android.content.Context
|
||||
import com.squareup.anvil.annotations.ContributesMultibinding
|
||||
@@ -22,8 +22,8 @@ import io.element.android.libraries.androidutils.system.getApplicationLabel
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.providers.api.Distributor
|
||||
import io.element.android.libraries.push.providers.api.PushProvider
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
import javax.inject.Inject
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import android.content.Context
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
@@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.push.providers.api.PushHandler
|
||||
import io.element.android.libraries.pushproviders.api.PushHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesTo
|
||||
import io.element.android.libraries.di.AppScope
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush.network
|
||||
package io.element.android.libraries.pushproviders.unifiedpush.network
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush.network
|
||||
package io.element.android.libraries.pushproviders.unifiedpush.network
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush.network
|
||||
package io.element.android.libraries.pushproviders.unifiedpush.network
|
||||
|
||||
import retrofit2.http.GET
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.push.providers.api.PushData
|
||||
import io.element.android.libraries.pushproviders.api.PushData
|
||||
import io.element.android.tests.testutils.assertThrowsInDebug
|
||||
import org.junit.Test
|
||||
|
||||
@@ -134,13 +134,6 @@
|
||||
<string name="room_timeline_beginning_of_room">"Dies ist der Anfang von %1$s."</string>
|
||||
<string name="room_timeline_beginning_of_room_no_name">"Dies ist der Beginn dieser Konversation."</string>
|
||||
<string name="room_timeline_read_marker_title">"Neu"</string>
|
||||
<string name="screen_analytics_prompt_data_usage">"Wir erfassen und analysieren "<b>"keine"</b>" Account-Daten"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Helfen Sie uns, Probleme zu identifizieren und %1$s zu verbessern, indem Sie anonyme Nutzungsdaten weitergeben."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"Sie können alle unsere Nutzerbedingungen %1$s lesen."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"hier"</string>
|
||||
<string name="screen_analytics_prompt_settings">"Sie können die Analyse jederzeit in den Einstellungen deaktivieren"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing">"Wir geben "<b>"keine"</b>" Informationen an Dritte weiter"</string>
|
||||
<string name="screen_analytics_prompt_title">"Helfen Sie %1$s zu verbessern"</string>
|
||||
<string name="screen_analytics_settings_share_data">"Teile Analyse-Daten"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Medienauswahl fehlgeschlagen, bitte versuche es erneut."</string>
|
||||
<string name="screen_report_content_block_user_hint">"Prüfe, ob du alle aktuellen und zukünftigen Nachrichten dieses Benutzers ausblenden möchtest"</string>
|
||||
|
||||
@@ -141,13 +141,6 @@
|
||||
<string name="room_timeline_beginning_of_room">"Acesta este începutul conversației %1$s."</string>
|
||||
<string name="room_timeline_beginning_of_room_no_name">"Acesta este începutul acestei conversații."</string>
|
||||
<string name="room_timeline_read_marker_title">"Nou"</string>
|
||||
<string name="screen_analytics_prompt_data_usage"><b>"Nu"</b>" înregistrăm sau profilăm datele contului"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Ajutați-ne să identificăm problemele și să îmbunătățim %1$s prin partajarea datelor de utilizare anonime."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"Puteți citi toate condițiile noastre %1$s."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"aici"</string>
|
||||
<string name="screen_analytics_prompt_settings">"Puteți dezactiva această opțiune oricând din setări"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing"><b>"Nu"</b>" împărtășim informații cu terți"</string>
|
||||
<string name="screen_analytics_prompt_title">"Ajutați la îmbunătățirea %1$s"</string>
|
||||
<string name="screen_analytics_settings_share_data">"Partajați datele analitice"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Selectarea fișierelor media a eșuat, încercați din nou."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Procesarea datelor media a eșuat, vă rugăm să încercați din nou."</string>
|
||||
|
||||
@@ -145,13 +145,6 @@
|
||||
<string name="room_timeline_beginning_of_room">"This is the beginning of %1$s."</string>
|
||||
<string name="room_timeline_beginning_of_room_no_name">"This is the beginning of this conversation."</string>
|
||||
<string name="room_timeline_read_marker_title">"New"</string>
|
||||
<string name="screen_analytics_prompt_data_usage">"We "<b>"don\'t"</b>" record or profile any account data"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Help us identify issues and improve %1$s by sharing anonymous usage data."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"You can read all our terms %1$s."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"here"</string>
|
||||
<string name="screen_analytics_prompt_settings">"You can turn this off anytime in settings"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing">"We "<b>"don\'t"</b>" share information with third parties"</string>
|
||||
<string name="screen_analytics_prompt_title">"Help improve %1$s"</string>
|
||||
<string name="screen_analytics_settings_share_data">"Share analytics data"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Failed selecting media, please try again."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Failed processing media to upload, please try again."</string>
|
||||
|
||||
@@ -101,7 +101,8 @@ fun DependencyHandlerScope.allLibrariesImpl() {
|
||||
}
|
||||
|
||||
fun DependencyHandlerScope.allServicesImpl() {
|
||||
implementation(project(":services:analytics:noop"))
|
||||
implementation(project(":services:analytics:impl"))
|
||||
implementation(project(":services:analyticsproviders:posthog"))
|
||||
implementation(project(":services:apperror:impl"))
|
||||
implementation(project(":services:appnavstate:impl"))
|
||||
implementation(project(":services:toolbox:impl"))
|
||||
|
||||
@@ -20,3 +20,8 @@ plugins {
|
||||
android {
|
||||
namespace = "io.element.android.services.analytics.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.services.analyticsproviders.api)
|
||||
implementation(libs.coroutines.core)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.analyticsproviders.api.AnalyticsProvider
|
||||
import io.element.android.services.analyticsproviders.api.trackers.AnalyticsTracker
|
||||
import io.element.android.services.analyticsproviders.api.trackers.ErrorTracker
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface AnalyticsService: AnalyticsTracker, ErrorTracker {
|
||||
fun getAvailableAnalyticsProviders(): List<AnalyticsProvider>
|
||||
|
||||
/**
|
||||
* Return a Flow of Boolean, true if the user has given their consent.
|
||||
*/
|
||||
fun getUserConsent(): Flow<Boolean>
|
||||
|
||||
/**
|
||||
* Update the user consent value.
|
||||
*/
|
||||
suspend fun setUserConsent(userConsent: Boolean)
|
||||
|
||||
/**
|
||||
* Return a Flow of Boolean, true if the user has been asked for their consent.
|
||||
*/
|
||||
fun didAskUserConsent(): Flow<Boolean>
|
||||
|
||||
/**
|
||||
* Store the fact that the user has been asked for their consent.
|
||||
*/
|
||||
suspend fun setDidAskUserConsent()
|
||||
|
||||
/**
|
||||
* Return a Flow of String, used for analytics Id.
|
||||
*/
|
||||
fun getAnalyticsId(): Flow<String>
|
||||
|
||||
/**
|
||||
* Update analyticsId from the AccountData.
|
||||
*/
|
||||
suspend fun setAnalyticsId(analyticsId: String)
|
||||
|
||||
/**
|
||||
* To be called when a session is destroyed.
|
||||
*/
|
||||
suspend fun onSignOut()
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("durationMs", durationMs)
|
||||
put("isVideo", isVideo)
|
||||
put("numParticipants", numParticipants)
|
||||
put("placed", placed)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("isVideo", isVideo)
|
||||
put("numParticipants", numParticipants)
|
||||
put("placed", placed)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("isVideo", isVideo)
|
||||
put("numParticipants", numParticipants)
|
||||
put("placed", placed)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("inThread", inThread)
|
||||
put("isEditing", isEditing)
|
||||
put("isReply", isReply)
|
||||
startsThread?.let { put("startsThread", it) }
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("isDM", isDM)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
context?.let { put("context", it) }
|
||||
cryptoModule?.let { put("cryptoModule", it.name) }
|
||||
put("domain", domain.name)
|
||||
put("name", name.name)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,468 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
index?.let { put("index", it) }
|
||||
interactionType?.let { put("interactionType", it.name) }
|
||||
put("name", name.name)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("isDM", isDM)
|
||||
put("isSpace", isSpace)
|
||||
put("roomSize", roomSize.name)
|
||||
trigger?.let { put("trigger", it.name) }
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
RoomDetailss,
|
||||
|
||||
/**
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
durationMs?.let { put("durationMs", it) }
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
context?.let { put("context", it) }
|
||||
itemCount?.let { put("itemCount", it) }
|
||||
put("name", name.name)
|
||||
put("timeMs", timeMs)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("granted", granted)
|
||||
put("permission", permission.name)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("authenticationType", authenticationType.name)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("command", command.name)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
put("errorCode", errorCode.name)
|
||||
put("errorReason", errorReason)
|
||||
put("refreshTokenAuth", refreshTokenAuth)
|
||||
put("softLogout", softLogout)
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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<String, Any>? {
|
||||
return mutableMapOf<String, Any>().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() }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user