Add settings to hide images and videos in the timeline.

Hide images, videos and stickers in the timeline.
Disable click on hidden content. It must be revealed first.
Add preview without BlurHash.
Also hide image in thumbnails.
This commit is contained in:
Benoit Marty 2024-10-02 19:47:44 +02:00
parent 98d9abecd9
commit dd2a1b3388
48 changed files with 775 additions and 140 deletions

View file

@ -13,5 +13,6 @@ sealed interface DeveloperSettingsEvents {
data class UpdateEnabledFeature(val feature: FeatureUiModel, val isEnabled: Boolean) : DeveloperSettingsEvents
data class SetCustomElementCallBaseUrl(val baseUrl: String?) : DeveloperSettingsEvents
data class SetSimplifiedSlidingSyncEnabled(val isEnabled: Boolean) : DeveloperSettingsEvents
data class SetHideImagesAndVideos(val value: Boolean) : DeveloperSettingsEvents
data object ClearCache : DeveloperSettingsEvents
}

View file

@ -71,6 +71,9 @@ class DeveloperSettingsPresenter @Inject constructor(
val isSimplifiedSlidingSyncEnabled by appPreferencesStore
.isSimplifiedSlidingSyncEnabledFlow()
.collectAsState(initial = false)
val hideImagesAndVideos by appPreferencesStore
.doesHideImagesAndVideosFlow()
.collectAsState(initial = false)
LaunchedEffect(Unit) {
FeatureFlags.entries
@ -114,6 +117,9 @@ class DeveloperSettingsPresenter @Inject constructor(
appPreferencesStore.setSimplifiedSlidingSyncEnabled(event.isEnabled)
logoutUseCase.logout(ignoreSdkError = true)
}
is DeveloperSettingsEvents.SetHideImagesAndVideos -> coroutineScope.launch {
appPreferencesStore.setHideImagesAndVideos(event.value)
}
}
}
@ -128,6 +134,7 @@ class DeveloperSettingsPresenter @Inject constructor(
validator = ::customElementCallUrlValidator,
),
isSimpleSlidingSyncEnabled = isSimplifiedSlidingSyncEnabled,
hideImagesAndVideos = hideImagesAndVideos,
eventSink = ::handleEvents
)
}

View file

@ -19,6 +19,7 @@ data class DeveloperSettingsState(
val clearCacheAction: AsyncData<Unit>,
val customElementCallBaseUrlState: CustomElementCallBaseUrlState,
val isSimpleSlidingSyncEnabled: Boolean,
val hideImagesAndVideos: Boolean,
val eventSink: (DeveloperSettingsEvents) -> Unit
)

View file

@ -31,6 +31,7 @@ fun aDeveloperSettingsState(
clearCacheAction: AsyncData<Unit> = AsyncData.Uninitialized,
customElementCallBaseUrlState: CustomElementCallBaseUrlState = aCustomElementCallBaseUrlState(),
isSimplifiedSlidingSyncEnabled: Boolean = false,
hideImagesAndVideos: Boolean = false,
eventSink: (DeveloperSettingsEvents) -> Unit = {},
) = DeveloperSettingsState(
features = aFeatureUiModelList(),
@ -39,6 +40,7 @@ fun aDeveloperSettingsState(
clearCacheAction = clearCacheAction,
customElementCallBaseUrlState = customElementCallBaseUrlState,
isSimpleSlidingSyncEnabled = isSimplifiedSlidingSyncEnabled,
hideImagesAndVideos = hideImagesAndVideos,
eventSink = eventSink,
)

View file

@ -40,9 +40,10 @@ fun DeveloperSettingsView(
title = stringResource(id = CommonStrings.common_developer_options)
) {
// Note: this is OK to hardcode strings in this debug screen.
SettingsCategory(state)
PreferenceCategory(
title = "Feature flags",
showTopDivider = false,
showTopDivider = true,
) {
FeatureListContent(state)
}
@ -92,6 +93,22 @@ fun DeveloperSettingsView(
}
}
@Composable
private fun SettingsCategory(
state: DeveloperSettingsState,
) {
PreferenceCategory(title = "Preferences", showTopDivider = false) {
PreferenceSwitch(
title = "Hide image & video previews",
subtitle = "When toggled image & video will not render in the timeline by default.",
isChecked = state.hideImagesAndVideos,
onCheckedChange = {
state.eventSink(DeveloperSettingsEvents.SetHideImagesAndVideos(it))
}
)
}
}
@Composable
private fun ElementCallCategory(
state: DeveloperSettingsState,

View file

@ -50,6 +50,7 @@ class DeveloperSettingsPresenterTest {
assertThat(initialState.customElementCallBaseUrlState).isNotNull()
assertThat(initialState.customElementCallBaseUrlState.baseUrl).isNull()
assertThat(initialState.isSimpleSlidingSyncEnabled).isFalse()
assertThat(initialState.hideImagesAndVideos).isFalse()
val loadedState = awaitItem()
assertThat(loadedState.rageshakeState.isEnabled).isFalse()
assertThat(loadedState.rageshakeState.isSupported).isTrue()
@ -179,6 +180,24 @@ class DeveloperSettingsPresenterTest {
}
}
@Test
fun `present - toggling hide image and video`() = runTest {
val preferences = InMemoryAppPreferencesStore()
val presenter = createDeveloperSettingsPresenter(preferencesStore = preferences)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitLastSequentialItem()
assertThat(initialState.hideImagesAndVideos).isFalse()
initialState.eventSink(DeveloperSettingsEvents.SetHideImagesAndVideos(true))
assertThat(awaitItem().hideImagesAndVideos).isTrue()
assertThat(preferences.doesHideImagesAndVideosFlow().first()).isTrue()
initialState.eventSink(DeveloperSettingsEvents.SetHideImagesAndVideos(false))
assertThat(awaitItem().hideImagesAndVideos).isFalse()
assertThat(preferences.doesHideImagesAndVideosFlow().first()).isFalse()
}
}
private fun createDeveloperSettingsPresenter(
featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(),
cacheSizeUseCase: FakeComputeCacheSizeUseCase = FakeComputeCacheSizeUseCase(),

View file

@ -45,6 +45,7 @@ class DeveloperSettingsViewTest {
}
}
@Config(qualifiers = "h1500dp")
@Test
fun `clicking on element call url open the dialogs and submit emits the expected event`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>()
@ -113,6 +114,18 @@ class DeveloperSettingsViewTest {
rule.onNodeWithText("Enable Simplified Sliding Sync").performClick()
eventsRecorder.assertSingle(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(true))
}
@Test
fun `clicking on the hide images and videos switch emits the expected event`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>()
rule.setDeveloperSettingsView(
state = aDeveloperSettingsState(
eventSink = eventsRecorder
),
)
rule.onNodeWithText("Hide image & video previews").performClick()
eventsRecorder.assertSingle(DeveloperSettingsEvents.SetHideImagesAndVideos(true))
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setDeveloperSettingsView(