Use eventSink instead of lambda in states.

This commit is contained in:
Benoit Marty 2025-06-10 16:01:45 +02:00
parent dc2d5a253a
commit fc5c811d76
7 changed files with 37 additions and 24 deletions

View file

@ -38,6 +38,7 @@ import io.element.android.libraries.designsystem.theme.components.IconSource
import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItem
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsEvents
import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
@ -149,7 +150,7 @@ private fun NotificationSettingsContentView(
Text(stringResource(R.string.full_screen_intent_banner_message)) Text(stringResource(R.string.full_screen_intent_banner_message))
}, },
onClick = { onClick = {
state.fullScreenIntentPermissionsState.openFullScreenIntentSettings() state.fullScreenIntentPermissionsState.eventSink(FullScreenIntentPermissionsEvents.OpenSettings)
} }
) )
} }

View file

@ -15,6 +15,7 @@ import io.element.android.libraries.designsystem.components.Announcement
import io.element.android.libraries.designsystem.components.AnnouncementType import io.element.android.libraries.designsystem.components.AnnouncementType
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsEvents
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -29,8 +30,8 @@ fun FullScreenIntentPermissionBanner(
description = stringResource(R.string.full_screen_intent_banner_message), description = stringResource(R.string.full_screen_intent_banner_message),
type = AnnouncementType.Actionable( type = AnnouncementType.Actionable(
actionText = stringResource(CommonStrings.action_continue), actionText = stringResource(CommonStrings.action_continue),
onDismissClick = state.dismissFullScreenIntentBanner, onDismissClick = { state.eventSink(FullScreenIntentPermissionsEvents.Dismiss) },
onActionClick = state.openFullScreenIntentSettings, onActionClick = { state.eventSink(FullScreenIntentPermissionsEvents.OpenSettings) },
), ),
modifier = modifier.roomListBannerPadding(), modifier = modifier.roomListBannerPadding(),
) )

View file

@ -0,0 +1,13 @@
/*
* 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.libraries.fullscreenintent.api
sealed interface FullScreenIntentPermissionsEvents {
data object Dismiss : FullScreenIntentPermissionsEvents
data object OpenSettings : FullScreenIntentPermissionsEvents
}

View file

@ -10,6 +10,5 @@ package io.element.android.libraries.fullscreenintent.api
data class FullScreenIntentPermissionsState( data class FullScreenIntentPermissionsState(
val permissionGranted: Boolean, val permissionGranted: Boolean,
val shouldDisplayBanner: Boolean, val shouldDisplayBanner: Boolean,
val dismissFullScreenIntentBanner: () -> Unit, val eventSink: (FullScreenIntentPermissionsEvents) -> Unit,
val openFullScreenIntentSettings: () -> Unit,
) )

View file

@ -10,11 +10,9 @@ package io.element.android.libraries.fullscreenintent.api
fun aFullScreenIntentPermissionsState( fun aFullScreenIntentPermissionsState(
permissionGranted: Boolean = true, permissionGranted: Boolean = true,
shouldDisplay: Boolean = false, shouldDisplay: Boolean = false,
openFullScreenIntentSettings: () -> Unit = {}, eventSink: (FullScreenIntentPermissionsEvents) -> Unit = {},
dismissFullScreenIntentBanner: () -> Unit = {},
) = FullScreenIntentPermissionsState( ) = FullScreenIntentPermissionsState(
permissionGranted = permissionGranted, permissionGranted = permissionGranted,
shouldDisplayBanner = shouldDisplay, shouldDisplayBanner = shouldDisplay,
openFullScreenIntentSettings = openFullScreenIntentSettings, eventSink = eventSink,
dismissFullScreenIntentBanner = dismissFullScreenIntentBanner,
) )

View file

@ -23,6 +23,7 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsEvents
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
import io.element.android.services.toolbox.api.intent.ExternalIntentLauncher import io.element.android.services.toolbox.api.intent.ExternalIntentLauncher
@ -60,15 +61,20 @@ class FullScreenIntentPermissionsPresenter @Inject constructor(
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val isGranted = notificationManagerCompat.canUseFullScreenIntent() val isGranted = notificationManagerCompat.canUseFullScreenIntent()
val isBannerDismissed by isFullScreenIntentBannerDismissed.collectAsState(initial = true) val isBannerDismissed by isFullScreenIntentBannerDismissed.collectAsState(initial = true)
fun handleEvents(event: FullScreenIntentPermissionsEvents) {
when (event) {
FullScreenIntentPermissionsEvents.Dismiss -> coroutineScope.launch {
dismissFullScreenIntentBanner()
}
FullScreenIntentPermissionsEvents.OpenSettings -> openFullScreenIntentSettings()
}
}
return FullScreenIntentPermissionsState( return FullScreenIntentPermissionsState(
permissionGranted = isGranted, permissionGranted = isGranted,
shouldDisplayBanner = !isBannerDismissed && !isGranted, shouldDisplayBanner = !isBannerDismissed && !isGranted,
dismissFullScreenIntentBanner = { eventSink = ::handleEvents,
coroutineScope.launch {
dismissFullScreenIntentBanner()
}
},
openFullScreenIntentSettings = ::openFullScreenIntentSettings,
) )
} }

View file

@ -15,6 +15,7 @@ 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.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsEvents
import io.element.android.libraries.fullscreenintent.impl.FullScreenIntentPermissionsPresenter import io.element.android.libraries.fullscreenintent.impl.FullScreenIntentPermissionsPresenter
import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory
@ -76,10 +77,8 @@ class FullScreenIntentPermissionsPresenterTest {
}.test { }.test {
skipItems(1) skipItems(1)
val loadedItem = awaitItem() val loadedItem = awaitItem()
loadedItem.dismissFullScreenIntentBanner() loadedItem.eventSink(FullScreenIntentPermissionsEvents.Dismiss)
runCurrent() runCurrent()
assertThat(awaitItem().shouldDisplayBanner).isFalse() assertThat(awaitItem().shouldDisplayBanner).isFalse()
} }
} }
@ -94,10 +93,8 @@ class FullScreenIntentPermissionsPresenterTest {
}.test { }.test {
skipItems(1) skipItems(1)
val loadedItem = awaitItem() val loadedItem = awaitItem()
loadedItem.openFullScreenIntentSettings() loadedItem.eventSink(FullScreenIntentPermissionsEvents.OpenSettings)
launchLambda.assertions().isCalledOnce() launchLambda.assertions().isCalledOnce()
cancelAndIgnoreRemainingEvents() cancelAndIgnoreRemainingEvents()
} }
} }
@ -115,10 +112,8 @@ class FullScreenIntentPermissionsPresenterTest {
}.test { }.test {
skipItems(1) skipItems(1)
val loadedItem = awaitItem() val loadedItem = awaitItem()
loadedItem.openFullScreenIntentSettings() loadedItem.eventSink(FullScreenIntentPermissionsEvents.OpenSettings)
launchLambda.assertions().isNeverCalled() launchLambda.assertions().isNeverCalled()
cancelAndIgnoreRemainingEvents() cancelAndIgnoreRemainingEvents()
} }
} }