Browse Source

Merge pull request #394 from vector-im/feature/bma/moveShowkaseButton

Move showkase button
feature/jme/open-room-member-details-when-clicking-on-user-data
Benoit Marty 1 year ago committed by GitHub
parent
commit
c27487839c
  1. 1
      .maestro/tests/init.yaml
  2. 9
      appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
  3. 21
      appnav/src/main/kotlin/io/element/android/appnav/root/RootEvents.kt
  4. 13
      appnav/src/main/kotlin/io/element/android/appnav/root/RootPresenter.kt
  5. 2
      appnav/src/main/kotlin/io/element/android/appnav/root/RootState.kt
  6. 4
      appnav/src/main/kotlin/io/element/android/appnav/root/RootStateProvider.kt
  7. 7
      appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt
  8. 71
      appnav/src/main/kotlin/io/element/android/appnav/root/ShowkaseButton.kt
  9. 17
      appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt
  10. 5
      build.gradle.kts
  11. 9
      docs/screenshot_testing.md
  12. 15
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt
  13. 62
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt
  14. 11
      libraries/featureflag/ui/src/main/kotlin/io/element/android/libraries/featureflag/ui/FeatureListView.kt
  15. BIN
      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
  16. BIN
      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
.maestro/tests/init.yaml

@ -3,6 +3,5 @@ appId: ${APP_ID}
- clearState - clearState
- launchApp: - launchApp:
clearKeychain: true clearKeychain: true
- tapOn: "Close showkase button"
- runFlow: ./assertions/assertInitDisplayed.yaml - runFlow: ./assertions/assertInitDisplayed.yaml
- takeScreenshot: build/maestro/000-FirstScreen - takeScreenshot: build/maestro/000-FirstScreen

9
appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt

