From 63116b4a0872edc53284362cbebf69a868f7c8f9 Mon Sep 17 00:00:00 2001 From: Eugene Date: Sun, 30 Aug 2026 13:55:35 +0300 Subject: [PATCH] RNDAMP-8921: use new bottom bar --- .../updater/presentation/UpdateDialog.kt | 89 +++++++------------ .../ru/shadowsparky/ui/BottomScaffold.kt | 42 ++++++--- .../shadowsparky/ui/components/ErrorInfo.kt | 6 +- 3 files changed, 66 insertions(+), 71 deletions(-) diff --git a/feature/updater/updater-client/src/commonMain/kotlin/ru/shadowsparky/updater/presentation/UpdateDialog.kt b/feature/updater/updater-client/src/commonMain/kotlin/ru/shadowsparky/updater/presentation/UpdateDialog.kt index dcf0dbb..5457317 100644 --- a/feature/updater/updater-client/src/commonMain/kotlin/ru/shadowsparky/updater/presentation/UpdateDialog.kt +++ b/feature/updater/updater-client/src/commonMain/kotlin/ru/shadowsparky/updater/presentation/UpdateDialog.kt @@ -5,7 +5,6 @@ import androiddev.feature.updater.updater_client.generated.resources.updater_btn import androiddev.feature.updater.updater_client.generated.resources.updater_btn_download import androiddev.feature.updater.updater_client.generated.resources.updater_btn_grant import androiddev.feature.updater.updater_client.generated.resources.updater_btn_install -import androiddev.feature.updater.updater_client.generated.resources.updater_btn_retry import androiddev.feature.updater.updater_client.generated.resources.updater_changelog_empty import androiddev.feature.updater.updater_client.generated.resources.updater_changelog_title import androiddev.feature.updater.updater_client.generated.resources.updater_desc_permission @@ -13,7 +12,6 @@ import androiddev.feature.updater.updater_client.generated.resources.updater_dow import androiddev.feature.updater.updater_client.generated.resources.updater_title_available import androiddev.feature.updater.updater_client.generated.resources.updater_title_completed import androiddev.feature.updater.updater_client.generated.resources.updater_title_downloading -import androiddev.feature.updater.updater_client.generated.resources.updater_title_error import androiddev.feature.updater.updater_client.generated.resources.updater_title_not_found import androiddev.feature.updater.updater_client.generated.resources.updater_title_permission import androiddev.feature.updater.updater_client.generated.resources.updater_title_ready @@ -43,16 +41,14 @@ import com.arkivanov.decompose.extensions.compose.subscribeAsState import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.stringResource import ru.shadowsparky.ui.components.AlertContent +import ru.shadowsparky.ui.components.ErrorContent import ru.shadowsparky.ui.components.LazyColumn import ru.shadowsparky.ui.components.Loading import ru.shadowsparky.updater.domain.UpdateState @OptIn(ExperimentalMaterial3Api::class) @Composable -fun UpdateDialog( - component: UpdateComponent, - modifier: Modifier = Modifier -) { +fun UpdateDialog(component: UpdateComponent, modifier: Modifier = Modifier) { val state by component.state.subscribeAsState() val canDismiss = remember(state) { !component.isForceUpdate } val isVisible = remember(state) { state !is UpdateState.Idle } @@ -90,8 +86,7 @@ fun UpdateDialog( is UpdateState.Error -> UpdateErrorContent( message = currentState.message, - onRetryClick = { component.checkUpdates() }, - focusRequester = focusRequester + onRetryClick = { component.checkUpdates() } ) is UpdateState.UpToDate -> { @@ -158,6 +153,9 @@ private fun UpdateAvailableContent( style = MaterialTheme.typography.bodyMedium ) } + item { + Spacer(modifier = Modifier.height(8.dp)) + } item { Button( onClick = onDownloadClick, @@ -290,76 +288,51 @@ private fun UpdateFinishedContent( private fun UpdateErrorContent( message: String, onRetryClick: () -> Unit, - focusRequester: FocusRequester, modifier: Modifier = Modifier ) { - Column( - modifier = modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - Text( - text = stringResource(Res.string.updater_title_error), - style = MaterialTheme.typography.titleLarge, - color = MaterialTheme.colorScheme.error - ) - Text(text = message, style = MaterialTheme.typography.bodyMedium) - Button( - onClick = onRetryClick, - modifier = Modifier.focusRequester(focusRequester).fillMaxWidth() - ) { - Text( - stringResource(Res.string.updater_btn_retry), - style = MaterialTheme.typography.labelLarge - ) - } - } + ErrorContent( + message, + modifier, + onClick = onRetryClick, + buttonModifier = Modifier.fillMaxWidth() + ) } @Preview @Composable private fun UpdateAvailablePreview() { - MaterialTheme { - UpdateAvailableContent( - versionName = "v1.4.0", - changeLog = "- Добавили темную тему\n- Исправили падение на главном экране\n- Повысили стабильность", - onDownloadClick = {}, - focusRequester = FocusRequester() - ) - } + UpdateAvailableContent( + versionName = "v1.4.0", + changeLog = "- Добавили темную тему\n- Исправили падение на главном экране\n- Повысили стабильность", + onDownloadClick = {}, + focusRequester = FocusRequester() + ) } @Preview @Composable private fun UpdateDownloadingPreview() { - MaterialTheme { - UpdateDownloadingContent( - progress = 0.45f, - downloadedBytes = 24_117_248L, // ~23 MB - totalBytes = 52_428_800L // 50 MB - ) - } + UpdateDownloadingContent( + progress = 0.45f, + downloadedBytes = 24_117_248L, // ~23 MB + totalBytes = 52_428_800L // 50 MB + ) } @Preview @Composable private fun UpdatePermissionPreview() { - MaterialTheme { - UpdatePermissionContent( - onGrantClick = {}, - focusRequester = FocusRequester() - ) - } + UpdatePermissionContent( + onGrantClick = {}, + focusRequester = FocusRequester() + ) } @Preview @Composable private fun UpdateErrorPreview() { - MaterialTheme { - UpdateErrorContent( - message = "Http status 503: Service Unavailable", - onRetryClick = {}, - focusRequester = FocusRequester() - ) - } + UpdateErrorContent( + message = "Http status 503: Service Unavailable", + onRetryClick = {} + ) } diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/BottomScaffold.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/BottomScaffold.kt index df62fa5..c86edee 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/BottomScaffold.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/BottomScaffold.kt @@ -3,23 +3,26 @@ 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.fillMaxWidth import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarDefaults -import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush @@ -62,26 +65,41 @@ private fun BottomBar( ) { navigationEntries?.let { entries -> Box( - modifier = Modifier - .fillMaxWidth() + modifier = Modifier.fillMaxWidth() .background( Brush.verticalGradient( listOf(Color.Transparent, MaterialTheme.colorScheme.surfaceContainer) ) ) .padding(8.dp) - .windowInsetsPadding(WindowInsets.navigationBars) + .windowInsetsPadding(WindowInsets.navigationBars), + contentAlignment = Alignment.Center ) { - NavigationBar( - containerColor = navBarContentColor(), - modifier = Modifier.clip(RoundedCornerShape(24.dp)).blurEffect() + Row( + modifier = Modifier.clip(RoundedCornerShape(24.dp)) + .wrapContentWidth() + .background(navBarContentColor()) + .blurEffect() + .padding(8.dp) ) { entries.forEach { entry -> - NavigationBarItem( - selected = currentRoute == entry.route, + val containerColor = if (currentRoute == entry.route) { + MaterialTheme.colorScheme.secondaryContainer + } else { + Color.Unspecified + } + val contentColor = if (currentRoute == entry.route) { + MaterialTheme.colorScheme.onSecondaryContainer + } else { + Color.Unspecified + } + IconButton( onClick = { onSelectNavigation?.invoke(entry.route) }, - icon = { Icon(entry.painter, contentDescription = entry.title) } - ) + modifier = Modifier.padding(4.dp), + colors = IconButtonDefaults.iconButtonColors(containerColor, contentColor) + ) { + Icon(entry.painter, contentDescription = entry.title) + } } } } diff --git a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/ErrorInfo.kt b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/ErrorInfo.kt index 53aee18..1716786 100644 --- a/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/ErrorInfo.kt +++ b/libs/ui/src/commonMain/kotlin/ru/shadowsparky/ui/components/ErrorInfo.kt @@ -14,8 +14,11 @@ import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -29,6 +32,7 @@ fun ErrorContent( retry: Boolean = true, onClick: () -> Unit ) { + val requester = remember { FocusRequester() } val buttonTextRes = if (retry) Res.string.retry else Res.string.ok Column( verticalArrangement = Arrangement.Center, @@ -47,7 +51,7 @@ fun ErrorContent( textAlign = TextAlign.Center ) Spacer(Modifier.height(8.dp)) - Button(modifier = buttonModifier, onClick = { onClick() }) { + Button(modifier = buttonModifier.focusRequester(requester), onClick = { onClick() }) { Text( text = stringResource(buttonTextRes), style = MaterialTheme.typography.bodyMedium