change (media preview config) : use the new apis

This commit is contained in:
ganfra 2025-06-26 20:52:44 +02:00
parent 682897cdb6
commit 0b748aa8cb
10 changed files with 158 additions and 60 deletions

View file

@ -8,27 +8,36 @@
package io.element.android.features.preferences.impl.advanced package io.element.android.features.preferences.impl.advanced
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember 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.Theme
import io.element.android.compound.theme.mapToTheme import io.element.android.compound.theme.mapToTheme
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runUpdatingState
import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.media.MediaPreviewValue import io.element.android.libraries.matrix.api.media.MediaPreviewValue
import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
class AdvancedSettingsPresenter @Inject constructor( class AdvancedSettingsPresenter @Inject constructor(
private val appPreferencesStore: AppPreferencesStore, private val appPreferencesStore: AppPreferencesStore,
private val sessionPreferencesStore: SessionPreferencesStore, private val sessionPreferencesStore: SessionPreferencesStore,
private val mediaPreviewConfigStateStore: MediaPreviewConfigStateStore,
@SessionCoroutineScope
private val sessionCoroutineScope: CoroutineScope,
) : Presenter<AdvancedSettingsState> { ) : Presenter<AdvancedSettingsState> {
@Composable @Composable
override fun present(): AdvancedSettingsState { override fun present(): AdvancedSettingsState {
val localCoroutineScope = rememberCoroutineScope()
val isDeveloperModeEnabled by remember { val isDeveloperModeEnabled by remember {
appPreferencesStore.isDeveloperModeEnabledFlow() appPreferencesStore.isDeveloperModeEnabledFlow()
}.collectAsState(initial = false) }.collectAsState(initial = false)
@ -41,13 +50,6 @@ class AdvancedSettingsPresenter @Inject constructor(
val theme = remember { val theme = remember {
appPreferencesStore.getThemeFlow().mapToTheme() appPreferencesStore.getThemeFlow().mapToTheme()
}.collectAsState(initial = Theme.System) }.collectAsState(initial = Theme.System)
val hideInviteAvatars by remember {
appPreferencesStore.getHideInviteAvatarsFlow()
}.collectAsState(false)
val timelineMediaPreviewValue by remember {
appPreferencesStore.getTimelineMediaPreviewValueFlow()
}.collectAsState(initial = MediaPreviewValue.On)
val themeOption by remember { val themeOption by remember {
derivedStateOf { derivedStateOf {
@ -61,28 +63,24 @@ class AdvancedSettingsPresenter @Inject constructor(
fun handleEvents(event: AdvancedSettingsEvents) { fun handleEvents(event: AdvancedSettingsEvents) {
when (event) { when (event) {
is AdvancedSettingsEvents.SetDeveloperModeEnabled -> localCoroutineScope.launch { is AdvancedSettingsEvents.SetDeveloperModeEnabled -> sessionCoroutineScope.launch {
appPreferencesStore.setDeveloperModeEnabled(event.enabled) appPreferencesStore.setDeveloperModeEnabled(event.enabled)
} }
is AdvancedSettingsEvents.SetSharePresenceEnabled -> localCoroutineScope.launch { is AdvancedSettingsEvents.SetSharePresenceEnabled -> sessionCoroutineScope.launch {
sessionPreferencesStore.setSharePresence(event.enabled) sessionPreferencesStore.setSharePresence(event.enabled)
} }
is AdvancedSettingsEvents.SetCompressMedia -> localCoroutineScope.launch { is AdvancedSettingsEvents.SetCompressMedia -> sessionCoroutineScope.launch {
sessionPreferencesStore.setCompressMedia(event.compress) sessionPreferencesStore.setCompressMedia(event.compress)
} }
is AdvancedSettingsEvents.SetTheme -> localCoroutineScope.launch { is AdvancedSettingsEvents.SetTheme -> sessionCoroutineScope.launch {
when (event.theme) { when (event.theme) {
ThemeOption.System -> appPreferencesStore.setTheme(Theme.System.name) ThemeOption.System -> appPreferencesStore.setTheme(Theme.System.name)
ThemeOption.Dark -> appPreferencesStore.setTheme(Theme.Dark.name) ThemeOption.Dark -> appPreferencesStore.setTheme(Theme.Dark.name)
ThemeOption.Light -> appPreferencesStore.setTheme(Theme.Light.name) ThemeOption.Light -> appPreferencesStore.setTheme(Theme.Light.name)
} }
} }
is AdvancedSettingsEvents.SetHideInviteAvatars -> localCoroutineScope.launch { is AdvancedSettingsEvents.SetHideInviteAvatars -> mediaPreviewConfigStateStore.setHideInviteAvatars(event.value)
appPreferencesStore.setHideInviteAvatars(event.value) is AdvancedSettingsEvents.SetTimelineMediaPreviewValue -> mediaPreviewConfigStateStore.setTimelineMediaPreviewValue(event.value)
}
is AdvancedSettingsEvents.SetTimelineMediaPreviewValue -> localCoroutineScope.launch {
appPreferencesStore.setTimelineMediaPreviewValue(event.value)
}
} }
} }
@ -91,9 +89,11 @@ class AdvancedSettingsPresenter @Inject constructor(
isSharePresenceEnabled = isSharePresenceEnabled, isSharePresenceEnabled = isSharePresenceEnabled,
doesCompressMedia = doesCompressMedia, doesCompressMedia = doesCompressMedia,
theme = themeOption, theme = themeOption,
hideInviteAvatars = hideInviteAvatars, hideInviteAvatars = mediaPreviewConfigStateStore.hideInviteAvatars.value,
timelineMediaPreviewValue = timelineMediaPreviewValue, timelineMediaPreviewValue = mediaPreviewConfigStateStore.timelineMediaPreviewValue.value,
eventSink = { handleEvents(it) } setHideInviteAvatarsAction = mediaPreviewConfigStateStore.setHideInviteAvatarsAction.value,
setTimelineMediaPreviewAction = mediaPreviewConfigStateStore.setTimelineMediaPreviewAction.value,
eventSink = ::handleEvents,
) )
} }
} }

View file

@ -10,6 +10,7 @@ package io.element.android.features.preferences.impl.advanced
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.components.preferences.DropdownOption import io.element.android.libraries.designsystem.components.preferences.DropdownOption
import io.element.android.libraries.matrix.api.media.MediaPreviewValue import io.element.android.libraries.matrix.api.media.MediaPreviewValue
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -21,6 +22,8 @@ data class AdvancedSettingsState(
val theme: ThemeOption, val theme: ThemeOption,
val hideInviteAvatars: Boolean, val hideInviteAvatars: Boolean,
val timelineMediaPreviewValue: MediaPreviewValue, val timelineMediaPreviewValue: MediaPreviewValue,
val setHideInviteAvatarsAction: AsyncAction<Unit>,
val setTimelineMediaPreviewAction: AsyncAction<Unit>,
val eventSink: (AdvancedSettingsEvents) -> Unit val eventSink: (AdvancedSettingsEvents) -> Unit
) )

View file

@ -8,6 +8,7 @@
package io.element.android.features.preferences.impl.advanced package io.element.android.features.preferences.impl.advanced
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.media.MediaPreviewValue import io.element.android.libraries.matrix.api.media.MediaPreviewValue
open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSettingsState> { open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSettingsState> {
@ -18,7 +19,9 @@ open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSett
aAdvancedSettingsState(isSharePresenceEnabled = true), aAdvancedSettingsState(isSharePresenceEnabled = true),
aAdvancedSettingsState(doesCompressMedia = true), aAdvancedSettingsState(doesCompressMedia = true),
aAdvancedSettingsState(hideInviteAvatars = true), aAdvancedSettingsState(hideInviteAvatars = true),
aAdvancedSettingsState(timelineMediaPreviewValue = MediaPreviewValue.Off) aAdvancedSettingsState(timelineMediaPreviewValue = MediaPreviewValue.Off),
aAdvancedSettingsState(setHideInviteAvatarsAction = AsyncAction.Loading),
aAdvancedSettingsState(setTimelineMediaPreviewAction = AsyncAction.Loading),
) )
} }
@ -29,6 +32,8 @@ fun aAdvancedSettingsState(
hideInviteAvatars: Boolean = false, hideInviteAvatars: Boolean = false,
theme: ThemeOption = ThemeOption.System, theme: ThemeOption = ThemeOption.System,
timelineMediaPreviewValue: MediaPreviewValue = MediaPreviewValue.On, timelineMediaPreviewValue: MediaPreviewValue = MediaPreviewValue.On,
setTimelineMediaPreviewAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
setHideInviteAvatarsAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
eventSink: (AdvancedSettingsEvents) -> Unit = {}, eventSink: (AdvancedSettingsEvents) -> Unit = {},
) = AdvancedSettingsState( ) = AdvancedSettingsState(
isDeveloperModeEnabled = isDeveloperModeEnabled, isDeveloperModeEnabled = isDeveloperModeEnabled,
@ -37,5 +42,7 @@ fun aAdvancedSettingsState(
theme = theme, theme = theme,
hideInviteAvatars = hideInviteAvatars, hideInviteAvatars = hideInviteAvatars,
timelineMediaPreviewValue = timelineMediaPreviewValue, timelineMediaPreviewValue = timelineMediaPreviewValue,
setTimelineMediaPreviewAction = setTimelineMediaPreviewAction,
setHideInviteAvatarsAction = setHideInviteAvatarsAction,
eventSink = eventSink eventSink = eventSink
) )

View file

@ -0,0 +1,109 @@
/*
* 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.preferences.impl.advanced
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.runUpdatingState
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.media.MediaPreviewService
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
interface MediaPreviewConfigStateStore {
val hideInviteAvatars: State<Boolean>
val timelineMediaPreviewValue: State<MediaPreviewValue>
val setHideInviteAvatarsAction: State<AsyncAction<Unit>>
val setTimelineMediaPreviewAction: State<AsyncAction<Unit>>
fun setHideInviteAvatars(hide: Boolean)
fun setTimelineMediaPreviewValue(value: MediaPreviewValue)
}
@ContributesBinding(SessionScope::class, boundType = MediaPreviewConfigStateStore::class)
@SingleIn(SessionScope::class)
class DefaultMediaPreviewConfigStateStore @Inject constructor(
@SessionCoroutineScope
private val sessionCoroutineScope: CoroutineScope,
private val mediaPreviewService: MediaPreviewService,
private val snackbarDispatcher: SnackbarDispatcher,
) : MediaPreviewConfigStateStore {
override val hideInviteAvatars = mutableStateOf(false)
override val timelineMediaPreviewValue = mutableStateOf(MediaPreviewValue.On)
override val setHideInviteAvatarsAction = mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized)
override val setTimelineMediaPreviewAction = mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized)
init {
val configFlow = mediaPreviewService.getMediaPreviewConfigFlow().shareIn(sessionCoroutineScope, SharingStarted.Eagerly)
val hideInviteAvatarsFlow = configFlow.mapNotNull { it?.hideInviteAvatar }.distinctUntilChanged()
val timelineMediaPreviewFlow = configFlow.mapNotNull { it?.mediaPreviewValue }.distinctUntilChanged()
hideInviteAvatarsFlow
.onEach {
Timber.d("Hide invi@te avatars changed to $it")
hideInviteAvatars.value = it
}
.launchIn(sessionCoroutineScope)
timelineMediaPreviewFlow
.onEach {
Timber.d("Timeline media preview value changed to $it")
timelineMediaPreviewValue.value = it
}
.launchIn(sessionCoroutineScope)
}
override fun setHideInviteAvatars(hide: Boolean) {
sessionCoroutineScope.launch {
Timber.d("Setting hide invite avatars to $hide")
val prevHideInviteAvatars = hideInviteAvatars.value
hideInviteAvatars.value = hide
runUpdatingState(setHideInviteAvatarsAction) {
mediaPreviewService
.setHideInviteAvatars(hide)
.onFailure {
hideInviteAvatars.value = prevHideInviteAvatars
snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_something_went_wrong_message))
}
}
}
}
override fun setTimelineMediaPreviewValue(value: MediaPreviewValue) {
sessionCoroutineScope.launch {
Timber.d("Setting timeline media preview value to $value")
val prevTimelineMediaPreviewValue = timelineMediaPreviewValue.value
timelineMediaPreviewValue.value = value
runUpdatingState(setTimelineMediaPreviewAction) {
mediaPreviewService
.setMediaPreviewValue(value)
.onFailure {
timelineMediaPreviewValue.value = prevTimelineMediaPreviewValue
snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_something_went_wrong_message))
}
}
}
}
}

View file

@ -11,10 +11,14 @@ import app.cash.molecule.RecompositionMode
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.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.media.MediaPreviewConfig
import io.element.android.libraries.matrix.api.media.MediaPreviewValue import io.element.android.libraries.matrix.api.media.MediaPreviewValue
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -144,7 +148,12 @@ class AdvancedSettingsPresenterTest {
@Test @Test
fun `present - timeline media preview value`() = runTest { fun `present - timeline media preview value`() = runTest {
val presenter = createAdvancedSettingsPresenter() val mediaPreviewConfigFlow = MutableStateFlow<MediaPreviewConfig?>(null)
val presenter = createAdvancedSettingsPresenter(
matrixClient = FakeMatrixClient(
mediaPreviewConfigFlow = mediaPreviewConfigFlow
)
)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
}.test { }.test {
@ -165,8 +174,10 @@ class AdvancedSettingsPresenterTest {
private fun createAdvancedSettingsPresenter( private fun createAdvancedSettingsPresenter(
appPreferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), appPreferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(),
sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(),
matrixClient: MatrixClient = FakeMatrixClient(),
) = AdvancedSettingsPresenter( ) = AdvancedSettingsPresenter(
appPreferencesStore = appPreferencesStore, appPreferencesStore = appPreferencesStore,
sessionPreferencesStore = sessionPreferencesStore, sessionPreferencesStore = sessionPreferencesStore,
matrixClient = matrixClient,
) )
} }

View file

@ -22,10 +22,8 @@ interface AppPreferencesStore {
suspend fun setTheme(theme: String) suspend fun setTheme(theme: String)
fun getThemeFlow(): Flow<String?> fun getThemeFlow(): Flow<String?>
suspend fun setHideInviteAvatars(value: Boolean)
fun getHideInviteAvatarsFlow(): Flow<Boolean> fun getHideInviteAvatarsFlow(): Flow<Boolean>
suspend fun setTimelineMediaPreviewValue(value: MediaPreviewValue)
fun getTimelineMediaPreviewValueFlow(): Flow<MediaPreviewValue> fun getTimelineMediaPreviewValueFlow(): Flow<MediaPreviewValue>
suspend fun setTracingLogLevel(logLevel: LogLevel) suspend fun setTracingLogLevel(logLevel: LogLevel)

View file

@ -85,24 +85,12 @@ class DefaultAppPreferencesStore @Inject constructor(
} }
} }
override suspend fun setHideInviteAvatars(value: Boolean) {
store.edit { prefs ->
prefs[hideInviteAvatarsKey] = value
}
}
override fun getHideInviteAvatarsFlow(): Flow<Boolean> { override fun getHideInviteAvatarsFlow(): Flow<Boolean> {
return store.data.map { prefs -> return store.data.map { prefs ->
prefs[hideInviteAvatarsKey] == true prefs[hideInviteAvatarsKey] == true
} }
} }
override suspend fun setTimelineMediaPreviewValue(value: MediaPreviewValue) {
store.edit { prefs ->
prefs[timelineMediaPreviewValueKey] = value.name
}
}
override fun getTimelineMediaPreviewValueFlow(): Flow<MediaPreviewValue> { override fun getTimelineMediaPreviewValueFlow(): Flow<MediaPreviewValue> {
return store.data.map { prefs -> return store.data.map { prefs ->
prefs[timelineMediaPreviewValueKey]?.let { MediaPreviewValue.valueOf(it) } ?: MediaPreviewValue.On prefs[timelineMediaPreviewValueKey]?.let { MediaPreviewValue.valueOf(it) } ?: MediaPreviewValue.On

View file

@ -55,18 +55,10 @@ class InMemoryAppPreferencesStore(
return theme return theme
} }
override suspend fun setHideInviteAvatars(value: Boolean) {
hideInviteAvatars.value = value
}
override fun getHideInviteAvatarsFlow(): Flow<Boolean> { override fun getHideInviteAvatarsFlow(): Flow<Boolean> {
return hideInviteAvatars return hideInviteAvatars
} }
override suspend fun setTimelineMediaPreviewValue(value: MediaPreviewValue) {
timelineMediaPreviewValue.value = value
}
override fun getTimelineMediaPreviewValueFlow(): Flow<MediaPreviewValue> { override fun getTimelineMediaPreviewValueFlow(): Flow<MediaPreviewValue> {
return timelineMediaPreviewValue return timelineMediaPreviewValue
} }

View file

@ -41,7 +41,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
import io.element.android.libraries.matrix.ui.messages.toPlainText import io.element.android.libraries.matrix.ui.messages.toPlainText
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.R
import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
@ -50,7 +49,6 @@ import io.element.android.libraries.push.impl.notifications.model.ResolvedPushEv
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.strings.StringProvider
import io.element.android.services.toolbox.api.systemclock.SystemClock import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.coroutines.flow.first
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -79,7 +77,6 @@ class DefaultNotifiableEventResolver @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
private val permalinkParser: PermalinkParser, private val permalinkParser: PermalinkParser,
private val callNotificationEventResolver: CallNotificationEventResolver, private val callNotificationEventResolver: CallNotificationEventResolver,
private val appPreferencesStore: AppPreferencesStore,
) : NotifiableEventResolver { ) : NotifiableEventResolver {
override suspend fun resolveEvents( override suspend fun resolveEvents(
sessionId: SessionId, sessionId: SessionId,
@ -117,6 +114,7 @@ class DefaultNotifiableEventResolver @Inject constructor(
): Result<ResolvedPushEvent> = runCatchingExceptions { ): Result<ResolvedPushEvent> = runCatchingExceptions {
when (val content = this.content) { when (val content = this.content) {
is NotificationContent.MessageLike.RoomMessage -> { is NotificationContent.MessageLike.RoomMessage -> {
val showMediaPreview = client.mediaPreviewService().getMediaPreviewValue() == MediaPreviewValue.On
val senderDisambiguatedDisplayName = getDisambiguatedDisplayName(content.senderId) val senderDisambiguatedDisplayName = getDisambiguatedDisplayName(content.senderId)
val messageBody = descriptionFromMessageContent(content, senderDisambiguatedDisplayName) val messageBody = descriptionFromMessageContent(content, senderDisambiguatedDisplayName)
val notifiableMessageEvent = buildNotifiableMessageEvent( val notifiableMessageEvent = buildNotifiableMessageEvent(
@ -129,8 +127,8 @@ class DefaultNotifiableEventResolver @Inject constructor(
timestamp = this.timestamp, timestamp = this.timestamp,
senderDisambiguatedDisplayName = senderDisambiguatedDisplayName, senderDisambiguatedDisplayName = senderDisambiguatedDisplayName,
body = messageBody, body = messageBody,
imageUriString = content.fetchImageIfPresent(client)?.toString(), imageUriString = if (showMediaPreview) content.fetchImageIfPresent(client)?.toString() else null,
imageMimeType = content.getImageMimetype(), imageMimeType = if (showMediaPreview) content.getImageMimetype() else null,
roomName = roomDisplayName, roomName = roomDisplayName,
roomIsDm = isDm, roomIsDm = isDm,
roomAvatarPath = roomAvatarUrl, roomAvatarPath = roomAvatarUrl,
@ -323,9 +321,6 @@ class DefaultNotifiableEventResolver @Inject constructor(
} }
private suspend fun NotificationContent.MessageLike.RoomMessage.fetchImageIfPresent(client: MatrixClient): Uri? { private suspend fun NotificationContent.MessageLike.RoomMessage.fetchImageIfPresent(client: MatrixClient): Uri? {
if (appPreferencesStore.getTimelineMediaPreviewValueFlow().first() != MediaPreviewValue.On) {
return null
}
val fileResult = when (val messageType = messageType) { val fileResult = when (val messageType = messageType) {
is ImageMessageType -> notificationMediaRepoFactory.create(client) is ImageMessageType -> notificationMediaRepoFactory.create(client)
.getMediaFile( .getMediaFile(
@ -349,10 +344,7 @@ class DefaultNotifiableEventResolver @Inject constructor(
.getOrNull() .getOrNull()
} }
private suspend fun NotificationContent.MessageLike.RoomMessage.getImageMimetype(): String? { private fun NotificationContent.MessageLike.RoomMessage.getImageMimetype(): String? {
if (appPreferencesStore.getTimelineMediaPreviewValueFlow().first() != MediaPreviewValue.On) {
return null
}
return when (val messageType = messageType) { return when (val messageType = messageType) {
is ImageMessageType -> messageType.info?.mimetype is ImageMessageType -> messageType.info?.mimetype
is VideoMessageType -> null // Use the thumbnail here? is VideoMessageType -> null // Use the thumbnail here?

View file

@ -826,7 +826,6 @@ class DefaultNotifiableEventResolverTest {
private fun createDefaultNotifiableEventResolver( private fun createDefaultNotifiableEventResolver(
notificationService: FakeNotificationService? = FakeNotificationService(), notificationService: FakeNotificationService? = FakeNotificationService(),
notificationResult: Result<Map<EventId, NotificationData>> = Result.success(emptyMap()), notificationResult: Result<Map<EventId, NotificationData>> = Result.success(emptyMap()),
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(),
callNotificationEventResolver: FakeCallNotificationEventResolver = FakeCallNotificationEventResolver(), callNotificationEventResolver: FakeCallNotificationEventResolver = FakeCallNotificationEventResolver(),
): DefaultNotifiableEventResolver { ): DefaultNotifiableEventResolver {
val context = RuntimeEnvironment.getApplication() as Context val context = RuntimeEnvironment.getApplication() as Context
@ -849,7 +848,6 @@ class DefaultNotifiableEventResolverTest {
context = context, context = context,
permalinkParser = FakePermalinkParser(), permalinkParser = FakePermalinkParser(),
callNotificationEventResolver = callNotificationEventResolver, callNotificationEventResolver = callNotificationEventResolver,
appPreferencesStore = appPreferencesStore,
) )
} }
} }