mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-19 00:11:45 +00:00
Implement theme selection system with 6 color themes
Add settings screen for users to choose between Crimson, Ocean, Violet, Emerald, Amber, and Rose themes. Each theme customizes accent colors (focus states, buttons) and includes subtle background tinting for a cohesive visual experience. Theme selection persists via DataStore.
This commit is contained in:
parent
e505570770
commit
c82d94c71e
21 changed files with 624 additions and 75 deletions
|
|
@ -8,9 +8,7 @@ plugins {
|
|||
|
||||
android {
|
||||
namespace = "com.nuvio.tv"
|
||||
compileSdk {
|
||||
version = release(36)
|
||||
}
|
||||
compileSdk = 36
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.nuvio.tv"
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -44,18 +45,27 @@ import androidx.compose.material.icons.filled.Bookmark
|
|||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import coil.compose.AsyncImage
|
||||
import com.nuvio.tv.data.local.ThemeDataStore
|
||||
import com.nuvio.tv.domain.model.AppTheme
|
||||
import com.nuvio.tv.ui.navigation.NuvioNavHost
|
||||
import com.nuvio.tv.ui.navigation.Screen
|
||||
import com.nuvio.tv.ui.theme.NuvioTheme
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var themeDataStore: ThemeDataStore
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
NuvioTheme {
|
||||
val currentTheme by themeDataStore.selectedTheme.collectAsState(initial = AppTheme.CRIMSON)
|
||||
|
||||
NuvioTheme(appTheme = currentTheme) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
shape = RectangleShape
|
||||
|
|
|
|||
40
app/src/main/java/com/nuvio/tv/data/local/ThemeDataStore.kt
Normal file
40
app/src/main/java/com/nuvio/tv/data/local/ThemeDataStore.kt
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package com.nuvio.tv.data.local
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import com.nuvio.tv.domain.model.AppTheme
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
private val Context.themeDataStore: DataStore<Preferences> by preferencesDataStore(name = "theme_settings")
|
||||
|
||||
@Singleton
|
||||
class ThemeDataStore @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
) {
|
||||
private val dataStore = context.themeDataStore
|
||||
|
||||
private val themeKey = stringPreferencesKey("selected_theme")
|
||||
|
||||
val selectedTheme: Flow<AppTheme> = dataStore.data.map { prefs ->
|
||||
val themeName = prefs[themeKey] ?: AppTheme.CRIMSON.name
|
||||
try {
|
||||
AppTheme.valueOf(themeName)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
AppTheme.CRIMSON
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setTheme(theme: AppTheme) {
|
||||
dataStore.edit { prefs ->
|
||||
prefs[themeKey] = theme.name
|
||||
}
|
||||
}
|
||||
}
|
||||
10
app/src/main/java/com/nuvio/tv/domain/model/AppTheme.kt
Normal file
10
app/src/main/java/com/nuvio/tv/domain/model/AppTheme.kt
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package com.nuvio.tv.domain.model
|
||||
|
||||
enum class AppTheme(val displayName: String) {
|
||||
CRIMSON("Crimson"),
|
||||
OCEAN("Ocean"),
|
||||
VIOLET("Violet"),
|
||||
EMERALD("Emerald"),
|
||||
AMBER("Amber"),
|
||||
ROSE("Rose")
|
||||
}
|
||||
|
|
@ -28,7 +28,6 @@ import androidx.tv.material3.Border
|
|||
import androidx.tv.material3.Card
|
||||
import androidx.tv.material3.CardDefaults
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Glow
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import coil.compose.AsyncImage
|
||||
|
|
@ -79,18 +78,12 @@ fun ContentCard(
|
|||
),
|
||||
border = CardDefaults.border(
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(3.dp, NuvioColors.FocusRing),
|
||||
border = BorderStroke(2.dp, NuvioColors.FocusRing),
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
)
|
||||
),
|
||||
scale = CardDefaults.scale(
|
||||
focusedScale = 1.08f
|
||||
),
|
||||
glow = CardDefaults.glow(
|
||||
focusedGlow = Glow(
|
||||
elevation = 8.dp,
|
||||
elevationColor = NuvioColors.FocusRing.copy(alpha = 0.3f)
|
||||
)
|
||||
focusedScale = 1.05f
|
||||
)
|
||||
) {
|
||||
Box(
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ private fun ContinueWatchingCard(
|
|||
),
|
||||
colors = CardDefaults.colors(
|
||||
containerColor = NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.BackgroundCard
|
||||
focusedContainerColor = NuvioColors.FocusBackground
|
||||
),
|
||||
border = CardDefaults.border(
|
||||
focusedBorder = Border(
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ private fun SidebarNavItem(
|
|||
label = "navItemBackground"
|
||||
)
|
||||
val borderColor by animateColorAsState(
|
||||
targetValue = if (isFocused) NuvioColors.BorderFocused else Color.Transparent,
|
||||
targetValue = if (isFocused) NuvioColors.FocusRing else Color.Transparent,
|
||||
label = "navItemBorder"
|
||||
)
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ private fun SidebarNavItem(
|
|||
.height(56.dp)
|
||||
.clip(shape)
|
||||
.background(backgroundColor)
|
||||
.border(width = 1.dp, color = borderColor, shape = shape)
|
||||
.border(width = 2.dp, color = borderColor, shape = shape)
|
||||
.then(if (focusRequester != null) Modifier.focusRequester(focusRequester) else Modifier)
|
||||
.onFocusChanged { state ->
|
||||
isFocused = state.isFocused
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.nuvio.tv.ui.screens.player.PlayerScreen
|
|||
import com.nuvio.tv.ui.screens.plugin.PluginScreen
|
||||
import com.nuvio.tv.ui.screens.search.SearchScreen
|
||||
import com.nuvio.tv.ui.screens.settings.SettingsScreen
|
||||
import com.nuvio.tv.ui.screens.settings.ThemeSettingsScreen
|
||||
import com.nuvio.tv.ui.screens.settings.TmdbSettingsScreen
|
||||
import com.nuvio.tv.ui.screens.stream.StreamScreen
|
||||
|
||||
|
|
@ -240,7 +241,8 @@ fun NuvioNavHost(
|
|||
composable(Screen.Settings.route) {
|
||||
SettingsScreen(
|
||||
onNavigateToPlugins = { navController.navigate(Screen.Plugins.route) },
|
||||
onNavigateToTmdb = { navController.navigate(Screen.TmdbSettings.route) }
|
||||
onNavigateToTmdb = { navController.navigate(Screen.TmdbSettings.route) },
|
||||
onNavigateToTheme = { navController.navigate(Screen.ThemeSettings.route) }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -250,6 +252,12 @@ fun NuvioNavHost(
|
|||
)
|
||||
}
|
||||
|
||||
composable(Screen.ThemeSettings.route) {
|
||||
ThemeSettingsScreen(
|
||||
onBackPress = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
|
||||
composable(Screen.AddonManager.route) {
|
||||
AddonManagerScreen()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ sealed class Screen(val route: String) {
|
|||
data object Library : Screen("library")
|
||||
data object Settings : Screen("settings")
|
||||
data object TmdbSettings : Screen("tmdb_settings")
|
||||
data object ThemeSettings : Screen("theme_settings")
|
||||
data object AddonManager : Screen("addon_manager")
|
||||
data object Plugins : Screen("plugins")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ fun SeasonTabs(
|
|||
),
|
||||
colors = CardDefaults.colors(
|
||||
containerColor = if (isSelected) NuvioColors.SurfaceVariant else NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.Primary
|
||||
focusedContainerColor = NuvioColors.Secondary
|
||||
),
|
||||
border = CardDefaults.border(
|
||||
focusedBorder = Border(
|
||||
|
|
@ -160,7 +160,7 @@ private fun EpisodeCard(
|
|||
),
|
||||
colors = CardDefaults.colors(
|
||||
containerColor = NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.BackgroundCard
|
||||
focusedContainerColor = NuvioColors.FocusBackground
|
||||
),
|
||||
border = CardDefaults.border(
|
||||
focusedBorder = Border(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.nuvio.tv.ui.screens.detail
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
|
|
@ -23,6 +24,7 @@ import androidx.compose.ui.focus.onFocusChanged
|
|||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.Button
|
||||
import androidx.tv.material3.ButtonDefaults
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
|
|
@ -164,13 +166,19 @@ private fun PlayButton(
|
|||
.onFocusChanged { isFocused = it.isFocused },
|
||||
colors = ButtonDefaults.colors(
|
||||
containerColor = androidx.compose.ui.graphics.Color.White,
|
||||
focusedContainerColor = androidx.compose.ui.graphics.Color(0xFFD0D0D0),
|
||||
focusedContainerColor = androidx.compose.ui.graphics.Color.White,
|
||||
contentColor = androidx.compose.ui.graphics.Color.Black,
|
||||
focusedContentColor = androidx.compose.ui.graphics.Color.Black
|
||||
),
|
||||
shape = ButtonDefaults.shape(
|
||||
shape = RoundedCornerShape(32.dp)
|
||||
),
|
||||
border = ButtonDefaults.border(
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(2.dp, NuvioColors.FocusRing),
|
||||
shape = RoundedCornerShape(32.dp)
|
||||
)
|
||||
),
|
||||
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 14.dp)
|
||||
) {
|
||||
Row(
|
||||
|
|
@ -206,10 +214,16 @@ private fun ActionIconButton(
|
|||
.onFocusChanged { isFocused = it.isFocused },
|
||||
colors = IconButtonDefaults.colors(
|
||||
containerColor = NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.Primary,
|
||||
focusedContainerColor = NuvioColors.Secondary,
|
||||
contentColor = NuvioColors.TextPrimary,
|
||||
focusedContentColor = NuvioColors.OnPrimary
|
||||
),
|
||||
border = IconButtonDefaults.border(
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(2.dp, NuvioColors.FocusRing),
|
||||
shape = CircleShape
|
||||
)
|
||||
),
|
||||
shape = IconButtonDefaults.shape(
|
||||
shape = CircleShape
|
||||
)
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ private fun LibraryTabs(
|
|||
shape = CardDefaults.shape(shape = RoundedCornerShape(20.dp)),
|
||||
colors = CardDefaults.colors(
|
||||
containerColor = if (isSelected) NuvioColors.SurfaceVariant else NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.Primary
|
||||
focusedContainerColor = NuvioColors.Secondary
|
||||
),
|
||||
border = CardDefaults.border(
|
||||
focusedBorder = Border(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.activity.compose.BackHandler
|
|||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
|
|
@ -54,6 +55,7 @@ import androidx.compose.ui.unit.sp
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.foundation.lazy.list.TvLazyColumn
|
||||
import androidx.tv.foundation.lazy.list.items
|
||||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.Button
|
||||
import androidx.tv.material3.ButtonDefaults
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
|
|
@ -265,8 +267,16 @@ private fun PluginHeader(
|
|||
Button(
|
||||
onClick = onAddRepository,
|
||||
colors = ButtonDefaults.colors(
|
||||
containerColor = NuvioColors.Primary,
|
||||
contentColor = Color.White
|
||||
containerColor = NuvioColors.Secondary,
|
||||
focusedContainerColor = NuvioColors.SecondaryVariant,
|
||||
contentColor = Color.White,
|
||||
focusedContentColor = Color.White
|
||||
),
|
||||
border = ButtonDefaults.border(
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(2.dp, NuvioColors.FocusRing),
|
||||
shape = RoundedCornerShape(50)
|
||||
)
|
||||
)
|
||||
) {
|
||||
Icon(
|
||||
|
|
@ -296,9 +306,15 @@ private fun RepositoryCard(
|
|||
.fillMaxWidth()
|
||||
.onFocusChanged { isFocused = it.isFocused },
|
||||
colors = ClickableSurfaceDefaults.colors(
|
||||
containerColor = if (isFocused) NuvioColors.FocusBackground else NuvioColors.BackgroundCard,
|
||||
containerColor = NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.FocusBackground
|
||||
),
|
||||
border = ClickableSurfaceDefaults.border(
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(2.dp, NuvioColors.FocusRing),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
)
|
||||
),
|
||||
shape = ClickableSurfaceDefaults.shape(RoundedCornerShape(12.dp))
|
||||
) {
|
||||
Row(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package com.nuvio.tv.ui.screens.settings
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
|
@ -19,6 +20,7 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.filled.ArrowForward
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material.icons.filled.Palette
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material.icons.filled.Tune
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -32,6 +34,7 @@ import androidx.compose.ui.focus.onFocusChanged
|
|||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.foundation.lazy.list.TvLazyColumn
|
||||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.Card
|
||||
import androidx.tv.material3.CardDefaults
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
|
|
@ -43,7 +46,8 @@ import com.nuvio.tv.ui.theme.NuvioColors
|
|||
@Composable
|
||||
fun SettingsScreen(
|
||||
onNavigateToPlugins: () -> Unit = {},
|
||||
onNavigateToTmdb: () -> Unit = {}
|
||||
onNavigateToTmdb: () -> Unit = {},
|
||||
onNavigateToTheme: () -> Unit = {}
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
|
@ -73,6 +77,15 @@ fun SettingsScreen(
|
|||
contentPadding = PaddingValues(bottom = 32.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
item {
|
||||
SettingsItem(
|
||||
icon = Icons.Default.Palette,
|
||||
title = "Appearance",
|
||||
subtitle = "Choose your color theme",
|
||||
onClick = onNavigateToTheme
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
SettingsItem(
|
||||
icon = Icons.Default.Build,
|
||||
|
|
@ -90,7 +103,7 @@ fun SettingsScreen(
|
|||
onClick = onNavigateToTmdb
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
item {
|
||||
SettingsItem(
|
||||
icon = Icons.Default.Settings,
|
||||
|
|
@ -127,7 +140,14 @@ private fun SettingsItem(
|
|||
.fillMaxWidth()
|
||||
.onFocusChanged { isFocused = it.isFocused },
|
||||
colors = CardDefaults.colors(
|
||||
containerColor = if (isFocused) NuvioColors.FocusBackground else NuvioColors.BackgroundCard
|
||||
containerColor = NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.FocusBackground
|
||||
),
|
||||
border = CardDefaults.border(
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(2.dp, NuvioColors.FocusRing),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
)
|
||||
),
|
||||
shape = CardDefaults.shape(RoundedCornerShape(12.dp))
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
@file:OptIn(ExperimentalTvMaterial3Api::class)
|
||||
|
||||
package com.nuvio.tv.ui.screens.settings
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
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.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.foundation.lazy.grid.TvGridCells
|
||||
import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid
|
||||
import androidx.tv.foundation.lazy.grid.items
|
||||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.Card
|
||||
import androidx.tv.material3.CardDefaults
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.nuvio.tv.domain.model.AppTheme
|
||||
import com.nuvio.tv.ui.theme.NuvioColors
|
||||
import com.nuvio.tv.ui.theme.ThemeColors
|
||||
|
||||
@Composable
|
||||
fun ThemeSettingsScreen(
|
||||
viewModel: ThemeSettingsViewModel = hiltViewModel(),
|
||||
onBackPress: () -> Unit
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
|
||||
BackHandler { onBackPress() }
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(NuvioColors.Background)
|
||||
.padding(horizontal = 48.dp, vertical = 24.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "Appearance",
|
||||
style = MaterialTheme.typography.headlineLarge,
|
||||
color = NuvioColors.TextPrimary
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text(
|
||||
text = "Choose your color theme",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = NuvioColors.TextSecondary
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
|
||||
TvLazyVerticalGrid(
|
||||
columns = TvGridCells.Fixed(3),
|
||||
contentPadding = PaddingValues(bottom = 32.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||
) {
|
||||
items(uiState.availableThemes) { theme ->
|
||||
ThemeCard(
|
||||
theme = theme,
|
||||
isSelected = theme == uiState.selectedTheme,
|
||||
onClick = { viewModel.onEvent(ThemeSettingsEvent.SelectTheme(theme)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ThemeCard(
|
||||
theme: AppTheme,
|
||||
isSelected: Boolean,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
var isFocused by remember { mutableStateOf(false) }
|
||||
val palette = ThemeColors.getColorPalette(theme)
|
||||
|
||||
Card(
|
||||
onClick = onClick,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.onFocusChanged { isFocused = it.isFocused },
|
||||
colors = CardDefaults.colors(
|
||||
containerColor = NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = palette.focusBackground
|
||||
),
|
||||
border = CardDefaults.border(
|
||||
border = if (isSelected) Border(
|
||||
border = BorderStroke(2.dp, palette.focusRing),
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) else Border.None,
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(2.dp, palette.focusRing),
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
)
|
||||
),
|
||||
shape = CardDefaults.shape(RoundedCornerShape(16.dp)),
|
||||
scale = CardDefaults.scale(focusedScale = 1.05f)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(20.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
// Color preview circle
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(64.dp)
|
||||
.clip(CircleShape)
|
||||
.background(palette.secondary),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (isSelected) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = "Selected",
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Text(
|
||||
text = theme.displayName,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = if (isFocused || isSelected) NuvioColors.TextPrimary else NuvioColors.TextSecondary
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
// Color bar showing the theme colors
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(4.dp)
|
||||
.clip(RoundedCornerShape(2.dp))
|
||||
.background(palette.focusRing)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.nuvio.tv.ui.screens.settings
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.nuvio.tv.data.local.ThemeDataStore
|
||||
import com.nuvio.tv.domain.model.AppTheme
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
data class ThemeSettingsUiState(
|
||||
val selectedTheme: AppTheme = AppTheme.CRIMSON,
|
||||
val availableThemes: List<AppTheme> = AppTheme.entries
|
||||
)
|
||||
|
||||
sealed class ThemeSettingsEvent {
|
||||
data class SelectTheme(val theme: AppTheme) : ThemeSettingsEvent()
|
||||
}
|
||||
|
||||
@HiltViewModel
|
||||
class ThemeSettingsViewModel @Inject constructor(
|
||||
private val themeDataStore: ThemeDataStore
|
||||
) : ViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(ThemeSettingsUiState())
|
||||
val uiState: StateFlow<ThemeSettingsUiState> = _uiState.asStateFlow()
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
themeDataStore.selectedTheme.collectLatest { theme ->
|
||||
_uiState.update { it.copy(selectedTheme = theme) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onEvent(event: ThemeSettingsEvent) {
|
||||
when (event) {
|
||||
is ThemeSettingsEvent.SelectTheme -> selectTheme(event.theme)
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectTheme(theme: AppTheme) {
|
||||
viewModelScope.launch {
|
||||
themeDataStore.setTheme(theme)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
package com.nuvio.tv.ui.screens.settings
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
|
@ -28,6 +29,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.foundation.lazy.list.TvLazyColumn
|
||||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.Card
|
||||
import androidx.tv.material3.CardDefaults
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
|
|
@ -171,7 +173,14 @@ private fun ToggleCard(
|
|||
.fillMaxWidth()
|
||||
.onFocusChanged { isFocused = it.isFocused },
|
||||
colors = CardDefaults.colors(
|
||||
containerColor = if (isFocused) NuvioColors.FocusBackground else NuvioColors.BackgroundCard
|
||||
containerColor = NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.FocusBackground
|
||||
),
|
||||
border = CardDefaults.border(
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(2.dp, NuvioColors.FocusRing),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
)
|
||||
),
|
||||
shape = CardDefaults.shape(RoundedCornerShape(12.dp))
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -497,7 +497,13 @@ private fun ErrorState(
|
|||
modifier = Modifier.onFocusChanged { isFocused = it.isFocused },
|
||||
colors = CardDefaults.colors(
|
||||
containerColor = NuvioColors.BackgroundCard,
|
||||
focusedContainerColor = NuvioColors.Primary
|
||||
focusedContainerColor = NuvioColors.Secondary
|
||||
),
|
||||
border = CardDefaults.border(
|
||||
focusedBorder = Border(
|
||||
border = BorderStroke(2.dp, NuvioColors.FocusRing),
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
)
|
||||
),
|
||||
shape = CardDefaults.shape(shape = RoundedCornerShape(8.dp))
|
||||
) {
|
||||
|
|
@ -583,7 +589,7 @@ private fun StreamCard(
|
|||
)
|
||||
),
|
||||
shape = CardDefaults.shape(shape = RoundedCornerShape(12.dp)),
|
||||
scale = CardDefaults.scale(focusedScale = 1.02f)
|
||||
scale = CardDefaults.scale(focusedScale = 1.05f)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -1,42 +1,122 @@
|
|||
package com.nuvio.tv.ui.theme
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.nuvio.tv.domain.model.AppTheme
|
||||
|
||||
object NuvioColors {
|
||||
// Primary Background - Deep charcoal (NO gradients)
|
||||
val Background = Color(0xFF0D0D0D)
|
||||
val BackgroundElevated = Color(0xFF1A1A1A)
|
||||
val BackgroundCard = Color(0xFF242424)
|
||||
/**
|
||||
* Dynamic color scheme that changes based on selected theme.
|
||||
* Background colors have subtle theme tinting.
|
||||
* Accent colors (secondary, focus) change per theme.
|
||||
*/
|
||||
class NuvioColorScheme(palette: ThemeColorPalette) {
|
||||
// Primary Background - Theme dependent with subtle tinting
|
||||
val Background = palette.background
|
||||
val BackgroundElevated = palette.backgroundElevated
|
||||
val BackgroundCard = palette.backgroundCard
|
||||
|
||||
// Surface colors
|
||||
// Surface colors (constant)
|
||||
val Surface = Color(0xFF1E1E1E)
|
||||
val SurfaceVariant = Color(0xFF2D2D2D)
|
||||
|
||||
// Primary accent - Neutral Grey
|
||||
// Primary accent - Neutral Grey (constant)
|
||||
val Primary = Color(0xFF9E9E9E)
|
||||
val PrimaryVariant = Color(0xFF6F6F6F)
|
||||
val OnPrimary = Color(0xFFFFFFFF)
|
||||
|
||||
// Secondary accent - Teal
|
||||
val Secondary = Color(0xFF00BFA6)
|
||||
val SecondaryVariant = Color(0xFF008F7A)
|
||||
// Secondary accent - Theme dependent
|
||||
val Secondary = palette.secondary
|
||||
val SecondaryVariant = palette.secondaryVariant
|
||||
|
||||
// Text colors
|
||||
// Text colors (constant)
|
||||
val TextPrimary = Color(0xFFFFFFFF)
|
||||
val TextSecondary = Color(0xFFB3B3B3)
|
||||
val TextTertiary = Color(0xFF808080)
|
||||
val TextDisabled = Color(0xFF4D4D4D)
|
||||
|
||||
// Focus states - Critical for TV navigation
|
||||
val FocusRing = Color(0xFF00E5CC) // Bright teal for high visibility
|
||||
val FocusBackground = Color(0xFF1A3D38) // Dark teal background
|
||||
// Focus states - Theme dependent
|
||||
val FocusRing = palette.focusRing
|
||||
val FocusBackground = palette.focusBackground
|
||||
|
||||
// Status colors
|
||||
// Status colors (constant)
|
||||
val Rating = Color(0xFFFFD700)
|
||||
val Error = Color(0xFFCF6679)
|
||||
val Success = Color(0xFF4CAF50)
|
||||
|
||||
// Borders
|
||||
val Border = Color(0xFF333333)
|
||||
val BorderFocused = Color(0xFF00E5CC) // Bright teal for high visibility
|
||||
val BorderFocused = palette.focusRing
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy NuvioColors object for backwards compatibility.
|
||||
* Components should migrate to using NuvioTheme.colors instead.
|
||||
* This object provides the current theme's colors via composition local.
|
||||
*/
|
||||
object NuvioColors {
|
||||
// Dynamic background colors - Theme dependent with subtle tinting
|
||||
val Background: Color
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = NuvioTheme.colors.Background
|
||||
|
||||
val BackgroundElevated: Color
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = NuvioTheme.colors.BackgroundElevated
|
||||
|
||||
val BackgroundCard: Color
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = NuvioTheme.colors.BackgroundCard
|
||||
|
||||
// Surface colors (constant)
|
||||
val Surface = Color(0xFF1E1E1E)
|
||||
val SurfaceVariant = Color(0xFF2D2D2D)
|
||||
|
||||
// Primary accent - Neutral Grey (constant)
|
||||
val Primary = Color(0xFF9E9E9E)
|
||||
val PrimaryVariant = Color(0xFF6F6F6F)
|
||||
val OnPrimary = Color(0xFFFFFFFF)
|
||||
|
||||
// Text colors (constant)
|
||||
val TextPrimary = Color(0xFFFFFFFF)
|
||||
val TextSecondary = Color(0xFFB3B3B3)
|
||||
val TextTertiary = Color(0xFF808080)
|
||||
val TextDisabled = Color(0xFF4D4D4D)
|
||||
|
||||
// Status colors (constant)
|
||||
val Rating = Color(0xFFFFD700)
|
||||
val Error = Color(0xFFCF6679)
|
||||
val Success = Color(0xFF4CAF50)
|
||||
|
||||
// Borders (non-focus constant)
|
||||
val Border = Color(0xFF333333)
|
||||
|
||||
// Dynamic accent colors - Theme dependent
|
||||
val Secondary: Color
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = NuvioTheme.colors.Secondary
|
||||
|
||||
val SecondaryVariant: Color
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = NuvioTheme.colors.SecondaryVariant
|
||||
|
||||
val FocusRing: Color
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = NuvioTheme.colors.FocusRing
|
||||
|
||||
val FocusBackground: Color
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = NuvioTheme.colors.FocusBackground
|
||||
|
||||
val BorderFocused: Color
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = NuvioTheme.colors.BorderFocused
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@ package com.nuvio.tv.ui.theme
|
|||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.darkColorScheme
|
||||
import com.nuvio.tv.domain.model.AppTheme
|
||||
|
||||
data class NuvioExtendedColors(
|
||||
val backgroundElevated: Color,
|
||||
|
|
@ -19,48 +21,62 @@ data class NuvioExtendedColors(
|
|||
)
|
||||
|
||||
val LocalNuvioColors = staticCompositionLocalOf {
|
||||
NuvioColorScheme(ThemeColors.Crimson)
|
||||
}
|
||||
|
||||
val LocalNuvioExtendedColors = staticCompositionLocalOf {
|
||||
NuvioExtendedColors(
|
||||
backgroundElevated = NuvioColors.BackgroundElevated,
|
||||
backgroundCard = NuvioColors.BackgroundCard,
|
||||
textSecondary = NuvioColors.TextSecondary,
|
||||
textTertiary = NuvioColors.TextTertiary,
|
||||
focusRing = NuvioColors.FocusRing,
|
||||
focusBackground = NuvioColors.FocusBackground,
|
||||
rating = NuvioColors.Rating
|
||||
backgroundElevated = Color(0xFF1A1A1A),
|
||||
backgroundCard = Color(0xFF242424),
|
||||
textSecondary = Color(0xFFB3B3B3),
|
||||
textTertiary = Color(0xFF808080),
|
||||
focusRing = ThemeColors.Crimson.focusRing,
|
||||
focusBackground = ThemeColors.Crimson.focusBackground,
|
||||
rating = Color(0xFFFFD700)
|
||||
)
|
||||
}
|
||||
|
||||
val LocalAppTheme = staticCompositionLocalOf { AppTheme.CRIMSON }
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun NuvioTheme(
|
||||
appTheme: AppTheme = AppTheme.CRIMSON,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val colorScheme = darkColorScheme(
|
||||
primary = NuvioColors.Primary,
|
||||
onPrimary = NuvioColors.OnPrimary,
|
||||
secondary = NuvioColors.Secondary,
|
||||
background = NuvioColors.Background,
|
||||
surface = NuvioColors.Surface,
|
||||
surfaceVariant = NuvioColors.SurfaceVariant,
|
||||
onBackground = NuvioColors.TextPrimary,
|
||||
onSurface = NuvioColors.TextPrimary,
|
||||
onSurfaceVariant = NuvioColors.TextSecondary,
|
||||
error = NuvioColors.Error
|
||||
val palette = ThemeColors.getColorPalette(appTheme)
|
||||
val colorScheme = NuvioColorScheme(palette)
|
||||
|
||||
val materialColorScheme = darkColorScheme(
|
||||
primary = colorScheme.Primary,
|
||||
onPrimary = colorScheme.OnPrimary,
|
||||
secondary = colorScheme.Secondary,
|
||||
background = colorScheme.Background,
|
||||
surface = colorScheme.Surface,
|
||||
surfaceVariant = colorScheme.SurfaceVariant,
|
||||
onBackground = colorScheme.TextPrimary,
|
||||
onSurface = colorScheme.TextPrimary,
|
||||
onSurfaceVariant = colorScheme.TextSecondary,
|
||||
error = colorScheme.Error
|
||||
)
|
||||
|
||||
val extendedColors = NuvioExtendedColors(
|
||||
backgroundElevated = NuvioColors.BackgroundElevated,
|
||||
backgroundCard = NuvioColors.BackgroundCard,
|
||||
textSecondary = NuvioColors.TextSecondary,
|
||||
textTertiary = NuvioColors.TextTertiary,
|
||||
focusRing = NuvioColors.FocusRing,
|
||||
focusBackground = NuvioColors.FocusBackground,
|
||||
rating = NuvioColors.Rating
|
||||
backgroundElevated = colorScheme.BackgroundElevated,
|
||||
backgroundCard = colorScheme.BackgroundCard,
|
||||
textSecondary = colorScheme.TextSecondary,
|
||||
textTertiary = colorScheme.TextTertiary,
|
||||
focusRing = colorScheme.FocusRing,
|
||||
focusBackground = colorScheme.FocusBackground,
|
||||
rating = colorScheme.Rating
|
||||
)
|
||||
|
||||
CompositionLocalProvider(LocalNuvioColors provides extendedColors) {
|
||||
CompositionLocalProvider(
|
||||
LocalNuvioColors provides colorScheme,
|
||||
LocalNuvioExtendedColors provides extendedColors,
|
||||
LocalAppTheme provides appTheme
|
||||
) {
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
colorScheme = materialColorScheme,
|
||||
typography = NuvioTypography,
|
||||
content = content
|
||||
)
|
||||
|
|
@ -68,7 +84,18 @@ fun NuvioTheme(
|
|||
}
|
||||
|
||||
object NuvioTheme {
|
||||
val colors: NuvioColorScheme
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = LocalNuvioColors.current
|
||||
|
||||
val extendedColors: NuvioExtendedColors
|
||||
@Composable
|
||||
get() = LocalNuvioColors.current
|
||||
@ReadOnlyComposable
|
||||
get() = LocalNuvioExtendedColors.current
|
||||
|
||||
val currentTheme: AppTheme
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = LocalAppTheme.current
|
||||
}
|
||||
|
|
|
|||
93
app/src/main/java/com/nuvio/tv/ui/theme/ThemeColors.kt
Normal file
93
app/src/main/java/com/nuvio/tv/ui/theme/ThemeColors.kt
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package com.nuvio.tv.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.nuvio.tv.domain.model.AppTheme
|
||||
|
||||
/**
|
||||
* Color palette for each theme.
|
||||
* Includes both accent colors and background tints for full theme customization.
|
||||
*/
|
||||
data class ThemeColorPalette(
|
||||
val secondary: Color,
|
||||
val secondaryVariant: Color,
|
||||
val focusRing: Color,
|
||||
val focusBackground: Color,
|
||||
// Background colors with subtle theme tinting
|
||||
val background: Color = Color(0xFF0D0D0D),
|
||||
val backgroundElevated: Color = Color(0xFF1A1A1A),
|
||||
val backgroundCard: Color = Color(0xFF242424)
|
||||
)
|
||||
|
||||
object ThemeColors {
|
||||
|
||||
val Crimson = ThemeColorPalette(
|
||||
secondary = Color(0xFFE53935),
|
||||
secondaryVariant = Color(0xFFC62828),
|
||||
focusRing = Color(0xFFFF5252),
|
||||
focusBackground = Color(0xFF3D1A1A),
|
||||
background = Color(0xFF0D0D0D),
|
||||
backgroundElevated = Color(0xFF1A1A1A),
|
||||
backgroundCard = Color(0xFF241A1A) // Warm red tint
|
||||
)
|
||||
|
||||
val Ocean = ThemeColorPalette(
|
||||
secondary = Color(0xFF1E88E5),
|
||||
secondaryVariant = Color(0xFF1565C0),
|
||||
focusRing = Color(0xFF42A5F5),
|
||||
focusBackground = Color(0xFF1A2D3D),
|
||||
background = Color(0xFF0D0D0F), // Cool blue tint
|
||||
backgroundElevated = Color(0xFF1A1A1E),
|
||||
backgroundCard = Color(0xFF1A1F24)
|
||||
)
|
||||
|
||||
val Violet = ThemeColorPalette(
|
||||
secondary = Color(0xFF8E24AA),
|
||||
secondaryVariant = Color(0xFF6A1B9A),
|
||||
focusRing = Color(0xFFAB47BC),
|
||||
focusBackground = Color(0xFF2D1A3D),
|
||||
background = Color(0xFF0D0D0F), // Purple tint
|
||||
backgroundElevated = Color(0xFF1A1A1E),
|
||||
backgroundCard = Color(0xFF1F1A24)
|
||||
)
|
||||
|
||||
val Emerald = ThemeColorPalette(
|
||||
secondary = Color(0xFF43A047),
|
||||
secondaryVariant = Color(0xFF2E7D32),
|
||||
focusRing = Color(0xFF66BB6A),
|
||||
focusBackground = Color(0xFF1A3D1E),
|
||||
background = Color(0xFF0D0D0D),
|
||||
backgroundElevated = Color(0xFF1A1A1A),
|
||||
backgroundCard = Color(0xFF1A241A) // Green tint
|
||||
)
|
||||
|
||||
val Amber = ThemeColorPalette(
|
||||
secondary = Color(0xFFFB8C00),
|
||||
secondaryVariant = Color(0xFFEF6C00),
|
||||
focusRing = Color(0xFFFFA726),
|
||||
focusBackground = Color(0xFF3D2D1A),
|
||||
background = Color(0xFF0F0D0D), // Warm amber tint
|
||||
backgroundElevated = Color(0xFF1E1A1A),
|
||||
backgroundCard = Color(0xFF24201A)
|
||||
)
|
||||
|
||||
val Rose = ThemeColorPalette(
|
||||
secondary = Color(0xFFD81B60),
|
||||
secondaryVariant = Color(0xFFC2185B),
|
||||
focusRing = Color(0xFFEC407A),
|
||||
focusBackground = Color(0xFF3D1A2D),
|
||||
background = Color(0xFF0D0D0D),
|
||||
backgroundElevated = Color(0xFF1A1A1A),
|
||||
backgroundCard = Color(0xFF241A1F) // Pink tint
|
||||
)
|
||||
|
||||
fun getColorPalette(theme: AppTheme): ThemeColorPalette {
|
||||
return when (theme) {
|
||||
AppTheme.CRIMSON -> Crimson
|
||||
AppTheme.OCEAN -> Ocean
|
||||
AppTheme.VIOLET -> Violet
|
||||
AppTheme.EMERALD -> Emerald
|
||||
AppTheme.AMBER -> Amber
|
||||
AppTheme.ROSE -> Rose
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue