Merge pull request #4581 from element-hq/feature/fga/advanced_settings_theme_rework
change (preferences) : use PreferenceDropdown for appearance
This commit is contained in:
@@ -7,16 +7,13 @@
|
||||
|
||||
package io.element.android.features.preferences.impl.advanced
|
||||
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
|
||||
|
||||
sealed interface AdvancedSettingsEvents {
|
||||
data class SetDeveloperModeEnabled(val enabled: Boolean) : AdvancedSettingsEvents
|
||||
data class SetSharePresenceEnabled(val enabled: Boolean) : AdvancedSettingsEvents
|
||||
data class SetCompressMedia(val compress: Boolean) : AdvancedSettingsEvents
|
||||
data object ChangeTheme : AdvancedSettingsEvents
|
||||
data object CancelChangeTheme : AdvancedSettingsEvents
|
||||
data class SetTheme(val theme: Theme) : AdvancedSettingsEvents
|
||||
data class SetTheme(val theme: ThemeOption) : AdvancedSettingsEvents
|
||||
data class SetTimelineMediaPreviewValue(val value: MediaPreviewValue) : AdvancedSettingsEvents
|
||||
data class SetHideInviteAvatars(val value: Boolean) : AdvancedSettingsEvents
|
||||
}
|
||||
|
||||
@@ -9,11 +9,10 @@ package io.element.android.features.preferences.impl.advanced
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.compound.theme.mapToTheme
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
@@ -39,11 +38,9 @@ class AdvancedSettingsPresenter @Inject constructor(
|
||||
val doesCompressMedia by remember {
|
||||
sessionPreferencesStore.doesCompressMedia()
|
||||
}.collectAsState(initial = true)
|
||||
val theme by remember {
|
||||
val theme = remember {
|
||||
appPreferencesStore.getThemeFlow().mapToTheme()
|
||||
}.collectAsState(initial = Theme.System)
|
||||
var showChangeThemeDialog by remember { mutableStateOf(false) }
|
||||
|
||||
val hideInviteAvatars by remember {
|
||||
appPreferencesStore.getHideInviteAvatarsFlow()
|
||||
}.collectAsState(false)
|
||||
@@ -52,6 +49,16 @@ class AdvancedSettingsPresenter @Inject constructor(
|
||||
appPreferencesStore.getTimelineMediaPreviewValueFlow()
|
||||
}.collectAsState(initial = MediaPreviewValue.On)
|
||||
|
||||
val themeOption by remember {
|
||||
derivedStateOf {
|
||||
when (theme.value) {
|
||||
Theme.System -> ThemeOption.System
|
||||
Theme.Dark -> ThemeOption.Dark
|
||||
Theme.Light -> ThemeOption.Light
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleEvents(event: AdvancedSettingsEvents) {
|
||||
when (event) {
|
||||
is AdvancedSettingsEvents.SetDeveloperModeEnabled -> localCoroutineScope.launch {
|
||||
@@ -63,11 +70,12 @@ class AdvancedSettingsPresenter @Inject constructor(
|
||||
is AdvancedSettingsEvents.SetCompressMedia -> localCoroutineScope.launch {
|
||||
sessionPreferencesStore.setCompressMedia(event.compress)
|
||||
}
|
||||
AdvancedSettingsEvents.CancelChangeTheme -> showChangeThemeDialog = false
|
||||
AdvancedSettingsEvents.ChangeTheme -> showChangeThemeDialog = true
|
||||
is AdvancedSettingsEvents.SetTheme -> localCoroutineScope.launch {
|
||||
appPreferencesStore.setTheme(event.theme.name)
|
||||
showChangeThemeDialog = false
|
||||
when (event.theme) {
|
||||
ThemeOption.System -> appPreferencesStore.setTheme(Theme.System.name)
|
||||
ThemeOption.Dark -> appPreferencesStore.setTheme(Theme.Dark.name)
|
||||
ThemeOption.Light -> appPreferencesStore.setTheme(Theme.Light.name)
|
||||
}
|
||||
}
|
||||
is AdvancedSettingsEvents.SetHideInviteAvatars -> localCoroutineScope.launch {
|
||||
appPreferencesStore.setHideInviteAvatars(event.value)
|
||||
@@ -82,8 +90,7 @@ class AdvancedSettingsPresenter @Inject constructor(
|
||||
isDeveloperModeEnabled = isDeveloperModeEnabled,
|
||||
isSharePresenceEnabled = isSharePresenceEnabled,
|
||||
doesCompressMedia = doesCompressMedia,
|
||||
theme = theme,
|
||||
showChangeThemeDialog = showChangeThemeDialog,
|
||||
theme = themeOption,
|
||||
hideInviteAvatars = hideInviteAvatars,
|
||||
timelineMediaPreviewValue = timelineMediaPreviewValue,
|
||||
eventSink = { handleEvents(it) }
|
||||
|
||||
@@ -7,16 +7,33 @@
|
||||
|
||||
package io.element.android.features.preferences.impl.advanced
|
||||
|
||||
import io.element.android.compound.theme.Theme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.libraries.designsystem.components.preferences.DropdownOption
|
||||
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
data class AdvancedSettingsState(
|
||||
val isDeveloperModeEnabled: Boolean,
|
||||
val isSharePresenceEnabled: Boolean,
|
||||
val doesCompressMedia: Boolean,
|
||||
val theme: Theme,
|
||||
val showChangeThemeDialog: Boolean,
|
||||
val theme: ThemeOption,
|
||||
val hideInviteAvatars: Boolean,
|
||||
val timelineMediaPreviewValue: MediaPreviewValue,
|
||||
val eventSink: (AdvancedSettingsEvents) -> Unit
|
||||
)
|
||||
|
||||
enum class ThemeOption : DropdownOption {
|
||||
System {
|
||||
@Composable
|
||||
override fun getText(): String = stringResource(CommonStrings.common_system)
|
||||
},
|
||||
Dark {
|
||||
@Composable
|
||||
override fun getText(): String = stringResource(CommonStrings.common_dark)
|
||||
},
|
||||
Light {
|
||||
@Composable
|
||||
override fun getText(): String = stringResource(CommonStrings.common_light)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
package io.element.android.features.preferences.impl.advanced
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
|
||||
|
||||
open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSettingsState> {
|
||||
@@ -16,7 +15,6 @@ open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSett
|
||||
get() = sequenceOf(
|
||||
aAdvancedSettingsState(),
|
||||
aAdvancedSettingsState(isDeveloperModeEnabled = true),
|
||||
aAdvancedSettingsState(showChangeThemeDialog = true),
|
||||
aAdvancedSettingsState(isSharePresenceEnabled = true),
|
||||
aAdvancedSettingsState(doesCompressMedia = true),
|
||||
aAdvancedSettingsState(hideInviteAvatars = true),
|
||||
@@ -28,16 +26,15 @@ fun aAdvancedSettingsState(
|
||||
isDeveloperModeEnabled: Boolean = false,
|
||||
isSharePresenceEnabled: Boolean = false,
|
||||
doesCompressMedia: Boolean = false,
|
||||
showChangeThemeDialog: Boolean = false,
|
||||
hideInviteAvatars: Boolean = false,
|
||||
theme: ThemeOption = ThemeOption.System,
|
||||
timelineMediaPreviewValue: MediaPreviewValue = MediaPreviewValue.On,
|
||||
eventSink: (AdvancedSettingsEvents) -> Unit = {},
|
||||
) = AdvancedSettingsState(
|
||||
isDeveloperModeEnabled = isDeveloperModeEnabled,
|
||||
isSharePresenceEnabled = isSharePresenceEnabled,
|
||||
doesCompressMedia = doesCompressMedia,
|
||||
theme = Theme.System,
|
||||
showChangeThemeDialog = showChangeThemeDialog,
|
||||
theme = theme,
|
||||
hideInviteAvatars = hideInviteAvatars,
|
||||
timelineMediaPreviewValue = timelineMediaPreviewValue,
|
||||
eventSink = eventSink
|
||||
|
||||
@@ -12,14 +12,11 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import im.vector.app.features.analytics.plan.Interaction
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.compound.theme.themes
|
||||
import io.element.android.features.preferences.impl.R
|
||||
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ListOption
|
||||
import io.element.android.libraries.designsystem.components.dialogs.SingleSelectionDialog
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceDropdown
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
@@ -34,8 +31,7 @@ import io.element.android.libraries.matrix.api.media.MediaPreviewValue
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.services.analytics.compose.LocalAnalyticsService
|
||||
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
@Composable
|
||||
fun AdvancedSettingsView(
|
||||
@@ -49,15 +45,12 @@ fun AdvancedSettingsView(
|
||||
onBackClick = onBackClick,
|
||||
title = stringResource(id = CommonStrings.common_advanced_settings)
|
||||
) {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(text = stringResource(id = CommonStrings.common_appearance))
|
||||
},
|
||||
trailingContent = ListItemContent.Text(
|
||||
state.theme.toHumanReadable()
|
||||
),
|
||||
onClick = {
|
||||
state.eventSink(AdvancedSettingsEvents.ChangeTheme)
|
||||
PreferenceDropdown(
|
||||
title = stringResource(id = CommonStrings.common_appearance),
|
||||
selectedOption = state.theme,
|
||||
options = ThemeOption.entries.toPersistentList(),
|
||||
onSelectOption = { logLevel ->
|
||||
state.eventSink(AdvancedSettingsEvents.SetTheme(logLevel))
|
||||
}
|
||||
)
|
||||
ListItem(
|
||||
@@ -108,21 +101,6 @@ fun AdvancedSettingsView(
|
||||
)
|
||||
ModerationAndSafety(state)
|
||||
}
|
||||
|
||||
if (state.showChangeThemeDialog) {
|
||||
SingleSelectionDialog(
|
||||
options = getOptions(),
|
||||
initialSelection = themes.indexOf(state.theme),
|
||||
onSelectOption = {
|
||||
state.eventSink(
|
||||
AdvancedSettingsEvents.SetTheme(
|
||||
themes[it]
|
||||
)
|
||||
)
|
||||
},
|
||||
onDismissRequest = { state.eventSink(AdvancedSettingsEvents.CancelChangeTheme) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -176,24 +154,6 @@ private fun ModerationAndSafety(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getOptions(): ImmutableList<ListOption> {
|
||||
return themes.map {
|
||||
ListOption(title = it.toHumanReadable())
|
||||
}.toImmutableList()
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Theme.toHumanReadable(): String {
|
||||
return stringResource(
|
||||
id = when (this) {
|
||||
Theme.System -> CommonStrings.common_system
|
||||
Theme.Dark -> CommonStrings.common_dark
|
||||
Theme.Light -> CommonStrings.common_light
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewWithLargeHeight
|
||||
@Composable
|
||||
internal fun AdvancedSettingsViewLightPreview(@PreviewParameter(AdvancedSettingsStateProvider::class) state: AdvancedSettingsState) =
|
||||
|
||||
@@ -7,22 +7,28 @@
|
||||
|
||||
package io.element.android.features.preferences.impl.developer.tracing
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.element.android.libraries.designsystem.components.preferences.DropdownOption
|
||||
|
||||
enum class LogLevelItem : DropdownOption {
|
||||
ERROR {
|
||||
override val text: String = "Error"
|
||||
@Composable
|
||||
override fun getText(): String = "Error"
|
||||
},
|
||||
WARN {
|
||||
override val text: String = "Warn"
|
||||
@Composable
|
||||
override fun getText(): String = "Warn"
|
||||
},
|
||||
INFO {
|
||||
override val text: String = "Info"
|
||||
@Composable
|
||||
override fun getText(): String = "Info"
|
||||
},
|
||||
DEBUG {
|
||||
override val text: String = "Debug"
|
||||
@Composable
|
||||
override fun getText(): String = "Debug"
|
||||
},
|
||||
TRACE {
|
||||
override val text: String = "Trace"
|
||||
@Composable
|
||||
override fun getText(): String = "Trace"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,10 @@ 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.compound.theme.Theme
|
||||
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
|
||||
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
||||
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import io.element.android.tests.testutils.awaitLastSequentialItem
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@@ -30,12 +29,12 @@ class AdvancedSettingsPresenterTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.isDeveloperModeEnabled).isFalse()
|
||||
assertThat(initialState.showChangeThemeDialog).isFalse()
|
||||
assertThat(initialState.isSharePresenceEnabled).isTrue()
|
||||
assertThat(initialState.doesCompressMedia).isTrue()
|
||||
assertThat(initialState.theme).isEqualTo(Theme.System)
|
||||
with(awaitItem()) {
|
||||
assertThat(isDeveloperModeEnabled).isFalse()
|
||||
assertThat(isSharePresenceEnabled).isTrue()
|
||||
assertThat(doesCompressMedia).isTrue()
|
||||
assertThat(theme).isEqualTo(ThemeOption.System)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,12 +44,17 @@ class AdvancedSettingsPresenterTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.isDeveloperModeEnabled).isFalse()
|
||||
initialState.eventSink.invoke(AdvancedSettingsEvents.SetDeveloperModeEnabled(true))
|
||||
assertThat(awaitItem().isDeveloperModeEnabled).isTrue()
|
||||
initialState.eventSink.invoke(AdvancedSettingsEvents.SetDeveloperModeEnabled(false))
|
||||
assertThat(awaitItem().isDeveloperModeEnabled).isFalse()
|
||||
with(awaitItem()) {
|
||||
assertThat(isDeveloperModeEnabled).isFalse()
|
||||
eventSink(AdvancedSettingsEvents.SetDeveloperModeEnabled(true))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(isDeveloperModeEnabled).isTrue()
|
||||
eventSink(AdvancedSettingsEvents.SetDeveloperModeEnabled(false))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(isDeveloperModeEnabled).isFalse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,12 +64,17 @@ class AdvancedSettingsPresenterTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.isSharePresenceEnabled).isTrue()
|
||||
initialState.eventSink.invoke(AdvancedSettingsEvents.SetSharePresenceEnabled(false))
|
||||
assertThat(awaitItem().isSharePresenceEnabled).isFalse()
|
||||
initialState.eventSink.invoke(AdvancedSettingsEvents.SetSharePresenceEnabled(true))
|
||||
assertThat(awaitItem().isSharePresenceEnabled).isTrue()
|
||||
with(awaitItem()) {
|
||||
assertThat(isSharePresenceEnabled).isTrue()
|
||||
eventSink(AdvancedSettingsEvents.SetSharePresenceEnabled(false))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(isSharePresenceEnabled).isFalse()
|
||||
eventSink(AdvancedSettingsEvents.SetSharePresenceEnabled(true))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(isSharePresenceEnabled).isTrue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,12 +84,17 @@ class AdvancedSettingsPresenterTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.doesCompressMedia).isTrue()
|
||||
initialState.eventSink.invoke(AdvancedSettingsEvents.SetCompressMedia(false))
|
||||
assertThat(awaitItem().doesCompressMedia).isFalse()
|
||||
initialState.eventSink.invoke(AdvancedSettingsEvents.SetCompressMedia(true))
|
||||
assertThat(awaitItem().doesCompressMedia).isTrue()
|
||||
with(awaitItem()) {
|
||||
assertThat(doesCompressMedia).isTrue()
|
||||
eventSink(AdvancedSettingsEvents.SetCompressMedia(false))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(doesCompressMedia).isFalse()
|
||||
eventSink(AdvancedSettingsEvents.SetCompressMedia(true))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(doesCompressMedia).isTrue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,20 +104,61 @@ class AdvancedSettingsPresenterTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
initialState.eventSink.invoke(AdvancedSettingsEvents.ChangeTheme)
|
||||
val withDialog = awaitItem()
|
||||
assertThat(withDialog.showChangeThemeDialog).isTrue()
|
||||
// Cancel
|
||||
withDialog.eventSink(AdvancedSettingsEvents.CancelChangeTheme)
|
||||
val withoutDialog = awaitItem()
|
||||
assertThat(withoutDialog.showChangeThemeDialog).isFalse()
|
||||
withDialog.eventSink.invoke(AdvancedSettingsEvents.ChangeTheme)
|
||||
assertThat(awaitItem().showChangeThemeDialog).isTrue()
|
||||
withDialog.eventSink(AdvancedSettingsEvents.SetTheme(Theme.Light))
|
||||
val withNewTheme = awaitItem()
|
||||
assertThat(withNewTheme.showChangeThemeDialog).isFalse()
|
||||
assertThat(withNewTheme.theme).isEqualTo(Theme.Light)
|
||||
with(awaitItem()) {
|
||||
assertThat(theme).isEqualTo(ThemeOption.System)
|
||||
eventSink(AdvancedSettingsEvents.SetTheme(ThemeOption.Dark))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(theme).isEqualTo(ThemeOption.Dark)
|
||||
eventSink(AdvancedSettingsEvents.SetTheme(ThemeOption.Light))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(theme).isEqualTo(ThemeOption.Light)
|
||||
eventSink(AdvancedSettingsEvents.SetTheme(ThemeOption.System))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(theme).isEqualTo(ThemeOption.System)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - hide invite avatars`() = runTest {
|
||||
val presenter = createAdvancedSettingsPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
with(awaitItem()) {
|
||||
assertThat(hideInviteAvatars).isFalse()
|
||||
eventSink(AdvancedSettingsEvents.SetHideInviteAvatars(true))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(hideInviteAvatars).isTrue()
|
||||
eventSink(AdvancedSettingsEvents.SetHideInviteAvatars(false))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(hideInviteAvatars).isFalse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - timeline media preview value`() = runTest {
|
||||
val presenter = createAdvancedSettingsPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
with(awaitItem()) {
|
||||
assertThat(timelineMediaPreviewValue).isEqualTo(MediaPreviewValue.On)
|
||||
eventSink(AdvancedSettingsEvents.SetTimelineMediaPreviewValue(MediaPreviewValue.Off))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(timelineMediaPreviewValue).isEqualTo(MediaPreviewValue.Off)
|
||||
eventSink(AdvancedSettingsEvents.SetTimelineMediaPreviewValue(MediaPreviewValue.Private))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(timelineMediaPreviewValue).isEqualTo(MediaPreviewValue.Private)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.Interaction
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.features.preferences.impl.R
|
||||
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analytics.compose.LocalAnalyticsService
|
||||
@@ -29,6 +29,7 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AdvancedSettingsViewTest {
|
||||
@@ -49,29 +50,17 @@ class AdvancedSettingsViewTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clicking on Appearance emits the expected event`() {
|
||||
val eventsRecorder = EventsRecorder<AdvancedSettingsEvents>()
|
||||
rule.setAdvancedSettingsView(
|
||||
state = aAdvancedSettingsState(
|
||||
eventSink = eventsRecorder
|
||||
),
|
||||
)
|
||||
rule.clickOn(CommonStrings.common_appearance)
|
||||
eventsRecorder.assertSingle(AdvancedSettingsEvents.ChangeTheme)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clicking on other theme emits the expected event`() {
|
||||
val eventsRecorder = EventsRecorder<AdvancedSettingsEvents>()
|
||||
rule.setAdvancedSettingsView(
|
||||
state = aAdvancedSettingsState(
|
||||
eventSink = eventsRecorder,
|
||||
showChangeThemeDialog = true
|
||||
),
|
||||
)
|
||||
rule.clickOn(CommonStrings.common_appearance)
|
||||
rule.clickOn(CommonStrings.common_dark)
|
||||
eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTheme(Theme.Dark))
|
||||
eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTheme(ThemeOption.Dark))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -140,6 +129,34 @@ class AdvancedSettingsViewTest {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "h640dp")
|
||||
fun `clicking on hide invite avatars emits the expected event`() {
|
||||
val eventsRecorder = EventsRecorder<AdvancedSettingsEvents>()
|
||||
rule.setAdvancedSettingsView(
|
||||
state = aAdvancedSettingsState(
|
||||
eventSink = eventsRecorder,
|
||||
hideInviteAvatars = false
|
||||
),
|
||||
)
|
||||
rule.clickOn(R.string.screen_advanced_settings_hide_invite_avatars_toggle_title)
|
||||
eventsRecorder.assertSingle(AdvancedSettingsEvents.SetHideInviteAvatars(true))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "h640dp")
|
||||
fun `clicking on timeline media preview emits the expected event`() {
|
||||
val eventsRecorder = EventsRecorder<AdvancedSettingsEvents>()
|
||||
rule.setAdvancedSettingsView(
|
||||
state = aAdvancedSettingsState(
|
||||
eventSink = eventsRecorder,
|
||||
timelineMediaPreviewValue = MediaPreviewValue.On
|
||||
),
|
||||
)
|
||||
rule.clickOn(R.string.screen_advanced_settings_show_media_timeline_always_hide)
|
||||
eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTimelineMediaPreviewValue(MediaPreviewValue.Off))
|
||||
}
|
||||
}
|
||||
|
||||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setAdvancedSettingsView(
|
||||
|
||||
@@ -99,9 +99,10 @@ fun <T : DropdownOption> PreferenceDropdown(
|
||||
*/
|
||||
interface DropdownOption {
|
||||
/**
|
||||
* The text to display for this option.
|
||||
* Returns the text to be displayed for this option.
|
||||
*/
|
||||
val text: String
|
||||
@Composable
|
||||
fun getText(): String
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -123,7 +124,7 @@ private fun <T : DropdownOption> DropdownTrailingContent(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = selectedOption?.text.orEmpty(),
|
||||
text = selectedOption?.getText().orEmpty(),
|
||||
maxLines = 1,
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
@@ -139,7 +140,7 @@ private fun <T : DropdownOption> DropdownTrailingContent(
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = option.text,
|
||||
text = option.getText(),
|
||||
style = ElementTheme.typography.fontBodyMdRegular
|
||||
)
|
||||
},
|
||||
@@ -158,13 +159,16 @@ private fun <T : DropdownOption> DropdownTrailingContent(
|
||||
internal fun PreferenceDropdownPreview() = ElementThemedPreview {
|
||||
val options = listOf(
|
||||
object : DropdownOption {
|
||||
override val text = "Option 1"
|
||||
@Composable
|
||||
override fun getText(): String = "Option 1"
|
||||
},
|
||||
object : DropdownOption {
|
||||
override val text = "Option 2"
|
||||
@Composable
|
||||
override fun getText(): String = "Option 2"
|
||||
},
|
||||
object : DropdownOption {
|
||||
override val text = "Option 3"
|
||||
@Composable
|
||||
override fun getText(): String = "Option 3"
|
||||
},
|
||||
).toImmutableList()
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user