redesign: modern indigo UI, new app icon, edge-to-edge theme
App icon: deep indigo-to-violet gradient background with white sync arrows; replaced flat #2196F3 with layered adaptive icon. Theme: disabled dynamic color; rich indigo/teal/amber Material3 palette; edge-to-edge with transparent status bar; tighter typography letterSpacing. HomeScreen: colored left accent bar per status; URL-decoded SAF paths; relative timestamps (Just now / N min ago / N hr ago); indigo status pills; FilledTonalButton empty state. PairDetailScreen: hero StatusBanner with large icon and relative time; InfoCard as bordered grid with icon backgrounds; colored dot event timeline; URL-decoded local path display. SettingsScreen: section headers with primary left bar; AccountCard with primaryContainer icon backgrounds; Security/About in bordered cards. Bump version to 1.0.13 (code 14). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,27 @@ package com.syncflow.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
val SyncBlue = Color(0xFF2196F3)
|
||||
val SyncGreen = Color(0xFF4CAF50)
|
||||
val SyncOrange = Color(0xFFFF9800)
|
||||
val SyncRed = Color(0xFFF44336)
|
||||
val SyncPurple = Color(0xFF9C27B0)
|
||||
// Primary — indigo
|
||||
val Indigo600 = Color(0xFF4F46E5)
|
||||
val Indigo900 = Color(0xFF312E81)
|
||||
val Indigo100 = Color(0xFFE0E7FF)
|
||||
val Indigo50 = Color(0xFFEEF2FF)
|
||||
|
||||
// Secondary — teal
|
||||
val Teal600 = Color(0xFF0D9488)
|
||||
val Teal100 = Color(0xFFCCFBF1)
|
||||
|
||||
// Tertiary — amber
|
||||
val Amber500 = Color(0xFFF59E0B)
|
||||
val Amber100 = Color(0xFFFEF3C7)
|
||||
|
||||
// Neutrals
|
||||
val Slate50 = Color(0xFFF8FAFC)
|
||||
val Slate100 = Color(0xFFF1F5F9)
|
||||
val Slate200 = Color(0xFFE2E8F0)
|
||||
val Slate600 = Color(0xFF475569)
|
||||
val Slate900 = Color(0xFF0F172A)
|
||||
|
||||
// Semantic
|
||||
val GreenSuccess = Color(0xFF16A34A)
|
||||
val RedError = Color(0xFFDC2626)
|
||||
|
||||
@@ -1,50 +1,77 @@
|
||||
package com.syncflow.ui.theme
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.view.WindowCompat
|
||||
|
||||
private val LightColors = lightColorScheme(
|
||||
primary = SyncBlue,
|
||||
onPrimary = androidx.compose.ui.graphics.Color.White,
|
||||
secondary = SyncGreen,
|
||||
tertiary = SyncPurple,
|
||||
primary = Indigo600,
|
||||
onPrimary = Color.White,
|
||||
primaryContainer = Indigo100,
|
||||
onPrimaryContainer = Indigo900,
|
||||
secondary = Teal600,
|
||||
onSecondary = Color.White,
|
||||
secondaryContainer = Teal100,
|
||||
tertiary = Amber500,
|
||||
tertiaryContainer = Amber100,
|
||||
background = Slate50,
|
||||
surface = Color.White,
|
||||
surfaceVariant = Slate100,
|
||||
onSurfaceVariant = Slate600,
|
||||
error = RedError,
|
||||
errorContainer = Color(0xFFFEE2E2),
|
||||
outline = Slate200,
|
||||
)
|
||||
|
||||
private val DarkColors = darkColorScheme(
|
||||
primary = SyncBlue,
|
||||
secondary = SyncGreen,
|
||||
tertiary = SyncPurple,
|
||||
primary = Color(0xFF818CF8),
|
||||
onPrimary = Indigo900,
|
||||
primaryContainer = Color(0xFF3730A3),
|
||||
onPrimaryContainer = Indigo100,
|
||||
secondary = Color(0xFF2DD4BF),
|
||||
onSecondary = Color(0xFF003731),
|
||||
secondaryContainer = Color(0xFF00504A),
|
||||
tertiary = Amber500,
|
||||
tertiaryContainer = Color(0xFF92400E),
|
||||
background = Color(0xFF0F0F1A),
|
||||
surface = Color(0xFF1A1A2E),
|
||||
surfaceVariant = Color(0xFF252538),
|
||||
onSurfaceVariant = Color(0xFF94A3B8),
|
||||
error = Color(0xFFF87171),
|
||||
errorContainer = Color(0xFF7F1D1D),
|
||||
outline = Color(0xFF334155),
|
||||
)
|
||||
|
||||
private val AppTypography = Typography(
|
||||
titleLarge = TextStyle(fontWeight = FontWeight.Bold, fontSize = 22.sp, letterSpacing = (-0.5).sp),
|
||||
titleMedium = TextStyle(fontWeight = FontWeight.SemiBold, fontSize = 16.sp, letterSpacing = (-0.25).sp),
|
||||
titleSmall = TextStyle(fontWeight = FontWeight.SemiBold, fontSize = 14.sp, letterSpacing = 0.sp),
|
||||
labelMedium = TextStyle(fontWeight = FontWeight.Medium, fontSize = 12.sp, letterSpacing = 0.1.sp),
|
||||
labelSmall = TextStyle(fontWeight = FontWeight.Medium, fontSize = 11.sp, letterSpacing = 0.1.sp),
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun SyncFlowTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
dynamicColor: Boolean = true,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val colorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val ctx = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(ctx) else dynamicLightColorScheme(ctx)
|
||||
}
|
||||
darkTheme -> DarkColors
|
||||
else -> LightColors
|
||||
}
|
||||
val colorScheme = if (darkTheme) DarkColors else LightColors
|
||||
val view = LocalView.current
|
||||
if (!view.isInEditMode) {
|
||||
SideEffect {
|
||||
val window = (view.context as Activity).window
|
||||
window.statusBarColor = colorScheme.primary.toArgb()
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
window.statusBarColor = android.graphics.Color.TRANSPARENT
|
||||
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
|
||||
}
|
||||
}
|
||||
MaterialTheme(colorScheme = colorScheme, typography = Typography(), content = content)
|
||||
MaterialTheme(colorScheme = colorScheme, typography = AppTypography, content = content)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user