Element config (#4471)

* Add handy extension "VariantDimension.buildConfigFieldStr"

* Update configuration for MapTiler.

* Update configuration for Sentry.

* Build AnalyticsConfig depending on analytics configuration.

* Configure analytics policy url.

* Add handy extension "VariantDimension.buildConfigFieldBoolean"

* Configure legal urls.

* Add a way to disable rageshake / reporting bugs.

* Update screenshots

* Quality

* Fix test

* Use `ifBlank` extension

* Add missing configuration for PostHog

* Update configuration for Rageshake.

* Add build log.

* Disable crash detection if rageshake feature is not available.
Disabled twice.

* Hide link to analytics policy if the link is missing.

* Fix test when run in enterprise context.

* Use RageshakeFeatureAvailability where appropriate.

* Rename file.

* Move some classes to their correct module.

* Update screenshots

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Benoit Marty
2025-03-27 11:25:04 +01:00
committed by GitHub
parent 0838f4259a
commit 87fd1372a9
95 changed files with 613 additions and 273 deletions

View File

@@ -1,3 +1,5 @@
import config.BuildTimeConfig
import extension.buildConfigFieldStr
import extension.setupAnvil
/*
@@ -12,6 +14,21 @@ plugins {
android {
namespace = "io.element.android.services.analyticsproviders.posthog"
buildFeatures {
buildConfig = true
}
defaultConfig {
buildConfigFieldStr(
name = "POSTHOG_HOST",
value = BuildTimeConfig.SERVICES_POSTHOG_HOST.takeIf { isEnterpriseBuild } ?: ""
)
buildConfigFieldStr(
name = "POSTHOG_APIKEY",
value = BuildTimeConfig.SERVICES_POSTHOG_APIKEY.takeIf { isEnterpriseBuild } ?: ""
)
}
}
setupAnvil()
@@ -21,6 +38,7 @@ dependencies {
implementation(libs.posthog) {
exclude("com.android.support", "support-annotations")
}
implementation(projects.features.enterprise.api)
implementation(projects.libraries.core)
implementation(projects.libraries.di)
implementation(projects.services.analyticsproviders.api)

View File

@@ -11,7 +11,6 @@ import android.content.Context
import com.posthog.PostHogInterface
import com.posthog.android.PostHogAndroid
import com.posthog.android.PostHogAndroidConfig
import io.element.android.libraries.core.extensions.isElement
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.ApplicationContext
import javax.inject.Inject
@@ -22,8 +21,7 @@ class PostHogFactory @Inject constructor(
private val posthogEndpointConfigProvider: PosthogEndpointConfigProvider,
) {
fun createPosthog(): PostHogInterface? {
if (!buildMeta.isElement()) return null
val endpoint = posthogEndpointConfigProvider.provide()
val endpoint = posthogEndpointConfigProvider.provide() ?: return null
return PostHogAndroid.with(
context,
PostHogAndroidConfig(

View File

@@ -10,4 +10,6 @@ package io.element.android.services.analyticsproviders.posthog
data class PosthogEndpointConfig(
val host: String,
val apiKey: String,
)
) {
val isValid = host.isNotBlank() && apiKey.isNotBlank()
}

View File

@@ -7,24 +7,40 @@
package io.element.android.services.analyticsproviders.posthog
import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.libraries.core.extensions.isElement
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.meta.BuildType
import javax.inject.Inject
class PosthogEndpointConfigProvider @Inject constructor(
private val buildMeta: BuildMeta,
private val enterpriseService: EnterpriseService,
) {
fun provide(): PosthogEndpointConfig {
return when (buildMeta.buildType) {
BuildType.RELEASE -> PosthogEndpointConfig(
host = "https://posthog.element.io",
apiKey = "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
)
BuildType.NIGHTLY,
BuildType.DEBUG -> PosthogEndpointConfig(
host = "https://posthog.element.dev",
apiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN",
)
fun provide(): PosthogEndpointConfig? {
return if (enterpriseService.isEnterpriseBuild) {
PosthogEndpointConfig(
host = BuildConfig.POSTHOG_HOST,
apiKey = BuildConfig.POSTHOG_APIKEY,
).takeIf {
// Note that if the config is invalid, this module will not be included in the build.
// So the configuration should be always valid.
it.isValid
}
} else if (buildMeta.isElement()) {
when (buildMeta.buildType) {
BuildType.RELEASE -> PosthogEndpointConfig(
host = "https://posthog.element.io",
apiKey = "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
)
BuildType.NIGHTLY,
BuildType.DEBUG -> PosthogEndpointConfig(
host = "https://posthog.element.dev",
apiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN",
)
}
} else {
null
}
}
}

View File

@@ -1,3 +1,5 @@
import config.BuildTimeConfig
import extension.buildConfigFieldStr
import extension.readLocalProperty
import extension.setupAnvil
@@ -19,13 +21,15 @@ android {
}
defaultConfig {
buildConfigField(
type = "String",
buildConfigFieldStr(
name = "SENTRY_DSN",
value = (System.getenv("ELEMENT_ANDROID_SENTRY_DSN")
?: readLocalProperty("services.analyticsproviders.sentry.dsn")
value = if (isEnterpriseBuild) {
BuildTimeConfig.SERVICES_SENTRY_DSN
} else {
System.getenv("ELEMENT_ANDROID_SENTRY_DSN")
?: readLocalProperty("services.analyticsproviders.sentry.dsn")
}
?: ""
).let { "\"$it\"" }
)
}
}

View File

@@ -41,9 +41,7 @@ class SentryAnalyticsProvider @Inject constructor(
Timber.tag(analyticsTag.value).d("Initializing Sentry")
if (Sentry.isEnabled()) return
val dsn = if (SentryConfig.DSN.isNotBlank()) {
SentryConfig.DSN
} else {
val dsn = SentryConfig.DSN.ifBlank {
Timber.w("No Sentry DSN provided, Sentry will not be initialized")
return
}