From 7321e271b8b38a92cc63e170fd95ba036ffebd4f Mon Sep 17 00:00:00 2001 From: Pierre-Yves Nicolas <6371790+pynicolas@users.noreply.github.com> Date: Thu, 3 Jul 2025 08:59:58 +0200 Subject: [PATCH] Colors, style adjustments --- .../org/mydomain/myscan/ui/theme/Color.kt | 52 ++++++++++-- .../org/mydomain/myscan/ui/theme/Theme.kt | 74 ++++++++++------- .../org/mydomain/myscan/view/CameraPreview.kt | 4 +- .../org/mydomain/myscan/view/CameraScreen.kt | 2 +- .../mydomain/myscan/view/DocumentScreen.kt | 81 +++++++++++++------ .../java/org/mydomain/myscan/view/PageList.kt | 2 +- 6 files changed, 153 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/org/mydomain/myscan/ui/theme/Color.kt b/app/src/main/java/org/mydomain/myscan/ui/theme/Color.kt index ca1f2bf..afc203d 100644 --- a/app/src/main/java/org/mydomain/myscan/ui/theme/Color.kt +++ b/app/src/main/java/org/mydomain/myscan/ui/theme/Color.kt @@ -16,10 +16,50 @@ package org.mydomain.myscan.ui.theme import androidx.compose.ui.graphics.Color -val Purple80 = Color(0xFFD0BCFF) -val PurpleGrey80 = Color(0xFFCCC2DC) -val Pink80 = Color(0xFFEFB8C8) +val Primary = Color(0xFF33BE41) +val OnPrimary = Color(0xFFFFFFFF) +val PrimaryContainer = Color(0xFF7BD785) +val OnPrimaryContainer = Color(0xFF0D3311) +val Secondary = Color(0xFF52CBA7) +val OnSecondary = Color(0xFFFFFFFF) +val SecondaryContainer = Color(0xFFBAE6D8) +val OnSecondaryContainer = Color(0xFF14332A) +val Tertiary = Color(0xFF8976D6) +val OnTertiary = Color(0xFFFFFFFF) +val TertiaryContainer = Color(0xFFCBC5E6) +val OnTertiaryContainer = Color(0xFF211C33) +val Error = Color(0xFFB3261E) +val OnError = Color(0xFFFFFFFF) +val ErrorContainer = Color(0xFFE6ACA9) +val OnErrorContainer = Color(0xFF330B09) +val Background = Color(0xFFfcfcfc) +val OnBackground = Color(0xFF313331) +val Surface = Color(0xFFfcfcfc) +val OnSurface = Color(0xFF313331) +val SurfaceVariant = Color(0xFFdbe6dc) +val OnSurfaceVariant = Color(0xFF576658) +val Outline = Color(0xFF829984) -val Purple40 = Color(0xFF6650a4) -val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) \ No newline at end of file +val PrimaryDark = Color(0xFF9AE6A1) +val OnPrimaryDark = Color(0xFF144C19) +val PrimaryContainerDark = Color(0xFF1B6622) +val OnPrimaryContainerDark = Color(0xFFB0E6B5) +val SecondaryDark = Color(0xFFA8E6D3) +val OnSecondaryDark = Color(0xFF1F4C3F) +val SecondaryContainerDark = Color(0xFF296654) +val OnSecondaryContainerDark = Color(0xFFBAE6D8) +val TertiaryDark = Color(0xFFC1B7E6) +val OnTertiaryDark = Color(0xFF312A4C) +val TertiaryContainerDark = Color(0xFF413866) +val OnTertiaryContainerDark = Color(0xFFCBC5E6) +val ErrorDark = Color(0xFFE69490) +val OnErrorDark = Color(0xFF4C100D) +val ErrorContainerDark = Color(0xFF661511) +val OnErrorContainerDark = Color(0xFFE6ACA9) +val BackgroundDark = Color(0xFF313331) +val OnBackgroundDark = Color(0xFFe3e6e3) +val SurfaceDark = Color(0xFF313331) +val OnSurfaceDark = Color(0xFFe3e6e3) +val SurfaceVariantDark = Color(0xFF576658) +val OnSurfaceVariantDark = Color(0xFFd6e6d8) +val OutlineDark = Color(0xFFa2b3a3) \ No newline at end of file diff --git a/app/src/main/java/org/mydomain/myscan/ui/theme/Theme.kt b/app/src/main/java/org/mydomain/myscan/ui/theme/Theme.kt index 48fc9ab..ff83002 100644 --- a/app/src/main/java/org/mydomain/myscan/ui/theme/Theme.kt +++ b/app/src/main/java/org/mydomain/myscan/ui/theme/Theme.kt @@ -14,52 +14,70 @@ */ package org.mydomain.myscan.ui.theme -import android.app.Activity -import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.dynamicDarkColorScheme -import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalContext private val DarkColorScheme = darkColorScheme( - primary = Purple80, - secondary = PurpleGrey80, - tertiary = Pink80 + primary = PrimaryDark, + onPrimary = OnPrimaryDark, + primaryContainer = PrimaryContainerDark, + onPrimaryContainer = OnPrimaryContainerDark, + secondary = SecondaryDark, + onSecondary = OnSecondaryDark, + secondaryContainer = SecondaryContainerDark, + onSecondaryContainer = OnSecondaryContainerDark, + tertiary = TertiaryDark, + onTertiary = OnTertiaryDark, + tertiaryContainer = TertiaryContainerDark, + onTertiaryContainer = OnTertiaryContainerDark, + error = ErrorDark, + onError = OnErrorDark, + errorContainer = ErrorContainerDark, + onErrorContainer = OnErrorContainerDark, + background = BackgroundDark, + onBackground = OnBackgroundDark, + surface = SurfaceDark, + onSurface = OnSurfaceDark, + surfaceVariant = SurfaceVariantDark, + onSurfaceVariant = OnSurfaceVariantDark, + outline = OutlineDark ) private val LightColorScheme = lightColorScheme( - primary = Purple40, - secondary = PurpleGrey40, - tertiary = Pink40 - - /* Other default colors to override - background = Color(0xFFFFFBFE), - surface = Color(0xFFFFFBFE), - onPrimary = Color.White, - onSecondary = Color.White, - onTertiary = Color.White, - onBackground = Color(0xFF1C1B1F), - onSurface = Color(0xFF1C1B1F), - */ + primary = Primary, + onPrimary = OnPrimary, + primaryContainer = PrimaryContainer, + onPrimaryContainer = OnPrimaryContainer, + secondary = Secondary, + onSecondary = OnSecondary, + secondaryContainer = SecondaryContainer, + onSecondaryContainer = OnSecondaryContainer, + tertiary = Tertiary, + onTertiary = OnTertiary, + tertiaryContainer = TertiaryContainer, + onTertiaryContainer = OnTertiaryContainer, + error = Error, + onError = OnError, + errorContainer = ErrorContainer, + onErrorContainer = OnErrorContainer, + background = Background, + onBackground = OnBackground, + surface = Surface, + onSurface = OnSurface, + surfaceVariant = SurfaceVariant, + onSurfaceVariant = OnSurfaceVariant, + outline = Outline ) @Composable fun MyScanTheme( darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, content: @Composable () -> Unit ) { val colorScheme = when { - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { - val context = LocalContext.current - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - } - darkTheme -> DarkColorScheme else -> LightColorScheme } diff --git a/app/src/main/java/org/mydomain/myscan/view/CameraPreview.kt b/app/src/main/java/org/mydomain/myscan/view/CameraPreview.kt index 9e22623..7ae37fa 100644 --- a/app/src/main/java/org/mydomain/myscan/view/CameraPreview.kt +++ b/app/src/main/java/org/mydomain/myscan/view/CameraPreview.kt @@ -34,6 +34,7 @@ import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.view.PreviewView import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect @@ -155,6 +156,7 @@ fun AnalysisOverlay(liveAnalysisState: LiveAnalysisState, debugMode: Boolean) { if (binaryMask == null) { return } + val quadColor = MaterialTheme.colorScheme.primary Canvas(modifier = Modifier.fillMaxSize()) { if (debugMode) { drawMask(this, binaryMask) @@ -167,7 +169,7 @@ fun AnalysisOverlay(liveAnalysisState: LiveAnalysisState, debugMode: Boolean) { toHeight = size.height.toInt() ) scaledQuad.edges().forEach { - drawLine(Color.Green, it.from.toOffset(), it.to.toOffset(), 10.0f) + drawLine(quadColor, it.from.toOffset(), it.to.toOffset(), 10.0f) } } } diff --git a/app/src/main/java/org/mydomain/myscan/view/CameraScreen.kt b/app/src/main/java/org/mydomain/myscan/view/CameraScreen.kt index 330759e..c440b83 100644 --- a/app/src/main/java/org/mydomain/myscan/view/CameraScreen.kt +++ b/app/src/main/java/org/mydomain/myscan/view/CameraScreen.kt @@ -391,7 +391,7 @@ fun CameraScreenFooter( Column (modifier = Modifier.background(MaterialTheme.colorScheme.surfaceContainer)) { pageList() BottomAppBar( - containerColor = Color.Transparent + containerColor = MaterialTheme.colorScheme.surfaceContainerHigh, ) { Row ( modifier = Modifier diff --git a/app/src/main/java/org/mydomain/myscan/view/DocumentScreen.kt b/app/src/main/java/org/mydomain/myscan/view/DocumentScreen.kt index 29aac64..7526f8f 100644 --- a/app/src/main/java/org/mydomain/myscan/view/DocumentScreen.kt +++ b/app/src/main/java/org/mydomain/myscan/view/DocumentScreen.kt @@ -37,12 +37,12 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.BottomAppBar import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.FilledIconButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.SmallFloatingActionButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar @@ -58,6 +58,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -91,8 +92,8 @@ fun DocumentScreen( topBar = { TopAppBar( colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.primaryContainer, - titleContentColor = MaterialTheme.colorScheme.primary, + containerColor = MaterialTheme.colorScheme.surfaceContainerHigh, + titleContentColor = MaterialTheme.colorScheme.onSurface, ), title = { Text("Finalize document") }, navigationIcon = { @@ -106,6 +107,7 @@ fun DocumentScreen( Column { PageList(pageIds, imageLoader, currentPageIndex, toCameraScreen) BottomAppBar( + containerColor = MaterialTheme.colorScheme.surfaceContainerHigh, actions = { Button(onClick = onSharePressed) { Icon(Icons.Default.Share, contentDescription = "Share") @@ -120,9 +122,12 @@ fun DocumentScreen( } }, floatingActionButton = { - FloatingActionButton(onClick = { showDialog.value = true }) { - Icon(Icons.Default.RestartAlt, contentDescription = "Close") - } + MyIconButton( + icon = Icons.Default.RestartAlt, + contentDescription = "Restart", + onClick = { showDialog.value = true }, + modifier = Modifier.padding(vertical = 8.dp) + ) } ) } @@ -147,7 +152,7 @@ private fun DocumentPreview( Column ( modifier = Modifier .fillMaxSize() - .background(MaterialTheme.colorScheme.surfaceContainer) + .background(MaterialTheme.colorScheme.surfaceContainerLow) .padding(padding) ) { Box ( @@ -163,23 +168,25 @@ private fun DocumentPreview( LaunchedEffect(imageId) { zoomState.reset() } - Image( - bitmap = imageBitmap, - contentDescription = null, - modifier = Modifier - .padding(4.dp) - .align(Alignment.Center) - .zoomable(zoomState) - ) + Box(modifier = Modifier.fillMaxSize(0.92f).align(Alignment.Center)) { + Image( + bitmap = imageBitmap, + contentDescription = null, + modifier = Modifier + .padding(4.dp) + .align(Alignment.Center) + .zoomable(zoomState) + ) + } } - SmallFloatingActionButton( + MyIconButton( + Icons.Outlined.Delete, + contentDescription = "Delete page", onClick = { onDeleteImage(imageId) }, modifier = Modifier .align(Alignment.TopEnd) - .padding(4.dp) - ) { - Icon(imageVector = Icons.Outlined.Delete, contentDescription = "Delete page") - } + .padding(8.dp) + ) Text("${currentPageIndex.intValue + 1} / ${pageIds.size}", color = MaterialTheme.colorScheme.inverseOnSurface, modifier = Modifier @@ -206,14 +213,14 @@ private fun PageList( onPageClick = { index -> currentPageIndex.value = index }, currentPageIndex = currentPageIndex.value, ) - SmallFloatingActionButton( + MyIconButton( + icon = Icons.Default.Add, onClick = toCameraScreen, + contentDescription = "Add page", modifier = Modifier .align(Alignment.CenterEnd) .padding(8.dp) - ) { - Icon(imageVector = Icons.Default.Add, contentDescription = "Add page") - } + ) } } @@ -239,6 +246,30 @@ fun NewDocumentDialog(onConfirm: () -> Unit, showDialog: MutableState) ) } +@Composable +fun MyIconButton( + icon: ImageVector, + contentDescription: String, + onClick: () -> Unit, + modifier: Modifier = Modifier +) { + FilledIconButton ( + onClick = onClick, + colors = IconButtonDefaults.outlinedIconButtonColors( + containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.6f), + contentColor = MaterialTheme.colorScheme.primary + ), + modifier = modifier.size(40.dp) + ) { + Icon( + imageVector = icon, + contentDescription = contentDescription, + tint = MaterialTheme.colorScheme.primary + ) + } +} + + @Composable @Preview fun DocumentScreenPreview() { diff --git a/app/src/main/java/org/mydomain/myscan/view/PageList.kt b/app/src/main/java/org/mydomain/myscan/view/PageList.kt index 32f2d9f..06b63b6 100644 --- a/app/src/main/java/org/mydomain/myscan/view/PageList.kt +++ b/app/src/main/java/org/mydomain/myscan/view/PageList.kt @@ -60,7 +60,7 @@ fun CommonPageList( LazyRow ( state = listState, contentPadding = PaddingValues(4.dp), - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surfaceContainer), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically ) {