@ -16,7 +16,6 @@
package io.element.android.appnav package io.element.android.appnav
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Parcelable import android.os.Parcelable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -24,7 +23,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.bumble.appyx.core.composable.Children import com.bumble.appyx.core.composable.Children
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
@ -53,7 +51,6 @@ import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.tests.uitests.openShowkase
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -140,17 +137,11 @@ class RootFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val activity = LocalContext.current as Activity
fun openShowkase() {
openShowkase(activity)
}
val state = presenter.present() val state = presenter.present()
RootView( RootView(
state = state, state = state,
modifier = modifier, modifier = modifier,
onOpenBugReport = this::onOpenBugReport, onOpenBugReport = this::onOpenBugReport,
onOpenShowkase = ::openShowkase
) { ) {
Children( Children(
navModel = backstack, navModel = backstack,

21
appnav/src/main/kotlin/io/element/android/appnav/root/RootEvents.kt

@ -1,21 +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.appnav.root
sealed interface RootEvents {
object HideShowkaseButton : RootEvents
}

13
appnav/src/main/kotlin/io/element/android/appnav/root/RootPresenter.kt

@ -17,8 +17,6 @@
package io.element.android.appnav.root package io.element.android.appnav.root
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import io.element.android.features.rageshake.api.crash.CrashDetectionPresenter import io.element.android.features.rageshake.api.crash.CrashDetectionPresenter
import io.element.android.features.rageshake.api.detection.RageshakeDetectionPresenter import io.element.android.features.rageshake.api.detection.RageshakeDetectionPresenter
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
@ -31,23 +29,12 @@ class RootPresenter @Inject constructor(
@Composable @Composable
override fun present(): RootState { override fun present(): RootState {
val isShowkaseButtonVisible = rememberSaveable {
mutableStateOf(true)
}
val rageshakeDetectionState = rageshakeDetectionPresenter.present() val rageshakeDetectionState = rageshakeDetectionPresenter.present()
val crashDetectionState = crashDetectionPresenter.present() val crashDetectionState = crashDetectionPresenter.present()
fun handleEvent(event: RootEvents) {
when (event) {
RootEvents.HideShowkaseButton -> isShowkaseButtonVisible.value = false
}
}
return RootState( return RootState(
isShowkaseButtonVisible = isShowkaseButtonVisible.value,
rageshakeDetectionState = rageshakeDetectionState, rageshakeDetectionState = rageshakeDetectionState,
crashDetectionState = crashDetectionState, crashDetectionState = crashDetectionState,
eventSink = ::handleEvent
) )
} }
} }

2
appnav/src/main/kotlin/io/element/android/appnav/root/RootState.kt

@ -22,8 +22,6 @@ import io.element.android.features.rageshake.api.detection.RageshakeDetectionSta
@Immutable @Immutable
data class RootState( data class RootState(
val isShowkaseButtonVisible: Boolean,
val rageshakeDetectionState: RageshakeDetectionState, val rageshakeDetectionState: RageshakeDetectionState,
val crashDetectionState: CrashDetectionState, val crashDetectionState: CrashDetectionState,
val eventSink: (RootEvents) -> Unit
) )

4
appnav/src/main/kotlin/io/element/android/appnav/root/RootStateProvider.kt

@ -24,12 +24,10 @@ open class RootStateProvider : PreviewParameterProvider<RootState> {
override val values: Sequence<RootState> override val values: Sequence<RootState>
get() = sequenceOf( get() = sequenceOf(
aRootState().copy( aRootState().copy(
isShowkaseButtonVisible = true,
rageshakeDetectionState = aRageshakeDetectionState().copy(showDialog = false), rageshakeDetectionState = aRageshakeDetectionState().copy(showDialog = false),
crashDetectionState = aCrashDetectionState().copy(crashDetected = true), crashDetectionState = aCrashDetectionState().copy(crashDetected = true),
), ),
aRootState().copy( aRootState().copy(
isShowkaseButtonVisible = true,
rageshakeDetectionState = aRageshakeDetectionState().copy(showDialog = true), rageshakeDetectionState = aRageshakeDetectionState().copy(showDialog = true),
crashDetectionState = aCrashDetectionState().copy(crashDetected = false), crashDetectionState = aCrashDetectionState().copy(crashDetected = false),
) )
@ -37,8 +35,6 @@ open class RootStateProvider : PreviewParameterProvider<RootState> {
} }
fun aRootState() = RootState( fun aRootState() = RootState(
isShowkaseButtonVisible = false,
rageshakeDetectionState = aRageshakeDetectionState(), rageshakeDetectionState = aRageshakeDetectionState(),
crashDetectionState = aCrashDetectionState(), crashDetectionState = aCrashDetectionState(),
eventSink = {}
) )

7
appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt

@ -37,7 +37,6 @@ fun RootView(
state: RootState, state: RootState,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onOpenBugReport: () -> Unit = {}, onOpenBugReport: () -> Unit = {},
onOpenShowkase: () -> Unit = {},
children: @Composable BoxScope.() -> Unit, children: @Composable BoxScope.() -> Unit,
) { ) {
Box( Box(
@ -46,7 +45,6 @@ fun RootView(
contentAlignment = Alignment.TopCenter, contentAlignment = Alignment.TopCenter,
) { ) {
children() children()
val eventSink = state.eventSink
fun onOpenBugReport() { fun onOpenBugReport() {
state.crashDetectionState.eventSink(CrashDetectionEvents.ResetAppHasCrashed) state.crashDetectionState.eventSink(CrashDetectionEvents.ResetAppHasCrashed)
@ -54,11 +52,6 @@ fun RootView(
onOpenBugReport.invoke() onOpenBugReport.invoke()
} }
ShowkaseButton(
isVisible = state.isShowkaseButtonVisible,
onCloseClicked = { eventSink(RootEvents.HideShowkaseButton) },
onClick = onOpenShowkase
)
RageshakeDetectionView( RageshakeDetectionView(
state = state.rageshakeDetectionState, state = state.rageshakeDetectionState,
onOpenBugReport = ::onOpenBugReport, onOpenBugReport = ::onOpenBugReport,

71
appnav/src/main/kotlin/io/element/android/appnav/root/ShowkaseButton.kt

@ -1,71 +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.appnav.root
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
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.IconButton
import io.element.android.libraries.designsystem.theme.components.Text
@Composable
internal fun ShowkaseButton(
isVisible: Boolean,
modifier: Modifier = Modifier,
onClick: () -> Unit = {},
onCloseClicked: () -> Unit = {},
) {
if (isVisible) {
Button(
modifier = modifier
.padding(top = 32.dp),
onClick = onClick
) {
Text(text = "Showkase Browser")
IconButton(
modifier = Modifier
.padding(start = 8.dp)
.size(16.dp),
onClick = onCloseClicked,
) {
Icon(imageVector = Icons.Filled.Close, contentDescription = "Close showkase button")
}
}
}
}
@Preview
@Composable
internal fun ShowkaseButtonLightPreview() = ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
internal fun ShowkaseButtonDarkPreview() = ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
ShowkaseButton(isVisible = true)
}

17
appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt

@ -22,7 +22,6 @@ import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow import app.cash.molecule.moleculeFlow
import app.cash.turbine.test import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.appnav.root.RootEvents
import io.element.android.appnav.root.RootPresenter import io.element.android.appnav.root.RootPresenter
import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter
import io.element.android.features.rageshake.impl.detection.DefaultRageshakeDetectionPresenter import io.element.android.features.rageshake.impl.detection.DefaultRageshakeDetectionPresenter
@ -44,21 +43,7 @@ class RootPresenterTest {
}.test { }.test {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.isShowkaseButtonVisible).isTrue() assertThat(initialState.crashDetectionState.crashDetected).isFalse()
}
}
@Test
fun `present - hide showkase button`() = runTest {
val presenter = createPresenter()
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
skipItems(1)
val initialState = awaitItem()
assertThat(initialState.isShowkaseButtonVisible).isTrue()
initialState.eventSink.invoke(RootEvents.HideShowkaseButton)
assertThat(awaitItem().isShowkaseButtonVisible).isFalse()
} }
} }

5
build.gradle.kts

@ -285,12 +285,15 @@ tasks.register("runQualityChecks") {
// Make sure to delete old screenshots before recording new ones // Make sure to delete old screenshots before recording new ones
subprojects { subprojects {
val snapshotsDir = File("${project.path}/src/test/snapshots") val snapshotsDir = File("${project.projectDir}/src/test/snapshots")
val removeOldScreenshotsTask = tasks.register("removeOldSnapshots") { val removeOldScreenshotsTask = tasks.register("removeOldSnapshots") {
onlyIf { snapshotsDir.exists() } onlyIf { snapshotsDir.exists() }
doFirst { doFirst {
println("Delete previous screenshots located at $snapshotsDir\n")
snapshotsDir.deleteRecursively() snapshotsDir.deleteRecursively()
} }
} }
tasks.findByName("recordPaparazzi")?.dependsOn(removeOldScreenshotsTask) tasks.findByName("recordPaparazzi")?.dependsOn(removeOldScreenshotsTask)
tasks.findByName("recordPaparazziDebug")?.dependsOn(removeOldScreenshotsTask)
tasks.findByName("recordPaparazziRelease")?.dependsOn(removeOldScreenshotsTask)
} }

9
docs/screenshot_testing.md

@ -30,11 +30,16 @@ If installed correctly, `git push` and `git pull` will now include LFS content.
## Recording ## Recording
It's recommended to delete the content of the folder `/snapshots` before recording. ```shell
./gradlew recordPaparazziDebug
```
The task will delete the content of the folder `/snapshots` before recording (see the task `removeOldSnapshots` defined in the project).
If this is not the case, you can run
```shell ```shell
rm -rf ./tests/uitests/src/test/snapshots rm -rf ./tests/uitests/src/test/snapshots
./gradlew recordPaparazziDebug
``` ```
Paparazzi will generate images in `:tests:uitests/src/test/snapshots`, which will need to be committed to the repository using Git LFS. Paparazzi will generate images in `:tests:uitests/src/test/snapshots`, which will need to be committed to the repository using Git LFS.

15
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt

@ -16,8 +16,11 @@
package io.element.android.features.preferences.impl.developer package io.element.android.features.preferences.impl.developer
import android.app.Activity
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import com.airbnb.android.showkase.ui.ShowkaseBrowserActivity
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.core.plugin.Plugin
@ -35,11 +38,21 @@ class DeveloperSettingsNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val activity = LocalContext.current as Activity
fun openShowkase() {
val intent = ShowkaseBrowserActivity.getIntent(
context = activity,
rootModuleCanonicalName = "io.element.android.libraries.designsystem.showkase.DesignSystemShowkaseRootModule"
)
activity.startActivity(intent)
}
val state = presenter.present() val state = presenter.present()
DeveloperSettingsView( DeveloperSettingsView(
state = state, state = state,
modifier = modifier, modifier = modifier,
onBackPressed = this::navigateUp onOpenShowkase = ::openShowkase,
onBackPressed = ::navigateUp
) )
} }
} }

62
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt

@ -14,28 +14,18 @@
* limitations under the License. * limitations under the License.
*/ */
@file:OptIn(ExperimentalMaterial3Api::class)
package io.element.android.features.preferences.impl.developer package io.element.android.features.preferences.impl.developer
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.libraries.designsystem.components.preferences.PreferenceTopAppBar import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.featureflag.ui.FeatureListView import io.element.android.libraries.featureflag.ui.FeatureListView
import io.element.android.libraries.featureflag.ui.model.FeatureUiModel import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
import io.element.android.libraries.ui.strings.R import io.element.android.libraries.ui.strings.R
@ -43,45 +33,42 @@ import io.element.android.libraries.ui.strings.R
@Composable @Composable
fun DeveloperSettingsView( fun DeveloperSettingsView(
state: DeveloperSettingsState, state: DeveloperSettingsState,
modifier: Modifier = Modifier, onOpenShowkase: () -> Unit,
onBackPressed: () -> Unit, onBackPressed: () -> Unit,
modifier: Modifier = Modifier,
) { ) {
Scaffold( PreferenceView(
modifier = modifier modifier = modifier,
.fillMaxSize() onBackPressed = onBackPressed,
.systemBarsPadding() title = stringResource(id = R.string.common_developer_options)
.imePadding(), ) {
contentWindowInsets = WindowInsets.statusBars, // Note: this is OK to hardcode strings in this debug screen.
topBar = { PreferenceCategory(title = "Feature flags") {
PreferenceTopAppBar( FeatureListContent(state)
title = stringResource(id = R.string.common_developer_options), }
onBackPressed = onBackPressed, PreferenceCategory(title = "Showkase") {
PreferenceText(
title = "Open Showkase browser",
onClick = onOpenShowkase
) )
},
content = {
FeatureListContent(it, state)
} }
) }
} }
@Composable @Composable
fun FeatureListContent( fun FeatureListContent(
paddingValues: PaddingValues,
state: DeveloperSettingsState, state: DeveloperSettingsState,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
fun onFeatureEnabled(feature: FeatureUiModel, isEnabled: Boolean) { fun onFeatureEnabled(feature: FeatureUiModel, isEnabled: Boolean) {
state.eventSink(DeveloperSettingsEvents.UpdateEnabledFeature(feature, isEnabled)) state.eventSink(DeveloperSettingsEvents.UpdateEnabledFeature(feature, isEnabled))
} }
Box( FeatureListView(
modifier = modifier modifier = modifier,
.padding(paddingValues) features = state.features,
.fillMaxSize() onCheckedChange = ::onFeatureEnabled,
) { )
FeatureListView(features = state.features, onCheckedChange = ::onFeatureEnabled)
}
} }
@Preview @Preview
@ -98,6 +85,7 @@ fun DeveloperSettingsViewDarkPreview(@PreviewParameter(DeveloperSettingsStatePro
private fun ContentToPreview(state: DeveloperSettingsState) { private fun ContentToPreview(state: DeveloperSettingsState) {
DeveloperSettingsView( DeveloperSettingsView(
state = state, state = state,
onOpenShowkase = {},
onBackPressed = {} onBackPressed = {}
) )
} }

11
libraries/featureflag/ui/src/main/kotlin/io/element/android/libraries/featureflag/ui/FeatureListView.kt

@ -16,8 +16,7 @@
package io.element.android.libraries.featureflag.ui package io.element.android.libraries.featureflag.ui
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -34,14 +33,10 @@ fun FeatureListView(
onCheckedChange: (FeatureUiModel, Boolean) -> Unit, onCheckedChange: (FeatureUiModel, Boolean) -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
LazyColumn( Column(
modifier = modifier, modifier = modifier,
) { ) {
items( features.forEach { feature ->
items = features,
key = { it.key }
) { feature ->
fun onCheckedChange(isChecked: Boolean) { fun onCheckedChange(isChecked: Boolean) {
onCheckedChange(feature, isChecked) onCheckedChange(feature, isChecked)
} }

BIN
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 (Stored with Git LFS)

Binary file not shown.

BIN
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 (Stored with Git LFS)

Binary file not shown.
Loading…
Cancel
Save