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_download
|
||||||
import androiddev.feature.updater.updater_client.generated.resources.updater_btn_grant
|
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_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_empty
|
||||||
import androiddev.feature.updater.updater_client.generated.resources.updater_changelog_title
|
import androiddev.feature.updater.updater_client.generated.resources.updater_changelog_title
|
||||||
import androiddev.feature.updater.updater_client.generated.resources.updater_desc_permission
|
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_available
|
||||||
import androiddev.feature.updater.updater_client.generated.resources.updater_title_completed
|
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_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_not_found
|
||||||
import androiddev.feature.updater.updater_client.generated.resources.updater_title_permission
|
import androiddev.feature.updater.updater_client.generated.resources.updater_title_permission
|
||||||
import androiddev.feature.updater.updater_client.generated.resources.updater_title_ready
|
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 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.ErrorContent
|
||||||
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.updater.domain.UpdateState
|
import ru.shadowsparky.updater.domain.UpdateState
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun UpdateDialog(
|
fun UpdateDialog(component: UpdateComponent, modifier: Modifier = Modifier) {
|
||||||
component: UpdateComponent,
|
|
||||||
modifier: Modifier = Modifier
|
|
||||||
) {
|
|
||||||
val state by component.state.subscribeAsState()
|
val state by component.state.subscribeAsState()
|
||||||
val canDismiss = remember(state) { !component.isForceUpdate }
|
val canDismiss = remember(state) { !component.isForceUpdate }
|
||||||
val isVisible = remember(state) { state !is UpdateState.Idle }
|
val isVisible = remember(state) { state !is UpdateState.Idle }
|
||||||
@@ -90,8 +86,7 @@ fun UpdateDialog(
|
|||||||
|
|
||||||
is UpdateState.Error -> UpdateErrorContent(
|
is UpdateState.Error -> UpdateErrorContent(
|
||||||
message = currentState.message,
|
message = currentState.message,
|
||||||
onRetryClick = { component.checkUpdates() },
|
onRetryClick = { component.checkUpdates() }
|
||||||
focusRequester = focusRequester
|
|
||||||
)
|
)
|
||||||
|
|
||||||
is UpdateState.UpToDate -> {
|
is UpdateState.UpToDate -> {
|
||||||
@@ -158,6 +153,9 @@ private fun UpdateAvailableContent(
|
|||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
}
|
||||||
item {
|
item {
|
||||||
Button(
|
Button(
|
||||||
onClick = onDownloadClick,
|
onClick = onDownloadClick,
|
||||||
@@ -290,76 +288,51 @@ private fun UpdateFinishedContent(
|
|||||||
private fun UpdateErrorContent(
|
private fun UpdateErrorContent(
|
||||||
message: String,
|
message: String,
|
||||||
onRetryClick: () -> Unit,
|
onRetryClick: () -> Unit,
|
||||||
focusRequester: FocusRequester,
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Column(
|
ErrorContent(
|
||||||
modifier = modifier.fillMaxWidth(),
|
message,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
modifier,
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
onClick = onRetryClick,
|
||||||
) {
|
buttonModifier = Modifier.fillMaxWidth()
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun UpdateAvailablePreview() {
|
private fun UpdateAvailablePreview() {
|
||||||
MaterialTheme {
|
UpdateAvailableContent(
|
||||||
UpdateAvailableContent(
|
versionName = "v1.4.0",
|
||||||
versionName = "v1.4.0",
|
changeLog = "- Добавили темную тему\n- Исправили падение на главном экране\n- Повысили стабильность",
|
||||||
changeLog = "- Добавили темную тему\n- Исправили падение на главном экране\n- Повысили стабильность",
|
onDownloadClick = {},
|
||||||
onDownloadClick = {},
|
focusRequester = FocusRequester()
|
||||||
focusRequester = FocusRequester()
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun UpdateDownloadingPreview() {
|
private fun UpdateDownloadingPreview() {
|
||||||
MaterialTheme {
|
UpdateDownloadingContent(
|
||||||
UpdateDownloadingContent(
|
progress = 0.45f,
|
||||||
progress = 0.45f,
|
downloadedBytes = 24_117_248L, // ~23 MB
|
||||||
downloadedBytes = 24_117_248L, // ~23 MB
|
totalBytes = 52_428_800L // 50 MB
|
||||||
totalBytes = 52_428_800L // 50 MB
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun UpdatePermissionPreview() {
|
private fun UpdatePermissionPreview() {
|
||||||
MaterialTheme {
|
UpdatePermissionContent(
|
||||||
UpdatePermissionContent(
|
onGrantClick = {},
|
||||||
onGrantClick = {},
|
focusRequester = FocusRequester()
|
||||||
focusRequester = FocusRequester()
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun UpdateErrorPreview() {
|
private fun UpdateErrorPreview() {
|
||||||
MaterialTheme {
|
UpdateErrorContent(
|
||||||
UpdateErrorContent(
|
message = "Http status 503: Service Unavailable",
|
||||||
message = "Http status 503: Service Unavailable",
|
onRetryClick = {}
|
||||||
onRetryClick = {},
|
)
|
||||||
focusRequester = FocusRequester()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,23 +3,26 @@ 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.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.layout.wrapContentWidth
|
||||||
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.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.NavigationBar
|
|
||||||
import androidx.compose.material3.NavigationBarDefaults
|
import androidx.compose.material3.NavigationBarDefaults
|
||||||
import androidx.compose.material3.NavigationBarItem
|
|
||||||
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.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
@@ -62,26 +65,41 @@ private fun <T : Route> BottomBar(
|
|||||||
) {
|
) {
|
||||||
navigationEntries?.let { entries ->
|
navigationEntries?.let { entries ->
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
|
||||||
.background(
|
.background(
|
||||||
Brush.verticalGradient(
|
Brush.verticalGradient(
|
||||||
listOf(Color.Transparent, MaterialTheme.colorScheme.surfaceContainer)
|
listOf(Color.Transparent, MaterialTheme.colorScheme.surfaceContainer)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
NavigationBar(
|
Row(
|
||||||
containerColor = navBarContentColor(),
|
modifier = Modifier.clip(RoundedCornerShape(24.dp))
|
||||||
modifier = Modifier.clip(RoundedCornerShape(24.dp)).blurEffect()
|
.wrapContentWidth()
|
||||||
|
.background(navBarContentColor())
|
||||||
|
.blurEffect()
|
||||||
|
.padding(8.dp)
|
||||||
) {
|
) {
|
||||||
entries.forEach { entry ->
|
entries.forEach { entry ->
|
||||||
NavigationBarItem(
|
val containerColor = if (currentRoute == entry.route) {
|
||||||
selected = 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) },
|
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.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -29,6 +32,7 @@ fun ErrorContent(
|
|||||||
retry: Boolean = true,
|
retry: Boolean = true,
|
||||||
onClick: () -> Unit
|
onClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
val requester = remember { FocusRequester() }
|
||||||
val buttonTextRes = if (retry) Res.string.retry else Res.string.ok
|
val buttonTextRes = if (retry) Res.string.retry else Res.string.ok
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
@@ -47,7 +51,7 @@ fun ErrorContent(
|
|||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
Button(modifier = buttonModifier, onClick = { onClick() }) {
|
Button(modifier = buttonModifier.focusRequester(requester), onClick = { onClick() }) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(buttonTextRes),
|
text = stringResource(buttonTextRes),
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
|||||||
Reference in New Issue
Block a user