From 4f7d3dc6bc02284413fc2cba33f1fb85b21df1e2 Mon Sep 17 00:00:00 2001 From: Eugene Date: Sat, 15 Aug 2026 12:25:09 +0300 Subject: [PATCH] update scaffolds --- .../vbox/shared/presentation/BottomBar.kt | 3 +- .../vbox/shared/presentation/MainScreen.kt | 10 +- .../vbox/shared/presentation/Navigation.kt | 29 --- .../shared/presentation/UiConfiguration.kt | 13 -- .../shared/presentation/chat/ChatScreen.kt | 4 +- .../shared/presentation/list/VideoScreen.kt | 2 +- .../presentation/loading/LoadingScreen.kt | 2 +- .../offline/OfflineVideoScreen.kt | 2 +- .../presentation/overview/OverviewScreen.kt | 4 +- .../overview/episode/EpisodeOverviewScreen.kt | 4 +- .../overview/season/SeasonOverviewScreen.kt | 2 +- .../presentation/saved/SavedMovieScreen.kt | 6 +- .../presentation/search/SearchScreen.kt | 10 +- .../presentation/settings/auth/AuthScreen.kt | 2 +- .../settings/pass/EditPasswordScreen.kt | 2 +- .../settings/serv/EditServScreen.kt | 4 +- .../chat/presentation/ChatScreen.kt | 2 +- .../videoplayer/ui/DefaultControls.kt | 15 +- gradle/libs.versions.toml | 14 +- libs/ui/build.gradle.kts | 2 + .../kotlin/ru/shadowsparky/ui/AppScaffold.kt | 182 +++++++++++------- .../ru/shadowsparky/ui/WindowExtensions.kt | 30 --- .../shadowsparky/ui/components/BackButton.kt | 6 +- .../shadowsparky/ui/components/IconButton.kt | 32 +++ .../ui/components/PasswordTextField.kt | 1 - .../ui/theme/ComponentDefaults.kt | 19 +- 26 files changed, 201 insertions(+), 201 deletions(-) delete mode 100644 apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/UiConfiguration.kt delete mode 100644 libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/WindowExtensions.kt create mode 100644 libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/IconButton.kt diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/BottomBar.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/BottomBar.kt index 317d449..86b5eae 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/BottomBar.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/BottomBar.kt @@ -17,7 +17,7 @@ import ru.shadowsparky.vbox.shared.presentation.nav.Route @Composable fun createNavigationList(): List> { - val list = listOf( + return listOf( NavigationEntry( Route.default, stringResource(Res.string.recommendations), @@ -44,7 +44,6 @@ fun createNavigationList(): List> { painterResource(Res.drawable.settings) ) ) - return list } fun List>.findTitle(route: Route): String? { diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/MainScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/MainScreen.kt index 9bf98f5..2052e10 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/MainScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/MainScreen.kt @@ -29,7 +29,7 @@ fun MainScreen(route: Route, child: Child, root: VBoxRootComponent) { @OptIn(ExperimentalMaterial3Api::class) @Composable -fun BaseMainScreen( +fun MainScreenScaffold( appBar: @Composable () -> Unit, route: Route, onNavigate: (Route) -> Unit, @@ -47,13 +47,9 @@ fun BaseMainScreen( @Composable private fun MainScreenInternal(route: Route, child: Child, onNavigate: (Route) -> Unit) { val navList = createNavigationList() - BaseMainScreen( + MainScreenScaffold( appBar = { - navList.findTitle(route)?.let { title -> - TopAppBar( - title = { Text(title) } - ) - } + navList.findTitle(route)?.let { title -> TopAppBar(title = { Text(title) }) } }, route = route, onNavigate = onNavigate, diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/Navigation.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/Navigation.kt index baadb6b..a20f118 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/Navigation.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/Navigation.kt @@ -1,15 +1,9 @@ package ru.shadowsparky.vbox.shared.presentation -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier import com.seiko.imageloader.LocalImageLoader -import ru.shadowsparky.koin import ru.shadowsparky.ui.nav.Nav import ru.shadowsparky.updater.presentation.UpdateDialog import ru.shadowsparky.vbox.shared.presentation.list.VideoScreen @@ -27,11 +21,6 @@ import ru.shadowsparky.vbox.shared.presentation.settings.register.RegisterScreen import ru.shadowsparky.vbox.shared.presentation.settings.serv.EditServScreen import ru.shadowsparky.vbox.shared.presentation.settings.tag.TagScreen -@Composable -fun Modifier.imePaddingInternal(): Modifier { - return koin.get().imePadding(this) -} - @Composable fun Nav(root: VBoxRootComponent, onAttach: @Composable () -> Unit = {}) { CompositionLocalProvider( @@ -74,21 +63,3 @@ private fun NavInternal(root: VBoxRootComponent, onAttach: @Composable () -> Uni UpdateDialog(root.updateComponent) } } - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun AppScaffold( - scrollBehavior: TopAppBarScrollBehavior? = null, - snackbarState: SnackbarHostState? = null, - modifier: Modifier = Modifier, - content: @Composable (padding: PaddingValues) -> Unit, - appBar: @Composable () -> Unit -) { - ru.shadowsparky.ui.AppScaffold( - modifier, - scrollBehavior, - snackbarState, - content = content, - appBar = { appBar() } - ) -} diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/UiConfiguration.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/UiConfiguration.kt deleted file mode 100644 index fda5298..0000000 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/UiConfiguration.kt +++ /dev/null @@ -1,13 +0,0 @@ -package ru.shadowsparky.vbox.shared.presentation - -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import org.koin.core.annotation.Single - -@Single -class UiConfiguration { - @Composable - fun imePadding(modifier: Modifier): Modifier { - return modifier - } -} diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/chat/ChatScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/chat/ChatScreen.kt index 20cba00..de9f6db 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/chat/ChatScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/chat/ChatScreen.kt @@ -11,14 +11,14 @@ import org.jetbrains.compose.resources.stringResource import ru.shadowsparky.chat.presentation.ChatComponent import ru.shadowsparky.chat.presentation.ChatContent import ru.shadowsparky.ui.components.TopAppBar -import ru.shadowsparky.vbox.shared.presentation.BaseMainScreen +import ru.shadowsparky.vbox.shared.presentation.MainScreenScaffold import ru.shadowsparky.vbox.shared.presentation.nav.Route @OptIn(ExperimentalMaterial3Api::class) @Composable fun ChatScreen(component: ChatComponent, route: Route, onNavigate: (Route) -> Unit) { val state by component.state.subscribeAsState() - BaseMainScreen( + MainScreenScaffold( appBar = { TopAppBar(title = { Text(stringResource(Res.string.chat_title_app_bar)) }) }, 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 b1341d9..e31d0b2 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 @@ -39,12 +39,12 @@ 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.AppScaffold import ru.shadowsparky.ui.components.ErrorContent import ru.shadowsparky.ui.components.LazyVerticalGrid import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.ui.theme.focusBorder import ru.shadowsparky.vbox.shared.domain.model.VideoItem -import ru.shadowsparky.vbox.shared.presentation.AppScaffold import ru.shadowsparky.vbox.shared.presentation.search.AppBarWithSearch @OptIn(ExperimentalMaterial3Api::class) diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/loading/LoadingScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/loading/LoadingScreen.kt index 2cf8b01..1c80b54 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/loading/LoadingScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/loading/LoadingScreen.kt @@ -5,8 +5,8 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import ru.shadowsparky.ui.AppScaffold import ru.shadowsparky.ui.components.Loading -import ru.shadowsparky.vbox.shared.presentation.AppScaffold @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/offline/OfflineVideoScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/offline/OfflineVideoScreen.kt index 57ae409..cb4d9ac 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/offline/OfflineVideoScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/offline/OfflineVideoScreen.kt @@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar @@ -45,6 +44,7 @@ import org.jetbrains.compose.resources.stringResource import ru.shadowsparky.ui.AppScaffold import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.ExpressiveLazyColumn +import ru.shadowsparky.ui.components.IconButton import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.vbox.shared.domain.EpisodeOfflineVideo import ru.shadowsparky.vbox.shared.domain.OfflineState 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 76692d9..b757bf1 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 @@ -41,7 +41,6 @@ import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -68,13 +67,14 @@ 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.AppScaffold import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.ErrorContent +import ru.shadowsparky.ui.components.IconButton import ru.shadowsparky.ui.components.LazyColumn import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.ui.components.TopAppBar import ru.shadowsparky.vbox.shared.domain.model.VideoDetails -import ru.shadowsparky.vbox.shared.presentation.AppScaffold import ru.shadowsparky.vbox.shared.presentation.getClipboardText import ru.shadowsparky.vbox.shared.presentation.settings.tag.LinkTagBottomSheet 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 f769ea0..2c4b944 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 @@ -24,7 +24,6 @@ import androidx.compose.material3.CircularWavyProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -44,15 +43,16 @@ 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.AppScaffold import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.ErrorContent import ru.shadowsparky.ui.components.ExpressiveLazyColumn +import ru.shadowsparky.ui.components.IconButton import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.ui.components.TopAppBar import ru.shadowsparky.vbox.shared.domain.OfflineState import ru.shadowsparky.vbox.shared.domain.OfflineVideo import ru.shadowsparky.vbox.shared.domain.model.Episode -import ru.shadowsparky.vbox.shared.presentation.AppScaffold import ru.shadowsparky.vbox.shared.presentation.getClipboardText @OptIn(ExperimentalMaterial3Api::class) 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 ab51ac6..f52888f 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,13 +20,13 @@ 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.AppScaffold import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.ErrorContent import ru.shadowsparky.ui.components.ExpressiveLazyColumn import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.ui.components.TopAppBar import ru.shadowsparky.vbox.shared.domain.model.Season -import ru.shadowsparky.vbox.shared.presentation.AppScaffold @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/saved/SavedMovieScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/saved/SavedMovieScreen.kt index aabac2e..e7c825a 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/saved/SavedMovieScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/saved/SavedMovieScreen.kt @@ -15,7 +15,6 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material3.Checkbox import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -30,10 +29,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import ru.shadowsparky.ui.components.AlertContent +import ru.shadowsparky.ui.components.IconButton import ru.shadowsparky.ui.components.LazyColumn import ru.shadowsparky.ui.components.TopAppBar import ru.shadowsparky.vbox.shared.domain.tag.TagInfo -import ru.shadowsparky.vbox.shared.presentation.BaseMainScreen +import ru.shadowsparky.vbox.shared.presentation.MainScreenScaffold import ru.shadowsparky.vbox.shared.presentation.list.VideoScreenContent import ru.shadowsparky.vbox.shared.presentation.nav.Route @@ -42,7 +42,7 @@ import ru.shadowsparky.vbox.shared.presentation.nav.Route fun SavedMovieScreen(comp: SavedMovieComponent, route: Route, onNavigate: (Route) -> Unit) { val tags by comp.userTags.collectAsStateWithLifecycle(null) var filterBottomSheetVisible by rememberSaveable { mutableStateOf(false) } - BaseMainScreen( + MainScreenScaffold( appBar = { TopAppBar( title = { Text(stringResource(Res.string.saved_movies)) }, 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 ae96f4c..a6b6ee6 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 @@ -24,7 +24,6 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.LinearWavyProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface @@ -65,8 +64,8 @@ import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import ru.shadowsparky.ui.components.AppBarWithSearch import ru.shadowsparky.ui.components.ExpressiveLazyColumn -import ru.shadowsparky.vbox.shared.presentation.BaseMainScreen -import ru.shadowsparky.vbox.shared.presentation.imePaddingInternal +import ru.shadowsparky.ui.components.IconButton +import ru.shadowsparky.vbox.shared.presentation.MainScreenScaffold import ru.shadowsparky.vbox.shared.presentation.nav.Route @OptIn(ExperimentalMaterial3Api::class) @@ -80,7 +79,7 @@ fun SearchScreen( var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue()) } - BaseMainScreen( + MainScreenScaffold( appBar = { SearchAppBar( textFieldValue = textFieldValue, @@ -153,8 +152,7 @@ fun OldSearchInfo( val keyboardController = LocalSoftwareKeyboardController.current val nestedScrollConnection = remember { HideKeyboardConnection { keyboardController } } ExpressiveLazyColumn( - modifier = Modifier.nestedScroll(nestedScrollConnection) - .imePaddingInternal(), + modifier = Modifier.nestedScroll(nestedScrollConnection), contentPadding = contentPaddingValues, content = { section { diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/auth/AuthScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/auth/AuthScreen.kt index ffb0906..6cb659a 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/auth/AuthScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/auth/AuthScreen.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.dp import kotlinx.coroutines.flow.Flow import org.jetbrains.compose.resources.stringResource +import ru.shadowsparky.ui.AppScaffold import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.ErrorAlert import ru.shadowsparky.ui.components.Loading @@ -42,7 +43,6 @@ import ru.shadowsparky.ui.components.PasswordTextField import ru.shadowsparky.vbox.shared.domain.model.EmptyLoginException import ru.shadowsparky.vbox.shared.domain.model.EmptyPasswordException import ru.shadowsparky.vbox.shared.domain.model.LoginException -import ru.shadowsparky.vbox.shared.presentation.AppScaffold @Composable fun AuthScreen(comp: AuthComponent) { diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/pass/EditPasswordScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/pass/EditPasswordScreen.kt index bc2e7cc..f3220c9 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/pass/EditPasswordScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/pass/EditPasswordScreen.kt @@ -32,10 +32,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch import org.jetbrains.compose.resources.stringResource +import ru.shadowsparky.ui.AppScaffold import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.ui.components.PasswordTextField -import ru.shadowsparky.vbox.shared.presentation.AppScaffold import ru.shadowsparky.vbox.shared.presentation.settings.auth.AuthState @OptIn(ExperimentalMaterial3Api::class) diff --git a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/serv/EditServScreen.kt b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/serv/EditServScreen.kt index 8ac6ac4..05a9583 100644 --- a/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/serv/EditServScreen.kt +++ b/apps/vbox/client/shared/src/commonMain/kotlin/ru/shadowsparky/vbox/shared/presentation/settings/serv/EditServScreen.kt @@ -11,7 +11,7 @@ import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton +import ru.shadowsparky.ui.components.IconButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -34,10 +34,10 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource +import ru.shadowsparky.ui.AppScaffold import ru.shadowsparky.ui.components.BackButton import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.ui.components.TopAppBar -import ru.shadowsparky.vbox.shared.presentation.AppScaffold @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @Composable 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 06c6eff..fecc22b 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 @@ -33,7 +33,6 @@ import androidx.compose.material3.Button import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField @@ -76,6 +75,7 @@ import ru.shadowsparky.chat.domain.ChatRoles import ru.shadowsparky.chat.domain.Message import ru.shadowsparky.chat.domain.TextToken import ru.shadowsparky.ui.components.AlertContent +import ru.shadowsparky.ui.components.IconButton import ru.shadowsparky.ui.components.LazyColumn import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.ui.components.TextPreference diff --git a/feature/video-player/src/commonMain/kotlin/ru/shadowsparky/videoplayer/ui/DefaultControls.kt b/feature/video-player/src/commonMain/kotlin/ru/shadowsparky/videoplayer/ui/DefaultControls.kt index 4a5ac30..1a3d039 100644 --- a/feature/video-player/src/commonMain/kotlin/ru/shadowsparky/videoplayer/ui/DefaultControls.kt +++ b/feature/video-player/src/commonMain/kotlin/ru/shadowsparky/videoplayer/ui/DefaultControls.kt @@ -8,7 +8,6 @@ import androiddev.feature.video_player.generated.resources.pause_24px import androiddev.feature.video_player.generated.resources.play_arrow_24px import androiddev.feature.video_player.generated.resources.replay_24px import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.focusGroup import androidx.compose.foundation.focusable import androidx.compose.foundation.gestures.detectTapGestures @@ -23,13 +22,13 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.CircularWavyProgressIndicator import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Slider import androidx.compose.material3.Text @@ -59,7 +58,9 @@ import androidx.compose.ui.unit.dp import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.jetbrains.compose.resources.painterResource +import ru.shadowsparky.ui.components.IconButton import ru.shadowsparky.ui.components.isTv +import ru.shadowsparky.ui.theme.focusBorder import ru.shadowsparky.videoplayer.AudioTrackInfo import ru.shadowsparky.videoplayer.ControlsState import ru.shadowsparky.videoplayer.PlayerController @@ -391,13 +392,5 @@ private fun Modifier.focusableWithBorder(requester: FocusRequester): Modifier { var isFocused by remember { mutableStateOf(false) } return this.focusRequester(requester) .onFocusChanged { isFocused = it.isFocused } - .border( - width = 2.dp, - color = if (isFocused) { - MaterialTheme.colorScheme.primary - } else { - Color.Transparent - }, - shape = RoundedCornerShape(24.dp) - ) + .focusBorder(false, CircleShape) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index eaf7118..c39eaf6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] activity-compose = "1.13.0" - -appcompat = "1.7.1" +material3-compose = "1.12.0-alpha03" +adaptiveLayout = "1.3.0-beta02" +appcompat = "1.8.0" coil-compose = "3.5.0" componentsResources = "1.11.1" -compose-material-version = "1.11.0-alpha03" compose-version = "1.11.1" desugar_jdk_libs = "2.1.5" foundation = "1.11.1" @@ -19,7 +19,7 @@ decompose-version = "3.5.0" image-loader = "1.10.0" junit = "4.13.2" lifecycleCoroutines = "2.5.0" -material = "1.11.4" +material = "1.12.0" materialVersion = "1.14.0" media3 = "1.11.0" mockk = "1.14.11" @@ -29,7 +29,7 @@ kotlinx-coroutines-core = "1.11.0" kotlinx-serialization-json = "1.11.0" ktor-plugin = "3.5.2" kxml2 = "2.4.1" -logback-classic = "1.6.1" +logback-classic = "1.6.3" multiplatform-settings = "1.3.0" postgresql = "42.7.13" runner = "1.7.0" @@ -53,6 +53,7 @@ krpc = "0.10.3" core = "1.19.0" [libraries] +adaptive-layout = { module = "org.jetbrains.compose.material3.adaptive:adaptive-layout", version.ref = "adaptiveLayout" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore-preferences-core" } androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } @@ -85,10 +86,11 @@ ktor-server-host-common-jvm = { module = "io.ktor:ktor-server-host-common-jvm" } ktor-server-core-jvm = { module = "io.ktor:ktor-server-core-jvm" } ktor-server-websockets-jvm = { module = "io.ktor:ktor-server-websockets-jvm" } material = { module = "com.google.android.material:material", version.ref = "materialVersion" } +material3-adaptive-navigation-suite = { module = "org.jetbrains.compose.material3:material3-adaptive-navigation-suite", version.ref = "material3-compose" } multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" } activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" } compose-gradle-plugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "compose-version" } -compose-material3 = { module = "org.jetbrains.compose.material3:material3", version.ref = "compose-material-version" } +compose-material3 = { module = "org.jetbrains.compose.material3:material3", version.ref = "material3-compose" } compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose-version" } compose-components-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "componentsResources" } compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "foundation" } diff --git a/libs/ui/build.gradle.kts b/libs/ui/build.gradle.kts index 7664252..092097e 100644 --- a/libs/ui/build.gradle.kts +++ b/libs/ui/build.gradle.kts @@ -13,6 +13,8 @@ kotlin { implementation(libs.haze) implementation(libs.haze.materials) implementation(libs.ui.tooling.preview) + implementation(libs.adaptive.layout) + implementation(libs.material3.adaptive.navigation.suite) } } } 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 96b5fbe..64e90cc 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/AppScaffold.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/AppScaffold.kt @@ -3,14 +3,12 @@ package ru.shadowsparky.ui import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.calculateEndPadding -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @@ -19,13 +17,17 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarDefaults import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.NavigationRail -import androidx.compose.material3.NavigationRailItem import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfoV2 +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteItem +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldDefaults +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteType import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable @@ -35,9 +37,9 @@ import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import ru.shadowsparky.ui.nav.Route +import ru.shadowsparky.ui.theme.focusBorder @Immutable data class NavigationEntry( @@ -64,11 +66,15 @@ fun AppScaffold( ) } -@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) +@OptIn( + ExperimentalMaterial3Api::class, + ExperimentalMaterial3ExpressiveApi::class, +) @Composable fun AppScaffold( modifier: Modifier = Modifier, - scrollBehavior: TopAppBarScrollBehavior? = TopAppBarDefaults.pinnedScrollBehavior(), + scrollBehavior: TopAppBarScrollBehavior? = + TopAppBarDefaults.pinnedScrollBehavior(), snackbarState: SnackbarHostState? = null, currentRoute: T? = null, navigationEntries: List>? = null, @@ -76,40 +82,111 @@ fun AppScaffold( appBar: @Composable (scroll: TopAppBarScrollBehavior?) -> Unit, content: @Composable (padding: PaddingValues) -> Unit, ) { - val windowType = currentWindowType() + val navigationSuiteType = when { + navigationEntries.isNullOrEmpty() -> NavigationSuiteType.None + else -> { NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(currentWindowAdaptiveInfoV2()) } + } val blurState = rememberBlurState() CompositionLocalProvider(LocalBlurState provides blurState) { + when (navigationSuiteType) { + NavigationSuiteType.NavigationBar -> { + BottomBarScaffold( + modifier, + navigationEntries, + currentRoute, + appBar, + content, + scrollBehavior, + onSelectNavigation, + snackbarState + ) + } + else -> { + DynamicNavigationScaffold( + modifier, + navigationSuiteType, + navigationEntries, + currentRoute, + onSelectNavigation, + scrollBehavior, + appBar, + snackbarState, + content + ) + } + } + } +} + +@Composable +private fun DynamicNavigationScaffold( + modifier: Modifier, + navigationSuiteType: NavigationSuiteType, + navigationEntries: List>?, + currentRoute: T?, + onSelectNavigation: ((T) -> Unit)?, + scrollBehavior: TopAppBarScrollBehavior?, + appBar: @Composable ((TopAppBarScrollBehavior?) -> Unit), + snackbarState: SnackbarHostState?, + content: @Composable ((PaddingValues) -> Unit) +) { + NavigationSuiteScaffold( + navigationSuiteType = navigationSuiteType, + navigationItems = { + navigationEntries.orEmpty().forEach { entry -> + NavigationSuiteItem( + navigationSuiteType = navigationSuiteType, + selected = currentRoute == entry.route, + onClick = { onSelectNavigation?.invoke(entry.route) }, + icon = { Icon(entry.painter, entry.title) }, + label = { + when (navigationSuiteType) { + NavigationSuiteType.NavigationDrawer -> Text(entry.title) + } + }, + modifier = Modifier.focusBorder(false, CircleShape) + ) + } + } + ) { Scaffold( - bottomBar = { - if (windowType.isCompact) { - BottomBar(navigationEntries, currentRoute, onSelectNavigation) - } - }, - topBar = { - appBar(scrollBehavior) - }, content = { - if (windowType.isExpanded && navigationEntries?.isNotEmpty() == true) { - ExpandedContent( - it, - navigationEntries, - currentRoute, - onSelectNavigation, - content - ) - } else { - content(it) - } - }, modifier = if (scrollBehavior != null) { + modifier = if (scrollBehavior != null) { modifier.nestedScroll(scrollBehavior.nestedScrollConnection) } else { modifier - }, snackbarHost = { - snackbarState?.let { SnackbarHost(it) } - } + }, + topBar = { appBar(scrollBehavior) }, + snackbarHost = { snackbarState?.let { SnackbarHost(it) } }, + content = content ) } } +@Composable +private fun BottomBarScaffold( + modifier: Modifier, + navigationEntries: List>?, + currentRoute: T?, + appBar: @Composable (scroll: TopAppBarScrollBehavior?) -> Unit, + content: @Composable (padding: PaddingValues) -> Unit, + scrollBehavior: TopAppBarScrollBehavior?, + onSelectNavigation: ((T) -> Unit)?, + snackbarState: SnackbarHostState? +) { + Scaffold( + bottomBar = { BottomBar(navigationEntries, currentRoute, onSelectNavigation) }, + topBar = { appBar(scrollBehavior) }, + modifier = if (scrollBehavior != null) { + modifier.nestedScroll(scrollBehavior.nestedScrollConnection) + } else { + modifier + }, snackbarHost = { + snackbarState?.let { SnackbarHost(it) } + }, + content = content + ) +} + @Composable private fun BottomBar( navigationEntries: List>?, @@ -121,11 +198,8 @@ private fun BottomBar( modifier = Modifier .fillMaxWidth() .background( - brush = Brush.verticalGradient( - colors = listOf( - Color.Transparent, - MaterialTheme.colorScheme.surfaceContainer - ) + Brush.verticalGradient( + listOf(Color.Transparent, MaterialTheme.colorScheme.surfaceContainer) ) ) .padding(8.dp) @@ -155,37 +229,3 @@ private fun navBarContentColor(): Color { NavigationBarDefaults.containerColor } } - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun ExpandedContent( - values: PaddingValues, - navigationEntries: List>, - currentRoute: T?, - onSelectNavigation: ((T) -> Unit)?, - content: @Composable ((PaddingValues) -> Unit) -) { - val topPadding = values.calculateTopPadding() - val bottomPadding = values.calculateBottomPadding() - val endPadding = values.calculateEndPadding(LayoutDirection.Ltr) - Row(modifier = Modifier.fillMaxSize()) { - NavigationRail(modifier = Modifier.padding(start = 4.dp, end = 4.dp, top = topPadding)) { - navigationEntries.forEach { entry -> - NavigationRailItem( - selected = currentRoute == entry.route, - onClick = { onSelectNavigation?.invoke(entry.route) }, - icon = { Icon(entry.painter, contentDescription = entry.title) } - ) - } - } - Box(modifier = Modifier.weight(1f)) { - content( - PaddingValues( - top = topPadding, - end = endPadding, - bottom = bottomPadding - ) - ) - } - } -} diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/WindowExtensions.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/WindowExtensions.kt deleted file mode 100644 index 0c09887..0000000 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/WindowExtensions.kt +++ /dev/null @@ -1,30 +0,0 @@ -package ru.shadowsparky.ui - -import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.platform.LocalWindowInfo - -@Composable -private fun currentWindowWidthDp(): Int { - val info = LocalWindowInfo.current - val density = LocalDensity.current - return with(density) { info.containerSize.width.toDp().value.toInt() } -} - -@Composable -fun currentWindowType(): WindowType { - return widthToSizeClass(currentWindowWidthDp()) -} - -sealed interface WindowType { - object Compact : WindowType - object Expanded : WindowType -} - -val WindowType.isExpanded: Boolean get() = this is WindowType.Expanded -val WindowType.isCompact: Boolean get() = this is WindowType.Compact - -private fun widthToSizeClass(widthDp: Int): WindowType = when { - widthDp >= 840 -> WindowType.Expanded - else -> WindowType.Compact -} diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/BackButton.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/BackButton.kt index e35001c..7afc5b4 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/BackButton.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/BackButton.kt @@ -4,12 +4,13 @@ import androiddev.libs.ui.generated.resources.Res import androiddev.libs.ui.generated.resources.back import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import org.jetbrains.compose.resources.painterResource +import ru.shadowsparky.ui.theme.focusBorder @Composable fun BackButton(doBack: () -> Unit) { @@ -20,7 +21,8 @@ fun BackButton(doBack: () -> Unit) { containerColor = MaterialTheme.colorScheme.primaryContainer.copy( 0.1f ) - ) + ), + modifier = Modifier.focusBorder(shape = CircleShape) ) { Icon(painterResource(Res.drawable.back), contentDescription = null) } } diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/IconButton.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/IconButton.kt new file mode 100644 index 0000000..ec21d49 --- /dev/null +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/IconButton.kt @@ -0,0 +1,32 @@ +package ru.shadowsparky.ui.components + +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonColors +import androidx.compose.material3.IconButtonDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import ru.shadowsparky.ui.theme.focusBorder + +@Composable +fun IconButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + colors: IconButtonColors = IconButtonDefaults.iconButtonColors(), + interactionSource: MutableInteractionSource? = null, + shape: Shape = IconButtonDefaults.standardShape, + content: @Composable () -> Unit, +) { + IconButton( + onClick, + modifier.focusBorder(false, CircleShape), + enabled, + colors, + interactionSource, + shape, + content + ) +} diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/PasswordTextField.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/PasswordTextField.kt index 086339c..a66a30a 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/PasswordTextField.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/PasswordTextField.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/theme/ComponentDefaults.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/theme/ComponentDefaults.kt index 1ccec1b..7d6a61a 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/theme/ComponentDefaults.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/theme/ComponentDefaults.kt @@ -17,6 +17,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp @@ -25,7 +26,8 @@ object ComponentDefaults { @Composable internal fun focusBorder( modifier: Modifier, - needScale: Boolean + needScale: Boolean, + borderShape: Shape ): Modifier { var isFocused by remember { mutableStateOf(false) } val borderColor by animateColorAsState( @@ -48,7 +50,7 @@ object ComponentDefaults { scaleX = scale scaleY = scale clip = true - shape = RoundedCornerShape(12.dp) + shape = borderShape } } else { modifier @@ -57,12 +59,19 @@ object ComponentDefaults { .border( width = borderWidth, color = borderColor, - shape = RoundedCornerShape(12.dp) + shape = borderShape ) } } @Composable -fun Modifier.focusBorder(needScale: Boolean = true): Modifier { - return ComponentDefaults.focusBorder(this, needScale) +fun Modifier.focusBorder( + needScale: Boolean = true, + shape: Shape = RoundedCornerShape(12.dp) +): Modifier { + return ComponentDefaults.focusBorder( + this, + needScale, + shape + ) }