From 43d28c5a3d0ef4e538f09ba419f86df0ce03802a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 18:12:17 +0200 Subject: [PATCH 01/12] No need to sort AnalyticsProvider (it was copied from PushProvider) --- .../android/features/analytics/test/FakeAnalyticsService.kt | 2 +- .../android/services/analytics/api/AnalyticsService.kt | 5 ++++- .../services/analytics/impl/DefaultAnalyticsService.kt | 4 ++-- .../services/analyticsproviders/api/AnalyticsProvider.kt | 5 ----- .../analyticsproviders/posthog/PosthogAnalyticsProvider.kt | 1 - .../services/analyticsproviders/posthog/PosthogConfig.kt | 1 - 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/features/analytics/test/src/main/kotlin/io/element/android/features/analytics/test/FakeAnalyticsService.kt b/features/analytics/test/src/main/kotlin/io/element/android/features/analytics/test/FakeAnalyticsService.kt index 6e84c58d2a..9e3fe8bb59 100644 --- a/features/analytics/test/src/main/kotlin/io/element/android/features/analytics/test/FakeAnalyticsService.kt +++ b/features/analytics/test/src/main/kotlin/io/element/android/features/analytics/test/FakeAnalyticsService.kt @@ -33,7 +33,7 @@ class FakeAnalyticsService( private val didAskUserConsentFlow = MutableStateFlow(didAskUserConsent) val capturedEvents = mutableListOf() - override fun getAvailableAnalyticsProviders(): List = emptyList() + override fun getAvailableAnalyticsProviders(): Set = emptySet() override fun getUserConsent(): Flow = isEnabledFlow diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt index 9c6fb2d522..309a885ad2 100644 --- a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt @@ -22,7 +22,10 @@ import io.element.android.services.analyticsproviders.api.trackers.ErrorTracker import kotlinx.coroutines.flow.Flow interface AnalyticsService: AnalyticsTracker, ErrorTracker { - fun getAvailableAnalyticsProviders(): List + /** + * Get the available analytics providers. + */ + fun getAvailableAnalyticsProviders(): Set /** * Return a Flow of Boolean, true if the user has given their consent. diff --git a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt index 5639f954ac..42acd29b56 100644 --- a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt +++ b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt @@ -56,8 +56,8 @@ class DefaultAnalyticsService @Inject constructor( observeSessions() } - override fun getAvailableAnalyticsProviders(): List { - return analyticsProviders.sortedBy { it.index } + override fun getAvailableAnalyticsProviders(): Set { + return analyticsProviders } override fun getUserConsent(): Flow { diff --git a/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsProvider.kt b/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsProvider.kt index 548f47d7ad..807c8d1413 100644 --- a/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsProvider.kt +++ b/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsProvider.kt @@ -20,11 +20,6 @@ import io.element.android.services.analyticsproviders.api.trackers.AnalyticsTrac import io.element.android.services.analyticsproviders.api.trackers.ErrorTracker interface AnalyticsProvider: AnalyticsTracker, ErrorTracker { - /** - * Allow to sort providers, from lower index to higher index. - */ - val index: Int - /** * User friendly name. */ diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt index 3b2d392896..fb2e341e1e 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt @@ -35,7 +35,6 @@ import javax.inject.Inject class PosthogAnalyticsProvider @Inject constructor( private val postHogFactory: PostHogFactory, ) : AnalyticsProvider { - override val index = PosthogConfig.index override val name = PosthogConfig.name private var posthog: PostHog? = null diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt index 877fb7dc9a..96d8659b11 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt @@ -17,7 +17,6 @@ package io.element.android.services.analyticsproviders.posthog object PosthogConfig { - const val index = 0 const val name = "Posthog" const val postHogHost = "https://posthog.element.dev" const val postHogApiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN" From a30837864e5909bee36f3c9d4b6e19c6d354b038 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 18:14:53 +0200 Subject: [PATCH 02/12] add posthog to dict. --- .idea/dictionaries/shared.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/.idea/dictionaries/shared.xml b/.idea/dictionaries/shared.xml index aafe02a2c8..2fc10f455b 100644 --- a/.idea/dictionaries/shared.xml +++ b/.idea/dictionaries/shared.xml @@ -8,6 +8,7 @@ measurables onboarding placeables + posthog showkase snackbar swipeable From 5a367c64c4ebbcefb3731f6ac0c0dda9358b2669 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 18:27:10 +0200 Subject: [PATCH 03/12] Restore NoopAnalyticsService (not used but can be useful for forks). --- services/analytics/noop/build.gradle.kts | 3 +- .../analytics/noop/NoopAnalyticsService.kt | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt diff --git a/services/analytics/noop/build.gradle.kts b/services/analytics/noop/build.gradle.kts index a5678f5cb3..000434a05c 100644 --- a/services/analytics/noop/build.gradle.kts +++ b/services/analytics/noop/build.gradle.kts @@ -19,7 +19,7 @@ plugins { } android { - namespace = "io.element.android.services.analytics.impl" + namespace = "io.element.android.services.analytics.noop" } anvil { @@ -28,6 +28,7 @@ anvil { dependencies { implementation(libs.dagger) + implementation(projects.libraries.architecture) implementation(projects.libraries.di) api(projects.services.analytics.api) } diff --git a/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt new file mode 100644 index 0000000000..f82e7ff550 --- /dev/null +++ b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.noop + +import com.squareup.anvil.annotations.ContributesBinding +import 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.libraries.di.AppScope +import io.element.android.libraries.di.SingleIn +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.flowOf +import javax.inject.Inject + +@SingleIn(AppScope::class) +@ContributesBinding(AppScope::class) +class NoopAnalyticsService @Inject constructor( +) : AnalyticsService { + override fun getAvailableAnalyticsProviders(): Set = emptySet() + override fun getUserConsent(): Flow = flowOf(false) + override suspend fun setUserConsent(userConsent: Boolean) = Unit + override fun didAskUserConsent(): Flow = flowOf(true) + override suspend fun setDidAskUserConsent() = Unit + override fun getAnalyticsId(): Flow = flowOf("") + override suspend fun setAnalyticsId(analyticsId: String) = Unit + override suspend fun onSignOut() = Unit + override suspend fun reset() = Unit + override fun capture(event: VectorAnalyticsEvent) = Unit + override fun screen(screen: VectorAnalyticsScreen) = Unit + override fun updateUserProperties(userProperties: UserProperties) = Unit + override fun trackError(throwable: Throwable) = Unit +} From f3e26276b20781d6c565928be666d233fbfafc59 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 18:35:22 +0200 Subject: [PATCH 04/12] Update tag value and make it internal. --- .../analyticsproviders/posthog/log/AnalyticsLoggerTag.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/log/AnalyticsLoggerTag.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/log/AnalyticsLoggerTag.kt index 8e64ca100d..a298bda1c5 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/log/AnalyticsLoggerTag.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/log/AnalyticsLoggerTag.kt @@ -18,4 +18,4 @@ package io.element.android.services.analyticsproviders.posthog.log import io.element.android.libraries.core.log.logger.LoggerTag -val analyticsTag = LoggerTag("Analytics") +internal val analyticsTag = LoggerTag("Posthog") From c93625080e1bfbff8a2682986daff69d4a78ccb0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 18:58:10 +0200 Subject: [PATCH 05/12] Implement Sentry module as an AnalyticsProvider. --- gradle/libs.versions.toml | 2 +- .../sentry/build.gradle.kts | 35 ++++++++ .../sentry/SentryAnalyticsProvider.kt | 79 +++++++++++++++++++ .../analyticsproviders/sentry/SentryConfig.kt | 24 ++++++ .../sentry/log/AnalyticsLoggerTag.kt | 21 +++++ 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 services/analyticsproviders/sentry/build.gradle.kts create mode 100644 services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt create mode 100644 services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt create mode 100644 services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/log/AnalyticsLoggerTag.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7ebf397ac7..fe9a5aa182 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:2.0.0" # Analytics posthog = "com.posthog.android:posthog:2.0.3" -sentry_android = "io.sentry:sentry-android:6.26.0" +sentry = "io.sentry:sentry-android:6.26.0" matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:42b2faa417c1e95f430bf8f6e379adba25ad5ef8" # Di diff --git a/services/analyticsproviders/sentry/build.gradle.kts b/services/analyticsproviders/sentry/build.gradle.kts new file mode 100644 index 0000000000..34c444eb7d --- /dev/null +++ b/services/analyticsproviders/sentry/build.gradle.kts @@ -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. + */ +plugins { + id("io.element.android-library") + alias(libs.plugins.anvil) +} + +android { + namespace = "io.element.android.services.analyticsproviders.sentry" +} + +anvil { + generateDaggerFactories.set(true) +} + +dependencies { + implementation(libs.dagger) + implementation(libs.sentry) + implementation(projects.libraries.core) + implementation(projects.libraries.di) + implementation(projects.services.analyticsproviders.api) +} diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt new file mode 100644 index 0000000000..6bc4df426f --- /dev/null +++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt @@ -0,0 +1,79 @@ +/* + * 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.analyticsproviders.sentry + +import android.content.Context +import com.squareup.anvil.annotations.ContributesMultibinding +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.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.di.ApplicationContext +import io.element.android.services.analyticsproviders.api.AnalyticsProvider +import io.element.android.services.analyticsproviders.sentry.log.analyticsTag +import io.sentry.Sentry +import io.sentry.SentryOptions +import io.sentry.android.core.SentryAndroid +import timber.log.Timber +import javax.inject.Inject + +@ContributesMultibinding(AppScope::class) +class SentryAnalyticsProvider @Inject constructor( + @ApplicationContext private val context: Context, + private val buildMeta: BuildMeta, +) : AnalyticsProvider { + override val name = SentryConfig.name + + override fun init() { + Timber.tag(analyticsTag.value).d("Initializing Sentry") + if (Sentry.isEnabled()) return + SentryAndroid.init(context) { options -> + options.dsn = SentryConfig.dns + options.beforeSend = SentryOptions.BeforeSendCallback { event, _ -> event } + options.tracesSampleRate = 1.0 + options.isEnableUserInteractionTracing = true + options.environment = buildMeta.buildType.toSentryEnv() + options.diagnosticLevel + } + } + + override fun stop() { + Timber.tag(analyticsTag.value).d("Stopping Sentry") + Sentry.close() + } + + override fun capture(event: VectorAnalyticsEvent) { + } + + override fun screen(screen: VectorAnalyticsScreen) { + } + + override fun updateUserProperties(userProperties: UserProperties) { + } + + override fun trackError(throwable: Throwable) { + Sentry.captureException(throwable) + } +} + +private fun BuildType.toSentryEnv() = when (this) { + BuildType.RELEASE -> SentryConfig.envRelease + BuildType.NIGHTLY, + BuildType.DEBUG -> SentryConfig.envDebug +} diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt new file mode 100644 index 0000000000..9d85290bf6 --- /dev/null +++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt @@ -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.services.analyticsproviders.sentry + +object SentryConfig { + const val name = "Sentry" + const val dns = "https://f6acc9cfc2024641b28c87ad95e73e66@sentry.tools.element.io/49" + const val envDebug = "DEBUG" + const val envRelease = "RELEASE" +} diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/log/AnalyticsLoggerTag.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/log/AnalyticsLoggerTag.kt new file mode 100644 index 0000000000..f792009ee4 --- /dev/null +++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/log/AnalyticsLoggerTag.kt @@ -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.services.analyticsproviders.sentry.log + +import io.element.android.libraries.core.log.logger.LoggerTag + +internal val analyticsTag = LoggerTag("Sentry") From c5c130ab671736c7244db8672286c612191f0ca2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 19:19:17 +0200 Subject: [PATCH 06/12] Ensure the application react correctly if analytics is disabled at compilation time. --- features/preferences/impl/build.gradle.kts | 1 + .../impl/root/PreferencesRootPresenter.kt | 4 ++++ .../preferences/impl/root/PreferencesRootState.kt | 1 + .../impl/root/PreferencesRootStateProvider.kt | 1 + .../preferences/impl/root/PreferencesRootView.kt | 12 +++++++----- .../impl/root/PreferencesRootPresenterTest.kt | 3 +++ .../main/kotlin/extension/DependencyHandleScope.kt | 2 ++ 7 files changed, 19 insertions(+), 5 deletions(-) diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index f183f7f1fa..5ca0c719fe 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -47,6 +47,7 @@ dependencies { implementation(projects.features.ftue.api) implementation(projects.libraries.matrixui) implementation(projects.features.logout.api) + implementation(projects.services.analytics.api) implementation(projects.services.toolbox.api) implementation(libs.datetime) implementation(libs.accompanist.placeholder) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt index 66ff62ee2b..0cd2e7f7db 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt @@ -35,6 +35,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.getCurrentUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus +import io.element.android.services.analytics.api.AnalyticsService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import javax.inject.Inject @@ -43,6 +44,7 @@ class PreferencesRootPresenter @Inject constructor( private val logoutPresenter: LogoutPreferencePresenter, private val matrixClient: MatrixClient, private val sessionVerificationService: SessionVerificationService, + private val analyticsService: AnalyticsService, private val buildType: BuildType, private val versionFormatter: VersionFormatter, private val snackbarDispatcher: SnackbarDispatcher, @@ -58,6 +60,7 @@ class PreferencesRootPresenter @Inject constructor( } val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() + val hasAnalyticsProviders = remember { analyticsService.getAvailableAnalyticsProviders().isNotEmpty() } // Session verification status (unknown, not verified, verified) val sessionVerifiedStatus by sessionVerificationService.sessionVerifiedStatus.collectAsState() @@ -72,6 +75,7 @@ class PreferencesRootPresenter @Inject constructor( myUser = matrixUser.value, version = versionFormatter.get(), showCompleteVerification = sessionIsNotVerified, + showAnalyticsSettings = hasAnalyticsProviders, showDeveloperSettings = showDeveloperSettings, snackbarMessage = snackbarMessage, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt index 2b0963c53c..540c470815 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt @@ -25,6 +25,7 @@ data class PreferencesRootState( val myUser: MatrixUser?, val version: String, val showCompleteVerification: Boolean, + val showAnalyticsSettings: Boolean, val showDeveloperSettings: Boolean, val snackbarMessage: SnackbarMessage?, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt index 9dbd54ffff..e8c148267f 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt @@ -25,6 +25,7 @@ fun aPreferencesRootState() = PreferencesRootState( myUser = null, version = "Version 1.1 (1)", showCompleteVerification = true, + showAnalyticsSettings = true, showDeveloperSettings = true, snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete), ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt index 01d790f8b9..90eade31ab 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt @@ -82,11 +82,13 @@ fun PreferencesRootView( ) Divider() } - PreferenceText( - title = stringResource(id = CommonStrings.common_analytics), - icon = Icons.Outlined.InsertChart, - onClick = onOpenAnalytics, - ) + if (state.showAnalyticsSettings) { + PreferenceText( + title = stringResource(id = CommonStrings.common_analytics), + icon = Icons.Outlined.InsertChart, + onClick = onOpenAnalytics, + ) + } PreferenceText( title = stringResource(id = CommonStrings.action_report_bug), icon = Icons.Outlined.BugReport, diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt index 91bb0c12f3..580426fcfa 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt @@ -20,6 +20,7 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.features.analytics.test.FakeAnalyticsService import io.element.android.features.logout.impl.DefaultLogoutPreferencePresenter import io.element.android.libraries.architecture.Async import io.element.android.libraries.core.meta.BuildType @@ -41,6 +42,7 @@ class PreferencesRootPresenterTest { logoutPresenter, matrixClient, FakeSessionVerificationService(), + FakeAnalyticsService(), BuildType.DEBUG, FakeVersionFormatter(), SnackbarDispatcher(), @@ -61,6 +63,7 @@ class PreferencesRootPresenterTest { ) ) assertThat(loadedState.showDeveloperSettings).isEqualTo(true) + assertThat(loadedState.showAnalyticsSettings).isEqualTo(false) } } } diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 88f499b993..cc6526a3e8 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -103,6 +103,8 @@ fun DependencyHandlerScope.allLibrariesImpl() { } fun DependencyHandlerScope.allServicesImpl() { + // For analytics configuration, either use noop, or use the impl, with at least one analyticsproviders implementation + // implementation(project(":services:analytics:noop")) implementation(project(":services:analytics:impl")) implementation(project(":services:analyticsproviders:posthog")) implementation(project(":services:apperror:impl")) From a774d96585f954865404170766979667480b2fa9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 19:19:59 +0200 Subject: [PATCH 07/12] Include Sentry module. --- plugins/src/main/kotlin/extension/DependencyHandleScope.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index cc6526a3e8..fb082e27a7 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -107,6 +107,8 @@ fun DependencyHandlerScope.allServicesImpl() { // implementation(project(":services:analytics:noop")) implementation(project(":services:analytics:impl")) implementation(project(":services:analyticsproviders:posthog")) + implementation(project(":services:analyticsproviders:sentry")) + implementation(project(":services:apperror:impl")) implementation(project(":services:appnavstate:impl")) implementation(project(":services:toolbox:impl")) From 3e7234f3af2c6d5ab0b2642d1cd400cc2a1a455a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 19:28:52 +0200 Subject: [PATCH 08/12] Disable Sentry auto-init --- .../sentry/src/main/AndroidManifest.xml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 services/analyticsproviders/sentry/src/main/AndroidManifest.xml diff --git a/services/analyticsproviders/sentry/src/main/AndroidManifest.xml b/services/analyticsproviders/sentry/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..079912fc00 --- /dev/null +++ b/services/analyticsproviders/sentry/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + From 6c9a36f56f33cd871a4cdd1f6444d840a1d5ddfd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 20:55:04 +0200 Subject: [PATCH 09/12] Add a way to crash this app on demand. Useful to test Crash detection, and analytics report, etc. --- .../preferences/impl/developer/DeveloperSettingsView.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt index 1ead19154d..82b477fcc9 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt @@ -56,6 +56,12 @@ fun DeveloperSettingsView( RageshakePreferencesView( state = state.rageshakeState, ) + PreferenceCategory(title = "Crash", showDivider = false) { + PreferenceText( + title = "Crash the app 💥!,", + onClick = { error("This crash is a test.") } + ) + } val cache = state.cacheSize PreferenceCategory(title = "Cache", showDivider = false) { PreferenceText( From a0dbba58b346172db8fc675cb166e265c5a8b29c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 21 Jul 2023 21:40:08 +0200 Subject: [PATCH 10/12] Fix typo --- .../preferences/impl/developer/DeveloperSettingsView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt index 82b477fcc9..7c5b5d91c8 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt @@ -58,7 +58,7 @@ fun DeveloperSettingsView( ) PreferenceCategory(title = "Crash", showDivider = false) { PreferenceText( - title = "Crash the app 💥!,", + title = "Crash the app 💥", onClick = { error("This crash is a test.") } ) } From 8fd9e332985ecabc28bd8a045e6820b595afc7b2 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 21 Jul 2023 19:53:55 +0000 Subject: [PATCH 11/12] Update screenshots --- ...eloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...eloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...loperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...loperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png index 4fb8f691f4..597ebdcb61 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb77df9e072715ed947537e4474d504b5b5d533bfe9cd888362a421fea5b53b5 -size 44068 +oid sha256:6c0a16524e1017274eeb0f07a50a47c6351af9a901355b54cccbc9ec799e79f4 +size 45174 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png index 4fb8f691f4..597ebdcb61 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb77df9e072715ed947537e4474d504b5b5d533bfe9cd888362a421fea5b53b5 -size 44068 +oid sha256:6c0a16524e1017274eeb0f07a50a47c6351af9a901355b54cccbc9ec799e79f4 +size 45174 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png index ff0fc9708e..e1ba6b44d4 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:004a25de04aac1ca9cbbad77581e0b52a6f8fba30aa2e64c03a791c54b297d5a -size 48875 +oid sha256:abb7854a1e47764a907434cdf32e138b95c947bab682da485eea86f9726cf3b9 +size 49946 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png index ff0fc9708e..e1ba6b44d4 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:004a25de04aac1ca9cbbad77581e0b52a6f8fba30aa2e64c03a791c54b297d5a -size 48875 +oid sha256:abb7854a1e47764a907434cdf32e138b95c947bab682da485eea86f9726cf3b9 +size 49946 From c0fdb01470087c6256459e78e82d326116bb49f8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 24 Jul 2023 11:02:02 +0200 Subject: [PATCH 12/12] Use dns for element-x-android project. --- .../android/services/analyticsproviders/sentry/SentryConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt index 9d85290bf6..f2048b59f0 100644 --- a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt +++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt @@ -18,7 +18,7 @@ package io.element.android.services.analyticsproviders.sentry object SentryConfig { const val name = "Sentry" - const val dns = "https://f6acc9cfc2024641b28c87ad95e73e66@sentry.tools.element.io/49" + const val dns = "https://32f7ff6a6e724f90838b7654042b2e81@sentry.tools.element.io/59" const val envDebug = "DEBUG" const val envRelease = "RELEASE" }