From c5a4963eeb5c29a29aaf6635f4b050313edaef8c Mon Sep 17 00:00:00 2001 From: Eugene Date: Sat, 8 Aug 2026 22:03:49 +0300 Subject: [PATCH] hide blur in ui module scope --- .../shared/presentation/list/VideoScreen.kt | 5 +- .../presentation/overview/OverviewScreen.kt | 8 +-- .../overview/episode/EpisodeOverviewScreen.kt | 5 +- .../overview/season/SeasonOverviewScreen.kt | 5 +- .../presentation/search/SearchScreen.kt | 19 +------ .../presentation/settings/SettingsScreen.kt | 4 -- .../chat/presentation/ChatScreen.kt | 8 +-- .../kotlin/ru/shadowsparky/ui/AppScaffold.kt | 3 +- .../kotlin/ru/shadowsparky/ui/Blur.kt | 17 +++---- .../ui/components/AppBarWithSearch.kt | 49 +++++++++++++++++++ .../shadowsparky/ui/components/LazyColumn.kt | 5 +- .../ui/components/LazyVerticalGrid.kt | 5 +- .../shadowsparky/ui/components/TopAppBar.kt | 5 +- 13 files changed, 70 insertions(+), 68 deletions(-) create mode 100644 libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/AppBarWithSearch.kt diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/list/VideoScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/list/VideoScreen.kt index f16c25c..8fb3c3d 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/list/VideoScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/list/VideoScreen.kt @@ -51,8 +51,6 @@ import androidx.compose.ui.unit.dp import com.seiko.imageloader.rememberImagePainter import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.stringResource -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurSource import ru.shadowsparky.ui.components.ErrorContent import ru.shadowsparky.ui.components.LazyVerticalGrid import ru.shadowsparky.ui.components.Loading @@ -139,13 +137,12 @@ private fun VideosInfo( onClick: (item: VideoItem) -> Unit ) { val requester = remember { FocusRequester() } - val blur = LocalBlurState.current val gridState = rememberLazyGridState() Box(modifier = Modifier.fillMaxSize()) { if (items.isNotEmpty()) { LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 130.dp), - modifier = Modifier.fillMaxSize().applyBlurSource(blur), + modifier = Modifier.fillMaxSize(), contentPadding = paddingValues, verticalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/OverviewScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/OverviewScreen.kt index fc57596..76692d9 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/OverviewScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/OverviewScreen.kt @@ -68,8 +68,6 @@ import com.seiko.imageloader.rememberImagePainter import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import ru.shadowsparky.domain.Clip -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurSource import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.ErrorContent import ru.shadowsparky.ui.components.LazyColumn @@ -244,13 +242,9 @@ fun DetailsInfo( onWatchClicked: () -> Unit ) { val requester = remember { FocusRequester() } - val blur = LocalBlurState.current val showDetails = rememberSaveable { mutableStateOf(false) } - LazyColumn( - modifier = Modifier.applyBlurSource(blur), - contentPadding = paddingValues - ) { + LazyColumn(contentPadding = paddingValues) { item { Poster(details.poster) } item { OverviewDescription(details, showDetails) } item { diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/episode/EpisodeOverviewScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/episode/EpisodeOverviewScreen.kt index 2e3f84d..f769ea0 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/episode/EpisodeOverviewScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/episode/EpisodeOverviewScreen.kt @@ -44,8 +44,6 @@ import androidx.compose.ui.unit.dp import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import ru.shadowsparky.domain.Clip -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurSource import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.ErrorContent import ru.shadowsparky.ui.components.ExpressiveLazyColumn @@ -177,10 +175,9 @@ fun EpisodesOverviewList( buttonText = stringResource(Res.string.retry) ) { loadLinks() } } else if (episodes != null) { - val blur = LocalBlurState.current val requester = remember { FocusRequester() } ExpressiveLazyColumn( - modifier = Modifier.applyBlurSource(blur).fillMaxSize(), + modifier = Modifier.fillMaxSize(), contentPadding = contentPadding, content = { section { diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/season/SeasonOverviewScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/season/SeasonOverviewScreen.kt index 08edb70..ab51ac6 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/season/SeasonOverviewScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/overview/season/SeasonOverviewScreen.kt @@ -20,8 +20,6 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.unit.dp import org.jetbrains.compose.resources.stringResource -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurSource import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.ErrorContent import ru.shadowsparky.ui.components.ExpressiveLazyColumn @@ -68,10 +66,9 @@ fun SeasonsInfo( paddingValues: PaddingValues, onClick: (Long) -> Unit ) { - val blur = LocalBlurState.current val requester = remember { FocusRequester() } ExpressiveLazyColumn( - Modifier.applyBlurSource(blur).fillMaxWidth(), + Modifier.fillMaxWidth(), contentPadding = paddingValues, content = { section { diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/search/SearchScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/search/SearchScreen.kt index 6873c3e..ae96f4c 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/search/SearchScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/search/SearchScreen.kt @@ -21,7 +21,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.AppBarWithSearch import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon @@ -33,7 +32,6 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.material3.TextFieldColors import androidx.compose.material3.TextFieldDefaults -import androidx.compose.material3.rememberSearchBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State @@ -65,11 +63,8 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurEffect -import ru.shadowsparky.ui.applyBlurSource +import ru.shadowsparky.ui.components.AppBarWithSearch import ru.shadowsparky.ui.components.ExpressiveLazyColumn -import ru.shadowsparky.ui.theme.ComponentDefaults import ru.shadowsparky.vbox.shared.presentation.BaseMainScreen import ru.shadowsparky.vbox.shared.presentation.imePaddingInternal import ru.shadowsparky.vbox.shared.presentation.nav.Route @@ -157,10 +152,8 @@ fun OldSearchInfo( ) { val keyboardController = LocalSoftwareKeyboardController.current val nestedScrollConnection = remember { HideKeyboardConnection { keyboardController } } - val blur = LocalBlurState.current ExpressiveLazyColumn( - modifier = Modifier.applyBlurSource(blur) - .nestedScroll(nestedScrollConnection) + modifier = Modifier.nestedScroll(nestedScrollConnection) .imePaddingInternal(), contentPadding = contentPaddingValues, content = { @@ -224,11 +217,7 @@ fun SearchAppBar( inputFocusRequester.freeFocus() } } - val blur = LocalBlurState.current AppBarWithSearch( - modifier = Modifier.applyBlurEffect(blur), - state = rememberSearchBarState(), - colors = ComponentDefaults.appBarWithSearchDefaults(), inputField = { TextField( value = textFieldValue, @@ -287,11 +276,7 @@ fun AppBarWithSearch( actions: @Composable RowScope.() -> Unit = {}, onBack: (() -> Unit) ) { - val blur = LocalBlurState.current AppBarWithSearch( - modifier = Modifier.applyBlurEffect(blur), - state = rememberSearchBarState(), - colors = ComponentDefaults.appBarWithSearchDefaults(), actions = { actions(this) }, navigationIcon = {}, inputField = { diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/SettingsScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/SettingsScreen.kt index afbc90c..783e457 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/SettingsScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/SettingsScreen.kt @@ -21,8 +21,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import org.jetbrains.compose.resources.stringResource -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurSource import ru.shadowsparky.ui.components.ExpressiveLazyColumn import ru.shadowsparky.ui.components.SwitchPreference import ru.shadowsparky.ui.components.TextPreference @@ -33,10 +31,8 @@ fun SettingsContent(comp: SettingsComponent, paddingValues: PaddingValues) { val servAddr by comp.serverInfo.collectAsState(null) val tokenInfo by comp.tokenInfo.collectAsState(null) val externalPlayerState by comp.externalPlayerState.collectAsState(null) - val blur = LocalBlurState.current val requester = remember { FocusRequester() } ExpressiveLazyColumn( - modifier = Modifier.applyBlurSource(blur), contentPadding = paddingValues, content = { section { diff --git a/feature/chat/chat-client/src/commonMain/kotlin/ru/shadowsparky/chat/presentation/ChatScreen.kt b/feature/chat/chat-client/src/commonMain/kotlin/ru/shadowsparky/chat/presentation/ChatScreen.kt index 75ab03c..a45b939 100644 --- a/feature/chat/chat-client/src/commonMain/kotlin/ru/shadowsparky/chat/presentation/ChatScreen.kt +++ b/feature/chat/chat-client/src/commonMain/kotlin/ru/shadowsparky/chat/presentation/ChatScreen.kt @@ -66,9 +66,6 @@ import org.jetbrains.compose.resources.stringResource import ru.shadowsparky.chat.domain.ChatRoles import ru.shadowsparky.chat.domain.Message import ru.shadowsparky.chat.domain.TextToken -import ru.shadowsparky.ui.BlurState -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurSource import ru.shadowsparky.ui.components.AlertContent import ru.shadowsparky.ui.components.LazyColumn import ru.shadowsparky.ui.components.Loading @@ -112,7 +109,6 @@ fun ChatContent( is ChatState.Data -> { ChatContent( contentPadding = PaddingValues(top = paddingValues.calculateTopPadding()), - LocalBlurState.current, state = state, onParseMessage = { component.parseMessage(it) }, onClickLink = { component.onLinkClicked(it) }, @@ -127,7 +123,6 @@ fun ChatContent( @Composable private fun ChatContent( contentPadding: PaddingValues, - blurState: BlurState?, state: ChatState.Data, onParseMessage: (String) -> List, onClickLink: (String) -> Unit, @@ -150,8 +145,7 @@ private fun ChatContent( Column(modifier = Modifier.fillMaxSize()) { LazyColumn( state = listState, - modifier = Modifier.applyBlurSource(blurState) - .focusRequester(listFocusRequester) + modifier = Modifier.focusRequester(listFocusRequester) .weight(1f) .fillMaxWidth(), contentPadding = contentPadding, diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/AppScaffold.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/AppScaffold.kt index 45ab286..5a4fe09 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/AppScaffold.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/AppScaffold.kt @@ -122,7 +122,6 @@ private fun BottomBar( currentRoute: T?, onSelectNavigation: ((T) -> Unit)? ) { - val blurState = LocalBlurState.current navigationEntries?.let { entries -> Box( modifier = Modifier @@ -140,7 +139,7 @@ private fun BottomBar( ) { NavigationBar( containerColor = ComponentDefaults.navBarContentColor(), - modifier = ComponentDefaults.roundedClip().applyBlurEffect(blurState) + modifier = ComponentDefaults.roundedClip().blurEffect() ) { entries.forEach { entry -> NavigationBarItem( diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/Blur.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/Blur.kt index d75c64d..04ad2c8 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/Blur.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/Blur.kt @@ -13,33 +13,30 @@ import dev.chrisbanes.haze.materials.HazeMaterials import dev.chrisbanes.haze.rememberHazeState import ru.shadowsparky.ui.components.isTv -private const val BLUR_ENABLED = true - -val LocalBlurState = compositionLocalOf { null } +internal val LocalBlurState = compositionLocalOf { null } @Composable -internal fun isBlurEnabled(): Boolean { - return BLUR_ENABLED && !isTv() -} +internal fun isBlurEnabled(): Boolean = !isTv() @Composable -fun rememberBlurState(): BlurState? { +internal fun rememberBlurState(): BlurState? { if (!isBlurEnabled()) return null val hazeState = rememberHazeState() return remember(hazeState) { BlurState(hazeState) } } -fun Modifier.applyBlurSource(state: BlurState?): Modifier { +@Composable +internal fun Modifier.blurSource(state: BlurState? = LocalBlurState.current): Modifier { state ?: return this return hazeSource(state.hazeState) } @OptIn(ExperimentalHazeMaterialsApi::class) @Composable -fun Modifier.applyBlurEffect(state: BlurState?): Modifier { +internal fun Modifier.blurEffect(state: BlurState? = LocalBlurState.current): Modifier { state ?: return this return hazeEffect(state.hazeState, HazeMaterials.thin()) } @Stable -class BlurState(internal val hazeState: HazeState) +internal class BlurState(internal val hazeState: HazeState) diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/AppBarWithSearch.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/AppBarWithSearch.kt new file mode 100644 index 0000000..def52c4 --- /dev/null +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/AppBarWithSearch.kt @@ -0,0 +1,49 @@ +package ru.shadowsparky.ui.components + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.material3.AppBarWithSearchColors +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.SearchBarDefaults +import androidx.compose.material3.SearchBarScrollBehavior +import androidx.compose.material3.SearchBarState +import androidx.compose.material3.rememberSearchBarState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp +import ru.shadowsparky.ui.blurEffect +import ru.shadowsparky.ui.theme.ComponentDefaults + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AppBarWithSearch( + inputField: @Composable () -> Unit, + modifier: Modifier = Modifier, + state: SearchBarState = rememberSearchBarState(), + navigationIcon: @Composable (() -> Unit)? = null, + actions: @Composable (RowScope.() -> Unit)? = null, + shape: Shape = SearchBarDefaults.inputFieldShape, + colors: AppBarWithSearchColors = ComponentDefaults.appBarWithSearchDefaults(), + tonalElevation: Dp = SearchBarDefaults.TonalElevation, + shadowElevation: Dp = SearchBarDefaults.ShadowElevation, + contentPadding: PaddingValues = SearchBarDefaults.AppBarContentPadding, + windowInsets: WindowInsets = SearchBarDefaults.windowInsets, + scrollBehavior: SearchBarScrollBehavior? = null, +) { + androidx.compose.material3.AppBarWithSearch( + state, + inputField, + modifier.blurEffect(), + navigationIcon, + actions, + shape, + colors, + tonalElevation, + shadowElevation, + contentPadding, + windowInsets, + scrollBehavior + ) +} diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/LazyColumn.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/LazyColumn.kt index 1fb48ff..cf5c767 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/LazyColumn.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/LazyColumn.kt @@ -14,8 +14,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurSource +import ru.shadowsparky.ui.blurSource @Composable expect fun isTv(): Boolean @@ -128,7 +127,7 @@ fun LazyColumn( if (isTv) { modifier.padding(contentPadding) } else { - modifier.applyBlurSource(LocalBlurState.current) + modifier.blurSource() }, state, if (isTv) PaddingValues(0.dp) else contentPadding, diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/LazyVerticalGrid.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/LazyVerticalGrid.kt index abfb1c0..f841bbc 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/LazyVerticalGrid.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/LazyVerticalGrid.kt @@ -14,8 +14,7 @@ import androidx.compose.foundation.rememberOverscrollEffect import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurSource +import ru.shadowsparky.ui.blurSource @Composable fun LazyVerticalGrid( @@ -38,7 +37,7 @@ fun LazyVerticalGrid( if (isTv) { modifier.padding(contentPadding) } else { - modifier.applyBlurSource(LocalBlurState.current) + modifier.blurSource() }, state, if (isTv) PaddingValues(0.dp) else contentPadding, diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/TopAppBar.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/TopAppBar.kt index 395f347..bdecf34 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/TopAppBar.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/TopAppBar.kt @@ -11,8 +11,7 @@ import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp -import ru.shadowsparky.ui.LocalBlurState -import ru.shadowsparky.ui.applyBlurEffect +import ru.shadowsparky.ui.blurEffect import ru.shadowsparky.ui.theme.ComponentDefaults @OptIn(ExperimentalMaterial3Api::class) @@ -30,7 +29,7 @@ fun TopAppBar( ) { TopAppBar( title = title, - modifier = modifier.applyBlurEffect(LocalBlurState.current), + modifier = modifier.blurEffect(), navigationIcon = navigationIcon, actions = actions, expandedHeight = expandedHeight,