Merge pull request #394 from vector-im/feature/bma/moveShowkaseButton
Move showkase button
This commit is contained in:
commit
c8dc2a5e57
16 changed files with 59 additions and 198 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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 = {}
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
content = {
|
|
||||||
FeatureListContent(it, state)
|
|
||||||
}
|
}
|
||||||
)
|
PreferenceCategory(title = "Showkase") {
|
||||||
|
PreferenceText(
|
||||||
|
title = "Open Showkase browser",
|
||||||
|
onClick = onOpenShowkase
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:d07bdb794fe858dfc3e3122c10b24dcf5a4918d21deb3c87686139a2d94f4f43
|
oid sha256:5d806cbab0f26fb4f471adb5fbecfc600603a7651c5391501d42b13b23617a4c
|
||||||
size 18918
|
size 29301
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:e944e15b9eb9477e57b002d6b16c8a28bc8bc25d8bef40cdf6982509e4424c7f
|
oid sha256:d04eb5d2ebb8b740edcaac00912994e8c164e7b5083595d4085d350af0ca6c33
|
||||||
size 18211
|
size 28482
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue