Skip to content

Commit

Permalink
Feat: Custom Colors.
Browse files Browse the repository at this point in the history
  • Loading branch information
oxyroid committed Jun 1, 2024
1 parent 06aaf90 commit 05a4d22
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ data class ColorScheme(
val isDark: Boolean,
@ColumnInfo("name")
val name: String,
)
) {
companion object {
const val NAME_TEMP = "temp"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ fun SettingRoute(
val cacheSpace by viewModel.cacheSpace.collectAsStateWithLifecycle()

val sheetState = rememberModalBottomSheetState()
var colorInt: Int? by remember { mutableStateOf(null) }
var isDark: Boolean? by remember { mutableStateOf(null) }
var colorScheme: ColorScheme? by remember { mutableStateOf(null) }

val createDocumentLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("text/*")) { uri ->
Expand Down Expand Up @@ -113,10 +112,7 @@ fun SettingRoute(
backup = backup,
restore = restore,
colorSchemes = colorSchemes,
openColorCanvas = { c, i ->
colorInt = c
isDark = i
},
openColorCanvas = { colorScheme = it },
restoreSchemes = viewModel::restoreSchemes,
onClipboard = { viewModel.onClipboard(it) },
onClearCache = { viewModel.clearCache() },
Expand All @@ -135,11 +131,12 @@ fun SettingRoute(
if (!tv) {
CanvasBottomSheet(
sheetState = sheetState,
colorInt = colorInt,
isDark = isDark,
colorScheme = colorScheme,
onApplyColor = { argb, isDark ->
viewModel.applyColor(colorScheme, argb, isDark)
},
onDismissRequest = {
colorInt = null
isDark = null
colorScheme = null
}
)
}
Expand Down Expand Up @@ -169,7 +166,7 @@ private fun SettingScreen(
restore: () -> Unit,
onClipboard: (String) -> Unit,
colorSchemes: List<ColorScheme>,
openColorCanvas: (Int, Boolean) -> Unit,
openColorCanvas: (ColorScheme) -> Unit,
restoreSchemes: () -> Unit,
cacheSpace: DataUnit,
onClearCache: () -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class SettingViewModel @Inject constructor(
private val playlistRepository: PlaylistRepository,
private val streamRepository: StreamRepository,
private val workManager: WorkManager,
preferences: Preferences,
private val preferences: Preferences,
private val messager: Messager,
private val localService: LocalPreparedService,
private val playerManager: PlayerManager,
Expand Down Expand Up @@ -325,6 +325,28 @@ class SettingViewModel @Inject constructor(
}
}

@OptIn(ExperimentalStdlibApi::class)
internal fun applyColor(
prev: ColorScheme?,
argb: Int,
isDark: Boolean
) {
preferences.argb = argb
preferences.darkMode = isDark
viewModelScope.launch {
if (prev != null) {
colorSchemeDao.delete(prev)
}
colorSchemeDao.insert(
ColorScheme(
argb = argb,
isDark = isDark,
name = "#${argb.toHexString(HexFormat.UpperCase)}"
)
)
}
}

internal fun restoreSchemes() {
val schemes = ColorSchemeExample.schemes
viewModelScope.launch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.m3u.data.database.model.ColorScheme
import com.m3u.i18n.R.string
import com.m3u.material.components.Icon
import com.m3u.material.ktx.createScheme
Expand All @@ -47,14 +48,17 @@ import com.m3u.ui.FontFamilies
@Composable
internal fun CanvasBottomSheet(
sheetState: SheetState,
colorInt: Int?,
isDark: Boolean?,
colorScheme: ColorScheme?,
onApplyColor: (Int, Boolean) -> Unit,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier
) {
val spacing = LocalSpacing.current
if (colorInt != null && isDark != null) {
var currentColorInt: Int by remember(colorInt) { mutableIntStateOf(colorInt) }
val argb = colorScheme?.argb
val isDark = colorScheme?.isDark
val isTemp = colorScheme?.name == ColorScheme.NAME_TEMP
if (argb != null && isDark != null) {
var currentColorInt: Int by remember(argb) { mutableIntStateOf(argb) }
var currentIsDark: Boolean by remember(isDark) { mutableStateOf(isDark) }

val scheme by remember {
Expand All @@ -68,7 +72,6 @@ internal fun CanvasBottomSheet(
) {
ModalBottomSheet(
sheetState = sheetState,
// windowInsets = WindowInsets(0),
onDismissRequest = onDismissRequest,
) {
Column(
Expand Down Expand Up @@ -120,15 +123,18 @@ internal fun CanvasBottomSheet(
)

val hasChanged by remember {
derivedStateOf { currentColorInt != colorInt || currentIsDark != isDark }
derivedStateOf { isTemp || currentColorInt != argb || currentIsDark != isDark }
}
SingleChoiceSegmentedButtonRow(
modifier = Modifier.fillMaxWidth()
) {
SegmentedButton(
selected = false,
enabled = hasChanged,
onClick = { /*TODO*/ },
onClick = {
onApplyColor(currentColorInt, currentIsDark)
onDismissRequest()
},
shape = SegmentedButtonDefaults.itemShape(
baseShape = RoundedCornerShape(8.dp),
index = 0,
Expand All @@ -155,7 +161,7 @@ internal fun CanvasBottomSheet(
disabledInactiveContentColor = LocalContentColor.current.copy(0.38f)
),
onClick = {
currentColorInt = colorInt
currentColorInt = argb
currentIsDark = isDark
},
shape = SegmentedButtonDefaults.itemShape(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.m3u.features.setting.fragments

import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
Expand All @@ -19,6 +20,8 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.stringResource
import com.m3u.core.architecture.preferences.hiltPreferences
import com.m3u.core.util.basic.title
Expand All @@ -31,18 +34,16 @@ import com.m3u.material.components.ThemeSelection
import com.m3u.material.ktx.includeChildGlowPadding
import com.m3u.material.ktx.isTelevision
import com.m3u.material.ktx.textHorizontalLabel
import com.m3u.material.model.LocalSpacing

@Composable
internal fun AppearanceFragment(
colorSchemes: List<ColorScheme>,
colorArgb: Int,
openColorCanvas: (Int, Boolean) -> Unit,
openColorCanvas: (ColorScheme) -> Unit,
restoreSchemes: () -> Unit,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues()
) {
val spacing = LocalSpacing.current
val preferences = hiltPreferences()

val isDarkMode = preferences.darkMode
Expand All @@ -68,27 +69,38 @@ internal fun AppearanceFragment(
items(
items = colorSchemes,
key = { "${it.argb}_${it.isDark}" }
) { colorPack ->
) { colorScheme ->
val selected =
!useDynamicColors && colorArgb == colorPack.argb && isDarkMode == colorPack.isDark
!useDynamicColors && colorArgb == colorScheme.argb && isDarkMode == colorScheme.isDark
ThemeSelection(
argb = colorPack.argb,
isDark = colorPack.isDark,
argb = colorScheme.argb,
isDark = colorScheme.isDark,
selected = selected,
onClick = {
preferences.useDynamicColors = false
preferences.argb = colorPack.argb
preferences.darkMode = colorPack.isDark
preferences.argb = colorScheme.argb
preferences.darkMode = colorScheme.isDark
},
onLongClick = { openColorCanvas(colorPack.argb, colorPack.isDark) },
name = colorPack.name,
onLongClick = { openColorCanvas(colorScheme) },
name = colorScheme.name,
leftContentDescription = stringResource(string.ui_theme_card_left),
rightContentDescription = stringResource(string.ui_theme_card_right)
)
}
item {
val inDarkTheme = isSystemInDarkTheme()
ThemeAddSelection {

openColorCanvas(
ColorScheme(
argb = Color(
red = (0..0xFF).random(),
green = (0..0xFF).random(),
blue = (0..0xFF).random()
).toArgb(),
isDark = inDarkTheme,
name = ColorScheme.NAME_TEMP
)
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
Expand Down Expand Up @@ -39,6 +40,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.tv.material3.Border
Expand Down Expand Up @@ -127,10 +129,15 @@ fun ThemeSelection(
color = colorScheme.tertiaryContainer,
textAlign = TextAlign.Center,
fontWeight = FontWeight.SemiBold,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.fillMaxWidth()
.background(colorScheme.onTertiaryContainer)
.padding(vertical = 2.dp)
.basicMarquee(
iterations = if (selected) Int.MAX_VALUE else 0
)
.padding(2.dp)
)
}
}
Expand Down

0 comments on commit 05a4d22

Please sign in to comment.