From 7e272ae01afc25426075f09e739774fdd373961e Mon Sep 17 00:00:00 2001 From: 283375 Date: Tue, 6 Oct 2026 00:07:30 +0800 Subject: [PATCH 1/8] refactor(ui): replace spacing dimens and raw dps with a token scale The new `Spacing` object defines a 4dp-grid scale plus semantic aliases, exposed as MaterialTheme.spacing, replacing all legacy dimensionResource calls and raw spacing dps. dimens.xml is also removed. Icon sizes, corner radii, and stroke widths are out of scope and stay untouched. --- .../ui/activities/EmergencyModeActivityUi.kt | 12 ++++----- .../ocrfromshare/AppIconLabelButton.kt | 8 +++--- .../ocrfromshare/OcrFromShareActions.kt | 4 +-- .../ocrfromshare/OcrFromShareScreen.kt | 20 +++++++------- .../ui/common/PermissionRequiredDialog.kt | 4 +-- .../datetimeeditor/DateTimeEditDialog.kt | 11 ++++---- .../ui/components/ArcaeaChartCard.kt | 7 +++-- .../ui/components/ArcaeaChartSelector.kt | 9 ++++--- .../ArcaeaPackAndSongQuickSearch.kt | 5 ++-- .../components/ArcaeaPackAndSongSelector.kt | 6 ++--- .../ui/components/ArcaeaPlayResultCard.kt | 12 ++++----- ...ArcaeaPlayResultValidatorWarningDetails.kt | 7 +++-- .../ui/components/BasicAlertDialogSurface.kt | 4 ++- .../arcaeaoffline/ui/components/IconRow.kt | 6 ++--- .../ui/components/ImagePreviewDialog.kt | 7 +++-- .../LinearProgressIndicatorWrapper.kt | 5 ++-- .../ui/components/ListGroupHeader.kt | 7 +++-- .../ui/components/NullableNumberInput.kt | 3 ++- .../ui/components/PlayRatingCalculator.kt | 5 ++-- .../ui/components/SelectDialog.kt | 9 +++---- .../components/ocr/OcrDependencyStatusChip.kt | 6 ++--- .../ocr/OcrDependencyStatusViewer.kt | 5 ++-- .../preferences/BasePreferencesWidget.kt | 9 +++---- .../preferences/SliderPreferencesWidget.kt | 5 ++-- .../arcaeaoffline/ui/screens/EmptyScreen.kt | 4 +-- .../ui/screens/database/DatabaseNavEntry.kt | 6 ++--- .../ui/screens/database/DatabaseStatus.kt | 9 ++++--- .../DatabaseAddPlayResultChartAction.kt | 5 ++-- .../DatabaseAddPlayResultPlayResultAction.kt | 5 ++-- .../DatabaseAddPlayResultScreen.kt | 10 +++---- .../database/bestlist/DatabaseBestListItem.kt | 11 ++++---- .../bestlist/DatabaseBestListScreen.kt | 10 +++---- .../DatabaseDeduplicatorGroupListItem.kt | 9 +++---- .../DatabaseDeduplicatorScreen.kt | 7 +++-- .../ui/screens/database/manage/ImportLogUi.kt | 13 +++++----- .../DatabasePlayResultListScreen.kt | 6 ++--- .../DatabasePlayResultListSortDialog.kt | 9 ++++--- .../database/r30list/DatabaseR30ListItem.kt | 7 +++-- .../database/r30list/DatabaseR30ListScreen.kt | 6 ++--- .../ocr/performance/OcrPerformanceScreen.kt | 24 ++++++++--------- .../screens/ocr/queue/OcrQueueCategoryItem.kt | 5 ++-- .../OcrQueueStagingFloatingActionButton.kt | 3 ++- .../ocr/queue/staging/OcrQueueStagingSheet.kt | 16 ++++++------ .../ocr/queue/tasklist/OcrQueueTaskList.kt | 8 +++--- .../queue/tasklist/OcrQueueTaskListItem.kt | 6 ++--- .../screens/overview/OverviewPotentialCard.kt | 10 +++---- .../ui/screens/overview/OverviewScreen.kt | 6 ++--- .../ui/screens/settings/SettingsNavEntry.kt | 4 +-- .../settings/about/SettingsAboutScreen.kt | 4 +-- .../settings/license/SettingsLicenseScreen.kt | 6 ++--- .../SettingsUnstableAlertCard.kt | 8 +++--- .../SettingsUnstableAlertScreen.kt | 5 ++-- .../utilities/UtilitiesCalculatorScreen.kt | 11 ++++---- .../UtilitiesChartRecommendScreen.kt | 24 ++++++++--------- app/src/main/res/values/dimens.xml | 16 ------------ .../ui/components/DecimalStepperTextField.kt | 6 +++-- .../sevive/arcaeaoffline/ui/theme/Spacing.kt | 26 +++++++++++++++++++ 57 files changed, 248 insertions(+), 233 deletions(-) delete mode 100644 app/src/main/res/values/dimens.xml create mode 100644 shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt index 4e248895..ac32f372 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt @@ -34,7 +34,6 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -46,6 +45,7 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.context.persistUriPermissions import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader +import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -109,10 +109,10 @@ fun EmergencyModeActivityUi( .consumeWindowInsets(padding), contentPadding = PaddingValues( - top = padding.calculateTopPadding() + dimensionResource(R.dimen.list_padding), - bottom = padding.calculateBottomPadding() + dimensionResource(R.dimen.list_padding), - start = dimensionResource(R.dimen.list_padding), - end = dimensionResource(R.dimen.list_padding), + top = padding.calculateTopPadding() + MaterialTheme.spacing.sm, + bottom = padding.calculateBottomPadding() + MaterialTheme.spacing.sm, + start = MaterialTheme.spacing.sm, + end = MaterialTheme.spacing.sm, ), ) { item { @@ -138,7 +138,7 @@ fun EmergencyModeActivityUi( Text(stringResource(R.string.emergency_mode_output_directory_select_button)) } - Spacer(Modifier.width(dimensionResource(R.dimen.list_padding))) + Spacer(Modifier.width(MaterialTheme.spacing.sm)) CompositionLocalProvider( LocalContentColor provides diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/AppIconLabelButton.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/AppIconLabelButton.kt index 56238319..bf2cad45 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/AppIconLabelButton.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/AppIconLabelButton.kt @@ -10,12 +10,12 @@ import androidx.compose.material3.Button import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.dp -import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun AppIconLabelButton( @@ -34,14 +34,14 @@ internal fun AppIconLabelButton( shape = RoundedCornerShape(20.dp), ) { Row( - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.action_button_icon_text_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.CenterVertically, ) { appIcon() Column( Modifier.weight(1f), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.icon_text_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap), ) { appLabel() diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/OcrFromShareActions.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/OcrFromShareActions.kt index 945db581..2977aee9 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/OcrFromShareActions.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/OcrFromShareActions.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.coroutines.launch @@ -31,6 +30,7 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.permissions.storage.SaveBitmapToGallery import xyz.sevive.arcaeaoffline.ui.common.PermissionRequiredDialog import xyz.sevive.arcaeaoffline.ui.components.IconRow +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun OcrFromShareActions(ocrFromShareViewModel: OcrFromShareViewModel) { @@ -63,7 +63,7 @@ internal fun OcrFromShareActions(ocrFromShareViewModel: OcrFromShareViewModel) { val scoreCached by ocrFromShareViewModel.scoreCached.collectAsStateWithLifecycle() Column { - Row(horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding))) { + Row(horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm)) { Button( onClick = { coroutineScope.launch { ocrFromShareViewModel.saveScore() } }, enabled = score != null && !scoreSaved && !scoreCached, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/OcrFromShareScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/OcrFromShareScreen.kt index 4021bc0d..c107cca6 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/OcrFromShareScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/ocrfromshare/OcrFromShareScreen.kt @@ -25,10 +25,10 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun OcrFromShareReturnToShareAppButton( @@ -111,12 +111,12 @@ internal fun OcrFromShareScreenContentMedium( .fillMaxSize() .consumeWindowInsets(innerPadding) .padding(innerPadding) - .padding(dimensionResource(R.dimen.page_padding)), - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.page_padding)), + .padding(MaterialTheme.spacing.pagePadding), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.pagePadding), ) { Column( Modifier.weight(1f), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { OcrFromShareOcrDependencyStatusCard(ocrDependencyViewersUiState) @@ -127,7 +127,7 @@ internal fun OcrFromShareScreenContentMedium( LazyColumn( Modifier.weight(1f), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { item { OcrFromShareOcrResult(viewModel) @@ -170,12 +170,12 @@ fun OcrFromShareScreenCompact( .consumeWindowInsets(innerPadding), contentPadding = PaddingValues( - top = innerPadding.calculateTopPadding() + dimensionResource(R.dimen.page_padding), - bottom = innerPadding.calculateBottomPadding() + dimensionResource(R.dimen.page_padding), - start = dimensionResource(R.dimen.page_padding), - end = dimensionResource(R.dimen.page_padding), + top = innerPadding.calculateTopPadding() + MaterialTheme.spacing.pagePadding, + bottom = innerPadding.calculateBottomPadding() + MaterialTheme.spacing.pagePadding, + start = MaterialTheme.spacing.pagePadding, + end = MaterialTheme.spacing.pagePadding, ), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { item { OcrFromShareOcrDependencyStatusCard(ocrDependencyViewersUiState) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/PermissionRequiredDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/PermissionRequiredDialog.kt index ef8bf961..a5d7d8f8 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/PermissionRequiredDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/PermissionRequiredDialog.kt @@ -17,7 +17,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -28,6 +27,7 @@ import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButton import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogDismissTextButton import xyz.sevive.arcaeaoffline.ui.components.preferences.BasePreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable fun rememberPermissionIcon(permission: String): ImageVector? = @@ -110,7 +110,7 @@ fun PermissionRequiredDialog( icon = { Icon(Icons.Default.Flaky, contentDescription = null) }, title = { Text(stringResource(R.string.permission_required_dialog_title)) }, text = { - Column(verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding))) { + Column(verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm)) { Text( pluralStringResource( R.plurals.permission_required_dialog_content, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/datetimeeditor/DateTimeEditDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/datetimeeditor/DateTimeEditDialog.kt index d60263bf..bb5b1bd3 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/datetimeeditor/DateTimeEditDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/datetimeeditor/DateTimeEditDialog.kt @@ -44,6 +44,10 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle +import kotlin.time.Clock +import kotlin.time.Instant import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalTime @@ -59,10 +63,7 @@ import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButton import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogDismissTextButton import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme -import java.time.format.DateTimeFormatter -import java.time.format.FormatStyle -import kotlin.time.Clock -import kotlin.time.Instant +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun SecondEditor( @@ -248,7 +249,7 @@ private fun DateTimeEditDialogRealDevicePreview() { ) } - Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + Column(verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm)) { Text(text = dateTime.format(LocalDateTime.Formats.ISO)) Button(onClick = { showDialog = true }) { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaChartCard.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaChartCard.kt index 4f36f768..1df484f5 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaChartCard.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaChartCard.kt @@ -32,12 +32,10 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import kotlinx.coroutines.flow.combine import org.koin.compose.koinInject -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.constants.ArcaeaRatingClass import xyz.sevive.arcaeaoffline.core.constants.ArcaeaRatingClassDisplay import xyz.sevive.arcaeaoffline.core.database.entities.ChartInfo @@ -47,6 +45,7 @@ import xyz.sevive.arcaeaoffline.core.database.repositories.DifficultyWithSongRep import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.ratingClassColor +import xyz.sevive.arcaeaoffline.ui.theme.spacing // Display data resolved as one atomic unit. Swapping the pair together is // what keeps the card consistent (title/level text and constant change in @@ -99,8 +98,8 @@ fun ArcaeaChartCard( shape = shape, ) { Row( - Modifier.padding(dimensionResource(R.dimen.card_padding)), - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + Modifier.padding(MaterialTheme.spacing.cardPadding), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.CenterVertically, ) { Image( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaChartSelector.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaChartSelector.kt index 78ff3856..54a450f7 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaChartSelector.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaChartSelector.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State @@ -16,7 +17,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import org.koin.compose.koinInject import xyz.sevive.arcaeaoffline.R @@ -25,6 +25,7 @@ import xyz.sevive.arcaeaoffline.core.database.entities.Difficulty import xyz.sevive.arcaeaoffline.core.database.entities.Song import xyz.sevive.arcaeaoffline.core.database.repositories.DifficultyRepository import xyz.sevive.arcaeaoffline.core.database.repositories.SongRepository +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun rememberArcaeaSong( @@ -79,8 +80,8 @@ fun ArcaeaChartSelector( } Column( - Modifier.padding(dimensionResource(R.dimen.card_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + Modifier.padding(MaterialTheme.spacing.cardPadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { ArcaeaPackAndSongSelector( song = song, @@ -89,7 +90,7 @@ fun ArcaeaChartSelector( Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.icon_text_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap), ) { Icon(painterResource(R.drawable.ic_rating_class), contentDescription = null) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongQuickSearch.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongQuickSearch.kt index c723ebbc..49feb4d9 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongQuickSearch.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongQuickSearch.kt @@ -36,6 +36,7 @@ import xyz.sevive.arcaeaoffline.core.database.entities.Pack import xyz.sevive.arcaeaoffline.core.database.entities.Song import xyz.sevive.arcaeaoffline.core.database.repositories.PackRepository import xyz.sevive.arcaeaoffline.core.database.repositories.SongRepository +import xyz.sevive.arcaeaoffline.ui.theme.spacing data class FilterResult( val packId: String, @@ -153,7 +154,7 @@ fun ArcaeaPackAndSongQuickSearch( candidates.forEachIndexed { i, candidate -> DropdownMenuItem( text = { - Column(verticalArrangement = Arrangement.spacedBy(2.dp)) { + Column(verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.xxs)) { Text(candidate.song.title, style = MaterialTheme.typography.labelLarge) Text( candidate.pack.name, @@ -168,7 +169,7 @@ fun ArcaeaPackAndSongQuickSearch( expanded = false focusManager.clearFocus() }, - contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding.plus(PaddingValues(vertical = 8.dp)), + contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding.plus(PaddingValues(vertical = MaterialTheme.spacing.sm)), ) if (i != candidates.lastIndex) { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongSelector.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongSelector.kt index baf05e12..b854bec3 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongSelector.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongSelector.kt @@ -3,6 +3,7 @@ package xyz.sevive.arcaeaoffline.ui.components import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State @@ -13,14 +14,13 @@ import androidx.compose.runtime.produceState import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import kotlinx.coroutines.flow.firstOrNull import org.koin.compose.koinInject -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.database.entities.Pack import xyz.sevive.arcaeaoffline.core.database.entities.Song import xyz.sevive.arcaeaoffline.core.database.repositories.PackRepository import xyz.sevive.arcaeaoffline.core.database.repositories.SongRepository +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun rememberArcaeaPacks(packRepo: PackRepository): State> = @@ -122,7 +122,7 @@ fun ArcaeaPackAndSongSelector( Column( modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { ArcaeaPackAndSongQuickSearch( onSelect = { filter -> diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultCard.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultCard.kt index d2f55c17..e7aefc14 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultCard.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultCard.kt @@ -40,7 +40,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalResources -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString @@ -51,6 +50,7 @@ import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp +import kotlin.time.Instant import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.constants.ArcaeaPlayResultClearType import xyz.sevive.arcaeaoffline.core.constants.ArcaeaPlayResultModifier @@ -66,7 +66,7 @@ import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.arcaeaColors import xyz.sevive.arcaeaoffline.ui.theme.extendedColorScheme import xyz.sevive.arcaeaoffline.ui.theme.playResultGradeGradientBrush -import kotlin.time.Instant +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun pflAnnotatedString( @@ -194,7 +194,7 @@ fun ArcaeaPlayResultCard( Row(verticalAlignment = Alignment.CenterVertically) { Column( Modifier - .width(exPlusWidthDp + dimensionResource(R.dimen.card_padding)) + .width(exPlusWidthDp + MaterialTheme.spacing.cardPadding) .fillMaxHeight(), horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -254,11 +254,11 @@ fun ArcaeaPlayResultCard( Column( Modifier .weight(1f) - .padding(dimensionResource(R.dimen.card_padding)), + .padding(MaterialTheme.spacing.cardPadding), ) { Text(scoreText, style = MaterialTheme.typography.titleLarge) - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + Row(horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm)) { Text( pflAnnotatedString("P", playResult.pure), color = MaterialTheme.arcaeaColors.pure, @@ -455,7 +455,7 @@ private fun PlayResultCardPreview() { playResult = playResults[i], difficultyWithSong = if (i >= 1) difficulty else null, chartInfo = if (i >= 1) chartInfo else null, - modifier = Modifier.padding(bottom = 4.dp), + modifier = Modifier.padding(bottom = MaterialTheme.spacing.xs), ) } } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultValidatorWarningDetails.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultValidatorWarningDetails.kt index 93f4ea93..d8ea025f 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultValidatorWarningDetails.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultValidatorWarningDetails.kt @@ -37,11 +37,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.sp -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.ArcaeaPlayResultValidatorMaxRecallOverflowWarning import xyz.sevive.arcaeaoffline.helpers.ArcaeaPlayResultValidatorPflOverflowWarning import xyz.sevive.arcaeaoffline.helpers.ArcaeaPlayResultValidatorPureMemoryFarLostNotZeroWarning @@ -49,6 +47,7 @@ import xyz.sevive.arcaeaoffline.helpers.ArcaeaPlayResultValidatorWarning import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.extendedColorScheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun ArcaeaPlayResultValidatorWarningDetailItem( @@ -64,7 +63,7 @@ private fun ArcaeaPlayResultValidatorWarningDetailItem( val context = LocalContext.current val density = LocalDensity.current - val padding = dimensionResource(R.dimen.card_padding) + val padding = MaterialTheme.spacing.cardPadding val messagePadding = remember(density) { val start = with(density) { 24.sp.toDp() + padding * 2 } @@ -87,7 +86,7 @@ private fun ArcaeaPlayResultValidatorWarningDetailItem( Modifier .minimumInteractiveComponentSize() .padding(padding), - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.CenterVertically, ) { CompositionLocalProvider( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/BasicAlertDialogSurface.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/BasicAlertDialogSurface.kt index 4dc81780..7984055c 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/BasicAlertDialogSurface.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/BasicAlertDialogSurface.kt @@ -4,11 +4,13 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.material3.AlertDialogDefaults import androidx.compose.material3.BasicAlertDialog import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties +import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -27,7 +29,7 @@ fun BasicAlertDialogSurface( shape = AlertDialogDefaults.shape, color = AlertDialogDefaults.containerColor, ) { - content(PaddingValues(all = 24.dp)) + content(PaddingValues(all = MaterialTheme.spacing.xl)) } } } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/IconRow.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/IconRow.kt index 813957b7..ef964f99 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/IconRow.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/IconRow.kt @@ -3,11 +3,11 @@ package xyz.sevive.arcaeaoffline.ui.components import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource -import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable fun IconRow( @@ -16,7 +16,7 @@ fun IconRow( ) { Row( modifier, - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.icon_text_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap), verticalAlignment = Alignment.CenterVertically, content = content, ) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ImagePreviewDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ImagePreviewDialog.kt index c3e10b26..02667d78 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ImagePreviewDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ImagePreviewDialog.kt @@ -31,13 +31,12 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.github.panpf.zoomimage.SketchZoomAsyncImage -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.context.getFilename +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun TopFileInfoCard( @@ -55,7 +54,7 @@ private fun TopFileInfoCard( ) { Text( if (toggle) filename else uri.toString(), - Modifier.padding(dimensionResource(R.dimen.page_padding)), + Modifier.padding(MaterialTheme.spacing.pagePadding), style = MaterialTheme.typography.labelLarge, ) } @@ -86,7 +85,7 @@ fun ImagePreviewDialogFullscreen( Box( Modifier .windowInsetsPadding(WindowInsets.navigationBars) - .padding(bottom = 28.dp) + .padding(bottom = MaterialTheme.spacing.xl) .fillMaxWidth(), ) { FilledTonalIconButton( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/LinearProgressIndicatorWrapper.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/LinearProgressIndicatorWrapper.kt index 39a1d6d9..36608cef 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/LinearProgressIndicatorWrapper.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/LinearProgressIndicatorWrapper.kt @@ -17,8 +17,9 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp -import xyz.sevive.arcaeaoffline.core.Progress import kotlin.math.roundToInt +import xyz.sevive.arcaeaoffline.core.Progress +import xyz.sevive.arcaeaoffline.ui.theme.spacing typealias PercentageFormatter = (Float) -> String @@ -69,7 +70,7 @@ fun LinearProgressIndicatorWrapper( Text(text = progressLabel, style = MaterialTheme.typography.bodyMedium) } - Spacer(modifier = Modifier.height(4.dp)) + Spacer(modifier = Modifier.height(MaterialTheme.spacing.xs)) if (isIndeterminate) { LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt index a4276da0..27e44ad0 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt @@ -11,17 +11,16 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight -import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.theme.spacing object ListGroupHeaderDefaults { val paddingValues @Composable get() = PaddingValues( - horizontal = dimensionResource(R.dimen.list_group_header_horizontal_padding), - vertical = dimensionResource(R.dimen.list_group_header_vertical_padding), + horizontal = MaterialTheme.spacing.lg, + vertical = MaterialTheme.spacing.sm, ) val contentColor @Composable get() = MaterialTheme.colorScheme.primary diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/NullableNumberInput.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/NullableNumberInput.kt index 8b5a565a..ca08803b 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/NullableNumberInput.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/NullableNumberInput.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.dp import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogDismissTextButtonDefaults +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun NullableNumberInputEditDialog( @@ -55,7 +56,7 @@ private fun NullableNumberInputEditDialog( AlertDialog( onDismissRequest = onDismiss, text = { - Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) { + Row(horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.xs)) { TextField( value = textFieldValue, onValueChange = { textFieldValue = it }, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/PlayRatingCalculator.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/PlayRatingCalculator.kt index 3623f5b4..00ae3951 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/PlayRatingCalculator.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/PlayRatingCalculator.kt @@ -34,6 +34,7 @@ import xyz.sevive.arcaeaoffline.ui.components.arcaea.rememberArcaeaScoreTextFiel import xyz.sevive.arcaeaoffline.ui.components.preferences.SwitchPreferencesWidget import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable fun PlayRatingCalculator( @@ -92,7 +93,7 @@ fun PlayRatingCalculator( Column(modifier) { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { OutlinedArcaeaScoreTextField( scoreTextFieldState, @@ -110,7 +111,7 @@ fun PlayRatingCalculator( } Row( - Modifier.padding(top = 16.dp), + Modifier.padding(top = MaterialTheme.spacing.lg), verticalAlignment = Alignment.CenterVertically, ) { Icon(Icons.AutoMirrored.Filled.ArrowRight, contentDescription = null) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SelectDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SelectDialog.kt index 8a8ea7b8..a9bb75b2 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SelectDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SelectDialog.kt @@ -14,11 +14,10 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.unit.dp -import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.theme.spacing /** * A simple selection dialog. @@ -38,7 +37,7 @@ fun SelectDialog( ) { BasicAlertDialogSurface(onDismissRequest = onDismiss) { if (labels.isEmpty()) { - Box(Modifier.padding(dimensionResource(R.dimen.page_padding) * 2)) { + Box(Modifier.padding(MaterialTheme.spacing.pagePadding * 2)) { Text("No options available.") } } else { @@ -60,8 +59,8 @@ fun SelectDialog( } else { Modifier }, - ).padding(horizontal = 16.dp, vertical = 8.dp), - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.icon_text_padding) * 2), + ).padding(horizontal = MaterialTheme.spacing.lg, vertical = MaterialTheme.spacing.sm), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap * 2), verticalAlignment = Alignment.CenterVertically, ) { RadioButton( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusChip.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusChip.kt index c9cc8bf7..a257dcc0 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusChip.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusChip.kt @@ -31,7 +31,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview @@ -41,6 +40,7 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.OcrDependencyStatus import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.extendedColorScheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing data class OcrDependencyStatusChipUiState( val icon: ImageVector = Icons.Default.QuestionMark, @@ -97,7 +97,7 @@ fun OcrDependencyStatusChip( modifier: Modifier = Modifier, ) { val padding by animateDpAsState( - targetValue = if (uiState.expanded) dimensionResource(R.dimen.icon_text_padding) else 0.dp, + targetValue = if (uiState.expanded) MaterialTheme.spacing.iconTextGap else 0.dp, label = "iconPadding", ) @@ -144,7 +144,7 @@ private fun OcrDependencyStatusChipSinglePreview() { Surface( Modifier .width(200.dp) - .padding(8.dp), + .padding(MaterialTheme.spacing.sm), ) { OcrDependencyStatusChip( OcrDependencyStatus.UNKNOWN, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusViewer.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusViewer.kt index 59fa38f9..9d953455 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusViewer.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusViewer.kt @@ -26,6 +26,7 @@ import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.preferences.BasePreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing object OcrDependencyStatusViewerDefaults { @Composable @@ -132,10 +133,10 @@ fun OcrDependencyStatusViewer( @Composable private fun OcrDependencyStatusViewerPreview() { ArcaeaOfflineTheme { - Card(Modifier.padding(8.dp)) { + Card(Modifier.padding(MaterialTheme.spacing.sm)) { Text( "Test Dependencies", - Modifier.padding(16.dp), + Modifier.padding(MaterialTheme.spacing.lg), style = MaterialTheme.typography.titleLarge, ) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/BasePreferencesWidget.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/BasePreferencesWidget.kt index c519567c..a722cccc 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/BasePreferencesWidget.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/BasePreferencesWidget.kt @@ -19,18 +19,17 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing private val HorizontalPadding @Composable - get() = dimensionResource(R.dimen.pref_widget_horizontal_padding) + get() = MaterialTheme.spacing.lg private val VerticalPadding @Composable - get() = dimensionResource(R.dimen.pref_widget_vertical_padding) + get() = MaterialTheme.spacing.lg @Composable fun BasePreferencesWidget( @@ -56,7 +55,7 @@ fun BasePreferencesWidget( Modifier .weight(1f) .padding(horizontal = HorizontalPadding, vertical = VerticalPadding), - verticalArrangement = Arrangement.spacedBy(2.dp), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.xxs), ) { CompositionLocalProvider( LocalTextStyle provides MaterialTheme.typography.bodyLarge, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SliderPreferencesWidget.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SliderPreferencesWidget.kt index 0e87f2fe..e0df9f62 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SliderPreferencesWidget.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SliderPreferencesWidget.kt @@ -12,9 +12,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.dimensionResource -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable fun SliderPreferencesWidget( @@ -33,7 +32,7 @@ fun SliderPreferencesWidget( trailingSlot = trailingSlot, ) { Column( - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { content?.invoke(this@Column) Slider( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/EmptyScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/EmptyScreen.kt index 9f9778ce..36a6958c 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/EmptyScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/EmptyScreen.kt @@ -13,10 +13,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable fun EmptyScreen( @@ -27,7 +27,7 @@ fun EmptyScreen( Column( Modifier.align(Alignment.Center), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { Icon( Icons.Default.Inbox, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/DatabaseNavEntry.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/DatabaseNavEntry.kt index a8c34de1..aaa1903a 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/DatabaseNavEntry.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/DatabaseNavEntry.kt @@ -13,6 +13,7 @@ import androidx.compose.material.icons.filled.CopyAll import androidx.compose.material.icons.filled.History import androidx.compose.material.icons.filled.Star import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar @@ -20,16 +21,15 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.koin.compose.viewmodel.koinViewModel -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.constants.ArcaeaScoringMode import xyz.sevive.arcaeaoffline.ui.navigation.DatabaseSubScreen import xyz.sevive.arcaeaoffline.ui.navigation.LocalListDetailNavigationContext import xyz.sevive.arcaeaoffline.ui.navigation.MainScreen import xyz.sevive.arcaeaoffline.ui.screens.NavEntryNavigateButton +import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -59,7 +59,7 @@ fun DatabaseNavEntry( statusUiState, Modifier .fillMaxWidth() - .padding(horizontal = dimensionResource(R.dimen.page_padding)), + .padding(horizontal = MaterialTheme.spacing.pagePadding), ) } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/DatabaseStatus.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/DatabaseStatus.kt index 8ba9d8a6..27e7f43f 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/DatabaseStatus.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/DatabaseStatus.kt @@ -12,6 +12,7 @@ import androidx.compose.material.icons.filled.MusicNote import androidx.compose.material.icons.filled.Translate import androidx.compose.material3.Card import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -19,13 +20,13 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.PreviewLightDark import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun DatabaseStatusIconRow( @@ -35,7 +36,7 @@ private fun DatabaseStatusIconRow( deletedItemCount: Int? = null, ) { Row( - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.Bottom, ) { IconRow { @@ -92,8 +93,8 @@ fun DatabaseStatus( Card(modifier) { Column( - Modifier.padding(dimensionResource(R.dimen.card_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + Modifier.padding(MaterialTheme.spacing.cardPadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { DatabaseStatusIconRow( icon = ImageVector.vectorResource(R.drawable.ic_database), diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultChartAction.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultChartAction.kt index 33f5a414..d971490c 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultChartAction.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultChartAction.kt @@ -12,6 +12,7 @@ import androidx.compose.material.icons.filled.TouchApp import androidx.compose.material3.Card import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.minimumInteractiveComponentSize @@ -22,7 +23,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import xyz.sevive.arcaeaoffline.R @@ -34,6 +34,7 @@ import xyz.sevive.arcaeaoffline.ui.components.BasicAlertDialogSurface import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.rememberArcaeaChartDisplay import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun SelectChartDialog( @@ -87,7 +88,7 @@ internal fun DatabaseAddPlayResultChartAction( IconRow( Modifier .minimumInteractiveComponentSize() - .padding(dimensionResource(R.dimen.card_padding)), + .padding(MaterialTheme.spacing.cardPadding), ) { Icon(Icons.Default.TouchApp, null) Text(stringResource(R.string.database_add_play_result_click_select_chart)) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultPlayResultAction.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultPlayResultAction.kt index 22ec61a6..16a2169e 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultPlayResultAction.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultPlayResultAction.kt @@ -12,6 +12,7 @@ import androidx.compose.material.icons.filled.Edit import androidx.compose.material3.Card import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.minimumInteractiveComponentSize @@ -22,7 +23,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import xyz.sevive.arcaeaoffline.R @@ -33,6 +33,7 @@ import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultCard import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultEditorDialog import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun DatabaseAddPlayResultPlayResultAction( @@ -68,7 +69,7 @@ internal fun DatabaseAddPlayResultPlayResultAction( IconRow( Modifier .minimumInteractiveComponentSize() - .padding(dimensionResource(R.dimen.card_padding)), + .padding(MaterialTheme.spacing.cardPadding), ) { Icon(Icons.Default.Block, null) Text(stringResource(R.string.database_add_play_result_select_chart_first)) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultScreen.kt index c13275ef..4cfd2d79 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultScreen.kt @@ -25,7 +25,6 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.koin.compose.viewmodel.koinViewModel @@ -34,6 +33,7 @@ import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader import xyz.sevive.arcaeaoffline.ui.navigation.DatabaseSubScreen +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun BottomActionsBar( @@ -86,7 +86,7 @@ internal fun DatabaseAddPlayResultScreen( modifier = Modifier .fillMaxWidth() - .padding(dimensionResource(R.dimen.page_padding)), + .padding(MaterialTheme.spacing.pagePadding), ) }, ) { innerPadding -> @@ -104,13 +104,13 @@ internal fun DatabaseAddPlayResultScreen( DatabaseAddPlayResultChartAction( difficulty = uiState.difficulty, onDifficultyChange = { viewModel.setDifficulty(it) }, - modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.list_group_header_horizontal_padding)), + modifier = Modifier.padding(horizontal = MaterialTheme.spacing.lg), ) } item { // Just adding a padding - Box(Modifier.padding(vertical = dimensionResource(R.dimen.list_padding))) {} + Box(Modifier.padding(vertical = MaterialTheme.spacing.sm)) {} } item { @@ -122,7 +122,7 @@ internal fun DatabaseAddPlayResultScreen( playResult = uiState.playResult, onPlayResultChange = { viewModel.setPlayResult(it) }, warnings = uiState.warnings, - modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.list_group_header_horizontal_padding)), + modifier = Modifier.padding(horizontal = MaterialTheme.spacing.lg), ) } } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListItem.kt index 4b7a0d60..f61a47cf 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListItem.kt @@ -15,13 +15,13 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview -import xyz.sevive.arcaeaoffline.R +import kotlin.time.Instant +import kotlin.uuid.Uuid import xyz.sevive.arcaeaoffline.core.constants.ArcaeaRatingClass import xyz.sevive.arcaeaoffline.core.database.entities.ChartInfo import xyz.sevive.arcaeaoffline.core.database.entities.DifficultyWithSong @@ -29,8 +29,7 @@ import xyz.sevive.arcaeaoffline.core.database.entities.PlayResult import xyz.sevive.arcaeaoffline.core.database.entities.PlayResultCalculated import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultCard import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme -import kotlin.time.Instant -import kotlin.uuid.Uuid +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun DatabaseBestListItem( @@ -60,7 +59,7 @@ internal fun DatabaseBestListItem( Row( modifier, - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.Bottom, ) { ArcaeaPlayResultCard( @@ -78,7 +77,7 @@ internal fun DatabaseBestListItem( ) { Text(indexText) - Spacer(Modifier.height(dimensionResource(R.dimen.list_padding))) + Spacer(Modifier.height(MaterialTheme.spacing.sm)) Text("PTT", style = MaterialTheme.typography.labelSmall) Text(item.playRatingText, style = MaterialTheme.typography.labelMedium) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListScreen.kt index 6875657e..a250d4be 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListScreen.kt @@ -21,6 +21,7 @@ import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Slider import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -30,16 +31,15 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle +import kotlin.math.round import org.koin.compose.viewmodel.koinViewModel -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.SubScreenTopAppBar import xyz.sevive.arcaeaoffline.ui.navigation.DatabaseSubScreen import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen -import kotlin.math.round +import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -100,8 +100,8 @@ fun DatabaseBestListScreen(viewModel: DatabaseBestListViewModel = koinViewModel( EmptyScreen(Modifier.fillMaxSize()) } else { LazyColumn( - contentPadding = PaddingValues(all = dimensionResource(R.dimen.page_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + contentPadding = PaddingValues(all = MaterialTheme.spacing.pagePadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { items(uiState.listItems, key = { it.index }) { DatabaseBestListItem(it, Modifier.animateItem()) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupListItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupListItem.kt index 103ae7d1..6da84a51 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupListItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupListItem.kt @@ -22,16 +22,15 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.text.font.FontWeight -import xyz.sevive.arcaeaoffline.R +import kotlin.uuid.Uuid import xyz.sevive.arcaeaoffline.core.database.entities.PlayResult import xyz.sevive.arcaeaoffline.helpers.ArcaeaPlayResultValidator import xyz.sevive.arcaeaoffline.ui.components.ArcaeaChartCard import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultCard import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultEditorDialog import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader -import kotlin.uuid.Uuid +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun DatabaseDeduplicatorGroupListItem( @@ -56,14 +55,14 @@ internal fun DatabaseDeduplicatorGroupListItem( } } - Column(verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.icon_text_padding))) { + Column(verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap)) { Row(verticalAlignment = Alignment.Bottom) { ListGroupHeader(Modifier.weight(1f)) { Row(verticalAlignment = Alignment.Bottom) { Text(item.index.toString(), fontWeight = FontWeight.Bold) Text( item.key, - Modifier.padding(start = dimensionResource(R.dimen.icon_text_padding)), + Modifier.padding(start = MaterialTheme.spacing.iconTextGap), style = MaterialTheme.typography.labelSmall, fontWeight = FontWeight.Light, ) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorScreen.kt index 96d535dc..bdf25c2b 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorScreen.kt @@ -24,16 +24,15 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.koin.compose.viewmodel.koinViewModel -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.components.LoadingOverlay import xyz.sevive.arcaeaoffline.ui.navigation.DatabaseSubScreen import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen import xyz.sevive.arcaeaoffline.ui.screens.database.playresultlist.DatabasePlayResultDeleteConfirmDialog +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable fun DatabaseDeduplicatorScreen(vm: DatabaseDeduplicatorViewModel = koinViewModel()) { @@ -127,8 +126,8 @@ fun DatabaseDeduplicatorScreen(vm: DatabaseDeduplicatorViewModel = koinViewModel EmptyScreen(Modifier.fillMaxSize()) } else { LazyColumn( - contentPadding = PaddingValues(all = dimensionResource(R.dimen.page_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + contentPadding = PaddingValues(all = MaterialTheme.spacing.pagePadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { items(uiState.listItems, key = { it.key }) { item -> DatabaseDeduplicatorGroupListItem( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/ImportLogUi.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/ImportLogUi.kt index 417ce911..1a0f9668 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/ImportLogUi.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/ImportLogUi.kt @@ -37,12 +37,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalResources -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview +import kotlin.time.Instant +import kotlin.uuid.Uuid import kotlinx.coroutines.launch -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.context.findActivity import xyz.sevive.arcaeaoffline.helpers.formatAsLocalizedDate import xyz.sevive.arcaeaoffline.helpers.formatAsLocalizedDateTime @@ -50,8 +50,7 @@ import xyz.sevive.arcaeaoffline.helpers.formatAsLocalizedTime import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme -import kotlin.time.Instant -import kotlin.uuid.Uuid +import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @Composable @@ -81,7 +80,7 @@ private fun ImportLogObjectUi( Row( modifier, - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.Top, ) { Column( @@ -138,7 +137,7 @@ internal fun ImportLogBottomSheet( Modifier .fillMaxSize() .consumeWindowInsets(innerPadding) - .padding(horizontal = dimensionResource(R.dimen.page_padding)), + .padding(horizontal = MaterialTheme.spacing.pagePadding), contentPadding = innerPadding, state = lazyColumnState, ) { @@ -153,7 +152,7 @@ internal fun ImportLogBottomSheet( it, Modifier .fillMaxWidth() - .padding(vertical = dimensionResource(R.dimen.list_padding)) + .padding(vertical = MaterialTheme.spacing.sm) .animateItem(), ) } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListScreen.kt index 337e60c5..7e3b4844 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListScreen.kt @@ -28,7 +28,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -37,6 +36,7 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.components.LoadingOverlay import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun DatabasePlayResultListAppBarActions( @@ -145,8 +145,8 @@ fun DatabasePlayResultListScreen(viewModel: DatabasePlayResultListViewModel = ko else -> { LazyColumn( - contentPadding = PaddingValues(all = dimensionResource(R.dimen.page_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + contentPadding = PaddingValues(all = MaterialTheme.spacing.pagePadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { items(listItems, key = { it.uuid }) { val isSelected by remember { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListSortDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListSortDialog.kt index aef09531..1594bc36 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListSortDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListSortDialog.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.AlertDialog import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.Surface import androidx.compose.material3.Switch @@ -20,7 +21,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark @@ -28,6 +28,7 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.preferences.BasePreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun DatabasePlayResultListSortDialogOrderSwitch( @@ -39,13 +40,13 @@ private fun DatabasePlayResultListSortDialogOrderSwitch( Modifier .clickable { onSortOrderChange(sortOrder.reverse()) } .padding( - horizontal = dimensionResource(R.dimen.pref_widget_horizontal_padding), - vertical = dimensionResource(R.dimen.pref_widget_vertical_padding), + horizontal = MaterialTheme.spacing.lg, + vertical = MaterialTheme.spacing.lg, ).then(modifier), contentAlignment = Alignment.Center, ) { Row( - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.CenterVertically, ) { IconRow { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/r30list/DatabaseR30ListItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/r30list/DatabaseR30ListItem.kt index 9ade5844..09b8dcf4 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/r30list/DatabaseR30ListItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/r30list/DatabaseR30ListItem.kt @@ -14,14 +14,13 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.withStyle -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultCard import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun DatabaseR30ListItem( @@ -56,7 +55,7 @@ internal fun DatabaseR30ListItem( Row( modifier, - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.Bottom, ) { ArcaeaPlayResultCard( @@ -74,7 +73,7 @@ internal fun DatabaseR30ListItem( ) { Text(indexText) - Spacer(Modifier.height(dimensionResource(R.dimen.list_padding))) + Spacer(Modifier.height(MaterialTheme.spacing.sm)) Text("PTT", style = MaterialTheme.typography.labelSmall) Text(playRatingText, style = MaterialTheme.typography.labelMedium) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/r30list/DatabaseR30ListScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/r30list/DatabaseR30ListScreen.kt index ecc503ce..284bef8e 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/r30list/DatabaseR30ListScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/r30list/DatabaseR30ListScreen.kt @@ -30,7 +30,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.koin.compose.viewmodel.koinViewModel @@ -44,6 +43,7 @@ import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButtonDefault import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogDismissTextButton import xyz.sevive.arcaeaoffline.ui.navigation.DatabaseSubScreen import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun DatabaseR30RebuildConfirmDialog( @@ -135,8 +135,8 @@ internal fun DatabaseR30ListScreen(viewModel: DatabaseR30ListViewModel = koinVie EmptyScreen(Modifier.fillMaxSize()) } else { LazyColumn( - contentPadding = PaddingValues(all = dimensionResource(R.dimen.page_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + contentPadding = PaddingValues(all = MaterialTheme.spacing.pagePadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { items(uiItems, key = { it.id }) { DatabaseR30ListItem(it, Modifier.animateItem()) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt index 39e8d2ab..f66f18f4 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt @@ -41,13 +41,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.platform.toClipEntry -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import java.util.Locale import kotlinx.coroutines.launch import org.koin.compose.viewmodel.koinViewModel import xyz.sevive.arcaeaoffline.R @@ -64,7 +64,7 @@ import xyz.sevive.arcaeaoffline.ui.components.preferences.BasePreferencesWidget import xyz.sevive.arcaeaoffline.ui.components.preferences.SliderPreferencesWidget import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget import xyz.sevive.arcaeaoffline.ui.navigation.OcrSubScreen -import java.util.Locale +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable fun OcrPerformanceScreen( @@ -146,7 +146,7 @@ fun OcrPerformanceScreen( Text( stringResource(R.string.ocr_performance_image_load_failed), color = MaterialTheme.colorScheme.error, - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier.padding(horizontal = MaterialTheme.spacing.lg), ) } } @@ -215,7 +215,7 @@ fun OcrPerformanceScreen( Text( stringResource(R.string.ocr_performance_benchmark_error, message), color = MaterialTheme.colorScheme.error, - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier.padding(horizontal = MaterialTheme.spacing.lg), ) } } @@ -232,7 +232,7 @@ fun OcrPerformanceScreen( parallel = uiState.resultParallel ?: uiState.parallelCount, result = result, snackbarHostState = snackbarHostState, - modifier = Modifier.padding(bottom = dimensionResource(R.dimen.list_padding)), + modifier = Modifier.padding(bottom = MaterialTheme.spacing.sm), ) } } @@ -267,10 +267,10 @@ private fun ResultCard( val coroutineScope = rememberCoroutineScope() val resources = LocalResources.current - Card(modifier = modifier.padding(horizontal = 16.dp)) { + Card(modifier = modifier.padding(horizontal = MaterialTheme.spacing.lg)) { Column( - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), - modifier = Modifier.padding(dimensionResource(R.dimen.card_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), + modifier = Modifier.padding(MaterialTheme.spacing.cardPadding), ) { Row( horizontalArrangement = Arrangement.SpaceBetween, @@ -299,7 +299,7 @@ private fun ResultCard( ) } } - Spacer(Modifier.height(dimensionResource(R.dimen.list_padding))) + Spacer(Modifier.height(MaterialTheme.spacing.sm)) KeyValueRow( label = stringResource(R.string.ocr_performance_result_median_label), value = stringResource(R.string.ocr_performance_result_median_value, result.medianPerImageMs), @@ -380,12 +380,12 @@ private fun HistoryRow( } Row( - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.Top, modifier = modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = dimensionResource(R.dimen.list_padding)), + .padding(horizontal = MaterialTheme.spacing.lg, vertical = MaterialTheme.spacing.sm), ) { Text( timestampText, @@ -394,7 +394,7 @@ private fun HistoryRow( ) Column( - verticalArrangement = Arrangement.spacedBy(2.dp), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.xxs), modifier = Modifier.weight(1f), ) { Text( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/OcrQueueCategoryItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/OcrQueueCategoryItem.kt index 96d323ed..9b47ea39 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/OcrQueueCategoryItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/OcrQueueCategoryItem.kt @@ -19,12 +19,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.tooling.preview.PreviewLightDark -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun OcrQueueCategoryItem( @@ -48,7 +47,7 @@ internal fun OcrQueueCategoryItem( trailingSlot = { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.icon_text_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap), ) { Text(countString, Modifier.secondaryItemAlpha()) tailSlot() diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingFloatingActionButton.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingFloatingActionButton.kt index 41a55ee5..d8e8de4e 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingFloatingActionButton.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingFloatingActionButton.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun OcrQueueStagingFloatingActionButton( @@ -64,7 +65,7 @@ internal fun OcrQueueStagingFloatingActionButton( private fun OcrQueueStagingFloatingActionButtonPreview() { ArcaeaOfflineTheme { Surface { - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + Row(horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm)) { OcrQueueStagingFloatingActionButton( onClick = {}, isVisible = true, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingSheet.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingSheet.kt index ecc2f5a1..6f9d511c 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingSheet.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingSheet.kt @@ -35,19 +35,19 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp +import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.delay import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.Progress import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.LinearProgressIndicatorWrapper import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme -import kotlin.time.Duration.Companion.seconds +import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -88,12 +88,12 @@ private fun PickerButton( Modifier .clickable(onClick = onClick) .height(IntrinsicSize.Min) - .padding(vertical = 36.dp) + .padding(vertical = MaterialTheme.spacing.xxl) .then(modifier), contentAlignment = Alignment.Center, ) { Column( - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), horizontalAlignment = Alignment.CenterHorizontally, ) { Icon( @@ -242,12 +242,12 @@ private fun BottomSheetContent( // Prevents the inner progress indicator's intrinsic width from expanding this column column(GridTrackSize.MinMax(0.dp, 1.fr)) column(GridTrackSize.MaxContent) - columnGap(24.dp) - rowGap(16.dp) + columnGap(MaterialTheme.spacing.xl) + rowGap(MaterialTheme.spacing.lg) }, Modifier - .padding(horizontal = 16.dp) - .padding(bottom = 16.dp), + .padding(horizontal = MaterialTheme.spacing.lg) + .padding(bottom = MaterialTheme.spacing.lg), ) { Text( stringResource(R.string.ocr_queue_staging_status), diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskList.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskList.kt index 95e4868e..45ee40e8 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskList.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskList.kt @@ -4,13 +4,13 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.database.entities.Difficulty import xyz.sevive.arcaeaoffline.core.database.entities.PlayResult import xyz.sevive.arcaeaoffline.ui.screens.ocr.queue.OcrQueueScreenViewModel +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun OcrQueueTaskList( @@ -22,8 +22,8 @@ internal fun OcrQueueTaskList( modifier: Modifier = Modifier, ) { LazyColumn( - modifier.padding(horizontal = dimensionResource(R.dimen.page_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + modifier.padding(horizontal = MaterialTheme.spacing.pagePadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { items(uiItems, key = { it.dbItem.id }) { OcrQueueTaskListItem( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskListItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskListItem.kt index 2acb3dc9..db228371 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskListItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskListItem.kt @@ -1,6 +1,7 @@ package xyz.sevive.arcaeaoffline.ui.screens.ocr.queue.tasklist import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -8,8 +9,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.database.entities.Difficulty import xyz.sevive.arcaeaoffline.core.database.entities.PlayResult import xyz.sevive.arcaeaoffline.ui.components.ArcaeaChartSelector @@ -17,6 +16,7 @@ import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultEditorDialog import xyz.sevive.arcaeaoffline.ui.components.BasicAlertDialogSurface import xyz.sevive.arcaeaoffline.ui.components.ImagePreviewDialogFullscreen import xyz.sevive.arcaeaoffline.ui.screens.ocr.queue.OcrQueueScreenViewModel +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun OcrQueueTaskListItem( @@ -69,7 +69,7 @@ internal fun OcrQueueTaskListItem( OcrQueueTaskListItemResult( uiItem, - Modifier.padding(dimensionResource(R.dimen.card_padding)), + Modifier.padding(MaterialTheme.spacing.cardPadding), ) } } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/overview/OverviewPotentialCard.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/overview/OverviewPotentialCard.kt index 667d1e72..9b7c5cba 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/overview/OverviewPotentialCard.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/overview/OverviewPotentialCard.kt @@ -19,7 +19,6 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle @@ -33,6 +32,7 @@ import xyz.sevive.arcaeaoffline.helpers.calculatePotential import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.extendedColorScheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun PotentialRow( @@ -143,7 +143,7 @@ internal fun OverviewPotentialCard( PotentialRow( label = stringResource(R.string.arcaea_potential), value = ArcaeaFormatters.potentialToText(uiState.potential, mainScale), - modifier = Modifier.fillMaxWidth().padding(dimensionResource(R.dimen.page_padding)), + modifier = Modifier.fillMaxWidth().padding(MaterialTheme.spacing.pagePadding), labelTextStyle = MaterialTheme.typography.headlineSmall, valueTextStyle = MaterialTheme.typography.displayLarge, ) @@ -151,8 +151,8 @@ internal fun OverviewPotentialCard( HorizontalDivider() Column( - Modifier.padding(dimensionResource(R.dimen.page_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + Modifier.padding(MaterialTheme.spacing.pagePadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { when (uiState.scoringMode) { ArcaeaScoringMode.B50 -> { @@ -172,7 +172,7 @@ internal fun OverviewPotentialCard( ) { Row( verticalAlignment = Alignment.Top, - horizontalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { Icon(painterResource(R.drawable.chart_line_alert), contentDescription = null) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/overview/OverviewScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/overview/OverviewScreen.kt index 00892bb9..2ec26cc4 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/overview/OverviewScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/overview/OverviewScreen.kt @@ -4,13 +4,13 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.koin.compose.viewmodel.koinViewModel -import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable fun OverviewScreen( @@ -23,7 +23,7 @@ fun OverviewScreen( modifier .safeDrawingPadding() .fillMaxSize(), - contentPadding = PaddingValues(all = dimensionResource(R.dimen.page_padding)), + contentPadding = PaddingValues(all = MaterialTheme.spacing.pagePadding), ) { item { OverviewPotentialCard(uiState) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/SettingsNavEntry.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/SettingsNavEntry.kt index 885330b6..aa58c093 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/SettingsNavEntry.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/SettingsNavEntry.kt @@ -19,7 +19,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import xyz.sevive.arcaeaoffline.R @@ -30,6 +29,7 @@ import xyz.sevive.arcaeaoffline.ui.navigation.MainScreen import xyz.sevive.arcaeaoffline.ui.navigation.SettingsSubScreen import xyz.sevive.arcaeaoffline.ui.screens.NavEntryNavigateButton import xyz.sevive.arcaeaoffline.ui.screens.settings.unstablealert.UnstableBuildAlertCard +import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -58,7 +58,7 @@ internal fun SettingsNavEntry( modifier = Modifier .fillMaxWidth() - .padding(horizontal = dimensionResource(R.dimen.page_padding)), + .padding(horizontal = MaterialTheme.spacing.pagePadding), showDetails = true, ) } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/about/SettingsAboutScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/about/SettingsAboutScreen.kt index 83617dc6..c06d8c4b 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/about/SettingsAboutScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/about/SettingsAboutScreen.kt @@ -19,7 +19,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.graphics.drawable.toBitmap @@ -28,6 +27,7 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.navigation.SettingsSubScreen import xyz.sevive.arcaeaoffline.ui.screens.NavEntryNavigateButton +import xyz.sevive.arcaeaoffline.ui.theme.spacing class AppIconBeingClickedTooManyTimesSoEmbarrassingException : Exception() { override val message: String = "(โ„ โ„โ€ขโ„ฯ‰โ„โ€ขโ„ โ„)" @@ -73,7 +73,7 @@ internal fun SettingsAboutScreen( item { Column( Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), horizontalAlignment = Alignment.CenterHorizontally, ) { AppIcon( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/license/SettingsLicenseScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/license/SettingsLicenseScreen.kt index cd5afe1a..ed5adebf 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/license/SettingsLicenseScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/license/SettingsLicenseScreen.kt @@ -4,22 +4,22 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import com.mikepenz.markdown.compose.LazyMarkdownSuccess import com.mikepenz.markdown.m3.Markdown import com.mikepenz.markdown.model.rememberMarkdownState import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.navigation.SettingsSubScreen +import xyz.sevive.arcaeaoffline.ui.theme.spacing private const val LICENSE_FILENAME = "gpl-3.0.md" @@ -52,7 +52,7 @@ internal fun SettingsLicenseScreen(modifier: Modifier = Modifier) { state, components, modifier, - contentPadding = PaddingValues(dimensionResource(R.dimen.page_padding)), + contentPadding = PaddingValues(MaterialTheme.spacing.pagePadding), ) }, loading = { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertCard.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertCard.kt index 81b2ab3d..780da63e 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertCard.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertCard.kt @@ -12,17 +12,17 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.components.IconRow +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable private fun UnstableBuildAlertCardContent(showDetails: Boolean = true) { - Column(Modifier.padding(dimensionResource(R.dimen.action_button_padding))) { + Column(Modifier.padding(MaterialTheme.spacing.lg)) { IconRow { Icon(painterResource(R.drawable.ic_unstable_build), null) Text( @@ -49,9 +49,9 @@ fun UnstableBuildAlertCard( shape: Shape = CutCornerShape( topStart = 0.dp, - topEnd = dimensionResource(R.dimen.action_button_padding), + topEnd = MaterialTheme.spacing.lg, bottomEnd = 0.dp, - bottomStart = dimensionResource(R.dimen.action_button_padding), + bottomStart = MaterialTheme.spacing.lg, ), colors: CardColors = CardDefaults.cardColors( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertScreen.kt index 7ed3d56a..5b6918fd 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertScreen.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -11,7 +12,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalResources -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.mikepenz.markdown.compose.LazyMarkdownSuccess @@ -21,6 +21,7 @@ import org.koin.compose.viewmodel.koinViewModel import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.navigation.SettingsSubScreen +import xyz.sevive.arcaeaoffline.ui.theme.spacing @Composable internal fun SettingsUnstableAlertScreen(vm: SettingsUnstableAlertScreenViewModel = koinViewModel()) { @@ -51,7 +52,7 @@ internal fun SettingsUnstableAlertScreen(vm: SettingsUnstableAlertScreenViewMode state, components, modifier, - contentPadding = PaddingValues(dimensionResource(R.dimen.page_padding)), + contentPadding = PaddingValues(MaterialTheme.spacing.pagePadding), ) }, loading = { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesCalculatorScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesCalculatorScreen.kt index 85951c01..4f45d8d3 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesCalculatorScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesCalculatorScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.QueueMusic import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -18,7 +19,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -37,6 +37,7 @@ import xyz.sevive.arcaeaoffline.ui.components.ArcaeaRatingClassSelector import xyz.sevive.arcaeaoffline.ui.components.PlayRatingCalculator import xyz.sevive.arcaeaoffline.ui.components.toRatingClassSelectorItems import xyz.sevive.arcaeaoffline.ui.navigation.UtilitiesSubScreen +import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -86,13 +87,13 @@ fun UtilitiesCalculatorScreen( title = stringResource(UtilitiesSubScreen.Calculator.title), ) { LazyColumn( - Modifier.padding(horizontal = dimensionResource(R.dimen.page_padding)), - verticalArrangement = Arrangement.spacedBy(16.dp), + Modifier.padding(horizontal = MaterialTheme.spacing.pagePadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.lg), ) { item { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.page_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.pagePadding), ) { Icon(Icons.AutoMirrored.Filled.QueueMusic, contentDescription = null) @@ -105,7 +106,7 @@ fun UtilitiesCalculatorScreen( item { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.page_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.pagePadding), ) { Icon(painterResource(R.drawable.ic_rating_class), contentDescription = null) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt index 94984fcf..742b51a2 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt @@ -43,11 +43,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import kotlin.math.round import kotlinx.serialization.Serializable import org.koin.androidx.compose.koinViewModel import xyz.sevive.arcaeaoffline.R @@ -71,7 +71,7 @@ import xyz.sevive.arcaeaoffline.ui.components.rememberDecimalStepperTextFieldSta import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters import xyz.sevive.arcaeaoffline.ui.navigation.UtilitiesSubScreen import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen -import kotlin.math.round +import xyz.sevive.arcaeaoffline.ui.theme.spacing private fun IntRange.average() = round((first + last) / 2.0).toInt() @@ -105,7 +105,7 @@ private fun ScoreRangeInput( Column( modifier, horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(8.dp), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { OutlinedArcaeaScoreTextField( rangeLastTextFieldState, @@ -147,7 +147,7 @@ private fun PlayRatingCalculatorDialog( Column( Modifier.padding(contentPadding), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(8.dp), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { Icon( Icons.Default.Calculate, @@ -157,7 +157,7 @@ private fun PlayRatingCalculatorDialog( Column( horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(2.dp), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.xxs), ) { Text(state.songTitle, style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Normal)) Text( @@ -227,7 +227,7 @@ private fun ResultsListItem( ) Row(verticalAlignment = Alignment.CenterVertically) { - Text(state.scoreText, Modifier.padding(start = 16.dp)) + Text(state.scoreText, Modifier.padding(start = MaterialTheme.spacing.lg)) Icon(Icons.AutoMirrored.Filled.ArrowRight, contentDescription = null) @@ -291,7 +291,7 @@ fun UtilitiesChartRecommendScreen( modifier = modifier, title = stringResource(UtilitiesSubScreen.Recommend.title), ) { - Column(Modifier.padding(horizontal = dimensionResource(R.dimen.page_padding))) { + Column(Modifier.padding(horizontal = MaterialTheme.spacing.pagePadding)) { Row( Modifier.clickable { isInputVisible = !isInputVisible }, verticalAlignment = Alignment.CenterVertically, @@ -303,7 +303,7 @@ fun UtilitiesChartRecommendScreen( LocalTextStyle provides MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.Normal), ) { Row( - horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.icon_text_padding)), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap), verticalAlignment = Alignment.CenterVertically, ) { Text("${ArcaeaFormatters.score(scoreRange.first)} ~ ${ArcaeaFormatters.score(scoreRange.last)}") @@ -334,7 +334,7 @@ fun UtilitiesChartRecommendScreen( Column { Row( Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), verticalAlignment = Alignment.CenterVertically, ) { ScoreRangeInput( @@ -357,7 +357,7 @@ fun UtilitiesChartRecommendScreen( ) } - Row(horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.icon_text_padding))) { + Row(horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap)) { CompositionLocalProvider( LocalTextStyle provides MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.Normal), ) { @@ -395,8 +395,8 @@ fun UtilitiesChartRecommendScreen( } LazyColumn( - contentPadding = PaddingValues(vertical = dimensionResource(R.dimen.list_padding)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.list_padding)), + contentPadding = PaddingValues(vertical = MaterialTheme.spacing.sm), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { if (uiState.charts.isEmpty()) { item { diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml deleted file mode 100644 index c92b4cec..00000000 --- a/app/src/main/res/values/dimens.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - 16dp - 4dp - 8dp - 8dp - - 16dp - 10dp - - 16dp - 16dp - - 8dp - 16dp - diff --git a/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/components/DecimalStepperTextField.kt b/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/components/DecimalStepperTextField.kt index 2f18f275..b29cd69d 100644 --- a/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/components/DecimalStepperTextField.kt +++ b/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/components/DecimalStepperTextField.kt @@ -18,6 +18,7 @@ import androidx.compose.material.icons.filled.Remove import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -47,6 +48,7 @@ import com.ionspin.kotlin.bignum.decimal.BigDecimal import com.ionspin.kotlin.bignum.decimal.RoundingMode import com.ionspin.kotlin.bignum.decimal.toBigDecimal import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing import xyz.sevive.arcaeaoffline.ui.utils.AutoRepeatController import xyz.sevive.arcaeaoffline.ui.utils.rememberAutoRepeatController @@ -402,8 +404,8 @@ private fun DecimalStepperTextFieldPreview() { ArcaeaOfflineTheme { Surface { Column( - Modifier.padding(16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), + Modifier.padding(MaterialTheme.spacing.lg), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.lg), ) { DecimalStepperTextField(state) diff --git a/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt b/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt new file mode 100644 index 00000000..69e8a233 --- /dev/null +++ b/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt @@ -0,0 +1,26 @@ +package xyz.sevive.arcaeaoffline.ui.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +/** + * Spacing scale on a 4dp grid, for paddings and content gaps only. + * Icon sizes, corner radii, and stroke widths are not part of this scale. + */ +object Spacing { + val xxs: Dp = 2.dp + val xs: Dp = 4.dp + val sm: Dp = 8.dp + val lg: Dp = 16.dp + val xl: Dp = 24.dp + val xxl: Dp = 32.dp + + val pagePadding: Dp = lg + val cardPadding: Dp = sm + val iconTextGap: Dp = xs + val dialogPadding: Dp = xl +} + +val MaterialTheme.spacing: Spacing + get() = Spacing From af98e6e9fd536ae5d73f0807a1862d594bc9d9ef Mon Sep 17 00:00:00 2001 From: 283375 Date: Tue, 6 Oct 2026 23:36:12 +0800 Subject: [PATCH 2/8] UtilitiesChartRecommendScreen ui refactor --- .../UtilitiesChartRecommendScreen.kt | 299 ++++++++++++------ 1 file changed, 199 insertions(+), 100 deletions(-) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt index 742b51a2..b0b96ad7 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt @@ -4,14 +4,19 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn @@ -29,6 +34,7 @@ import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard import androidx.compose.material3.ShapeDefaults +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -42,12 +48,13 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import kotlin.math.round import kotlinx.serialization.Serializable import org.koin.androidx.compose.koinViewModel import xyz.sevive.arcaeaoffline.R @@ -72,6 +79,7 @@ import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters import xyz.sevive.arcaeaoffline.ui.navigation.UtilitiesSubScreen import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen import xyz.sevive.arcaeaoffline.ui.theme.spacing +import kotlin.math.round private fun IntRange.average() = round((first + last) / 2.0).toInt() @@ -242,6 +250,69 @@ private fun ResultsListItem( } } +private val ParametersCardCollapsedHeight = 48.dp +private val ParametersCardTopPadding = MaterialTheme.spacing.xs + +/** + * Floating parameters panel. It overlays the results list, which clears its + * collapsed height via [ParametersCardCollapsedHeight]. + */ +@Composable +private fun ParametersCard( + expanded: Boolean, + onExpandedChange: (Boolean) -> Unit, + summary: @Composable () -> Unit, + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit, +) { + val arrowRotation by animateFloatAsState(if (expanded) 0f else -90f) + + Surface( + modifier = modifier, + shape = MaterialTheme.shapes.large, + color = MaterialTheme.colorScheme.surfaceContainerHigh, + // M3 elevation level 3 (dialog tier) + shadowElevation = 6.dp, + ) { + Column { + Row( + Modifier + .fillMaxWidth() + .heightIn(min = ParametersCardCollapsedHeight) + .clickable { onExpandedChange(!expanded) } + .padding(horizontal = MaterialTheme.spacing.lg, vertical = ParametersCardTopPadding), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + stringResource(R.string.utilities_recommend_input), + style = MaterialTheme.typography.titleMedium, + ) + + AnimatedVisibility(!expanded) { + summary() + } + + Spacer(Modifier.weight(1f)) + + Icon( + Icons.Default.ExpandMore, + contentDescription = null, + Modifier.graphicsLayer { rotationZ = arrowRotation }, + ) + } + + AnimatedVisibility(expanded) { + Column( + Modifier.padding(top = MaterialTheme.spacing.sm), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), + content = content, + ) + } + } + } +} + @Composable fun UtilitiesChartRecommendScreen( modifier: Modifier = Modifier, @@ -272,9 +343,6 @@ fun UtilitiesChartRecommendScreen( } var isInputVisible by rememberSaveable { mutableStateOf(false) } - val expandArrowRotateDegree by animateFloatAsState( - if (isInputVisible) 0f else -90f, - ) var showCalculatorDialog by rememberSaveable { mutableStateOf(false) } var calculatorDialogState by rememberSerializable { mutableStateOf(PlayRatingCalculatorDialogState()) } @@ -291,14 +359,83 @@ fun UtilitiesChartRecommendScreen( modifier = modifier, title = stringResource(UtilitiesSubScreen.Recommend.title), ) { - Column(Modifier.padding(horizontal = MaterialTheme.spacing.pagePadding)) { - Row( - Modifier.clickable { isInputVisible = !isInputVisible }, - verticalAlignment = Alignment.CenterVertically, + Box(Modifier.fillMaxSize()) { + // The card floats with top padding. The list and the top + // scrim both clear the card's bottom edge plus a lg gap. + val listTopInset = ParametersCardCollapsedHeight + ParametersCardTopPadding + MaterialTheme.spacing.lg + + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = + PaddingValues( + top = listTopInset, + bottom = MaterialTheme.spacing.sm, + ), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { - ListGroupHeader(stringResource(R.string.utilities_recommend_input)) + item { + Row(verticalAlignment = Alignment.CenterVertically) { + ListGroupHeader(stringResource(R.string.utilities_recommend_results)) + + Spacer(Modifier.weight(1f)) + + AnimatedVisibility( + visible = uiState.isLoading, + enter = fadeIn(), + exit = fadeOut(), + ) { + CircularProgressIndicator( + Modifier + .padding(end = MaterialTheme.spacing.lg) + .size(18.dp), + ) + } + } + } + + if (uiState.charts.isEmpty()) { + item { + EmptyScreen( + Modifier + .fillMaxSize() + .padding(horizontal = MaterialTheme.spacing.pagePadding), + ) + } + } else { + items(uiState.charts, { it.difficultyWithSong.songId + it.difficultyWithSong.ratingClass.name }) { item -> + val state = ResultsListItemState(item, scoreRange, targetPlayRating, uiState.clearType) + + ResultsListItem( + state = state, + onOpenCalculator = { + calculatorDialogState = PlayRatingCalculatorDialogState(item, state.score) + showCalculatorDialog = true + }, + Modifier + .padding(horizontal = MaterialTheme.spacing.pagePadding) + .animateItem(), + ) + } + } + } + + Box( + Modifier + .align(Alignment.TopCenter) + .fillMaxWidth() + .height(listTopInset) + .background( + Brush.verticalGradient( + 0f to MaterialTheme.colorScheme.background, + 1f to Color.Transparent, + ), + ), + ) - AnimatedVisibility(!isInputVisible) { + ParametersCard( + expanded = isInputVisible, + onExpandedChange = { isInputVisible = it }, + summary = { CompositionLocalProvider( LocalTextStyle provides MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.Normal), ) { @@ -319,102 +456,64 @@ fun UtilitiesChartRecommendScreen( Text(targetPlayRating.toString(), fontWeight = FontWeight.Bold) } } + }, + modifier = + Modifier + .align(Alignment.TopCenter) + .padding( + horizontal = MaterialTheme.spacing.pagePadding, + vertical = MaterialTheme.spacing.sm, + ).fillMaxWidth(), + ) { + Row( + Modifier + .fillMaxWidth() + .padding(horizontal = MaterialTheme.spacing.lg), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), + verticalAlignment = Alignment.CenterVertically, + ) { + ScoreRangeInput( + scoreRange = scoreRange, + onRangeFirstChange = { viewModel.setScoreRange(it..scoreRange.last) }, + onRangeLastChange = { viewModel.setScoreRange(scoreRange.first..it) }, + Modifier.weight(1f), + ) + + Icon( + Icons.Default.Link, + contentDescription = null, + Modifier.rotate(-45f), + ) + + DecimalStepperTextField( + targetPlayRatingTextFieldState, + Modifier.weight(1f), + label = { Text(stringResource(R.string.utilities_recommend_target_play_rating)) }, + ) } - Spacer(Modifier.weight(1f)) - - Icon( - Icons.Default.ExpandMore, - contentDescription = null, - Modifier.graphicsLayer { rotationZ = expandArrowRotateDegree }, - ) - } - - AnimatedVisibility(isInputVisible) { - Column { - Row( - Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), - verticalAlignment = Alignment.CenterVertically, + Row( + Modifier.padding(horizontal = MaterialTheme.spacing.lg), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap), + ) { + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.Normal), ) { - ScoreRangeInput( - scoreRange = scoreRange, - onRangeFirstChange = { viewModel.setScoreRange(it..scoreRange.last) }, - onRangeLastChange = { viewModel.setScoreRange(scoreRange.first..it) }, - Modifier.weight(1f), - ) - - Icon( - Icons.Default.Link, - contentDescription = null, - Modifier.rotate(-45f), - ) - - DecimalStepperTextField( - targetPlayRatingTextFieldState, - Modifier.weight(1f), - label = { Text(stringResource(R.string.utilities_recommend_target_play_rating)) }, - ) - } - - Row(horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.iconTextGap)) { - CompositionLocalProvider( - LocalTextStyle provides MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.Normal), - ) { - TextButton({ viewModel.setScoreRange(9_900_000..10_000_000) }) { Text("EX+") } - TextButton({ viewModel.setScoreRange(9_800_000..9_899_999) }) { Text("EX") } - TextButton({ viewModel.setScoreRange(9_500_000..9_799_999) }) { Text("AA") } - } - } - - if (uiState.scoringMode == ArcaeaScoringMode.B50) { - SwitchPreferencesWidget( - value = uiState.clearType != null && uiState.clearType != ArcaeaPlayResultClearType.TRACK_LOST, - onValueChange = { cleared -> - viewModel.setClearType(if (cleared) ArcaeaPlayResultClearType.NORMAL_CLEAR else null) - }, - title = stringResource(R.string.play_rating_cleared), - description = stringResource(R.string.play_rating_cleared_description), - ) + TextButton({ viewModel.setScoreRange(9_900_000..10_000_000) }) { Text("EX+") } + TextButton({ viewModel.setScoreRange(9_800_000..9_899_999) }) { Text("EX") } + TextButton({ viewModel.setScoreRange(9_500_000..9_799_999) }) { Text("AA") } } } - } - Row(verticalAlignment = Alignment.CenterVertically) { - ListGroupHeader(stringResource(R.string.utilities_recommend_results)) - - Spacer(Modifier.weight(1f)) - - AnimatedVisibility( - visible = uiState.isLoading, - enter = fadeIn(), - exit = fadeOut(), - ) { - CircularProgressIndicator(Modifier.size(18.dp)) - } - } - - LazyColumn( - contentPadding = PaddingValues(vertical = MaterialTheme.spacing.sm), - verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), - ) { - if (uiState.charts.isEmpty()) { - item { - EmptyScreen(Modifier.fillMaxSize()) - } - } else { - items(uiState.charts, { it.difficultyWithSong.songId + it.difficultyWithSong.ratingClass.name }) { item -> - val state = ResultsListItemState(item, scoreRange, targetPlayRating, uiState.clearType) - - ResultsListItem( - state = state, - onOpenCalculator = { - calculatorDialogState = PlayRatingCalculatorDialogState(item, state.score) - showCalculatorDialog = true - }, - Modifier.animateItem(), - ) - } + if (uiState.scoringMode == ArcaeaScoringMode.B50) { + SwitchPreferencesWidget( + value = uiState.clearType != null && uiState.clearType != ArcaeaPlayResultClearType.TRACK_LOST, + onValueChange = { cleared -> + viewModel.setClearType(if (cleared) ArcaeaPlayResultClearType.NORMAL_CLEAR else null) + }, + title = stringResource(R.string.play_rating_cleared), + description = stringResource(R.string.play_rating_cleared_description), + ) } } } From d986e320a3493e29da3170b4f2a8a70d3cf7a15a Mon Sep 17 00:00:00 2001 From: 283375 Date: Wed, 7 Oct 2026 00:57:50 +0800 Subject: [PATCH 3/8] fix ListGroupHeader --- .../ui/activities/EmergencyModeActivityUi.kt | 16 +++++-- .../ui/components/ListGroupHeader.kt | 47 ++++++------------- 2 files changed, 26 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt index ac32f372..34196a1f 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt @@ -1,6 +1,7 @@ package xyz.sevive.arcaeaoffline.ui.activities import android.content.Intent +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow @@ -9,6 +10,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons @@ -111,15 +113,13 @@ fun EmergencyModeActivityUi( PaddingValues( top = padding.calculateTopPadding() + MaterialTheme.spacing.sm, bottom = padding.calculateBottomPadding() + MaterialTheme.spacing.sm, - start = MaterialTheme.spacing.sm, - end = MaterialTheme.spacing.sm, ), ) { item { ListGroupHeader(stringResource(R.string.emergency_mode_output_directory_title)) } item { - Column { + Column(Modifier.padding(horizontal = MaterialTheme.spacing.pagePadding)) { IconRow { Icon(Icons.Default.Code, contentDescription = null) Text( @@ -166,7 +166,10 @@ fun EmergencyModeActivityUi( ListGroupHeader(stringResource(R.string.emergency_mode_ocr_title)) } item { - FlowRow { + FlowRow( + Modifier.padding(horizontal = MaterialTheme.spacing.pagePadding), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), + ) { Button(onClick = { viewModel.deleteAllOcrDependencies() }) { IconRow { Icon(Icons.Default.DeleteForever, contentDescription = null) @@ -187,7 +190,10 @@ fun EmergencyModeActivityUi( ListGroupHeader(stringResource(R.string.emergency_mode_database_title)) } item { - FlowRow { + FlowRow( + Modifier.padding(horizontal = MaterialTheme.spacing.pagePadding), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), + ) { Button( onClick = { viewModel.copyDatabase(context) }, enabled = outputDirectoryValid, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt index 27e44ad0..18ec0096 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt @@ -1,7 +1,6 @@ package xyz.sevive.arcaeaoffline.ui.components import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalTextStyle @@ -10,36 +9,28 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import xyz.sevive.arcaeaoffline.ui.theme.spacing -object ListGroupHeaderDefaults { - val paddingValues - @Composable get() = - PaddingValues( - horizontal = MaterialTheme.spacing.lg, - vertical = MaterialTheme.spacing.sm, - ) - val contentColor - @Composable get() = MaterialTheme.colorScheme.primary - val textStyle - @Composable get() = MaterialTheme.typography.bodyMedium.copy(fontWeight = FontWeight.Light) -} - +/** + * Section header carrying its own horizontal gutter. Place it directly in an + * edge-to-edge container instead of a horizontally padded container. + */ @Composable fun ListGroupHeader( modifier: Modifier = Modifier, - paddingValues: PaddingValues = ListGroupHeaderDefaults.paddingValues, - contentColor: Color = ListGroupHeaderDefaults.contentColor, - textStyle: TextStyle = ListGroupHeaderDefaults.textStyle, content: @Composable () -> Unit, ) { - Box(modifier = modifier.padding(paddingValues)) { + Box( + modifier = + modifier.padding( + horizontal = MaterialTheme.spacing.lg, + vertical = MaterialTheme.spacing.sm, + ), + ) { CompositionLocalProvider( - LocalContentColor provides contentColor, - LocalTextStyle provides textStyle, + LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant, + LocalTextStyle provides MaterialTheme.typography.bodyMedium.copy(fontWeight = FontWeight.SemiBold), ) { content() } @@ -50,16 +41,8 @@ fun ListGroupHeader( fun ListGroupHeader( text: String, modifier: Modifier = Modifier, - paddingValues: PaddingValues = ListGroupHeaderDefaults.paddingValues, - contentColor: Color = ListGroupHeaderDefaults.contentColor, - textStyle: TextStyle = ListGroupHeaderDefaults.textStyle, ) { - ListGroupHeader( - modifier = modifier, - paddingValues = paddingValues, - contentColor = contentColor, - textStyle = textStyle, - ) { - Text(text = text) + ListGroupHeader(modifier = modifier) { + Text(text) } } From 0371cd35e0128c23301876ce46d9efb1daffb57e Mon Sep 17 00:00:00 2001 From: 283375 Date: Wed, 7 Oct 2026 02:17:47 +0800 Subject: [PATCH 4/8] rename `PreferencesWidget`s to SettingsItems --- .../ui/common/PermissionRequiredDialog.kt | 4 +- .../datetimeeditor/DateTimeEditDialog.kt | 15 +- .../ArcaeaPackAndSongQuickSearch.kt | 5 +- .../ui/components/ArcaeaPlayResultCard.kt | 5 +- .../LinearProgressIndicatorWrapper.kt | 3 +- .../ui/components/PlayRatingCalculator.kt | 4 +- .../ui/components/SettingsItems.kt | 347 ++++++++++++++++++ .../ocr/OcrDependencyStatusViewer.kt | 5 +- .../preferences/BasePreferencesWidget.kt | 88 ----- .../preferences/CheckboxPreferencesWidget.kt | 56 --- .../preferences/SelectPreferencesWidget.kt | 52 --- .../preferences/SliderPreferencesWidget.kt | 70 ---- .../preferences/SwitchPreferencesWidget.kt | 56 --- .../preferences/TextPreferencesWidget.kt | 78 ---- .../resources/RemoteResourceDownloadItem.kt | 4 +- .../ui/screens/NavEntryNavigateButton.kt | 4 +- .../database/bestlist/DatabaseBestListItem.kt | 4 +- .../bestlist/DatabaseBestListScreen.kt | 2 +- ...seDeduplicatorGroupByValuesSelectDialog.kt | 4 +- .../DatabaseDeduplicatorGroupListItem.kt | 2 +- .../DatabaseDeduplicatorWizardDialog.kt | 10 +- .../database/manage/DatabaseManageExport.kt | 4 +- .../database/manage/DatabaseManageImport.kt | 16 +- .../database/manage/DatabaseManageScreen.kt | 14 +- .../ui/screens/database/manage/ImportLogUi.kt | 4 +- .../DatabasePlayResultListSortDialog.kt | 4 +- .../ocr/dependencies/OcrDependenciesScreen.kt | 6 +- .../ocr/performance/OcrPerformanceScreen.kt | 15 +- .../screens/ocr/queue/OcrQueueCategoryItem.kt | 4 +- .../OcrQueuePreferencesBottomSheet.kt | 10 +- .../ocr/queue/staging/OcrQueueStagingSheet.kt | 2 +- .../tasklist/OcrQueueTaskListItemHeader.kt | 6 +- .../ui/screens/settings/SettingsNavEntry.kt | 4 +- .../settings/general/SettingsGeneralScreen.kt | 8 +- .../UtilitiesChartRecommendScreen.kt | 4 +- 35 files changed, 431 insertions(+), 488 deletions(-) create mode 100644 app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SettingsItems.kt delete mode 100644 app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/BasePreferencesWidget.kt delete mode 100644 app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/CheckboxPreferencesWidget.kt delete mode 100644 app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SelectPreferencesWidget.kt delete mode 100644 app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SliderPreferencesWidget.kt delete mode 100644 app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SwitchPreferencesWidget.kt delete mode 100644 app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/TextPreferencesWidget.kt diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/PermissionRequiredDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/PermissionRequiredDialog.kt index a5d7d8f8..bd4e19bb 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/PermissionRequiredDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/PermissionRequiredDialog.kt @@ -23,9 +23,9 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha +import xyz.sevive.arcaeaoffline.ui.components.BaseSettingsItem import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButton import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogDismissTextButton -import xyz.sevive.arcaeaoffline.ui.components.preferences.BasePreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing @@ -78,7 +78,7 @@ private fun PermissionWidget( val content = rememberPermissionDescription(permission) val icon = rememberPermissionIcon(permission) - BasePreferencesWidget( + BaseSettingsItem( title = { PermissionTitle(permission) }, content = { Text( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/datetimeeditor/DateTimeEditDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/datetimeeditor/DateTimeEditDialog.kt index bb5b1bd3..a41769d8 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/datetimeeditor/DateTimeEditDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/common/datetimeeditor/DateTimeEditDialog.kt @@ -43,11 +43,6 @@ import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import java.time.format.DateTimeFormatter -import java.time.format.FormatStyle -import kotlin.time.Clock -import kotlin.time.Instant import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalTime @@ -59,11 +54,15 @@ import kotlinx.datetime.toJavaLocalDate import kotlinx.datetime.toJavaLocalTime import kotlinx.datetime.toLocalDateTime import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButton import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogDismissTextButton -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle +import kotlin.time.Clock +import kotlin.time.Instant @Composable private fun SecondEditor( @@ -200,7 +199,7 @@ internal fun DateTimeEditDialog( text = { LazyColumn { item { - TextPreferencesWidget( + TextItem( onClick = { showDateEditDialog = true }, leadingIcon = Icons.Default.CalendarMonth, leadingIconTint = MaterialTheme.colorScheme.secondary, @@ -211,7 +210,7 @@ internal fun DateTimeEditDialog( } item { - TextPreferencesWidget( + TextItem( onClick = { showTimeEditDialog = true }, leadingIcon = Icons.Default.AccessTime, leadingIconTint = MaterialTheme.colorScheme.secondary, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongQuickSearch.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongQuickSearch.kt index 49feb4d9..2627df13 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongQuickSearch.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPackAndSongQuickSearch.kt @@ -169,7 +169,10 @@ fun ArcaeaPackAndSongQuickSearch( expanded = false focusManager.clearFocus() }, - contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding.plus(PaddingValues(vertical = MaterialTheme.spacing.sm)), + contentPadding = + ExposedDropdownMenuDefaults.ItemContentPadding.plus( + PaddingValues(vertical = MaterialTheme.spacing.sm), + ), ) if (i != candidates.lastIndex) { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultCard.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultCard.kt index e7aefc14..46144504 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultCard.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ArcaeaPlayResultCard.kt @@ -50,7 +50,6 @@ import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp -import kotlin.time.Instant import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.constants.ArcaeaPlayResultClearType import xyz.sevive.arcaeaoffline.core.constants.ArcaeaPlayResultModifier @@ -60,13 +59,13 @@ import xyz.sevive.arcaeaoffline.core.database.entities.DifficultyWithSong import xyz.sevive.arcaeaoffline.core.database.entities.PlayResult import xyz.sevive.arcaeaoffline.helpers.ArcaeaPlayResultValidatorWarning import xyz.sevive.arcaeaoffline.helpers.formatAsLocalizedDateTime -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.arcaeaColors import xyz.sevive.arcaeaoffline.ui.theme.extendedColorScheme import xyz.sevive.arcaeaoffline.ui.theme.playResultGradeGradientBrush import xyz.sevive.arcaeaoffline.ui.theme.spacing +import kotlin.time.Instant @Composable private fun pflAnnotatedString( @@ -111,7 +110,7 @@ private fun PlayResultDetailsDialog( LazyColumn { items.entries.forEach { item { - TextPreferencesWidget(title = it.key, content = it.value) + TextItem(title = it.key, content = it.value) } } } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/LinearProgressIndicatorWrapper.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/LinearProgressIndicatorWrapper.kt index 36608cef..7f060377 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/LinearProgressIndicatorWrapper.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/LinearProgressIndicatorWrapper.kt @@ -16,10 +16,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle -import androidx.compose.ui.unit.dp -import kotlin.math.roundToInt import xyz.sevive.arcaeaoffline.core.Progress import xyz.sevive.arcaeaoffline.ui.theme.spacing +import kotlin.math.roundToInt typealias PercentageFormatter = (Float) -> String diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/PlayRatingCalculator.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/PlayRatingCalculator.kt index 00ae3951..9c92258a 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/PlayRatingCalculator.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/PlayRatingCalculator.kt @@ -24,14 +24,12 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.calculators.calculateClearBonus import xyz.sevive.arcaeaoffline.core.calculators.calculatePlayRating import xyz.sevive.arcaeaoffline.core.constants.ArcaeaPlayResultClearType import xyz.sevive.arcaeaoffline.ui.components.arcaea.OutlinedArcaeaScoreTextField import xyz.sevive.arcaeaoffline.ui.components.arcaea.rememberArcaeaScoreTextFieldState -import xyz.sevive.arcaeaoffline.ui.components.preferences.SwitchPreferencesWidget import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing @@ -124,7 +122,7 @@ fun PlayRatingCalculator( } if (countClearBonus) { - SwitchPreferencesWidget( + SwitchItem( value = clearType != null && clearType != ArcaeaPlayResultClearType.TRACK_LOST, onValueChange = { cleared -> clearType = if (cleared) ArcaeaPlayResultClearType.NORMAL_CLEAR else null }, title = stringResource(R.string.play_rating_cleared), diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SettingsItems.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SettingsItems.kt new file mode 100644 index 00000000..0bdade27 --- /dev/null +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SettingsItems.kt @@ -0,0 +1,347 @@ +package xyz.sevive.arcaeaoffline.ui.components + +import androidx.annotation.IntRange +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.BugReport +import androidx.compose.material3.Checkbox +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Slider +import androidx.compose.material3.Surface +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.minimumInteractiveComponentSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.tooling.preview.PreviewLightDark +import xyz.sevive.arcaeaoffline.helpers.DISABLED_ALPHA +import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha +import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing + +private val HorizontalPadding + @Composable + get() = MaterialTheme.spacing.lg +private val VerticalPadding + @Composable + get() = MaterialTheme.spacing.lg + +@Composable +fun BaseSettingsItem( + title: @Composable ColumnScope.() -> Unit, + modifier: Modifier = Modifier, + onClick: (() -> Unit)? = null, + leadingSlot: (@Composable () -> Unit)? = null, + trailingSlot: (@Composable () -> Unit)? = null, + content: (@Composable ColumnScope.() -> Unit)? = null, +) { + Row( + Modifier + .clickable(onClick != null) { onClick?.invoke() } + .minimumInteractiveComponentSize() + .then(modifier), + verticalAlignment = Alignment.CenterVertically, + ) { + leadingSlot?.let { + Box(Modifier.padding(start = HorizontalPadding, end = HorizontalPadding / 2)) { it() } + } + + Column( + Modifier + .weight(1f) + .padding(horizontal = HorizontalPadding, vertical = VerticalPadding), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.xxs), + ) { + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.bodyLarge, + ) { + title(this@Column) + } + content?.let { it(this@Column) } + } + + trailingSlot?.let { + Box(Modifier.padding(start = HorizontalPadding / 2, end = HorizontalPadding)) { it() } + } + } +} + +@PreviewLightDark +@Composable +private fun BaseSettingsItemPreview() { + ArcaeaOfflineTheme { + Surface { + BaseSettingsItem( + title = { Text("Title") }, + leadingSlot = { Icon(Icons.Default.BugReport, contentDescription = null) }, + trailingSlot = { Text("Trailing") }, + ) { + Text("Lorem ipsum dolor sit amet", style = MaterialTheme.typography.bodySmall) + } + } + } +} + +@Composable +fun CheckboxItem( + value: Boolean, + onValueChange: (Boolean) -> Unit, + title: @Composable ColumnScope.() -> Unit, + modifier: Modifier = Modifier, + leadingSlot: (@Composable () -> Unit)? = null, + content: (@Composable ColumnScope.() -> Unit)? = null, +) { + BaseSettingsItem( + onClick = { onValueChange(!value) }, + title = title, + modifier = modifier, + content = content, + leadingSlot = leadingSlot, + trailingSlot = { + Checkbox( + checked = value, + onCheckedChange = null, + ) + }, + ) +} + +@Composable +fun CheckboxItem( + value: Boolean, + onValueChange: (Boolean) -> Unit, + title: String, + modifier: Modifier = Modifier, + icon: ImageVector? = null, + iconTint: Color = MaterialTheme.colorScheme.primary, + description: String? = null, +) { + CheckboxItem( + value = value, + onValueChange = onValueChange, + title = { Text(title) }, + leadingSlot = icon?.let { { Icon(icon, contentDescription = null, tint = iconTint) } }, + modifier = modifier, + content = description?.let { { Text(description, Modifier.secondaryItemAlpha()) } }, + ) +} + +@Composable +fun SwitchItem( + value: Boolean, + onValueChange: (Boolean) -> Unit, + title: @Composable ColumnScope.() -> Unit, + modifier: Modifier = Modifier, + leadingSlot: (@Composable () -> Unit)? = null, + content: (@Composable ColumnScope.() -> Unit)? = null, +) { + BaseSettingsItem( + onClick = { onValueChange(!value) }, + title = title, + modifier = modifier, + content = content, + leadingSlot = leadingSlot, + trailingSlot = { + Switch( + checked = value, + onCheckedChange = null, + ) + }, + ) +} + +@Composable +fun SwitchItem( + value: Boolean, + onValueChange: (Boolean) -> Unit, + title: String, + modifier: Modifier = Modifier, + icon: ImageVector? = null, + iconTint: Color = MaterialTheme.colorScheme.primary, + description: String? = null, +) { + SwitchItem( + value = value, + onValueChange = onValueChange, + title = { Text(title) }, + leadingSlot = icon?.let { { Icon(icon, contentDescription = null, tint = iconTint) } }, + modifier = modifier, + content = description?.let { { Text(description, Modifier.secondaryItemAlpha()) } }, + ) +} + +data class SelectOption( + val value: T, + val label: String, + val description: String? = null, +) + +/** + * A radio-button list of mutually exclusive options; renders one + * [BaseSettingsItem] row per option without an outer container. + */ +@Composable +fun SelectItem( + options: List>, + selected: T, + onSelect: (T) -> Unit, + modifier: Modifier = Modifier, +) { + Column(modifier) { + options.forEach { option -> + BaseSettingsItem( + onClick = { onSelect(option.value) }, + title = { Text(option.label) }, + content = + option.description?.let { description -> + { + Text( + description, + Modifier.secondaryItemAlpha(), + style = MaterialTheme.typography.bodySmall, + ) + } + }, + leadingSlot = { + RadioButton( + selected = option.value == selected, + onClick = null, + ) + }, + ) + } + } +} + +@Composable +fun SliderItem( + value: Float, + onValueChange: (Float) -> Unit, + title: @Composable ColumnScope.() -> Unit, + valueRange: ClosedFloatingPointRange = 0f..1f, + @IntRange(from = 0) steps: Int = 0, + leadingSlot: (@Composable () -> Unit)? = null, + trailingSlot: (@Composable () -> Unit)? = null, + content: (@Composable ColumnScope.() -> Unit)? = null, +) { + BaseSettingsItem( + title = title, + leadingSlot = leadingSlot, + trailingSlot = trailingSlot, + ) { + Column( + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), + ) { + content?.invoke(this@Column) + Slider( + value = value, + onValueChange = onValueChange, + valueRange = valueRange, + steps = steps, + ) + } + } +} + +@Composable +fun SliderItem( + value: Float, + onValueChange: (Float) -> Unit, + title: String, + valueRange: ClosedFloatingPointRange = 0f..1f, + @IntRange(from = 0) steps: Int = 0, + icon: ImageVector? = null, + iconTint: Color = MaterialTheme.colorScheme.primary, + trailingSlot: (@Composable () -> Unit)? = null, + description: String? = null, +) { + SliderItem( + value = value, + onValueChange = onValueChange, + title = { Text(title) }, + valueRange = valueRange, + steps = steps, + leadingSlot = icon?.let { { Icon(icon, contentDescription = null, tint = iconTint) } }, + trailingSlot = trailingSlot, + content = description?.let { { Text(description, Modifier.secondaryItemAlpha()) } }, + ) +} + +@Composable +fun TextItem( + title: String, + modifier: Modifier = Modifier, + content: String? = null, + leadingSlot: (@Composable () -> Unit)? = null, + trailingSlot: (@Composable () -> Unit)? = null, + enabled: Boolean = true, + onClick: (() -> Unit)? = null, +) { + CompositionLocalProvider( + LocalContentColor provides + LocalContentColor.current.copy( + alpha = if (enabled) 1f else DISABLED_ALPHA, + ), + ) { + BaseSettingsItem( + title = { Text(title) }, + content = + content?.let { + { + Text( + it, + Modifier.secondaryItemAlpha(), + style = MaterialTheme.typography.bodySmall, + ) + } + }, + leadingSlot = leadingSlot, + trailingSlot = trailingSlot, + onClick = if (enabled) onClick else null, + modifier = modifier, + ) + } +} + +@Composable +fun TextItem( + title: String, + modifier: Modifier = Modifier, + content: String? = null, + leadingIcon: ImageVector? = null, + leadingIconTint: Color = MaterialTheme.colorScheme.primary, + trailingIcon: ImageVector? = null, + trailingIconTint: Color = LocalContentColor.current, + enabled: Boolean = true, + onClick: (() -> Unit)? = null, +) { + TextItem( + title = title, + content = content, + leadingSlot = + leadingIcon?.let { + { Icon(it, contentDescription = null, tint = leadingIconTint) } + }, + trailingSlot = + trailingIcon?.let { + { Icon(it, contentDescription = null, tint = trailingIconTint) } + }, + onClick = onClick, + enabled = enabled, + modifier = modifier, + ) +} diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusViewer.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusViewer.kt index 9d953455..5e0b64b6 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusViewer.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ocr/OcrDependencyStatusViewer.kt @@ -20,11 +20,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.tooling.preview.PreviewLightDark -import androidx.compose.ui.unit.dp import xyz.sevive.arcaeaoffline.helpers.OcrDependencyStatus import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha +import xyz.sevive.arcaeaoffline.ui.components.BaseSettingsItem import xyz.sevive.arcaeaoffline.ui.components.IconRow -import xyz.sevive.arcaeaoffline.ui.components.preferences.BasePreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing @@ -76,7 +75,7 @@ fun OcrDependencyStatusViewer( ) } - BasePreferencesWidget( + BaseSettingsItem( onClick = details?.let { { showDetails = true } }, title = { title() }, leadingSlot = icon, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/BasePreferencesWidget.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/BasePreferencesWidget.kt deleted file mode 100644 index a722cccc..00000000 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/BasePreferencesWidget.kt +++ /dev/null @@ -1,88 +0,0 @@ -package xyz.sevive.arcaeaoffline.ui.components.preferences - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.BugReport -import androidx.compose.material3.Icon -import androidx.compose.material3.LocalTextStyle -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.material3.minimumInteractiveComponentSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.PreviewLightDark -import androidx.compose.ui.unit.dp -import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme -import xyz.sevive.arcaeaoffline.ui.theme.spacing - -private val HorizontalPadding - @Composable - get() = MaterialTheme.spacing.lg -private val VerticalPadding - @Composable - get() = MaterialTheme.spacing.lg - -@Composable -fun BasePreferencesWidget( - title: @Composable ColumnScope.() -> Unit, - modifier: Modifier = Modifier, - onClick: (() -> Unit)? = null, - leadingSlot: (@Composable () -> Unit)? = null, - trailingSlot: (@Composable () -> Unit)? = null, - content: (@Composable ColumnScope.() -> Unit)? = null, -) { - Row( - Modifier - .clickable(onClick != null) { onClick?.invoke() } - .minimumInteractiveComponentSize() - .then(modifier), - verticalAlignment = Alignment.CenterVertically, - ) { - leadingSlot?.let { - Box(Modifier.padding(start = HorizontalPadding, end = HorizontalPadding / 2)) { it() } - } - - Column( - Modifier - .weight(1f) - .padding(horizontal = HorizontalPadding, vertical = VerticalPadding), - verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.xxs), - ) { - CompositionLocalProvider( - LocalTextStyle provides MaterialTheme.typography.bodyLarge, - ) { - title(this@Column) - } - content?.let { it(this@Column) } - } - - trailingSlot?.let { - Box(Modifier.padding(start = HorizontalPadding / 2, end = HorizontalPadding)) { it() } - } - } -} - -@PreviewLightDark -@Composable -private fun BasePreferencesWidgetPreview() { - ArcaeaOfflineTheme { - Surface { - BasePreferencesWidget( - title = { Text("Title") }, - leadingSlot = { Icon(Icons.Default.BugReport, contentDescription = null) }, - trailingSlot = { Text("Trailing") }, - ) { - Text("Lorem ipsum dolor sit amet", style = MaterialTheme.typography.bodySmall) - } - } - } -} diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/CheckboxPreferencesWidget.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/CheckboxPreferencesWidget.kt deleted file mode 100644 index a5f0ba3e..00000000 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/CheckboxPreferencesWidget.kt +++ /dev/null @@ -1,56 +0,0 @@ -package xyz.sevive.arcaeaoffline.ui.components.preferences - -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.material3.Checkbox -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha - -@Composable -fun CheckboxPreferencesWidget( - value: Boolean, - onValueChange: (Boolean) -> Unit, - title: @Composable ColumnScope.() -> Unit, - modifier: Modifier = Modifier, - leadingSlot: (@Composable () -> Unit)? = null, - content: (@Composable ColumnScope.() -> Unit)? = null, -) { - BasePreferencesWidget( - onClick = { onValueChange(!value) }, - title = title, - modifier = modifier, - content = content, - leadingSlot = leadingSlot, - trailingSlot = { - Checkbox( - checked = value, - onCheckedChange = null, - ) - }, - ) -} - -@Composable -fun CheckboxPreferencesWidget( - value: Boolean, - onValueChange: (Boolean) -> Unit, - title: String, - modifier: Modifier = Modifier, - icon: ImageVector? = null, - iconTint: Color = MaterialTheme.colorScheme.primary, - description: String? = null, -) { - CheckboxPreferencesWidget( - value = value, - onValueChange = onValueChange, - title = { Text(title) }, - leadingSlot = icon?.let { { Icon(icon, contentDescription = null, tint = iconTint) } }, - modifier = modifier, - content = description?.let { { Text(description, Modifier.secondaryItemAlpha()) } }, - ) -} diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SelectPreferencesWidget.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SelectPreferencesWidget.kt deleted file mode 100644 index fccfe46f..00000000 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SelectPreferencesWidget.kt +++ /dev/null @@ -1,52 +0,0 @@ -package xyz.sevive.arcaeaoffline.ui.components.preferences - -import androidx.compose.foundation.layout.Column -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.RadioButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha - -data class SelectPreferencesOption( - val value: T, - val label: String, - val description: String? = null, -) - -/** - * A radio-button list of mutually exclusive options; renders one - * [BasePreferencesWidget] row per option without an outer container. - */ -@Composable -fun SelectPreferencesWidget( - options: List>, - selected: T, - onSelect: (T) -> Unit, - modifier: Modifier = Modifier, -) { - Column(modifier) { - options.forEach { option -> - BasePreferencesWidget( - onClick = { onSelect(option.value) }, - title = { Text(option.label) }, - content = - option.description?.let { description -> - { - Text( - description, - Modifier.secondaryItemAlpha(), - style = MaterialTheme.typography.bodySmall, - ) - } - }, - leadingSlot = { - RadioButton( - selected = option.value == selected, - onClick = null, - ) - }, - ) - } - } -} diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SliderPreferencesWidget.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SliderPreferencesWidget.kt deleted file mode 100644 index e0df9f62..00000000 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SliderPreferencesWidget.kt +++ /dev/null @@ -1,70 +0,0 @@ -package xyz.sevive.arcaeaoffline.ui.components.preferences - -import androidx.annotation.IntRange -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Slider -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha -import xyz.sevive.arcaeaoffline.ui.theme.spacing - -@Composable -fun SliderPreferencesWidget( - value: Float, - onValueChange: (Float) -> Unit, - title: @Composable ColumnScope.() -> Unit, - valueRange: ClosedFloatingPointRange = 0f..1f, - @IntRange(from = 0) steps: Int = 0, - leadingSlot: (@Composable () -> Unit)? = null, - trailingSlot: (@Composable () -> Unit)? = null, - content: (@Composable ColumnScope.() -> Unit)? = null, -) { - BasePreferencesWidget( - title = title, - leadingSlot = leadingSlot, - trailingSlot = trailingSlot, - ) { - Column( - verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), - ) { - content?.invoke(this@Column) - Slider( - value = value, - onValueChange = onValueChange, - valueRange = valueRange, - steps = steps, - ) - } - } -} - -@Composable -fun SliderPreferencesWidget( - value: Float, - onValueChange: (Float) -> Unit, - title: String, - valueRange: ClosedFloatingPointRange = 0f..1f, - @IntRange(from = 0) steps: Int = 0, - icon: ImageVector? = null, - iconTint: Color = MaterialTheme.colorScheme.primary, - trailingSlot: (@Composable () -> Unit)? = null, - description: String? = null, -) { - SliderPreferencesWidget( - value = value, - onValueChange = onValueChange, - title = { Text(title) }, - valueRange = valueRange, - steps = steps, - leadingSlot = icon?.let { { Icon(icon, contentDescription = null, tint = iconTint) } }, - trailingSlot = trailingSlot, - content = description?.let { { Text(description, Modifier.secondaryItemAlpha()) } }, - ) -} diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SwitchPreferencesWidget.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SwitchPreferencesWidget.kt deleted file mode 100644 index 5437d825..00000000 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/SwitchPreferencesWidget.kt +++ /dev/null @@ -1,56 +0,0 @@ -package xyz.sevive.arcaeaoffline.ui.components.preferences - -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Switch -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha - -@Composable -fun SwitchPreferencesWidget( - value: Boolean, - onValueChange: (Boolean) -> Unit, - title: @Composable ColumnScope.() -> Unit, - modifier: Modifier = Modifier, - leadingSlot: (@Composable () -> Unit)? = null, - content: (@Composable ColumnScope.() -> Unit)? = null, -) { - BasePreferencesWidget( - onClick = { onValueChange(!value) }, - title = title, - modifier = modifier, - content = content, - leadingSlot = leadingSlot, - trailingSlot = { - Switch( - checked = value, - onCheckedChange = null, - ) - }, - ) -} - -@Composable -fun SwitchPreferencesWidget( - value: Boolean, - onValueChange: (Boolean) -> Unit, - title: String, - modifier: Modifier = Modifier, - icon: ImageVector? = null, - iconTint: Color = MaterialTheme.colorScheme.primary, - description: String? = null, -) { - SwitchPreferencesWidget( - value = value, - onValueChange = onValueChange, - title = { Text(title) }, - leadingSlot = icon?.let { { Icon(icon, contentDescription = null, tint = iconTint) } }, - modifier = modifier, - content = description?.let { { Text(description, Modifier.secondaryItemAlpha()) } }, - ) -} diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/TextPreferencesWidget.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/TextPreferencesWidget.kt deleted file mode 100644 index 490f77fc..00000000 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/preferences/TextPreferencesWidget.kt +++ /dev/null @@ -1,78 +0,0 @@ -package xyz.sevive.arcaeaoffline.ui.components.preferences - -import androidx.compose.material3.Icon -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import xyz.sevive.arcaeaoffline.helpers.DISABLED_ALPHA -import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha - -@Composable -fun TextPreferencesWidget( - title: String, - modifier: Modifier = Modifier, - content: String? = null, - leadingSlot: (@Composable () -> Unit)? = null, - trailingSlot: (@Composable () -> Unit)? = null, - enabled: Boolean = true, - onClick: (() -> Unit)? = null, -) { - CompositionLocalProvider( - LocalContentColor provides - LocalContentColor.current.copy( - alpha = if (enabled) 1f else DISABLED_ALPHA, - ), - ) { - BasePreferencesWidget( - title = { Text(title) }, - content = - content?.let { - { - Text( - it, - Modifier.secondaryItemAlpha(), - style = MaterialTheme.typography.bodySmall, - ) - } - }, - leadingSlot = leadingSlot, - trailingSlot = trailingSlot, - onClick = if (enabled) onClick else null, - modifier = modifier, - ) - } -} - -@Composable -fun TextPreferencesWidget( - title: String, - modifier: Modifier = Modifier, - content: String? = null, - leadingIcon: ImageVector? = null, - leadingIconTint: Color = MaterialTheme.colorScheme.primary, - trailingIcon: ImageVector? = null, - trailingIconTint: Color = LocalContentColor.current, - enabled: Boolean = true, - onClick: (() -> Unit)? = null, -) { - TextPreferencesWidget( - title = title, - content = content, - leadingSlot = - leadingIcon?.let { - { Icon(it, contentDescription = null, tint = leadingIconTint) } - }, - trailingSlot = - trailingIcon?.let { - { Icon(it, contentDescription = null, tint = trailingIconTint) } - }, - onClick = onClick, - enabled = enabled, - modifier = modifier, - ) -} diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/resources/RemoteResourceDownloadItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/resources/RemoteResourceDownloadItem.kt index 5437d4a0..98d8445b 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/resources/RemoteResourceDownloadItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/resources/RemoteResourceDownloadItem.kt @@ -11,7 +11,7 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.api.ArcaeaResourcesRemoteFileInfo import xyz.sevive.arcaeaoffline.core.api.DownloadableResource import xyz.sevive.arcaeaoffline.core.api.RemoteResourcesInfoUiState -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.TextItem @Composable private fun contentFor( @@ -48,7 +48,7 @@ fun RemoteResourceDownloadItem( ) { val fileInfo = infoState.info?.get(resource) - TextPreferencesWidget( + TextItem( onClick = onDownload, // fileInfo is null only while remote info is unknown (refresh failed or not yet fetched); // downloading on an unprobed path would just 404, so wait for a successful refresh. diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/NavEntryNavigateButton.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/NavEntryNavigateButton.kt index aed09804..2fd67d5b 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/NavEntryNavigateButton.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/NavEntryNavigateButton.kt @@ -6,7 +6,7 @@ import androidx.compose.material.icons.automirrored.filled.ArrowRight import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.TextItem @Composable fun NavEntryNavigateButton( @@ -15,7 +15,7 @@ fun NavEntryNavigateButton( icon: ImageVector? = null, onClick: () -> Unit, ) { - TextPreferencesWidget( + TextItem( title = title, content = description, leadingIcon = icon, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListItem.kt index f61a47cf..77f89970 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListItem.kt @@ -20,8 +20,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview -import kotlin.time.Instant -import kotlin.uuid.Uuid import xyz.sevive.arcaeaoffline.core.constants.ArcaeaRatingClass import xyz.sevive.arcaeaoffline.core.database.entities.ChartInfo import xyz.sevive.arcaeaoffline.core.database.entities.DifficultyWithSong @@ -30,6 +28,8 @@ import xyz.sevive.arcaeaoffline.core.database.entities.PlayResultCalculated import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultCard import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing +import kotlin.time.Instant +import kotlin.uuid.Uuid @Composable internal fun DatabaseBestListItem( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListScreen.kt index a250d4be..240e1eb7 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/bestlist/DatabaseBestListScreen.kt @@ -33,13 +33,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle -import kotlin.math.round import org.koin.compose.viewmodel.koinViewModel import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.SubScreenTopAppBar import xyz.sevive.arcaeaoffline.ui.navigation.DatabaseSubScreen import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen import xyz.sevive.arcaeaoffline.ui.theme.spacing +import kotlin.math.round @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupByValuesSelectDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupByValuesSelectDialog.kt index d0e55244..9283fe8f 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupByValuesSelectDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupByValuesSelectDialog.kt @@ -13,8 +13,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.components.CheckboxItem import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButton -import xyz.sevive.arcaeaoffline.ui.components.preferences.CheckboxPreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme private val groupByValueResIdMap = @@ -40,7 +40,7 @@ private fun DatabaseDeduplicatorGroupByValuesSelectDialogContent( ) { @Composable fun ValueWrapper(targetValue: GroupByValue) { - CheckboxPreferencesWidget( + CheckboxItem( value = values.contains(targetValue), onValueChange = { enabled -> onValueChange(targetValue, enabled) }, title = groupByValueTitle(targetValue), diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupListItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupListItem.kt index 6da84a51..46b22587 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupListItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorGroupListItem.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight -import kotlin.uuid.Uuid import xyz.sevive.arcaeaoffline.core.database.entities.PlayResult import xyz.sevive.arcaeaoffline.helpers.ArcaeaPlayResultValidator import xyz.sevive.arcaeaoffline.ui.components.ArcaeaChartCard @@ -31,6 +30,7 @@ import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultCard import xyz.sevive.arcaeaoffline.ui.components.ArcaeaPlayResultEditorDialog import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader import xyz.sevive.arcaeaoffline.ui.theme.spacing +import kotlin.uuid.Uuid @Composable internal fun DatabaseDeduplicatorGroupListItem( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorWizardDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorWizardDialog.kt index 737ce265..3847c49c 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorWizardDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/deduplicator/DatabaseDeduplicatorWizardDialog.kt @@ -17,10 +17,10 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButton import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButtonDefaults import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogDismissTextButton -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.extendedColorScheme @Composable @@ -69,7 +69,7 @@ internal fun DatabaseDeduplicatorWizardDialog( text = { LazyColumn { item { - TextPreferencesWidget( + TextItem( onClick = { onAutoSelect(AutoSelectMode.IDENTICAL) }, title = stringResource(R.string.database_deduplicator_auto_select_identical), content = stringResource(R.string.database_deduplicator_description_auto_select_identical), @@ -77,7 +77,7 @@ internal fun DatabaseDeduplicatorWizardDialog( } item { - TextPreferencesWidget( + TextItem( onClick = { onAutoSelect(AutoSelectMode.PROPERTIES_PRIORITY) }, title = stringResource(R.string.database_deduplicator_auto_select_properties_priority), content = stringResource(R.string.database_deduplicator_description_auto_select_properties_priority), @@ -85,7 +85,7 @@ internal fun DatabaseDeduplicatorWizardDialog( } item { - TextPreferencesWidget( + TextItem( onClick = { onAutoSelect(AutoSelectMode.R30_PRIORITY) }, title = stringResource(R.string.database_deduplicator_auto_select_r30_priority), content = stringResource(R.string.database_deduplicator_description_auto_select_r30_priority), @@ -96,7 +96,7 @@ internal fun DatabaseDeduplicatorWizardDialog( CompositionLocalProvider( LocalContentColor provides MaterialTheme.extendedColorScheme.warning, ) { - TextPreferencesWidget( + TextItem( onClick = { showAutoMergeConfirmDialog = true }, leadingIcon = Icons.Default.Merge, leadingIconTint = LocalContentColor.current, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageExport.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageExport.kt index ba887ce5..ccfb208e 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageExport.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageExport.kt @@ -10,7 +10,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import xyz.sevive.arcaeaoffline.R -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.TextItem import kotlin.time.Clock private class CreateJsonDocument : ActivityResultContracts.CreateDocument("application/json") @@ -26,7 +26,7 @@ fun DatabaseManageExport( } Column(modifier) { - TextPreferencesWidget( + TextItem( onClick = { exportPlayResultsHandler.launch( "arcaea-offline-data-exchange-${Clock.System.now().toEpochMilliseconds()}", diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageImport.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageImport.kt index 8b6d7079..c216a632 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageImport.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageImport.kt @@ -15,7 +15,7 @@ import androidx.compose.ui.res.vectorResource import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.rememberFileChooserLauncher import xyz.sevive.arcaeaoffline.ui.components.ArcaeaAppIcon -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.TextItem @Composable private fun joinImportEntries(entries: List): String = remember(entries) { entries.joinToString(" ยท ") } @@ -73,21 +73,21 @@ fun DatabaseManageImport( ) Column(modifier) { - TextPreferencesWidget( + TextItem( onClick = { importPacklistLauncher.launch("*/*") }, title = stringResource(R.string.database_manage_import_packlist), content = descPacklist, leadingIcon = Icons.Default.DataObject, ) - TextPreferencesWidget( + TextItem( onClick = { importSonglistLauncher.launch("*/*") }, title = stringResource(R.string.database_manage_import_songlist), content = descSonglist, leadingIcon = Icons.Default.DataObject, ) - TextPreferencesWidget( + TextItem( onClick = { importArcaeaApkLauncher.launch("*/*") }, title = stringResource(R.string.database_manage_import_from_arcaea_apk), content = descArcaeaApk, @@ -95,28 +95,28 @@ fun DatabaseManageImport( ) if (canImportLists) { - TextPreferencesWidget( + TextItem( onClick = onImportFromInstalledArcaea, title = stringResource(R.string.database_manage_import_from_arcaea_installed), content = descArcaeaApk, leadingSlot = { ArcaeaAppIcon() }, ) } else { - TextPreferencesWidget( + TextItem( title = stringResource(R.string.arcaea_button_resource_unavailable), leadingSlot = { ArcaeaAppIcon(forceDisabled = true) }, enabled = false, ) } - TextPreferencesWidget( + TextItem( onClick = { importChartInfoDatabaseLauncher.launch("*/*") }, title = stringResource(R.string.database_manage_import_chart_info_database), content = joinImportEntries(listOf(descChartInfoEntries)), leadingIcon = ImageVector.vectorResource(R.drawable.ic_database), ) - TextPreferencesWidget( + TextItem( onClick = { importSt3Launcher.launch("*/*") }, title = stringResource(R.string.arcaea_st3), content = joinImportEntries(listOf(descPlayResultEntries)), diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageScreen.kt index 27c0856a..b9bfa300 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageScreen.kt @@ -34,9 +34,9 @@ import xyz.sevive.arcaeaoffline.core.constants.ArcaeaScoringMode import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader -import xyz.sevive.arcaeaoffline.ui.components.preferences.SelectPreferencesOption -import xyz.sevive.arcaeaoffline.ui.components.preferences.SelectPreferencesWidget -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.SelectItem +import xyz.sevive.arcaeaoffline.ui.components.SelectOption +import xyz.sevive.arcaeaoffline.ui.components.TextItem @Composable fun DatabaseManageScreen( @@ -84,15 +84,15 @@ fun DatabaseManageScreen( item { val scoringMode by viewModel.scoringMode.collectAsStateWithLifecycle() - SelectPreferencesWidget( + SelectItem( options = listOf( - SelectPreferencesOption( + SelectOption( value = ArcaeaScoringMode.B30_R10, label = stringResource(R.string.database_manage_scoring_mode_b30_r10), description = ArcaeaScoringMode.B30_R10.key.toString(), ), - SelectPreferencesOption( + SelectOption( value = ArcaeaScoringMode.B50, label = stringResource(R.string.database_manage_scoring_mode_b50), description = ArcaeaScoringMode.B50.key.toString(), @@ -141,7 +141,7 @@ fun DatabaseManageScreen( item { val isFetchingRemoteInfo = uiState.remoteResourcesInfoState.isFetching - TextPreferencesWidget( + TextItem( onClick = { viewModel.refreshRemoteResourcesInfo() }, enabled = !isFetchingRemoteInfo, leadingSlot = { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/ImportLogUi.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/ImportLogUi.kt index 1a0f9668..f672a86b 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/ImportLogUi.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/ImportLogUi.kt @@ -40,8 +40,6 @@ import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview -import kotlin.time.Instant -import kotlin.uuid.Uuid import kotlinx.coroutines.launch import xyz.sevive.arcaeaoffline.helpers.context.findActivity import xyz.sevive.arcaeaoffline.helpers.formatAsLocalizedDate @@ -51,6 +49,8 @@ import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha import xyz.sevive.arcaeaoffline.ui.screens.EmptyScreen import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing +import kotlin.time.Instant +import kotlin.uuid.Uuid @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @Composable diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListSortDialog.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListSortDialog.kt index 1594bc36..611471cb 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListSortDialog.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/playresultlist/DatabasePlayResultListSortDialog.kt @@ -25,8 +25,8 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import xyz.sevive.arcaeaoffline.R +import xyz.sevive.arcaeaoffline.ui.components.BaseSettingsItem import xyz.sevive.arcaeaoffline.ui.components.IconRow -import xyz.sevive.arcaeaoffline.ui.components.preferences.BasePreferencesWidget import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing @@ -80,7 +80,7 @@ private fun DatabasePlayResultListSortDialogContent( targetSortByValue: DatabasePlayResultListViewModel.SortByValue, modifier: Modifier = Modifier, ) { - BasePreferencesWidget( + BaseSettingsItem( title = { Text(label) }, leadingSlot = { RadioButton(selected = sortByValue == targetSortByValue, onClick = null) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/dependencies/OcrDependenciesScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/dependencies/OcrDependenciesScreen.kt index 69f3eedc..d603e60c 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/dependencies/OcrDependenciesScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/dependencies/OcrDependenciesScreen.kt @@ -23,9 +23,9 @@ import xyz.sevive.arcaeaoffline.helpers.ArcaeaResourcesStateHolder import xyz.sevive.arcaeaoffline.helpers.rememberFileChooserLauncher import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.components.ArcaeaAppIcon +import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.components.ocr.OcrDependencyCrnnModelStatusViewer import xyz.sevive.arcaeaoffline.ui.components.ocr.OcrDependencyImageHashesDatabaseStatusViewer -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget import xyz.sevive.arcaeaoffline.ui.components.resources.RemoteResourceDownloadItem import xyz.sevive.arcaeaoffline.ui.navigation.OcrSubScreen @@ -65,7 +65,7 @@ fun OcrDependenciesScreen( val remoteDownloadUiState by viewModel.imageHashesDatabaseRemoteDownloadUiState.collectAsStateWithLifecycle() - TextPreferencesWidget( + TextItem( enabled = !importRunning && !remoteDownloadUiState.isWorking, onClick = { imageHashesDatabaseFileChooserLauncher.launch("*/*") }, leadingIcon = Icons.Default.FileOpen, @@ -107,7 +107,7 @@ fun OcrDependenciesScreen( R.string.arcaea_button_resource_unavailable } - TextPreferencesWidget( + TextItem( enabled = buildHashesDatabaseButtonEnabled, onClick = { viewModel.requestImageHashesDatabaseBuild() }, leadingSlot = { ArcaeaAppIcon(forceDisabled = !canBuildHashesDatabase) }, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt index f66f18f4..c05d8a82 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt @@ -45,9 +45,7 @@ import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import java.util.Locale import kotlinx.coroutines.launch import org.koin.compose.viewmodel.koinViewModel import xyz.sevive.arcaeaoffline.R @@ -57,14 +55,15 @@ import xyz.sevive.arcaeaoffline.helpers.formatAsLocalizedDate import xyz.sevive.arcaeaoffline.helpers.formatAsLocalizedTime import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha import xyz.sevive.arcaeaoffline.ui.SubScreenContainer +import xyz.sevive.arcaeaoffline.ui.components.BaseSettingsItem import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.LinearProgressIndicatorWrapper import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader -import xyz.sevive.arcaeaoffline.ui.components.preferences.BasePreferencesWidget -import xyz.sevive.arcaeaoffline.ui.components.preferences.SliderPreferencesWidget -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.SliderItem +import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.navigation.OcrSubScreen import xyz.sevive.arcaeaoffline.ui.theme.spacing +import java.util.Locale @Composable fun OcrPerformanceScreen( @@ -95,7 +94,7 @@ fun OcrPerformanceScreen( item { val selectedUris = uiState.selectedImageUris val hasSelection = selectedUris.isNotEmpty() - TextPreferencesWidget( + TextItem( title = stringResource(R.string.ocr_performance_pick_images_button), content = selectedUris.takeIf { hasSelection }?.let { @@ -163,7 +162,7 @@ fun OcrPerformanceScreen( label = "benchmarkRunningState", ) { running -> if (!running) { - SliderPreferencesWidget( + SliderItem( value = uiState.parallelCount.toFloat(), onValueChange = viewModel::onParallelCountChange, icon = Icons.AutoMirrored.Default.Sort, @@ -184,7 +183,7 @@ fun OcrPerformanceScreen( }, ) } else { - BasePreferencesWidget( + BaseSettingsItem( title = { uiState.runningParallel?.let { parallel -> Text( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/OcrQueueCategoryItem.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/OcrQueueCategoryItem.kt index 9b47ea39..a77ae287 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/OcrQueueCategoryItem.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/OcrQueueCategoryItem.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.tooling.preview.PreviewLightDark import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing @@ -37,7 +37,7 @@ internal fun OcrQueueCategoryItem( ) { val countString = remember(count) { count.toString() } - TextPreferencesWidget( + TextItem( onClick = onClick, title = title, modifier = modifier, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/preferences/OcrQueuePreferencesBottomSheet.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/preferences/OcrQueuePreferencesBottomSheet.kt index 8c85ed3d..7bf2944b 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/preferences/OcrQueuePreferencesBottomSheet.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/preferences/OcrQueuePreferencesBottomSheet.kt @@ -20,8 +20,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.koin.compose.viewmodel.koinViewModel import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader -import xyz.sevive.arcaeaoffline.ui.components.preferences.SliderPreferencesWidget -import xyz.sevive.arcaeaoffline.ui.components.preferences.SwitchPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.SliderItem +import xyz.sevive.arcaeaoffline.ui.components.SwitchItem import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import kotlin.math.round @@ -38,7 +38,7 @@ private fun Content( } item { - SwitchPreferencesWidget( + SwitchItem( value = uiState.checkIsImage, onValueChange = { onSetCheckIsImage(it) }, title = stringResource(R.string.ocr_queue_add_image_options_check_is_image), @@ -46,7 +46,7 @@ private fun Content( } item { - SwitchPreferencesWidget( + SwitchItem( value = uiState.checkIsArcaeaImage, onValueChange = { onSetCheckIsArcaeaImage(it) }, title = stringResource(R.string.ocr_queue_add_image_options_detect_screenshot), @@ -58,7 +58,7 @@ private fun Content( } item { - SliderPreferencesWidget( + SliderItem( value = uiState.parallelCount.toFloat(), onValueChange = { onSetParallelCount(round(it).toInt()) }, icon = Icons.AutoMirrored.Default.Sort, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingSheet.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingSheet.kt index 6f9d511c..dd225f7c 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingSheet.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/staging/OcrQueueStagingSheet.kt @@ -40,7 +40,6 @@ import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp -import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.delay import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.Progress @@ -48,6 +47,7 @@ import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.LinearProgressIndicatorWrapper import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import xyz.sevive.arcaeaoffline.ui.theme.spacing +import kotlin.time.Duration.Companion.seconds @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskListItemHeader.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskListItemHeader.kt index 5ed2f703..b4b91480 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskListItemHeader.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/tasklist/OcrQueueTaskListItemHeader.kt @@ -43,7 +43,7 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.database.entities.OcrQueueTask import xyz.sevive.arcaeaoffline.database.entities.OcrQueueTaskStatus import xyz.sevive.arcaeaoffline.helpers.context.getFilename -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.screens.ocr.queue.OcrQueueScreenViewModel import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme import kotlin.time.Clock @@ -60,14 +60,14 @@ private fun TaskDetailsDialog( text = { LazyColumn { item { - TextPreferencesWidget( + TextItem( title = "ID", content = dbItem.id.toString(), ) } item { - TextPreferencesWidget( + TextItem( title = "Uri", content = dbItem.fileUri.toString(), ) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/SettingsNavEntry.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/SettingsNavEntry.kt index aa58c093..6adb262a 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/SettingsNavEntry.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/SettingsNavEntry.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.data.IS_UNSTABLE_VERSION -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget +import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.navigation.LocalListDetailNavigationContext import xyz.sevive.arcaeaoffline.ui.navigation.MainScreen import xyz.sevive.arcaeaoffline.ui.navigation.SettingsSubScreen @@ -86,7 +86,7 @@ internal fun SettingsNavEntry( CompositionLocalProvider( LocalContentColor provides MaterialTheme.colorScheme.error, ) { - TextPreferencesWidget( + TextItem( title = stringResource(R.string.emergency_mode_title), leadingIcon = ImageVector.vectorResource(R.drawable.ic_activity_emergency_mode), leadingIconTint = LocalContentColor.current, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/general/SettingsGeneralScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/general/SettingsGeneralScreen.kt index c64611bb..cf61694a 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/general/SettingsGeneralScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/general/SettingsGeneralScreen.kt @@ -23,10 +23,10 @@ import androidx.compose.ui.text.input.KeyboardType import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.api.ArcaeaResourcesApiClient import xyz.sevive.arcaeaoffline.ui.SubScreenContainer +import xyz.sevive.arcaeaoffline.ui.components.SwitchItem +import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogConfirmButton import xyz.sevive.arcaeaoffline.ui.components.dialogs.DialogDismissTextButton -import xyz.sevive.arcaeaoffline.ui.components.preferences.SwitchPreferencesWidget -import xyz.sevive.arcaeaoffline.ui.components.preferences.TextPreferencesWidget import xyz.sevive.arcaeaoffline.ui.navigation.SettingsSubScreen import xyz.sevive.arcaeaoffline.ui.screens.settings.SettingsViewModel @@ -110,7 +110,7 @@ internal fun SettingsGeneralScreen( ) { LazyColumn(modifier) { item { - SwitchPreferencesWidget( + SwitchItem( value = uiState.autoSendCrashReports, onValueChange = { onSetAutoSendCrashReports(it) }, icon = Icons.Default.BugReport, @@ -119,7 +119,7 @@ internal fun SettingsGeneralScreen( } item { - TextPreferencesWidget( + TextItem( onClick = { showBaseUrlEditDialog = true }, leadingIcon = Icons.Default.CloudDownload, title = stringResource(R.string.settings_general_pref_resources_api_base_url), diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt index b0b96ad7..d95a6cb0 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt @@ -71,9 +71,9 @@ import xyz.sevive.arcaeaoffline.ui.components.BasicAlertDialogSurface import xyz.sevive.arcaeaoffline.ui.components.DecimalStepperTextField import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader import xyz.sevive.arcaeaoffline.ui.components.PlayRatingCalculator +import xyz.sevive.arcaeaoffline.ui.components.SwitchItem import xyz.sevive.arcaeaoffline.ui.components.arcaea.OutlinedArcaeaScoreTextField import xyz.sevive.arcaeaoffline.ui.components.arcaea.rememberArcaeaScoreTextFieldState -import xyz.sevive.arcaeaoffline.ui.components.preferences.SwitchPreferencesWidget import xyz.sevive.arcaeaoffline.ui.components.rememberDecimalStepperTextFieldState import xyz.sevive.arcaeaoffline.ui.helpers.ArcaeaFormatters import xyz.sevive.arcaeaoffline.ui.navigation.UtilitiesSubScreen @@ -506,7 +506,7 @@ fun UtilitiesChartRecommendScreen( } if (uiState.scoringMode == ArcaeaScoringMode.B50) { - SwitchPreferencesWidget( + SwitchItem( value = uiState.clearType != null && uiState.clearType != ArcaeaPlayResultClearType.TRACK_LOST, onValueChange = { cleared -> viewModel.setClearType(if (cleared) ArcaeaPlayResultClearType.NORMAL_CLEAR else null) From edaf199628f4a5eed65dc435d72473fd977917a5 Mon Sep 17 00:00:00 2001 From: 283375 Date: Wed, 7 Oct 2026 03:47:26 +0800 Subject: [PATCH 5/8] split ListGroupHeader and SettingsGroupHeader --- .../ui/activities/EmergencyModeActivityUi.kt | 10 ++--- .../ui/components/ListGroupHeader.kt | 12 +++--- .../ui/components/SettingsItems.kt | 42 +++++++++++++++++++ .../DatabaseAddPlayResultScreen.kt | 12 ++---- .../database/manage/DatabaseManageScreen.kt | 17 +++----- .../ocr/performance/OcrPerformanceScreen.kt | 10 ++--- .../OcrQueuePreferencesBottomSheet.kt | 6 +-- .../arcaeaoffline/ui/theme/Typography.kt | 12 ++++++ 8 files changed, 81 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt index 34196a1f..e686fde9 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/activities/EmergencyModeActivityUi.kt @@ -3,7 +3,6 @@ package xyz.sevive.arcaeaoffline.ui.activities import android.content.Intent import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -46,7 +45,7 @@ import io.github.vinceglb.filekit.path import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.helpers.context.persistUriPermissions import xyz.sevive.arcaeaoffline.ui.components.IconRow -import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader +import xyz.sevive.arcaeaoffline.ui.components.SettingsGroupHeader import xyz.sevive.arcaeaoffline.ui.theme.spacing @OptIn(ExperimentalMaterial3Api::class) @@ -78,7 +77,6 @@ private fun UiTopAppBar(modifier: Modifier = Modifier) { ) } -@OptIn(ExperimentalLayoutApi::class) @Composable fun EmergencyModeActivityUi( modifier: Modifier = Modifier, @@ -116,7 +114,7 @@ fun EmergencyModeActivityUi( ), ) { item { - ListGroupHeader(stringResource(R.string.emergency_mode_output_directory_title)) + SettingsGroupHeader(stringResource(R.string.emergency_mode_output_directory_title)) } item { Column(Modifier.padding(horizontal = MaterialTheme.spacing.pagePadding)) { @@ -163,7 +161,7 @@ fun EmergencyModeActivityUi( } item { - ListGroupHeader(stringResource(R.string.emergency_mode_ocr_title)) + SettingsGroupHeader(stringResource(R.string.emergency_mode_ocr_title)) } item { FlowRow( @@ -187,7 +185,7 @@ fun EmergencyModeActivityUi( } item { - ListGroupHeader(stringResource(R.string.emergency_mode_database_title)) + SettingsGroupHeader(stringResource(R.string.emergency_mode_database_title)) } item { FlowRow( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt index 18ec0096..83c4df8d 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/ListGroupHeader.kt @@ -9,12 +9,14 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight +import xyz.sevive.arcaeaoffline.ui.theme.header import xyz.sevive.arcaeaoffline.ui.theme.spacing /** - * Section header carrying its own horizontal gutter. Place it directly in an - * edge-to-edge container instead of a horizontally padded container. + * Group header for items in an edge-to-edge scrolling list. + * Place it directly in the list, not inside a horizontally padded container. + * + * For headers above [BaseSettingsItem] rows, prefer [SettingsGroupHeader]. */ @Composable fun ListGroupHeader( @@ -29,8 +31,8 @@ fun ListGroupHeader( ), ) { CompositionLocalProvider( - LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant, - LocalTextStyle provides MaterialTheme.typography.bodyMedium.copy(fontWeight = FontWeight.SemiBold), + LocalContentColor provides MaterialTheme.typography.header.color, + LocalTextStyle provides MaterialTheme.typography.header, ) { content() } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SettingsItems.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SettingsItems.kt index 0bdade27..b1cfa08d 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SettingsItems.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/SettingsItems.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.BugReport @@ -31,6 +32,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark import xyz.sevive.arcaeaoffline.helpers.DISABLED_ALPHA import xyz.sevive.arcaeaoffline.helpers.secondaryItemAlpha import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.header import xyz.sevive.arcaeaoffline.ui.theme.spacing private val HorizontalPadding @@ -40,6 +42,46 @@ private val VerticalPadding @Composable get() = MaterialTheme.spacing.lg +/** + * Group header whose text aligns with [BaseSettingsItem] titles by sharing + * the same gutter. + */ +@Composable +fun SettingsGroupHeader( + text: String, + modifier: Modifier = Modifier, +) { + SettingsGroupHeader(modifier = modifier) { + Text(text) + } +} + +@Composable +fun SettingsGroupHeader( + modifier: Modifier = Modifier, + content: @Composable () -> Unit, +) { + Box( + modifier = + modifier + .fillMaxWidth() + .padding( + top = MaterialTheme.spacing.xl, + bottom = MaterialTheme.spacing.sm, + start = HorizontalPadding, + end = HorizontalPadding, + ), + contentAlignment = Alignment.CenterStart, + ) { + CompositionLocalProvider( + LocalContentColor provides MaterialTheme.typography.header.color, + LocalTextStyle provides MaterialTheme.typography.header, + ) { + content() + } + } +} + @Composable fun BaseSettingsItem( title: @Composable ColumnScope.() -> Unit, diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultScreen.kt index 4cfd2d79..19581585 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/addplayresult/DatabaseAddPlayResultScreen.kt @@ -1,6 +1,5 @@ package xyz.sevive.arcaeaoffline.ui.screens.database.addplayresult -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets @@ -31,7 +30,7 @@ import org.koin.compose.viewmodel.koinViewModel import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.components.IconRow -import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader +import xyz.sevive.arcaeaoffline.ui.components.SettingsGroupHeader import xyz.sevive.arcaeaoffline.ui.navigation.DatabaseSubScreen import xyz.sevive.arcaeaoffline.ui.theme.spacing @@ -97,7 +96,7 @@ internal fun DatabaseAddPlayResultScreen( contentPadding = innerPadding, ) { item { - ListGroupHeader(stringResource(R.string.database_add_play_result_select_chart_header)) + SettingsGroupHeader(stringResource(R.string.database_add_play_result_select_chart_header)) } item { @@ -109,12 +108,7 @@ internal fun DatabaseAddPlayResultScreen( } item { - // Just adding a padding - Box(Modifier.padding(vertical = MaterialTheme.spacing.sm)) {} - } - - item { - ListGroupHeader(stringResource(R.string.database_add_play_result_edit_play_result_header)) + SettingsGroupHeader(stringResource(R.string.database_add_play_result_edit_play_result_header)) } item { diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageScreen.kt index b9bfa300..9db3f0ac 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/database/manage/DatabaseManageScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Tune import androidx.compose.material.icons.filled.Upload import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -33,9 +32,9 @@ import xyz.sevive.arcaeaoffline.R import xyz.sevive.arcaeaoffline.core.constants.ArcaeaScoringMode import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.components.IconRow -import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader import xyz.sevive.arcaeaoffline.ui.components.SelectItem import xyz.sevive.arcaeaoffline.ui.components.SelectOption +import xyz.sevive.arcaeaoffline.ui.components.SettingsGroupHeader import xyz.sevive.arcaeaoffline.ui.components.TextItem @Composable @@ -73,7 +72,7 @@ fun DatabaseManageScreen( ) { LazyColumn(modifier) { item { - ListGroupHeader { + SettingsGroupHeader { IconRow { Icon(Icons.Default.Tune, contentDescription = null) Text(stringResource(R.string.database_manage_scoring_mode_title)) @@ -104,10 +103,8 @@ fun DatabaseManageScreen( ) } - item { HorizontalDivider() } - item { - ListGroupHeader { + SettingsGroupHeader { IconRow { Icon(Icons.Default.Download, contentDescription = null) Text(stringResource(R.string.database_manage_import_title)) @@ -128,10 +125,8 @@ fun DatabaseManageScreen( ) } - item { HorizontalDivider() } - item { - ListGroupHeader { + SettingsGroupHeader { IconRow { Icon(Icons.Default.CloudDownload, contentDescription = null) Text(stringResource(R.string.database_manage_download_title)) @@ -171,10 +166,8 @@ fun DatabaseManageScreen( ) } - item { HorizontalDivider() } - item { - ListGroupHeader { + SettingsGroupHeader { IconRow { Icon(Icons.Default.Upload, contentDescription = null) Text(stringResource(R.string.database_manage_export_title)) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt index c05d8a82..5bb9944a 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/performance/OcrPerformanceScreen.kt @@ -58,7 +58,7 @@ import xyz.sevive.arcaeaoffline.ui.SubScreenContainer import xyz.sevive.arcaeaoffline.ui.components.BaseSettingsItem import xyz.sevive.arcaeaoffline.ui.components.IconRow import xyz.sevive.arcaeaoffline.ui.components.LinearProgressIndicatorWrapper -import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader +import xyz.sevive.arcaeaoffline.ui.components.SettingsGroupHeader import xyz.sevive.arcaeaoffline.ui.components.SliderItem import xyz.sevive.arcaeaoffline.ui.components.TextItem import xyz.sevive.arcaeaoffline.ui.navigation.OcrSubScreen @@ -88,7 +88,7 @@ fun OcrPerformanceScreen( ) { LazyColumn(modifier) { item { - ListGroupHeader(stringResource(R.string.ocr_performance_images_title)) + SettingsGroupHeader(stringResource(R.string.ocr_performance_images_title)) } item { @@ -153,7 +153,7 @@ fun OcrPerformanceScreen( item { HorizontalDivider() } item { - ListGroupHeader(stringResource(R.string.ocr_performance_concurrency_title)) + SettingsGroupHeader(stringResource(R.string.ocr_performance_concurrency_title)) } item { @@ -223,7 +223,7 @@ fun OcrPerformanceScreen( item { HorizontalDivider() } item { - ListGroupHeader(stringResource(R.string.ocr_performance_result_title)) + SettingsGroupHeader(stringResource(R.string.ocr_performance_result_title)) } item { @@ -240,7 +240,7 @@ fun OcrPerformanceScreen( item { HorizontalDivider() } item { - ListGroupHeader(stringResource(R.string.ocr_performance_history_title)) + SettingsGroupHeader(stringResource(R.string.ocr_performance_history_title)) } // Newest first, easier to compare recent runs diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/preferences/OcrQueuePreferencesBottomSheet.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/preferences/OcrQueuePreferencesBottomSheet.kt index 7bf2944b..1e642711 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/preferences/OcrQueuePreferencesBottomSheet.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/ocr/queue/preferences/OcrQueuePreferencesBottomSheet.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.koin.compose.viewmodel.koinViewModel import xyz.sevive.arcaeaoffline.R -import xyz.sevive.arcaeaoffline.ui.components.ListGroupHeader +import xyz.sevive.arcaeaoffline.ui.components.SettingsGroupHeader import xyz.sevive.arcaeaoffline.ui.components.SliderItem import xyz.sevive.arcaeaoffline.ui.components.SwitchItem import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme @@ -34,7 +34,7 @@ private fun Content( ) { LazyColumn { item { - ListGroupHeader(stringResource(R.string.ocr_queue_add_image_options_title)) + SettingsGroupHeader(stringResource(R.string.ocr_queue_add_image_options_title)) } item { @@ -54,7 +54,7 @@ private fun Content( } item { - ListGroupHeader(stringResource(R.string.ocr_queue_queue_options_title)) + SettingsGroupHeader(stringResource(R.string.ocr_queue_queue_options_title)) } item { diff --git a/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Typography.kt b/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Typography.kt index c8262494..ae1ff1df 100644 --- a/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Typography.kt +++ b/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Typography.kt @@ -1,6 +1,18 @@ package xyz.sevive.arcaeaoffline.ui.theme +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Typography +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight // Set of Material typography styles to start with val Typography = Typography() + +val Typography.header: TextStyle + @Composable + get() = + bodyMedium.copy( + color = MaterialTheme.colorScheme.onSurfaceVariant, + fontWeight = FontWeight.SemiBold, + ) From 77b8d15b01407b6ef9f16a38615aa89b90275c97 Mon Sep 17 00:00:00 2001 From: 283375 Date: Wed, 7 Oct 2026 03:55:20 +0800 Subject: [PATCH 6/8] apply missed spacing --- .../main/kotlin/xyz/sevive/arcaeaoffline/desktop/Main.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/desktopApp/src/main/kotlin/xyz/sevive/arcaeaoffline/desktop/Main.kt b/desktopApp/src/main/kotlin/xyz/sevive/arcaeaoffline/desktop/Main.kt index b011675a..84a60acf 100644 --- a/desktopApp/src/main/kotlin/xyz/sevive/arcaeaoffline/desktop/Main.kt +++ b/desktopApp/src/main/kotlin/xyz/sevive/arcaeaoffline/desktop/Main.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -27,6 +28,7 @@ import xyz.sevive.arcaeaoffline.ui.components.arcaea.OutlinedArcaeaScoreTextFiel import xyz.sevive.arcaeaoffline.ui.components.arcaea.rememberArcaeaScoreTextFieldState import xyz.sevive.arcaeaoffline.ui.components.rememberArcaeaConstantStepperTextFieldState import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme +import xyz.sevive.arcaeaoffline.ui.theme.spacing fun main() = application { @@ -49,8 +51,8 @@ fun CalculatorScreen() { val result = calculatePlayRating(score, constant) Column( - Modifier.padding(16.dp).width(400.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), + Modifier.padding(MaterialTheme.spacing.lg).width(400.dp), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.sm), ) { OutlinedArcaeaScoreTextField(scoreTextFieldState) From 41cc49c093f4a06f8875d3d5bb043a5430c7df01 Mon Sep 17 00:00:00 2001 From: 283375 Date: Wed, 7 Oct 2026 09:42:34 +0800 Subject: [PATCH 7/8] fixup --- .../ui/components/BasicAlertDialogSurface.kt | 3 +-- .../settings/unstablealert/SettingsUnstableAlertCard.kt | 4 ++-- .../ui/screens/utilities/UtilitiesChartRecommendScreen.kt | 8 ++++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/BasicAlertDialogSurface.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/BasicAlertDialogSurface.kt index 7984055c..ae2bfd82 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/BasicAlertDialogSurface.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/components/BasicAlertDialogSurface.kt @@ -8,7 +8,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import xyz.sevive.arcaeaoffline.ui.theme.spacing @@ -29,7 +28,7 @@ fun BasicAlertDialogSurface( shape = AlertDialogDefaults.shape, color = AlertDialogDefaults.containerColor, ) { - content(PaddingValues(all = MaterialTheme.spacing.xl)) + content(PaddingValues(all = MaterialTheme.spacing.dialogPadding)) } } } diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertCard.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertCard.kt index 780da63e..10baf085 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertCard.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/settings/unstablealert/SettingsUnstableAlertCard.kt @@ -49,9 +49,9 @@ fun UnstableBuildAlertCard( shape: Shape = CutCornerShape( topStart = 0.dp, - topEnd = MaterialTheme.spacing.lg, + topEnd = 16.dp, bottomEnd = 0.dp, - bottomStart = MaterialTheme.spacing.lg, + bottomStart = 16.dp, ), colors: CardColors = CardDefaults.cardColors( diff --git a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt index d95a6cb0..faa3b08e 100644 --- a/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt +++ b/app/src/main/java/xyz/sevive/arcaeaoffline/ui/screens/utilities/UtilitiesChartRecommendScreen.kt @@ -252,6 +252,7 @@ private fun ResultsListItem( private val ParametersCardCollapsedHeight = 48.dp private val ParametersCardTopPadding = MaterialTheme.spacing.xs +private val ParametersCardOuterVerticalPadding = MaterialTheme.spacing.sm /** * Floating parameters panel. It overlays the results list, which clears its @@ -362,7 +363,10 @@ fun UtilitiesChartRecommendScreen( Box(Modifier.fillMaxSize()) { // The card floats with top padding. The list and the top // scrim both clear the card's bottom edge plus a lg gap. - val listTopInset = ParametersCardCollapsedHeight + ParametersCardTopPadding + MaterialTheme.spacing.lg + val listTopInset = + ParametersCardCollapsedHeight + + ParametersCardOuterVerticalPadding + + MaterialTheme.spacing.lg LazyColumn( modifier = Modifier.fillMaxSize(), @@ -462,7 +466,7 @@ fun UtilitiesChartRecommendScreen( .align(Alignment.TopCenter) .padding( horizontal = MaterialTheme.spacing.pagePadding, - vertical = MaterialTheme.spacing.sm, + vertical = ParametersCardOuterVerticalPadding, ).fillMaxWidth(), ) { Row( From 298a3bcc3b1e0afcaf9f7d482215867ce1c4d71e Mon Sep 17 00:00:00 2001 From: 283375 Date: Wed, 7 Oct 2026 12:04:18 +0800 Subject: [PATCH 8/8] add comments --- .../kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt b/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt index 69e8a233..a8e8c2bd 100644 --- a/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt +++ b/shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/ui/theme/Spacing.kt @@ -22,5 +22,8 @@ object Spacing { val dialogPadding: Dp = xl } +/** + * Placeholder for future CompositionLocal runtime-varying scale if introduced. + */ val MaterialTheme.spacing: Spacing get() = Spacing