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

@ -0,0 +1,12 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.api
fun interface RageshakeFeatureAvailability {
fun isAvailable(): Boolean
}

View file

@ -8,6 +8,7 @@
package io.element.android.features.rageshake.api.preferences
data class RageshakePreferencesState(
val isFeatureEnabled: Boolean,
val isEnabled: Boolean,
val isSupported: Boolean,
val sensitivity: Float,

View file

@ -12,14 +12,21 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
open class RageshakePreferencesStateProvider : PreviewParameterProvider<RageshakePreferencesState> {
override val values: Sequence<RageshakePreferencesState>
get() = sequenceOf(
aRageshakePreferencesState().copy(isEnabled = true, isSupported = true, sensitivity = 0.5f),
aRageshakePreferencesState().copy(isEnabled = true, isSupported = false, sensitivity = 0.5f),
aRageshakePreferencesState(isEnabled = true, isSupported = true, sensitivity = 0.5f),
aRageshakePreferencesState(isEnabled = true, isSupported = false, sensitivity = 0.5f),
)
}
fun aRageshakePreferencesState() = RageshakePreferencesState(
isEnabled = false,
isSupported = true,
sensitivity = 0.3f,
eventSink = {}
fun aRageshakePreferencesState(
isFeatureEnabled: Boolean = true,
isEnabled: Boolean = false,
isSupported: Boolean = true,
sensitivity: Float = 0.3f,
eventSink: (RageshakePreferencesEvents) -> Unit = {}
) = RageshakePreferencesState(
isFeatureEnabled = isFeatureEnabled,
isEnabled = isEnabled,
isSupported = isSupported,
sensitivity = sensitivity,
eventSink = eventSink,
)

View file

@ -36,28 +36,30 @@ fun RageshakePreferencesView(
}
Column(modifier = modifier) {
PreferenceCategory(title = stringResource(id = R.string.settings_rageshake)) {
if (state.isSupported) {
PreferenceSwitch(
title = stringResource(id = CommonStrings.preference_rageshake),
isChecked = state.isEnabled,
onCheckedChange = ::onEnabledChanged
)
PreferenceSlide(
title = stringResource(id = R.string.settings_rageshake_detection_threshold),
// summary = stringResource(id = CommonStrings.settings_rageshake_detection_threshold_summary),
value = state.sensitivity,
enabled = state.isEnabled,
// 5 possible values - steps are in ]0, 1[
steps = 3,
onValueChange = ::onSensitivityChanged
)
} else {
ListItem(
headlineContent = {
Text("Rageshaking is not supported by your device")
},
)
if (state.isFeatureEnabled) {
PreferenceCategory(title = stringResource(id = R.string.settings_rageshake)) {
if (state.isSupported) {
PreferenceSwitch(
title = stringResource(id = CommonStrings.preference_rageshake),
isChecked = state.isEnabled,
onCheckedChange = ::onEnabledChanged
)
PreferenceSlide(
title = stringResource(id = R.string.settings_rageshake_detection_threshold),
// summary = stringResource(id = CommonStrings.settings_rageshake_detection_threshold_summary),
value = state.sensitivity,
enabled = state.isEnabled,
// 5 possible values - steps are in ]0, 1[
steps = 3,
onValueChange = ::onSensitivityChanged
)
} else {
ListItem(
headlineContent = {
Text("Rageshaking is not supported by your device")
},
)
}
}
}
}

View file

@ -0,0 +1,22 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.impl
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.appconfig.RageshakeConfig
import io.element.android.appconfig.isEnabled
import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.libraries.di.AppScope
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class DefaultRageshakeFeatureAvailability @Inject constructor() : RageshakeFeatureAvailability {
override fun isAvailable(): Boolean {
return RageshakeConfig.isEnabled
}
}

View file

@ -16,10 +16,10 @@ import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import io.element.android.features.rageshake.api.crash.CrashDataStore
import io.element.android.features.rageshake.api.reporter.BugReporter
import io.element.android.features.rageshake.api.reporter.BugReporterListener
import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder
import io.element.android.features.rageshake.impl.crash.CrashDataStore
import io.element.android.features.rageshake.impl.screenshot.ScreenshotHolder
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter
import kotlinx.coroutines.CoroutineScope

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.api.crash
package io.element.android.features.rageshake.impl.crash
import kotlinx.coroutines.flow.Flow

View file

@ -9,15 +9,17 @@ package io.element.android.features.rageshake.impl.crash
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.rageshake.api.crash.CrashDataStore
import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.features.rageshake.api.crash.CrashDetectionEvents
import io.element.android.features.rageshake.api.crash.CrashDetectionPresenter
import io.element.android.features.rageshake.api.crash.CrashDetectionState
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.AppScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -25,12 +27,18 @@ import javax.inject.Inject
class DefaultCrashDetectionPresenter @Inject constructor(
private val buildMeta: BuildMeta,
private val crashDataStore: CrashDataStore,
) :
CrashDetectionPresenter {
private val rageshakeFeatureAvailability: RageshakeFeatureAvailability,
) : CrashDetectionPresenter {
@Composable
override fun present(): CrashDetectionState {
val localCoroutineScope = rememberCoroutineScope()
val crashDetected = crashDataStore.appHasCrashed().collectAsState(initial = false)
val crashDetected = remember {
if (rageshakeFeatureAvailability.isAvailable()) {
crashDataStore.appHasCrashed()
} else {
flowOf(false)
}
}.collectAsState(false)
fun handleEvents(event: CrashDetectionEvents) {
when (event) {

View file

@ -15,7 +15,6 @@ import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.rageshake.api.crash.CrashDataStore
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext

View file

@ -20,9 +20,9 @@ import io.element.android.features.rageshake.api.detection.RageshakeDetectionPre
import io.element.android.features.rageshake.api.detection.RageshakeDetectionState
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvents
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter
import io.element.android.features.rageshake.api.rageshake.RageShake
import io.element.android.features.rageshake.api.screenshot.ImageResult
import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder
import io.element.android.features.rageshake.impl.rageshake.RageShake
import io.element.android.features.rageshake.impl.screenshot.ScreenshotHolder
import io.element.android.libraries.di.AppScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -75,7 +75,8 @@ class DefaultRageshakeDetectionPresenter @Inject constructor(
LaunchedEffect(preferencesState.sensitivity) {
rageShake.setSensitivity(preferencesState.sensitivity)
}
val shouldStart = preferencesState.isEnabled &&
val shouldStart = preferencesState.isFeatureEnabled &&
preferencesState.isEnabled &&
preferencesState.isSupported &&
isStarted.value &&
!takeScreenshot.value &&

View file

@ -11,14 +11,16 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvents
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState
import io.element.android.features.rageshake.api.rageshake.RageShake
import io.element.android.features.rageshake.api.rageshake.RageshakeDataStore
import io.element.android.features.rageshake.impl.rageshake.RageShake
import io.element.android.features.rageshake.impl.rageshake.RageshakeDataStore
import io.element.android.libraries.di.AppScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -28,6 +30,7 @@ import javax.inject.Inject
class DefaultRageshakePreferencesPresenter @Inject constructor(
private val rageshake: RageShake,
private val rageshakeDataStore: RageshakeDataStore,
private val rageshakeFeatureAvailability: RageshakeFeatureAvailability,
) : RageshakePreferencesPresenter {
@Composable
override fun present(): RageshakePreferencesState {
@ -35,6 +38,7 @@ class DefaultRageshakePreferencesPresenter @Inject constructor(
val isSupported: MutableState<Boolean> = rememberSaveable {
mutableStateOf(rageshake.isAvailable())
}
val isFeatureAvailable = remember { rageshakeFeatureAvailability.isAvailable() }
val isEnabled = rageshakeDataStore
.isEnabled()
.collectAsState(initial = false)
@ -51,6 +55,7 @@ class DefaultRageshakePreferencesPresenter @Inject constructor(
}
return RageshakePreferencesState(
isFeatureEnabled = isFeatureAvailable,
isEnabled = isEnabled.value,
isSupported = isSupported.value,
sensitivity = sensitivity.value,

View file

@ -13,7 +13,6 @@ import android.hardware.SensorManager
import androidx.core.content.getSystemService
import com.squareup.anvil.annotations.ContributesBinding
import com.squareup.seismic.ShakeDetector
import io.element.android.features.rageshake.api.rageshake.RageShake
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.SingleIn

View file

@ -15,7 +15,6 @@ import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.floatPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.rageshake.api.rageshake.RageshakeDataStore
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.api.rageshake
package io.element.android.features.rageshake.impl.rageshake
interface RageShake {
/**

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.api.rageshake
package io.element.android.features.rageshake.impl.rageshake
import kotlinx.coroutines.flow.Flow

View file

@ -13,10 +13,10 @@ import androidx.core.net.toFile
import androidx.core.net.toUri
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.appconfig.RageshakeConfig
import io.element.android.features.rageshake.api.crash.CrashDataStore
import io.element.android.features.rageshake.api.reporter.BugReporter
import io.element.android.features.rageshake.api.reporter.BugReporterListener
import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder
import io.element.android.features.rageshake.impl.crash.CrashDataStore
import io.element.android.features.rageshake.impl.screenshot.ScreenshotHolder
import io.element.android.libraries.androidutils.file.compressFile
import io.element.android.libraries.androidutils.file.safeDelete
import io.element.android.libraries.core.coroutine.CoroutineDispatchers

View file

@ -11,7 +11,6 @@ import android.content.Context
import android.graphics.Bitmap
import androidx.core.net.toUri
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder
import io.element.android.libraries.androidutils.bitmap.writeBitmap
import io.element.android.libraries.androidutils.file.safeDelete
import io.element.android.libraries.di.AppScope

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.api.screenshot
package io.element.android.features.rageshake.impl.screenshot
import android.graphics.Bitmap

View file

@ -11,13 +11,13 @@ 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.rageshake.api.crash.CrashDataStore
import io.element.android.features.rageshake.api.reporter.BugReporter
import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder
import io.element.android.features.rageshake.test.crash.A_CRASH_DATA
import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import io.element.android.features.rageshake.test.screenshot.A_SCREENSHOT_URI
import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder
import io.element.android.features.rageshake.impl.crash.A_CRASH_DATA
import io.element.android.features.rageshake.impl.crash.CrashDataStore
import io.element.android.features.rageshake.impl.crash.FakeCrashDataStore
import io.element.android.features.rageshake.impl.screenshot.A_SCREENSHOT_URI
import io.element.android.features.rageshake.impl.screenshot.FakeScreenshotHolder
import io.element.android.features.rageshake.impl.screenshot.ScreenshotHolder
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.test.A_FAILURE_REASON
import io.element.android.tests.testutils.WarmUpRule

View file

@ -5,9 +5,8 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.test.crash
package io.element.android.features.rageshake.impl.crash
import io.element.android.features.rageshake.api.crash.CrashDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow

View file

@ -12,9 +12,9 @@ import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.rageshake.api.crash.CrashDetectionEvents
import io.element.android.features.rageshake.impl.crash.A_CRASH_DATA
import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter
import io.element.android.features.rageshake.test.crash.A_CRASH_DATA
import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import io.element.android.features.rageshake.impl.crash.FakeCrashDataStore
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.tests.testutils.WarmUpRule
@ -51,6 +51,20 @@ class CrashDetectionPresenterTest {
}
}
@Test
fun `present - initial state crash is ignored if the feature is not available`() = runTest {
val presenter = createPresenter(
FakeCrashDataStore(appHasCrashed = true),
isFeatureAvailable = false,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.crashDetected).isFalse()
}
}
@Test
fun `present - reset app has crashed`() = runTest {
val presenter = createPresenter(
@ -86,8 +100,10 @@ class CrashDetectionPresenterTest {
private fun createPresenter(
crashDataStore: FakeCrashDataStore = FakeCrashDataStore(),
buildMeta: BuildMeta = aBuildMeta(),
isFeatureAvailable: Boolean = true,
) = DefaultCrashDetectionPresenter(
buildMeta = buildMeta,
crashDataStore = crashDataStore,
rageshakeFeatureAvailability = { isFeatureAvailable },
)
}

View file

@ -15,9 +15,9 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvents
import io.element.android.features.rageshake.api.screenshot.ImageResult
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.features.rageshake.test.screenshot.FakeScreenshotHolder
import io.element.android.features.rageshake.impl.rageshake.FakeRageShake
import io.element.android.features.rageshake.impl.rageshake.FakeRageshakeDataStore
import io.element.android.features.rageshake.impl.screenshot.FakeScreenshotHolder
import io.element.android.libraries.matrix.test.AN_EXCEPTION
import io.element.android.tests.testutils.WarmUpRule
import io.mockk.mockk
@ -52,6 +52,7 @@ class RageshakeDetectionPresenterTest {
preferencesPresenter = DefaultRageshakePreferencesPresenter(
rageshake = rageshake,
rageshakeDataStore = rageshakeDataStore,
rageshakeFeatureAvailability = { true },
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -76,6 +77,7 @@ class RageshakeDetectionPresenterTest {
preferencesPresenter = DefaultRageshakePreferencesPresenter(
rageshake = rageshake,
rageshakeDataStore = rageshakeDataStore,
rageshakeFeatureAvailability = { true },
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -101,6 +103,7 @@ class RageshakeDetectionPresenterTest {
preferencesPresenter = DefaultRageshakePreferencesPresenter(
rageshake = rageshake,
rageshakeDataStore = rageshakeDataStore,
rageshakeFeatureAvailability = { true },
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -135,6 +138,7 @@ class RageshakeDetectionPresenterTest {
preferencesPresenter = DefaultRageshakePreferencesPresenter(
rageshake = rageshake,
rageshakeDataStore = rageshakeDataStore,
rageshakeFeatureAvailability = { true },
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -169,6 +173,7 @@ class RageshakeDetectionPresenterTest {
preferencesPresenter = DefaultRageshakePreferencesPresenter(
rageshake = rageshake,
rageshakeDataStore = rageshakeDataStore,
rageshakeFeatureAvailability = { true },
)
)
moleculeFlow(RecompositionMode.Immediate) {

View file

@ -12,9 +12,9 @@ import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvents
import io.element.android.features.rageshake.test.rageshake.A_SENSITIVITY
import io.element.android.features.rageshake.test.rageshake.FakeRageShake
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
import io.element.android.features.rageshake.impl.rageshake.A_SENSITIVITY
import io.element.android.features.rageshake.impl.rageshake.FakeRageShake
import io.element.android.features.rageshake.impl.rageshake.FakeRageshakeDataStore
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@ -28,7 +28,8 @@ class RageshakePreferencesPresenterTest {
fun `present - initial state available`() = runTest {
val presenter = DefaultRageshakePreferencesPresenter(
FakeRageShake(isAvailableValue = true),
FakeRageshakeDataStore(isEnabled = true)
FakeRageshakeDataStore(isEnabled = true),
rageshakeFeatureAvailability = { true },
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
@ -44,7 +45,8 @@ class RageshakePreferencesPresenterTest {
fun `present - initial state not available`() = runTest {
val presenter = DefaultRageshakePreferencesPresenter(
FakeRageShake(isAvailableValue = false),
FakeRageshakeDataStore(isEnabled = true)
FakeRageshakeDataStore(isEnabled = true),
rageshakeFeatureAvailability = { true },
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
@ -60,7 +62,8 @@ class RageshakePreferencesPresenterTest {
fun `present - enable and disable`() = runTest {
val presenter = DefaultRageshakePreferencesPresenter(
FakeRageShake(isAvailableValue = true),
FakeRageshakeDataStore(isEnabled = true)
FakeRageshakeDataStore(isEnabled = true),
rageshakeFeatureAvailability = { true },
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
@ -79,7 +82,8 @@ class RageshakePreferencesPresenterTest {
fun `present - set sensitivity`() = runTest {
val presenter = DefaultRageshakePreferencesPresenter(
FakeRageShake(isAvailableValue = true),
FakeRageshakeDataStore(isEnabled = true)
FakeRageshakeDataStore(isEnabled = true),
rageshakeFeatureAvailability = { true },
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()

View file

@ -5,9 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.test.rageshake
import io.element.android.features.rageshake.api.rageshake.RageShake
package io.element.android.features.rageshake.impl.rageshake
class FakeRageShake(
private var isAvailableValue: Boolean = true

View file

@ -5,9 +5,8 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.test.rageshake
package io.element.android.features.rageshake.impl.rageshake
import io.element.android.features.rageshake.api.rageshake.RageshakeDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow

View file

@ -8,9 +8,10 @@
package io.element.android.features.rageshake.impl.reporter
import com.google.common.truth.Truth.assertThat
import io.element.android.appconfig.RageshakeConfig
import io.element.android.features.rageshake.api.reporter.BugReporterListener
import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder
import io.element.android.features.rageshake.impl.crash.FakeCrashDataStore
import io.element.android.features.rageshake.impl.screenshot.FakeScreenshotHolder
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
import io.element.android.libraries.matrix.test.FakeSdkMetadata
@ -138,7 +139,7 @@ class DefaultBugReporterTest {
val foundValues = collectValuesFromFormData(request)
assertThat(foundValues["app"]).isEqualTo("element-x-android")
assertThat(foundValues["app"]).isEqualTo(RageshakeConfig.BUG_REPORT_APP_NAME)
assertThat(foundValues["can_contact"]).isEqualTo("true")
assertThat(foundValues["device_id"]).isEqualTo("ABCDEFGH")
assertThat(foundValues["sdk_sha"]).isEqualTo("123456789")

View file

@ -16,7 +16,9 @@ class DefaultBugReporterUrlProviderTest {
@Test
fun `test DefaultBugReporterUrlProvider`() {
val sut = DefaultBugReporterUrlProvider()
val result = sut.provide()
assertThat(result).isEqualTo(RageshakeConfig.BUG_REPORT_URL.toHttpUrl())
if (RageshakeConfig.BUG_REPORT_URL.isNotEmpty()) {
val result = sut.provide()
assertThat(result).isEqualTo(RageshakeConfig.BUG_REPORT_URL.toHttpUrl())
}
}
}

View file

@ -5,10 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.rageshake.test.screenshot
package io.element.android.features.rageshake.impl.screenshot
import android.graphics.Bitmap
import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder
const val A_SCREENSHOT_URI = "file://content/uri"