RNDAMP-8921: use new bottom bar
This commit is contained in:
+31
-58
@@ -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 = {}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 <T : Route> 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user