update scaffolds
This commit is contained in:
+1
-2
@@ -17,7 +17,7 @@ import ru.shadowsparky.vbox.shared.presentation.nav.Route
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun createNavigationList(): List<NavigationEntry<Route>> {
|
fun createNavigationList(): List<NavigationEntry<Route>> {
|
||||||
val list = listOf(
|
return listOf(
|
||||||
NavigationEntry(
|
NavigationEntry(
|
||||||
Route.default,
|
Route.default,
|
||||||
stringResource(Res.string.recommendations),
|
stringResource(Res.string.recommendations),
|
||||||
@@ -44,7 +44,6 @@ fun createNavigationList(): List<NavigationEntry<Route>> {
|
|||||||
painterResource(Res.drawable.settings)
|
painterResource(Res.drawable.settings)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<NavigationEntry<*>>.findTitle(route: Route): String? {
|
fun List<NavigationEntry<*>>.findTitle(route: Route): String? {
|
||||||
|
|||||||
+3
-7
@@ -29,7 +29,7 @@ fun MainScreen(route: Route, child: Child, root: VBoxRootComponent) {
|
|||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BaseMainScreen(
|
fun MainScreenScaffold(
|
||||||
appBar: @Composable () -> Unit,
|
appBar: @Composable () -> Unit,
|
||||||
route: Route,
|
route: Route,
|
||||||
onNavigate: (Route) -> Unit,
|
onNavigate: (Route) -> Unit,
|
||||||
@@ -47,13 +47,9 @@ fun BaseMainScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun MainScreenInternal(route: Route, child: Child, onNavigate: (Route) -> Unit) {
|
private fun MainScreenInternal(route: Route, child: Child, onNavigate: (Route) -> Unit) {
|
||||||
val navList = createNavigationList()
|
val navList = createNavigationList()
|
||||||
BaseMainScreen(
|
MainScreenScaffold(
|
||||||
appBar = {
|
appBar = {
|
||||||
navList.findTitle(route)?.let { title ->
|
navList.findTitle(route)?.let { title -> TopAppBar(title = { Text(title) }) }
|
||||||
TopAppBar(
|
|
||||||
title = { Text(title) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
route = route,
|
route = route,
|
||||||
onNavigate = onNavigate,
|
onNavigate = onNavigate,
|
||||||
|
|||||||
-29
@@ -1,15 +1,9 @@
|
|||||||
package ru.shadowsparky.vbox.shared.presentation
|
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.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import com.seiko.imageloader.LocalImageLoader
|
import com.seiko.imageloader.LocalImageLoader
|
||||||
import ru.shadowsparky.koin
|
|
||||||
import ru.shadowsparky.ui.nav.Nav
|
import ru.shadowsparky.ui.nav.Nav
|
||||||
import ru.shadowsparky.updater.presentation.UpdateDialog
|
import ru.shadowsparky.updater.presentation.UpdateDialog
|
||||||
import ru.shadowsparky.vbox.shared.presentation.list.VideoScreen
|
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.serv.EditServScreen
|
||||||
import ru.shadowsparky.vbox.shared.presentation.settings.tag.TagScreen
|
import ru.shadowsparky.vbox.shared.presentation.settings.tag.TagScreen
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Modifier.imePaddingInternal(): Modifier {
|
|
||||||
return koin.get<UiConfiguration>().imePadding(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Nav(root: VBoxRootComponent, onAttach: @Composable () -> Unit = {}) {
|
fun Nav(root: VBoxRootComponent, onAttach: @Composable () -> Unit = {}) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
@@ -74,21 +63,3 @@ private fun NavInternal(root: VBoxRootComponent, onAttach: @Composable () -> Uni
|
|||||||
UpdateDialog(root.updateComponent)
|
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() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
-13
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-2
@@ -11,14 +11,14 @@ import org.jetbrains.compose.resources.stringResource
|
|||||||
import ru.shadowsparky.chat.presentation.ChatComponent
|
import ru.shadowsparky.chat.presentation.ChatComponent
|
||||||
import ru.shadowsparky.chat.presentation.ChatContent
|
import ru.shadowsparky.chat.presentation.ChatContent
|
||||||
import ru.shadowsparky.ui.components.TopAppBar
|
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
|
import ru.shadowsparky.vbox.shared.presentation.nav.Route
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatScreen(component: ChatComponent, route: Route, onNavigate: (Route) -> Unit) {
|
fun ChatScreen(component: ChatComponent, route: Route, onNavigate: (Route) -> Unit) {
|
||||||
val state by component.state.subscribeAsState()
|
val state by component.state.subscribeAsState()
|
||||||
BaseMainScreen(
|
MainScreenScaffold(
|
||||||
appBar = {
|
appBar = {
|
||||||
TopAppBar(title = { Text(stringResource(Res.string.chat_title_app_bar)) })
|
TopAppBar(title = { Text(stringResource(Res.string.chat_title_app_bar)) })
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -39,12 +39,12 @@ import androidx.compose.ui.unit.dp
|
|||||||
import com.seiko.imageloader.rememberImagePainter
|
import com.seiko.imageloader.rememberImagePainter
|
||||||
import org.jetbrains.compose.resources.StringResource
|
import org.jetbrains.compose.resources.StringResource
|
||||||
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.ErrorContent
|
||||||
import ru.shadowsparky.ui.components.LazyVerticalGrid
|
import ru.shadowsparky.ui.components.LazyVerticalGrid
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.ui.theme.focusBorder
|
import ru.shadowsparky.ui.theme.focusBorder
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.VideoItem
|
import ru.shadowsparky.vbox.shared.domain.model.VideoItem
|
||||||
import ru.shadowsparky.vbox.shared.presentation.AppScaffold
|
|
||||||
import ru.shadowsparky.vbox.shared.presentation.search.AppBarWithSearch
|
import ru.shadowsparky.vbox.shared.presentation.search.AppBarWithSearch
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|||||||
+1
-1
@@ -5,8 +5,8 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import ru.shadowsparky.ui.AppScaffold
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.vbox.shared.presentation.AppScaffold
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
@@ -45,6 +44,7 @@ import org.jetbrains.compose.resources.stringResource
|
|||||||
import ru.shadowsparky.ui.AppScaffold
|
import ru.shadowsparky.ui.AppScaffold
|
||||||
import ru.shadowsparky.ui.components.BackButton
|
import ru.shadowsparky.ui.components.BackButton
|
||||||
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
||||||
|
import ru.shadowsparky.ui.components.IconButton
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.vbox.shared.domain.EpisodeOfflineVideo
|
import ru.shadowsparky.vbox.shared.domain.EpisodeOfflineVideo
|
||||||
import ru.shadowsparky.vbox.shared.domain.OfflineState
|
import ru.shadowsparky.vbox.shared.domain.OfflineState
|
||||||
|
|||||||
+2
-2
@@ -41,7 +41,6 @@ import androidx.compose.material3.DropdownMenu
|
|||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.painterResource
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
import ru.shadowsparky.domain.Clip
|
import ru.shadowsparky.domain.Clip
|
||||||
|
import ru.shadowsparky.ui.AppScaffold
|
||||||
import ru.shadowsparky.ui.components.BackButton
|
import ru.shadowsparky.ui.components.BackButton
|
||||||
import ru.shadowsparky.ui.components.ErrorContent
|
import ru.shadowsparky.ui.components.ErrorContent
|
||||||
|
import ru.shadowsparky.ui.components.IconButton
|
||||||
import ru.shadowsparky.ui.components.LazyColumn
|
import ru.shadowsparky.ui.components.LazyColumn
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.ui.components.TopAppBar
|
import ru.shadowsparky.ui.components.TopAppBar
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.VideoDetails
|
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.getClipboardText
|
||||||
import ru.shadowsparky.vbox.shared.presentation.settings.tag.LinkTagBottomSheet
|
import ru.shadowsparky.vbox.shared.presentation.settings.tag.LinkTagBottomSheet
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,6 @@ import androidx.compose.material3.CircularWavyProgressIndicator
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.painterResource
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
import ru.shadowsparky.domain.Clip
|
import ru.shadowsparky.domain.Clip
|
||||||
|
import ru.shadowsparky.ui.AppScaffold
|
||||||
import ru.shadowsparky.ui.components.BackButton
|
import ru.shadowsparky.ui.components.BackButton
|
||||||
import ru.shadowsparky.ui.components.ErrorContent
|
import ru.shadowsparky.ui.components.ErrorContent
|
||||||
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
||||||
|
import ru.shadowsparky.ui.components.IconButton
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.ui.components.TopAppBar
|
import ru.shadowsparky.ui.components.TopAppBar
|
||||||
import ru.shadowsparky.vbox.shared.domain.OfflineState
|
import ru.shadowsparky.vbox.shared.domain.OfflineState
|
||||||
import ru.shadowsparky.vbox.shared.domain.OfflineVideo
|
import ru.shadowsparky.vbox.shared.domain.OfflineVideo
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.Episode
|
import ru.shadowsparky.vbox.shared.domain.model.Episode
|
||||||
import ru.shadowsparky.vbox.shared.presentation.AppScaffold
|
|
||||||
import ru.shadowsparky.vbox.shared.presentation.getClipboardText
|
import ru.shadowsparky.vbox.shared.presentation.getClipboardText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|||||||
+1
-1
@@ -20,13 +20,13 @@ import androidx.compose.ui.focus.FocusRequester
|
|||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
|
import ru.shadowsparky.ui.AppScaffold
|
||||||
import ru.shadowsparky.ui.components.BackButton
|
import ru.shadowsparky.ui.components.BackButton
|
||||||
import ru.shadowsparky.ui.components.ErrorContent
|
import ru.shadowsparky.ui.components.ErrorContent
|
||||||
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.ui.components.TopAppBar
|
import ru.shadowsparky.ui.components.TopAppBar
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.Season
|
import ru.shadowsparky.vbox.shared.domain.model.Season
|
||||||
import ru.shadowsparky.vbox.shared.presentation.AppScaffold
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
+3
-3
@@ -15,7 +15,6 @@ import androidx.compose.foundation.lazy.items
|
|||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.painterResource
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
import ru.shadowsparky.ui.components.AlertContent
|
import ru.shadowsparky.ui.components.AlertContent
|
||||||
|
import ru.shadowsparky.ui.components.IconButton
|
||||||
import ru.shadowsparky.ui.components.LazyColumn
|
import ru.shadowsparky.ui.components.LazyColumn
|
||||||
import ru.shadowsparky.ui.components.TopAppBar
|
import ru.shadowsparky.ui.components.TopAppBar
|
||||||
import ru.shadowsparky.vbox.shared.domain.tag.TagInfo
|
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.list.VideoScreenContent
|
||||||
import ru.shadowsparky.vbox.shared.presentation.nav.Route
|
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) {
|
fun SavedMovieScreen(comp: SavedMovieComponent, route: Route, onNavigate: (Route) -> Unit) {
|
||||||
val tags by comp.userTags.collectAsStateWithLifecycle(null)
|
val tags by comp.userTags.collectAsStateWithLifecycle(null)
|
||||||
var filterBottomSheetVisible by rememberSaveable { mutableStateOf(false) }
|
var filterBottomSheetVisible by rememberSaveable { mutableStateOf(false) }
|
||||||
BaseMainScreen(
|
MainScreenScaffold(
|
||||||
appBar = {
|
appBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text(stringResource(Res.string.saved_movies)) },
|
title = { Text(stringResource(Res.string.saved_movies)) },
|
||||||
|
|||||||
+4
-6
@@ -24,7 +24,6 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.LinearWavyProgressIndicator
|
import androidx.compose.material3.LinearWavyProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
@@ -65,8 +64,8 @@ import org.jetbrains.compose.resources.painterResource
|
|||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
import ru.shadowsparky.ui.components.AppBarWithSearch
|
import ru.shadowsparky.ui.components.AppBarWithSearch
|
||||||
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
||||||
import ru.shadowsparky.vbox.shared.presentation.BaseMainScreen
|
import ru.shadowsparky.ui.components.IconButton
|
||||||
import ru.shadowsparky.vbox.shared.presentation.imePaddingInternal
|
import ru.shadowsparky.vbox.shared.presentation.MainScreenScaffold
|
||||||
import ru.shadowsparky.vbox.shared.presentation.nav.Route
|
import ru.shadowsparky.vbox.shared.presentation.nav.Route
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -80,7 +79,7 @@ fun SearchScreen(
|
|||||||
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
|
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
|
||||||
mutableStateOf(TextFieldValue())
|
mutableStateOf(TextFieldValue())
|
||||||
}
|
}
|
||||||
BaseMainScreen(
|
MainScreenScaffold(
|
||||||
appBar = {
|
appBar = {
|
||||||
SearchAppBar(
|
SearchAppBar(
|
||||||
textFieldValue = textFieldValue,
|
textFieldValue = textFieldValue,
|
||||||
@@ -153,8 +152,7 @@ fun OldSearchInfo(
|
|||||||
val keyboardController = LocalSoftwareKeyboardController.current
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
val nestedScrollConnection = remember { HideKeyboardConnection { keyboardController } }
|
val nestedScrollConnection = remember { HideKeyboardConnection { keyboardController } }
|
||||||
ExpressiveLazyColumn(
|
ExpressiveLazyColumn(
|
||||||
modifier = Modifier.nestedScroll(nestedScrollConnection)
|
modifier = Modifier.nestedScroll(nestedScrollConnection),
|
||||||
.imePaddingInternal(),
|
|
||||||
contentPadding = contentPaddingValues,
|
contentPadding = contentPaddingValues,
|
||||||
content = {
|
content = {
|
||||||
section {
|
section {
|
||||||
|
|||||||
+1
-1
@@ -35,6 +35,7 @@ import androidx.compose.ui.text.input.ImeAction
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
|
import ru.shadowsparky.ui.AppScaffold
|
||||||
import ru.shadowsparky.ui.components.BackButton
|
import ru.shadowsparky.ui.components.BackButton
|
||||||
import ru.shadowsparky.ui.components.ErrorAlert
|
import ru.shadowsparky.ui.components.ErrorAlert
|
||||||
import ru.shadowsparky.ui.components.Loading
|
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.EmptyLoginException
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.EmptyPasswordException
|
import ru.shadowsparky.vbox.shared.domain.model.EmptyPasswordException
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.LoginException
|
import ru.shadowsparky.vbox.shared.domain.model.LoginException
|
||||||
import ru.shadowsparky.vbox.shared.presentation.AppScaffold
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AuthScreen(comp: AuthComponent) {
|
fun AuthScreen(comp: AuthComponent) {
|
||||||
|
|||||||
+1
-1
@@ -32,10 +32,10 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
|
import ru.shadowsparky.ui.AppScaffold
|
||||||
import ru.shadowsparky.ui.components.BackButton
|
import ru.shadowsparky.ui.components.BackButton
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.ui.components.PasswordTextField
|
import ru.shadowsparky.ui.components.PasswordTextField
|
||||||
import ru.shadowsparky.vbox.shared.presentation.AppScaffold
|
|
||||||
import ru.shadowsparky.vbox.shared.presentation.settings.auth.AuthState
|
import ru.shadowsparky.vbox.shared.presentation.settings.auth.AuthState
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@ import androidx.compose.foundation.text.KeyboardActions
|
|||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
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.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -34,10 +34,10 @@ import androidx.compose.ui.text.input.TextFieldValue
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
|
import ru.shadowsparky.ui.AppScaffold
|
||||||
import ru.shadowsparky.ui.components.BackButton
|
import ru.shadowsparky.ui.components.BackButton
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.ui.components.TopAppBar
|
import ru.shadowsparky.ui.components.TopAppBar
|
||||||
import ru.shadowsparky.vbox.shared.presentation.AppScaffold
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,6 @@ import androidx.compose.material3.Button
|
|||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.LinearProgressIndicator
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
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.Message
|
||||||
import ru.shadowsparky.chat.domain.TextToken
|
import ru.shadowsparky.chat.domain.TextToken
|
||||||
import ru.shadowsparky.ui.components.AlertContent
|
import ru.shadowsparky.ui.components.AlertContent
|
||||||
|
import ru.shadowsparky.ui.components.IconButton
|
||||||
import ru.shadowsparky.ui.components.LazyColumn
|
import ru.shadowsparky.ui.components.LazyColumn
|
||||||
import ru.shadowsparky.ui.components.Loading
|
import ru.shadowsparky.ui.components.Loading
|
||||||
import ru.shadowsparky.ui.components.TextPreference
|
import ru.shadowsparky.ui.components.TextPreference
|
||||||
|
|||||||
+4
-11
@@ -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.play_arrow_24px
|
||||||
import androiddev.feature.video_player.generated.resources.replay_24px
|
import androiddev.feature.video_player.generated.resources.replay_24px
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
|
||||||
import androidx.compose.foundation.focusGroup
|
import androidx.compose.foundation.focusGroup
|
||||||
import androidx.compose.foundation.focusable
|
import androidx.compose.foundation.focusable
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
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.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.CircularWavyProgressIndicator
|
import androidx.compose.material3.CircularWavyProgressIndicator
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Slider
|
import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -59,7 +58,9 @@ import androidx.compose.ui.unit.dp
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
|
import ru.shadowsparky.ui.components.IconButton
|
||||||
import ru.shadowsparky.ui.components.isTv
|
import ru.shadowsparky.ui.components.isTv
|
||||||
|
import ru.shadowsparky.ui.theme.focusBorder
|
||||||
import ru.shadowsparky.videoplayer.AudioTrackInfo
|
import ru.shadowsparky.videoplayer.AudioTrackInfo
|
||||||
import ru.shadowsparky.videoplayer.ControlsState
|
import ru.shadowsparky.videoplayer.ControlsState
|
||||||
import ru.shadowsparky.videoplayer.PlayerController
|
import ru.shadowsparky.videoplayer.PlayerController
|
||||||
@@ -391,13 +392,5 @@ private fun Modifier.focusableWithBorder(requester: FocusRequester): Modifier {
|
|||||||
var isFocused by remember { mutableStateOf(false) }
|
var isFocused by remember { mutableStateOf(false) }
|
||||||
return this.focusRequester(requester)
|
return this.focusRequester(requester)
|
||||||
.onFocusChanged { isFocused = it.isFocused }
|
.onFocusChanged { isFocused = it.isFocused }
|
||||||
.border(
|
.focusBorder(false, CircleShape)
|
||||||
width = 2.dp,
|
|
||||||
color = if (isFocused) {
|
|
||||||
MaterialTheme.colorScheme.primary
|
|
||||||
} else {
|
|
||||||
Color.Transparent
|
|
||||||
},
|
|
||||||
shape = RoundedCornerShape(24.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
[versions]
|
[versions]
|
||||||
activity-compose = "1.13.0"
|
activity-compose = "1.13.0"
|
||||||
|
material3-compose = "1.12.0-alpha03"
|
||||||
appcompat = "1.7.1"
|
adaptiveLayout = "1.3.0-beta02"
|
||||||
|
appcompat = "1.8.0"
|
||||||
coil-compose = "3.5.0"
|
coil-compose = "3.5.0"
|
||||||
componentsResources = "1.11.1"
|
componentsResources = "1.11.1"
|
||||||
compose-material-version = "1.11.0-alpha03"
|
|
||||||
compose-version = "1.11.1"
|
compose-version = "1.11.1"
|
||||||
desugar_jdk_libs = "2.1.5"
|
desugar_jdk_libs = "2.1.5"
|
||||||
foundation = "1.11.1"
|
foundation = "1.11.1"
|
||||||
@@ -19,7 +19,7 @@ decompose-version = "3.5.0"
|
|||||||
image-loader = "1.10.0"
|
image-loader = "1.10.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
lifecycleCoroutines = "2.5.0"
|
lifecycleCoroutines = "2.5.0"
|
||||||
material = "1.11.4"
|
material = "1.12.0"
|
||||||
materialVersion = "1.14.0"
|
materialVersion = "1.14.0"
|
||||||
media3 = "1.11.0"
|
media3 = "1.11.0"
|
||||||
mockk = "1.14.11"
|
mockk = "1.14.11"
|
||||||
@@ -29,7 +29,7 @@ kotlinx-coroutines-core = "1.11.0"
|
|||||||
kotlinx-serialization-json = "1.11.0"
|
kotlinx-serialization-json = "1.11.0"
|
||||||
ktor-plugin = "3.5.2"
|
ktor-plugin = "3.5.2"
|
||||||
kxml2 = "2.4.1"
|
kxml2 = "2.4.1"
|
||||||
logback-classic = "1.6.1"
|
logback-classic = "1.6.3"
|
||||||
multiplatform-settings = "1.3.0"
|
multiplatform-settings = "1.3.0"
|
||||||
postgresql = "42.7.13"
|
postgresql = "42.7.13"
|
||||||
runner = "1.7.0"
|
runner = "1.7.0"
|
||||||
@@ -53,6 +53,7 @@ krpc = "0.10.3"
|
|||||||
core = "1.19.0"
|
core = "1.19.0"
|
||||||
|
|
||||||
[libraries]
|
[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-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-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore-preferences-core" }
|
||||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
|
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-core-jvm = { module = "io.ktor:ktor-server-core-jvm" }
|
||||||
ktor-server-websockets-jvm = { module = "io.ktor:ktor-server-websockets-jvm" }
|
ktor-server-websockets-jvm = { module = "io.ktor:ktor-server-websockets-jvm" }
|
||||||
material = { module = "com.google.android.material:material", version.ref = "materialVersion" }
|
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" }
|
multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" }
|
||||||
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" }
|
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-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-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-components-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "componentsResources" }
|
||||||
compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "foundation" }
|
compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "foundation" }
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ kotlin {
|
|||||||
implementation(libs.haze)
|
implementation(libs.haze)
|
||||||
implementation(libs.haze.materials)
|
implementation(libs.haze.materials)
|
||||||
implementation(libs.ui.tooling.preview)
|
implementation(libs.ui.tooling.preview)
|
||||||
|
implementation(libs.adaptive.layout)
|
||||||
|
implementation(libs.material3.adaptive.navigation.suite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,12 @@ package ru.shadowsparky.ui
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
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.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
@@ -19,13 +17,17 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
import androidx.compose.material3.NavigationBarDefaults
|
import androidx.compose.material3.NavigationBarDefaults
|
||||||
import androidx.compose.material3.NavigationBarItem
|
import androidx.compose.material3.NavigationBarItem
|
||||||
import androidx.compose.material3.NavigationRail
|
|
||||||
import androidx.compose.material3.NavigationRailItem
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
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.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.Immutable
|
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.Color
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ru.shadowsparky.ui.nav.Route
|
import ru.shadowsparky.ui.nav.Route
|
||||||
|
import ru.shadowsparky.ui.theme.focusBorder
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class NavigationEntry<out T : Route>(
|
data class NavigationEntry<out T : Route>(
|
||||||
@@ -64,11 +66,15 @@ fun AppScaffold(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(
|
||||||
|
ExperimentalMaterial3Api::class,
|
||||||
|
ExperimentalMaterial3ExpressiveApi::class,
|
||||||
|
)
|
||||||
@Composable
|
@Composable
|
||||||
fun <T : Route> AppScaffold(
|
fun <T : Route> AppScaffold(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
scrollBehavior: TopAppBarScrollBehavior? = TopAppBarDefaults.pinnedScrollBehavior(),
|
scrollBehavior: TopAppBarScrollBehavior? =
|
||||||
|
TopAppBarDefaults.pinnedScrollBehavior(),
|
||||||
snackbarState: SnackbarHostState? = null,
|
snackbarState: SnackbarHostState? = null,
|
||||||
currentRoute: T? = null,
|
currentRoute: T? = null,
|
||||||
navigationEntries: List<NavigationEntry<T>>? = null,
|
navigationEntries: List<NavigationEntry<T>>? = null,
|
||||||
@@ -76,40 +82,111 @@ fun <T : Route> AppScaffold(
|
|||||||
appBar: @Composable (scroll: TopAppBarScrollBehavior?) -> Unit,
|
appBar: @Composable (scroll: TopAppBarScrollBehavior?) -> Unit,
|
||||||
content: @Composable (padding: PaddingValues) -> Unit,
|
content: @Composable (padding: PaddingValues) -> Unit,
|
||||||
) {
|
) {
|
||||||
val windowType = currentWindowType()
|
val navigationSuiteType = when {
|
||||||
|
navigationEntries.isNullOrEmpty() -> NavigationSuiteType.None
|
||||||
|
else -> { NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(currentWindowAdaptiveInfoV2()) }
|
||||||
|
}
|
||||||
val blurState = rememberBlurState()
|
val blurState = rememberBlurState()
|
||||||
CompositionLocalProvider(LocalBlurState provides blurState) {
|
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 <T : Route> DynamicNavigationScaffold(
|
||||||
|
modifier: Modifier,
|
||||||
|
navigationSuiteType: NavigationSuiteType,
|
||||||
|
navigationEntries: List<NavigationEntry<T>>?,
|
||||||
|
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(
|
Scaffold(
|
||||||
bottomBar = {
|
modifier = if (scrollBehavior != null) {
|
||||||
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.nestedScroll(scrollBehavior.nestedScrollConnection)
|
modifier.nestedScroll(scrollBehavior.nestedScrollConnection)
|
||||||
} else {
|
} else {
|
||||||
modifier
|
modifier
|
||||||
}, snackbarHost = {
|
},
|
||||||
snackbarState?.let { SnackbarHost(it) }
|
topBar = { appBar(scrollBehavior) },
|
||||||
}
|
snackbarHost = { snackbarState?.let { SnackbarHost(it) } },
|
||||||
|
content = content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun <T : Route> BottomBarScaffold(
|
||||||
|
modifier: Modifier,
|
||||||
|
navigationEntries: List<NavigationEntry<T>>?,
|
||||||
|
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
|
@Composable
|
||||||
private fun <T : Route> BottomBar(
|
private fun <T : Route> BottomBar(
|
||||||
navigationEntries: List<NavigationEntry<T>>?,
|
navigationEntries: List<NavigationEntry<T>>?,
|
||||||
@@ -121,11 +198,8 @@ private fun <T : Route> BottomBar(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(
|
.background(
|
||||||
brush = Brush.verticalGradient(
|
Brush.verticalGradient(
|
||||||
colors = listOf(
|
listOf(Color.Transparent, MaterialTheme.colorScheme.surfaceContainer)
|
||||||
Color.Transparent,
|
|
||||||
MaterialTheme.colorScheme.surfaceContainer
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
@@ -155,37 +229,3 @@ private fun navBarContentColor(): Color {
|
|||||||
NavigationBarDefaults.containerColor
|
NavigationBarDefaults.containerColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
private fun <T : Route> ExpandedContent(
|
|
||||||
values: PaddingValues,
|
|
||||||
navigationEntries: List<NavigationEntry<T>>,
|
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -4,12 +4,13 @@ import androiddev.libs.ui.generated.resources.Res
|
|||||||
import androiddev.libs.ui.generated.resources.back
|
import androiddev.libs.ui.generated.resources.back
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.IconButtonDefaults
|
import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
|
import ru.shadowsparky.ui.theme.focusBorder
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BackButton(doBack: () -> Unit) {
|
fun BackButton(doBack: () -> Unit) {
|
||||||
@@ -20,7 +21,8 @@ fun BackButton(doBack: () -> Unit) {
|
|||||||
containerColor = MaterialTheme.colorScheme.primaryContainer.copy(
|
containerColor = MaterialTheme.colorScheme.primaryContainer.copy(
|
||||||
0.1f
|
0.1f
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
|
modifier = Modifier.focusBorder(shape = CircleShape)
|
||||||
) { Icon(painterResource(Res.drawable.back), contentDescription = null) }
|
) { Icon(painterResource(Res.drawable.back), contentDescription = null) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.onFocusChanged
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Shape
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
@@ -25,7 +26,8 @@ object ComponentDefaults {
|
|||||||
@Composable
|
@Composable
|
||||||
internal fun focusBorder(
|
internal fun focusBorder(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
needScale: Boolean
|
needScale: Boolean,
|
||||||
|
borderShape: Shape
|
||||||
): Modifier {
|
): Modifier {
|
||||||
var isFocused by remember { mutableStateOf(false) }
|
var isFocused by remember { mutableStateOf(false) }
|
||||||
val borderColor by animateColorAsState(
|
val borderColor by animateColorAsState(
|
||||||
@@ -48,7 +50,7 @@ object ComponentDefaults {
|
|||||||
scaleX = scale
|
scaleX = scale
|
||||||
scaleY = scale
|
scaleY = scale
|
||||||
clip = true
|
clip = true
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = borderShape
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
modifier
|
modifier
|
||||||
@@ -57,12 +59,19 @@ object ComponentDefaults {
|
|||||||
.border(
|
.border(
|
||||||
width = borderWidth,
|
width = borderWidth,
|
||||||
color = borderColor,
|
color = borderColor,
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = borderShape
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Modifier.focusBorder(needScale: Boolean = true): Modifier {
|
fun Modifier.focusBorder(
|
||||||
return ComponentDefaults.focusBorder(this, needScale)
|
needScale: Boolean = true,
|
||||||
|
shape: Shape = RoundedCornerShape(12.dp)
|
||||||
|
): Modifier {
|
||||||
|
return ComponentDefaults.focusBorder(
|
||||||
|
this,
|
||||||
|
needScale,
|
||||||
|
shape
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user