diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt index f00ba72..6a618fe 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt @@ -1,10 +1,7 @@ package it.vfsfitvnm.vimusic import android.annotation.SuppressLint -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.content.ServiceConnection +import android.content.* import android.net.Uri import android.os.Bundle import android.os.IBinder @@ -27,9 +24,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.text.ExperimentalTextApi import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.valentinilk.shimmer.LocalShimmerTheme import com.valentinilk.shimmer.defaultShimmerTheme +import it.vfsfitvnm.vimusic.enums.ColorPaletteMode +import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness import it.vfsfitvnm.vimusic.service.PlayerService import it.vfsfitvnm.vimusic.ui.components.BottomSheetMenu import it.vfsfitvnm.vimusic.ui.components.LocalMenuState @@ -37,15 +37,11 @@ import it.vfsfitvnm.vimusic.ui.components.rememberBottomSheetState import it.vfsfitvnm.vimusic.ui.components.rememberMenuState import it.vfsfitvnm.vimusic.ui.screens.HomeScreen import it.vfsfitvnm.vimusic.ui.screens.IntentUriScreen +import it.vfsfitvnm.vimusic.ui.styling.Appearance import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography -import it.vfsfitvnm.vimusic.ui.styling.rememberTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.views.PlayerView -import it.vfsfitvnm.vimusic.utils.LocalPreferences -import it.vfsfitvnm.vimusic.utils.intent -import it.vfsfitvnm.vimusic.utils.rememberHapticFeedback -import it.vfsfitvnm.vimusic.utils.rememberPreferences +import it.vfsfitvnm.vimusic.utils.* class MainActivity : ComponentActivity() { @@ -75,30 +71,77 @@ class MainActivity : ComponentActivity() { } @SuppressLint("BatteryLife") - @OptIn(ExperimentalFoundationApi::class, ExperimentalAnimationApi::class) + @OptIn(ExperimentalFoundationApi::class, ExperimentalAnimationApi::class, + ExperimentalTextApi::class + ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) uri = intent?.data setContent { - val preferences = rememberPreferences() + val isSystemInDarkTheme = isSystemInDarkTheme() + + var appearance by remember(isSystemInDarkTheme) { + with(preferences) { + val colorPaletteMode = getEnum(colorPaletteModeKey, ColorPaletteMode.System) + val thumbnailRoundness = getEnum(thumbnailRoundnessKey, ThumbnailRoundness.Light) + + mutableStateOf( + Appearance( + colorPalette = colorPaletteMode.palette(isSystemInDarkTheme), + typography = colorPaletteMode.typography(isSystemInDarkTheme), + thumbnailShape = thumbnailRoundness.shape() + ) + ) + } + } + + DisposableEffect(isSystemInDarkTheme) { + val listener = + SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key -> + when (key) { + colorPaletteModeKey -> { + val colorPaletteMode = sharedPreferences.getEnum(key, ColorPaletteMode.System) + + appearance = appearance.copy( + colorPalette = colorPaletteMode.palette(isSystemInDarkTheme), + typography = colorPaletteMode.typography(isSystemInDarkTheme), + ) + } + thumbnailRoundnessKey -> { + val thumbnailRoundness = sharedPreferences.getEnum(key, ThumbnailRoundness.Light) + + appearance = appearance.copy( + thumbnailShape = thumbnailRoundness.shape() + ) + } + } + } + + with(preferences) { + registerOnSharedPreferenceChangeListener(listener) + + onDispose { + unregisterOnSharedPreferenceChangeListener(listener) + } + } + } + val systemUiController = rememberSystemUiController() - val colorPalette = preferences.colorPaletteMode.palette(isSystemInDarkTheme()) - - val rippleTheme = remember(colorPalette.text, colorPalette.isDark) { + val rippleTheme = remember(appearance.colorPalette.text, appearance.colorPalette.isDark) { object : RippleTheme { @Composable override fun defaultColor(): Color = RippleTheme.defaultRippleColor( - contentColor = colorPalette.text, - lightTheme = !colorPalette.isDark + contentColor = appearance.colorPalette.text, + lightTheme = !appearance.colorPalette.isDark ) @Composable override fun rippleAlpha(): RippleAlpha = RippleTheme.defaultRippleAlpha( - contentColor = colorPalette.text, - lightTheme = !colorPalette.isDark + contentColor = appearance.colorPalette.text, + lightTheme = !appearance.colorPalette.isDark ) } } @@ -122,17 +165,15 @@ class MainActivity : ComponentActivity() { } SideEffect { - systemUiController.setSystemBarsColor(colorPalette.background, !colorPalette.isDark) + systemUiController.setSystemBarsColor(appearance.colorPalette.background, !appearance.colorPalette.isDark) } CompositionLocalProvider( + LocalAppearance provides appearance, LocalOverscrollConfiguration provides null, LocalIndication provides rememberRipple(bounded = false), LocalRippleTheme provides rippleTheme, - LocalPreferences provides preferences, - LocalColorPalette provides colorPalette, LocalShimmerTheme provides shimmerTheme, - LocalTypography provides rememberTypography(colorPalette.text), LocalPlayerServiceBinder provides binder, LocalMenuState provides rememberMenuState(), LocalHapticFeedback provides rememberHapticFeedback() @@ -140,7 +181,7 @@ class MainActivity : ComponentActivity() { BoxWithConstraints( modifier = Modifier .fillMaxSize() - .background(colorPalette.background) + .background(appearance.colorPalette.background) ) { when (val uri = uri) { null -> { @@ -173,4 +214,4 @@ class MainActivity : ComponentActivity() { } } -val LocalPlayerServiceBinder = staticCompositionLocalOf { null } \ No newline at end of file +val LocalPlayerServiceBinder = staticCompositionLocalOf { null } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainApplication.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainApplication.kt index 17f3247..a7c82ca 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainApplication.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainApplication.kt @@ -4,7 +4,10 @@ import android.app.Application import coil.ImageLoader import coil.ImageLoaderFactory import coil.disk.DiskCache -import it.vfsfitvnm.vimusic.utils.Preferences +import it.vfsfitvnm.vimusic.enums.CoilDiskCacheMaxSize +import it.vfsfitvnm.vimusic.utils.coilDiskCacheMaxSizeKey +import it.vfsfitvnm.vimusic.utils.getEnum +import it.vfsfitvnm.vimusic.utils.preferences class MainApplication : Application(), ImageLoaderFactory { @@ -19,7 +22,7 @@ class MainApplication : Application(), ImageLoaderFactory { .diskCache( DiskCache.Builder() .directory(filesDir.resolve("coil")) - .maxSizeBytes(Preferences().coilDiskCacheMaxSize.bytes) + .maxSizeBytes(preferences.getEnum(coilDiskCacheMaxSizeKey, CoilDiskCacheMaxSize.`128MB`).bytes) .build() ) .build() diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ColorPaletteMode.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ColorPaletteMode.kt index 6f41f84..cd2e193 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ColorPaletteMode.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ColorPaletteMode.kt @@ -1,9 +1,20 @@ package it.vfsfitvnm.vimusic.enums +import androidx.compose.ui.text.ExperimentalTextApi +import androidx.compose.ui.text.PlatformTextStyle +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp +import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.ui.styling.BlackColorPalette import it.vfsfitvnm.vimusic.ui.styling.ColorPalette import it.vfsfitvnm.vimusic.ui.styling.DarkColorPalette import it.vfsfitvnm.vimusic.ui.styling.LightColorPalette +import it.vfsfitvnm.vimusic.ui.styling.Typography + enum class ColorPaletteMode { Light, @@ -22,4 +33,50 @@ enum class ColorPaletteMode { } } } + + @OptIn(ExperimentalTextApi::class) + fun typography(isSystemInDarkMode: Boolean): Typography { + val color = palette(isSystemInDarkMode).text + + val textStyle = TextStyle( + fontFamily = FontFamily( + Font( + resId = R.font.poppins_w300, + weight = FontWeight.Light + ), + Font( + resId = R.font.poppins_w400, + weight = FontWeight.Normal + ), + Font( + resId = R.font.poppins_w400_italic, + weight = FontWeight.Normal, + style = FontStyle.Italic + ), + Font( + resId = R.font.poppins_w500, + weight = FontWeight.Medium + ), + Font( + resId = R.font.poppins_w600, + weight = FontWeight.SemiBold + ), + Font( + resId = R.font.poppins_w700, + weight = FontWeight.Bold + ), + ), + fontWeight = FontWeight.Normal, + color = color, + platformStyle = @Suppress("DEPRECATION") PlatformTextStyle(includeFontPadding = false) + ) + + return Typography( + xxs = textStyle.copy(fontSize = 12.sp), + xs = textStyle.copy(fontSize = 14.sp), + s = textStyle.copy(fontSize = 16.sp), + m = textStyle.copy(fontSize = 18.sp), + l = textStyle.copy(fontSize = 20.sp), + ) + } } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ThumbnailRoundness.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ThumbnailRoundness.kt index 787841a..01bcb6e 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ThumbnailRoundness.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ThumbnailRoundness.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.dp -import it.vfsfitvnm.vimusic.utils.LocalPreferences +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance enum class ThumbnailRoundness { None, @@ -14,15 +14,19 @@ enum class ThumbnailRoundness { Medium, Heavy; + fun shape(): Shape { + return when (this) { + None -> RectangleShape + Light -> RoundedCornerShape(2.dp) + Medium -> RoundedCornerShape(4.dp) + Heavy -> RoundedCornerShape(8.dp) + } + } + companion object { val shape: Shape @Composable @ReadOnlyComposable - get() = when (LocalPreferences.current.thumbnailRoundness) { - None -> RectangleShape - Light -> RoundedCornerShape(2.dp) - Medium -> RoundedCornerShape(4.dp) - Heavy -> RoundedCornerShape(8.dp) - } + get() = LocalAppearance.current.thumbnailShape } } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/PlayerService.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/PlayerService.kt index 54f21f7..19e2bd5 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/PlayerService.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/PlayerService.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat.startForegroundService +import androidx.core.content.edit import androidx.core.content.getSystemService import androidx.core.net.toUri import androidx.media3.common.* @@ -116,17 +117,14 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene createNotificationChannel() - getSharedPreferences( - Preferences.fileName, - Context.MODE_PRIVATE - ).registerOnSharedPreferenceChangeListener(this) + preferences.registerOnSharedPreferenceChangeListener(this) - val preferences = Preferences() - isPersistentQueueEnabled = preferences.persistentQueue - isVolumeNormalizationEnabled = preferences.volumeNormalization - isInvincibilityEnabled = preferences.isInvincibilityEnabled + val preferences = preferences + isPersistentQueueEnabled = preferences.getBoolean(persistentQueueKey, false) + isVolumeNormalizationEnabled = preferences.getBoolean(volumeNormalizationKey, false) + isInvincibilityEnabled = preferences.getBoolean(isInvincibilityEnabledKey, false) - val cacheEvictor = when (val size = preferences.exoPlayerDiskCacheMaxSize) { + val cacheEvictor = when (val size = preferences.getEnum(exoPlayerDiskCacheMaxSizeKey, ExoPlayerDiskCacheMaxSize.`2GB`)) { ExoPlayerDiskCacheMaxSize.Unlimited -> NoOpCacheEvictor() else -> LeastRecentlyUsedCacheEvictor(size.bytes) } @@ -146,8 +144,8 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene .setUsePlatformDiagnostics(false) .build() - player.repeatMode = preferences.repeatMode - player.skipSilenceEnabled = preferences.skipSilence + player.repeatMode = preferences.getInt(repeatModeKey, Player.REPEAT_MODE_OFF) + player.skipSilenceEnabled = preferences.getBoolean(skipSilenceKey, false) player.addListener(this) player.addAnalyticsListener(PlaybackStatsListener(false, this)) @@ -184,10 +182,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene override fun onDestroy() { maybeSavePlayerQueue() - getSharedPreferences( - Preferences.fileName, - Context.MODE_PRIVATE - ).unregisterOnSharedPreferenceChangeListener(this) + preferences.unregisterOnSharedPreferenceChangeListener(this) player.removeListener(this) player.stop() @@ -289,14 +284,16 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene } private fun normalizeVolume() { - if (isVolumeNormalizationEnabled) { - player.volume = player.currentMediaItem?.let { mediaItem -> + player.volume = if (isVolumeNormalizationEnabled) { + player.currentMediaItem?.let { mediaItem -> songPendingLoudnessDb.getOrElse(mediaItem.mediaId) { mediaItem.mediaMetadata.extras?.getFloatOrNull("loudnessDb") }?.takeIf { it > 0 }?.let { loudnessDb -> (1f - (0.01f + loudnessDb / 14)).coerceIn(0.1f, 1f) } } ?: 1f + } else { + 1f } } @@ -309,6 +306,10 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene else -> PlaybackState.STATE_NONE } + override fun onRepeatModeChanged(repeatMode: Int) { + preferences.edit { putInt(repeatModeKey, repeatMode) } + } + override fun onEvents(player: Player, events: Player.Events) { if (player.duration != C.TIME_UNSET) { metadataBuilder @@ -362,12 +363,16 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { when (key) { - Preferences.Keys.persistentQueue -> isPersistentQueueEnabled = + persistentQueueKey -> isPersistentQueueEnabled = sharedPreferences.getBoolean(key, isPersistentQueueEnabled) - Preferences.Keys.volumeNormalization -> isVolumeNormalizationEnabled = - sharedPreferences.getBoolean(key, isVolumeNormalizationEnabled) - Preferences.Keys.isInvincibilityEnabled -> isInvincibilityEnabled = + volumeNormalizationKey -> { + isVolumeNormalizationEnabled = + sharedPreferences.getBoolean(key, isVolumeNormalizationEnabled) + normalizeVolume() + } + isInvincibilityEnabledKey -> isInvincibilityEnabled = sharedPreferences.getBoolean(key, isInvincibilityEnabled) + skipSilenceKey -> player.skipSilenceEnabled = sharedPreferences.getBoolean(key, false) } } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Dialog.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Dialog.kt index 9071430..abae40c 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Dialog.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Dialog.kt @@ -34,8 +34,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import it.vfsfitvnm.vimusic.ui.components.ChunkyButton -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.* import kotlinx.coroutines.delay @@ -56,8 +55,7 @@ fun TextFieldDialog( val focusRequester = remember { FocusRequester() } - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current var textFieldValue by rememberSaveable(initialTextInput, stateSaver = TextFieldValue.Saver) { mutableStateOf( @@ -162,8 +160,7 @@ fun ConfirmationDialog( confirmText: String = "Confirm", onCancel: () -> Unit = onDismiss ) { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current DefaultDialog( onDismiss = onDismiss, @@ -211,6 +208,8 @@ inline fun DefaultDialog( horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, crossinline content: @Composable ColumnScope.() -> Unit ) { + val (colorPalette) = LocalAppearance.current + Dialog( onDismissRequest = onDismiss, properties = DialogProperties(usePlatformDefaultWidth = false) @@ -220,7 +219,7 @@ inline fun DefaultDialog( modifier = modifier .padding(all = 48.dp) .background( - color = LocalColorPalette.current.elevatedBackground, + color = colorPalette.elevatedBackground, shape = RoundedCornerShape(8.dp) ) .padding(horizontal = 24.dp, vertical = 16.dp), @@ -240,15 +239,14 @@ inline fun ValueSelectorDialog( modifier: Modifier = Modifier, crossinline valueText: (T) -> String = { it.toString() } ) { - val typography = LocalTypography.current - val colorPalette = LocalColorPalette.current + val (colorPalette, typography) = LocalAppearance.current Dialog(onDismissRequest = onDismiss) { Column( modifier = modifier .padding(all = 48.dp) .background( - color = LocalColorPalette.current.elevatedBackground, + color = colorPalette.elevatedBackground, shape = RoundedCornerShape(8.dp) ) .padding(vertical = 16.dp), diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt index 2d8bae9..7495f30 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt @@ -31,8 +31,7 @@ import it.vfsfitvnm.vimusic.ui.components.Pager import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute import it.vfsfitvnm.vimusic.ui.screens.rememberCreatePlaylistRoute -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.* import it.vfsfitvnm.youtubemusic.models.NavigationEndpoint import kotlinx.coroutines.Dispatchers @@ -371,8 +370,7 @@ fun MediaItemMenu( onSetSleepTimer?.let { onSetSleepTimer -> val binder = LocalPlayerServiceBinder.current - val typography = LocalTypography.current - val colorPalette = LocalColorPalette.current + val (colorPalette, typography) = LocalAppearance.current var isShowingSleepTimerDialog by remember { mutableStateOf(false) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Menu.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Menu.kt index b00fd80..ba82a3e 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Menu.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Menu.kt @@ -16,8 +16,7 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import it.vfsfitvnm.vimusic.R -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.medium import it.vfsfitvnm.vimusic.utils.secondary @@ -27,7 +26,7 @@ inline fun Menu( modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit ) { - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current Column( modifier = modifier @@ -52,8 +51,7 @@ fun MenuEntry( secondaryText: String? = null, isEnabled: Boolean = true, ) { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current Row( verticalAlignment = Alignment.CenterVertically, @@ -99,7 +97,7 @@ fun MenuIconButton( onClick: () -> Unit, modifier: Modifier = Modifier ) { - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current Box( modifier = modifier diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Switch.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Switch.kt index 1573026..3185962 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Switch.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Switch.kt @@ -16,7 +16,7 @@ import androidx.compose.ui.geometry.center import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shadow import androidx.compose.ui.unit.dp -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.drawCircle @@ -25,7 +25,7 @@ fun Switch( isChecked: Boolean, modifier: Modifier = Modifier, ) { - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current val backgroundColor by animateColorAsState(if (isChecked) colorPalette.primaryContainer else colorPalette.lightBackground) val color by animateColorAsState(if (isChecked) colorPalette.onPrimaryContainer else colorPalette.textDisabled) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt index 5097910..e538811 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt @@ -17,8 +17,7 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.align import it.vfsfitvnm.vimusic.utils.secondary import it.vfsfitvnm.vimusic.utils.semiBold @@ -32,7 +31,7 @@ fun TextCard( onClick: (() -> Unit)? = null, content: @Composable TextCardScope.() -> Unit, ) { - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current Column( modifier = modifier @@ -72,17 +71,19 @@ interface TextCardScope { private object TextCardScopeImpl : TextCardScope { @Composable override fun Title(text: String) { + val (_, typography) = LocalAppearance.current BasicText( text = text, - style = LocalTypography.current.xxs.semiBold, + style = typography.xxs.semiBold, ) } @Composable override fun Text(text: String) { + val (_, typography) = LocalAppearance.current BasicText( text = text, - style = LocalTypography.current.xxs.secondary.align(TextAlign.Justify), + style = typography.xxs.secondary.align(TextAlign.Justify), ) } } @@ -90,9 +91,10 @@ private object TextCardScopeImpl : TextCardScope { private object IconTextCardScopeImpl : TextCardScope { @Composable override fun Title(text: String) { + val (_, typography) = LocalAppearance.current BasicText( text = text, - style = LocalTypography.current.xxs.semiBold, + style = typography.xxs.semiBold, modifier = Modifier .padding(horizontal = 16.dp) ) @@ -100,9 +102,10 @@ private object IconTextCardScopeImpl : TextCardScope { @Composable override fun Text(text: String) { + val (_, typography) = LocalAppearance.current BasicText( text = text, - style = LocalTypography.current.xxs.secondary, + style = typography.xxs.secondary, modifier = Modifier .padding(horizontal = 16.dp) ) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextPlaceholder.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextPlaceholder.kt index 682d03f..0f99173 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextPlaceholder.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextPlaceholder.kt @@ -10,20 +10,18 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import kotlin.random.Random @Composable fun TextPlaceholder( modifier: Modifier = Modifier ) { + val (colorPalette) = LocalAppearance.current Spacer( modifier = modifier .padding(vertical = 4.dp) - .background( - color = LocalColorPalette.current.darkGray, - shape = RoundedCornerShape(0.dp) - ) + .background(color = colorPalette.darkGray, shape = RoundedCornerShape(0.dp)) .fillMaxWidth(remember { 0.25f + Random.nextFloat() * 0.5f }) .height(16.dp) ) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/AlbumScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/AlbumScreen.kt index ec93325..1ad00da 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/AlbumScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/AlbumScreen.kt @@ -28,16 +28,17 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import it.vfsfitvnm.route.RouteHandler -import it.vfsfitvnm.vimusic.* +import it.vfsfitvnm.vimusic.Database +import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness import it.vfsfitvnm.vimusic.models.* +import it.vfsfitvnm.vimusic.query import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.* import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem import it.vfsfitvnm.vimusic.utils.* @@ -90,8 +91,7 @@ fun AlbumScreen( val context = LocalContext.current val binder = LocalPlayerServiceBinder.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val menuState = LocalMenuState.current @@ -356,6 +356,8 @@ private fun LoadingOrError( errorMessage: String? = null, onRetry: (() -> Unit)? = null ) { + val (colorPalette) = LocalAppearance.current + LoadingOrError( errorMessage = errorMessage, onRetry = onRetry @@ -369,7 +371,7 @@ private fun LoadingOrError( ) { Spacer( modifier = Modifier - .background(color = LocalColorPalette.current.darkGray, shape = ThumbnailRoundness.shape) + .background(color = colorPalette.darkGray, shape = ThumbnailRoundness.shape) .size(Dimensions.thumbnails.album) ) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt index 113cb26..3a26826 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt @@ -36,10 +36,7 @@ import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu import it.vfsfitvnm.vimusic.ui.components.themed.LoadingOrError import it.vfsfitvnm.vimusic.ui.components.themed.TextCard import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder -import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography -import it.vfsfitvnm.vimusic.ui.styling.px +import it.vfsfitvnm.vimusic.ui.styling.* import it.vfsfitvnm.vimusic.ui.views.SongItem import it.vfsfitvnm.vimusic.utils.* import it.vfsfitvnm.youtubemusic.YouTube @@ -77,8 +74,7 @@ fun ArtistScreen( host { val binder = LocalPlayerServiceBinder.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val artistResult by remember(browseId) { Database.artist(browseId).map { artist -> @@ -294,7 +290,7 @@ private fun LoadingOrError( errorMessage: String? = null, onRetry: (() -> Unit)? = null ) { - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current LoadingOrError( errorMessage = errorMessage, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/BuiltInPlaylistScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/BuiltInPlaylistScreen.kt index 76c2966..0447756 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/BuiltInPlaylistScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/BuiltInPlaylistScreen.kt @@ -29,10 +29,7 @@ import it.vfsfitvnm.vimusic.models.DetailedSong import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.* -import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography -import it.vfsfitvnm.vimusic.ui.styling.px +import it.vfsfitvnm.vimusic.ui.styling.* import it.vfsfitvnm.vimusic.ui.views.SongItem import it.vfsfitvnm.vimusic.utils.* import kotlinx.coroutines.Dispatchers @@ -66,8 +63,7 @@ fun BuiltInPlaylistScreen( val menuState = LocalMenuState.current val binder = LocalPlayerServiceBinder.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val thumbnailSize = Dimensions.thumbnails.song.px diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/HomeScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/HomeScreen.kt index 6105fa2..0c8d830 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/HomeScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/HomeScreen.kt @@ -50,10 +50,7 @@ import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.DropdownMenu import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog -import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography -import it.vfsfitvnm.vimusic.ui.styling.px +import it.vfsfitvnm.vimusic.ui.styling.* import it.vfsfitvnm.vimusic.ui.views.PlaylistPreviewItem import it.vfsfitvnm.vimusic.ui.views.SongItem import it.vfsfitvnm.vimusic.utils.* @@ -64,8 +61,7 @@ import kotlinx.coroutines.Dispatchers @ExperimentalAnimationApi @Composable fun HomeScreen() { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val lazyListState = rememberLazyListState() @@ -82,10 +78,11 @@ fun HomeScreen() { Database.playlistPreviews() }.collectAsState(initial = emptyList(), context = Dispatchers.IO) - val preferences = LocalPreferences.current + var songSortBy by rememberPreference(songSortByKey, SongSortBy.DateAdded) + var songSortOrder by rememberPreference(songSortOrderKey, SortOrder.Descending) - val songCollection by remember(preferences.songSortBy, preferences.songSortOrder) { - Database.songs(preferences.songSortBy, preferences.songSortOrder) + val songCollection by remember(songSortBy, songSortOrder) { + Database.songs(songSortBy, songSortOrder) }.collectAsState(initial = emptyList(), context = Dispatchers.IO) RouteHandler(listenToGlobalEmitter = true) { @@ -153,6 +150,9 @@ fun HomeScreen() { val binder = LocalPlayerServiceBinder.current + val isFirstLaunch by rememberPreference(isFirstLaunchKey, true) + val isCachedPlaylistShown by rememberPreference(isCachedPlaylistShownKey, false) + val thumbnailSize = Dimensions.thumbnails.song.px var isGridExpanded by remember { @@ -199,7 +199,7 @@ fun HomeScreen() { } .padding(horizontal = 16.dp, vertical = 8.dp) .run { - if (preferences.isFirstLaunch) { + if (isFirstLaunch) { drawBehind { drawCircle( color = colorPalette.red, @@ -321,7 +321,7 @@ fun HomeScreen() { } } - if (preferences.isCachedPlaylistShown) { + if (isCachedPlaylistShown) { item { Box( modifier = Modifier @@ -492,16 +492,16 @@ fun HomeScreen() { ) { Item( text = "PLAY TIME", - isSelected = preferences.songSortBy == SongSortBy.PlayTime, + isSelected = songSortBy == SongSortBy.PlayTime, onClick = { - preferences.songSortBy = SongSortBy.PlayTime + songSortBy = SongSortBy.PlayTime } ) Item( text = "DATE ADDED", - isSelected = preferences.songSortBy == SongSortBy.DateAdded, + isSelected = songSortBy == SongSortBy.DateAdded, onClick = { - preferences.songSortBy = SongSortBy.DateAdded + songSortBy = SongSortBy.DateAdded } ) } @@ -518,14 +518,14 @@ fun HomeScreen() { .width(IntrinsicSize.Max), ) { Item( - text = when (preferences.songSortOrder) { + text = when (songSortOrder) { SortOrder.Ascending -> "ASCENDING" SortOrder.Descending -> "DESCENDING" }, textColor = colorPalette.text, backgroundColor = colorPalette.elevatedBackground, onClick = { - preferences.songSortOrder = !preferences.songSortOrder + songSortOrder = !songSortOrder } ) } @@ -556,7 +556,7 @@ fun HomeScreen() { }, onThumbnailContent = { AnimatedVisibility( - visible = preferences.songSortBy == SongSortBy.PlayTime, + visible = songSortBy == SongSortBy.PlayTime, enter = fadeIn(), exit = fadeOut(), modifier = Modifier diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/IntentUriScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/IntentUriScreen.kt index 65efa1f..5af51c7 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/IntentUriScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/IntentUriScreen.kt @@ -27,7 +27,7 @@ import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.* import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.utils.asMediaItem import it.vfsfitvnm.vimusic.utils.enqueue @@ -61,7 +61,7 @@ fun IntentUriScreen(uri: Uri) { host { val menuState = LocalMenuState.current - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current val binder = LocalPlayerServiceBinder.current val thumbnailSizePx = Dimensions.thumbnails.song.px diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/LocalPlaylistScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/LocalPlaylistScreen.kt index 8fa63a6..309c2f3 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/LocalPlaylistScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/LocalPlaylistScreen.kt @@ -32,8 +32,7 @@ import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.* import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem import it.vfsfitvnm.vimusic.utils.* @@ -73,8 +72,7 @@ fun LocalPlaylistScreen( val menuState = LocalMenuState.current val binder = LocalPlayerServiceBinder.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val thumbnailSize = Dimensions.thumbnails.song.px diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/PlaylistScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/PlaylistScreen.kt index b52dbca..e8da6cc 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/PlaylistScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/PlaylistScreen.kt @@ -36,8 +36,7 @@ import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.* import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem import it.vfsfitvnm.vimusic.utils.* @@ -73,8 +72,7 @@ fun PlaylistScreen( val context = LocalContext.current val binder = LocalPlayerServiceBinder.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val menuState = LocalMenuState.current val thumbnailSizePx = Dimensions.thumbnails.playlist.px @@ -387,7 +385,7 @@ private fun LoadingOrError( errorMessage: String? = null, onRetry: (() -> Unit)? = null ) { - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current LoadingOrError( errorMessage = errorMessage, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchResultScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchResultScreen.kt index e289bfe..aab2bcb 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchResultScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchResultScreen.kt @@ -37,8 +37,7 @@ import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu import it.vfsfitvnm.vimusic.ui.components.themed.TextCard import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem import it.vfsfitvnm.vimusic.utils.* @@ -53,29 +52,29 @@ fun SearchResultScreen( query: String, onSearchAgain: () -> Unit, ) { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current - val preferences = LocalPreferences.current + val (colorPalette, typography) = LocalAppearance.current val binder = LocalPlayerServiceBinder.current + var searchFilter by rememberPreference(searchFilterKey, YouTube.Item.Song.Filter.value) + val lazyListState = rememberLazyListState() - val items = remember(preferences.searchFilter) { + val items = remember(searchFilter) { mutableStateListOf() } - var continuationResult by remember(preferences.searchFilter) { + var continuationResult by remember(searchFilter) { mutableStateOf?>(null) } - val onLoad = relaunchableEffect(preferences.searchFilter) { + val onLoad = relaunchableEffect(searchFilter) { withContext(Dispatchers.Main) { val token = continuationResult?.getOrNull() continuationResult = null continuationResult = withContext(Dispatchers.IO) { - YouTube.search(query, preferences.searchFilter, token) + YouTube.search(query, searchFilter, token) }?.map { searchResult -> items.addAll(searchResult.items) searchResult.continuation @@ -186,14 +185,14 @@ fun SearchResultScreen( value = YouTube.Item.FeaturedPlaylist.Filter.value ), ), - value = preferences.searchFilter, + value = searchFilter, selectedBackgroundColor = colorPalette.primaryContainer, unselectedBackgroundColor = colorPalette.lightBackground, selectedTextStyle = typography.xs.medium.color(colorPalette.onPrimaryContainer), unselectedTextStyle = typography.xs.medium, shape = RoundedCornerShape(36.dp), onValueChanged = { - preferences.searchFilter = it + searchFilter = it }, modifier = Modifier .padding(vertical = 8.dp) @@ -255,7 +254,7 @@ fun SearchResultScreen( } ?: item(key = "loading") { LoadingOrError( itemCount = if (items.isEmpty()) 8 else 3, - isLoadingArtists = preferences.searchFilter == YouTube.Item.Artist.Filter.value + isLoadingArtists = searchFilter == YouTube.Item.Artist.Filter.value ) } } @@ -268,7 +267,7 @@ fun SmallSongItemShimmer( thumbnailSizeDp: Dp, modifier: Modifier = Modifier ) { - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current Row( verticalAlignment = Alignment.CenterVertically, @@ -293,7 +292,7 @@ fun SmallArtistItemShimmer( thumbnailSizeDp: Dp, modifier: Modifier = Modifier ) { - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current Row( verticalAlignment = Alignment.CenterVertically, @@ -422,7 +421,7 @@ fun SmallPlaylistItem( thumbnailSizePx: Int, modifier: Modifier = Modifier ) { - val typography = LocalTypography.current + val (_, typography) = LocalAppearance.current Row( verticalAlignment = Alignment.CenterVertically, @@ -474,7 +473,7 @@ fun SmallAlbumItem( thumbnailSizePx: Int, modifier: Modifier = Modifier, ) { - val typography = LocalTypography.current + val (_, typography) = LocalAppearance.current Row( verticalAlignment = Alignment.CenterVertically, @@ -526,7 +525,7 @@ fun SmallArtistItem( thumbnailSizePx: Int, modifier: Modifier = Modifier, ) { - val typography = LocalTypography.current + val (_, typography) = LocalAppearance.current Row( verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchScreen.kt index dde4084..62f18fb 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchScreen.kt @@ -37,8 +37,7 @@ import it.vfsfitvnm.vimusic.query import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.LoadingOrError import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.medium import it.vfsfitvnm.vimusic.utils.secondary import it.vfsfitvnm.youtubemusic.YouTube @@ -104,8 +103,7 @@ fun SearchScreen( } host { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val isOpenableUrl = remember(textFieldValue.text) { listOf( diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SettingsScreen.kt index 0152330..3eb3559 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SettingsScreen.kt @@ -23,8 +23,7 @@ import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.Switch import it.vfsfitvnm.vimusic.ui.components.themed.ValueSelectorDialog import it.vfsfitvnm.vimusic.ui.screens.settings.* -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.* @@ -92,9 +91,9 @@ fun SettingsScreen() { } host { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current - val preferences = LocalPreferences.current + val (colorPalette, typography) = LocalAppearance.current + + var isFirstLaunch by rememberPreference(isFirstLaunchKey, true) Column( modifier = Modifier @@ -242,9 +241,9 @@ fun SettingsScreen() { title = "Other", description = "Advanced settings", route = otherSettingsRoute, - withAlert = LocalPreferences.current.isFirstLaunch, + withAlert = isFirstLaunch, onClick = { - preferences.isFirstLaunch = false + isFirstLaunch = false } ) @@ -324,8 +323,7 @@ fun SwitchSettingEntry( modifier: Modifier = Modifier, isEnabled: Boolean = true ) { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current Row( horizontalArrangement = Arrangement.spacedBy(16.dp), @@ -370,8 +368,8 @@ fun SettingsEntry( onClick: () -> Unit, isEnabled: Boolean = true ) { - val typography = LocalTypography.current - val colorPalette = LocalColorPalette.current + val (_, typography) = LocalAppearance.current + val (colorPalette) = LocalAppearance.current Column( modifier = modifier @@ -422,7 +420,7 @@ fun BaseSettingsEntry( titleTextStyle: @Composable TextStyle.() -> TextStyle = { this }, textStyle: @Composable TextStyle.() -> TextStyle = { this }, ) { - val typography = LocalTypography.current + val (_, typography) = LocalAppearance.current Column( modifier = modifier @@ -447,11 +445,11 @@ fun SettingsEntryGroupText( title: String, modifier: Modifier = Modifier, ) { - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current BasicText( text = title.uppercase(), - style = typography.xxs.semiBold.copy(LocalColorPalette.current.blue), + style = typography.xxs.semiBold.copy(colorPalette.blue), modifier = modifier .padding(start = 24.dp, top = 24.dp) .padding(horizontal = 32.dp) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AboutScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AboutScreen.kt index 6c5dd89..a44e2a9 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AboutScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AboutScreen.kt @@ -16,12 +16,11 @@ import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.vimusic.BuildConfig import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.ui.components.TopAppBar -import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen -import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute +import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.bold import it.vfsfitvnm.vimusic.utils.secondary import it.vfsfitvnm.vimusic.utils.semiBold @@ -48,8 +47,7 @@ fun AboutScreen() { } host { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val uriHandler = LocalUriHandler.current Column( diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AppearanceSettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AppearanceSettingsScreen.kt index 29ffd1b..1a91597 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AppearanceSettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AppearanceSettingsScreen.kt @@ -5,18 +5,20 @@ import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.BasicText import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.vimusic.R +import it.vfsfitvnm.vimusic.enums.ColorPaletteMode +import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.screens.* -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography -import it.vfsfitvnm.vimusic.utils.LocalPreferences -import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance +import it.vfsfitvnm.vimusic.utils.* @ExperimentalAnimationApi @Composable @@ -40,9 +42,11 @@ fun AppearanceSettingsScreen() { } host { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current - val preferences = LocalPreferences.current + val (colorPalette, typography) = LocalAppearance.current + + var colorPaletteMode by rememberPreference(colorPaletteModeKey, ColorPaletteMode.System) + var thumbnailRoundness by rememberPreference(thumbnailRoundnessKey, ThumbnailRoundness.Light) + var isCachedPlaylistShown by rememberPreference(isCachedPlaylistShownKey, false) Column( modifier = Modifier @@ -81,9 +85,9 @@ fun AppearanceSettingsScreen() { EnumValueSelectorSettingsEntry( title = "Theme mode", - selectedValue = preferences.colorPaletteMode, + selectedValue = colorPaletteMode, onValueSelected = { - preferences.colorPaletteMode = it + colorPaletteMode = it } ) @@ -91,9 +95,9 @@ fun AppearanceSettingsScreen() { EnumValueSelectorSettingsEntry( title = "Thumbnail roundness", - selectedValue = preferences.thumbnailRoundness, + selectedValue = thumbnailRoundness, onValueSelected = { - preferences.thumbnailRoundness = it + thumbnailRoundness = it } ) @@ -102,9 +106,9 @@ fun AppearanceSettingsScreen() { SwitchSettingEntry( title = "Cached playlist", text = "Display a playlist whose songs can be played offline", - isChecked = preferences.isCachedPlaylistShown, + isChecked = isCachedPlaylistShown, onCheckedChange = { - preferences.isCachedPlaylistShown = it + isCachedPlaylistShown = it } ) } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt index 8d3c42a..89f2a3a 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt @@ -31,8 +31,7 @@ import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.intent import it.vfsfitvnm.vimusic.utils.semiBold import java.io.FileInputStream @@ -64,8 +63,7 @@ fun BackupAndRestoreScreen() { } host { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val context = LocalContext.current val backupLauncher = diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/CacheSettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/CacheSettingsScreen.kt index 8525f51..6013e49 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/CacheSettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/CacheSettingsScreen.kt @@ -16,13 +16,15 @@ import coil.annotation.ExperimentalCoilApi import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R +import it.vfsfitvnm.vimusic.enums.CoilDiskCacheMaxSize import it.vfsfitvnm.vimusic.enums.ExoPlayerDiskCacheMaxSize import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.TextCard import it.vfsfitvnm.vimusic.ui.screens.* -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography -import it.vfsfitvnm.vimusic.utils.LocalPreferences +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance +import it.vfsfitvnm.vimusic.utils.coilDiskCacheMaxSizeKey +import it.vfsfitvnm.vimusic.utils.exoPlayerDiskCacheMaxSizeKey +import it.vfsfitvnm.vimusic.utils.rememberPreference import it.vfsfitvnm.vimusic.utils.semiBold import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -51,11 +53,12 @@ fun CacheSettingsScreen() { host { val context = LocalContext.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current - val preferences = LocalPreferences.current + val (colorPalette, typography) = LocalAppearance.current val binder = LocalPlayerServiceBinder.current + var coilDiskCacheMaxSize by rememberPreference(coilDiskCacheMaxSizeKey, CoilDiskCacheMaxSize.`128MB`) + var exoPlayerDiskCacheMaxSize by rememberPreference(exoPlayerDiskCacheMaxSizeKey, ExoPlayerDiskCacheMaxSize.`2GB`) + val coroutineScope = rememberCoroutineScope() Column( @@ -100,9 +103,9 @@ fun CacheSettingsScreen() { EnumValueSelectorSettingsEntry( title = "Max size", - selectedValue = preferences.coilDiskCacheMaxSize, + selectedValue = coilDiskCacheMaxSize, onValueSelected = { - preferences.coilDiskCacheMaxSize = it + coilDiskCacheMaxSize = it } ) @@ -114,9 +117,7 @@ fun CacheSettingsScreen() { diskCacheSize ) } (${ - diskCacheSize * 100 / preferences.coilDiskCacheMaxSize.bytes.coerceAtLeast( - 1 - ) + diskCacheSize * 100 / coilDiskCacheMaxSize.bytes.coerceAtLeast(1) }%)", ) @@ -143,9 +144,9 @@ fun CacheSettingsScreen() { EnumValueSelectorSettingsEntry( title = "Max size", - selectedValue = preferences.exoPlayerDiskCacheMaxSize, + selectedValue = exoPlayerDiskCacheMaxSize, onValueSelected = { - preferences.exoPlayerDiskCacheMaxSize = it + exoPlayerDiskCacheMaxSize = it } ) @@ -154,7 +155,7 @@ fun CacheSettingsScreen() { text = buildString { append(Formatter.formatShortFileSize(context, diskCacheSize)) - when (val size = preferences.exoPlayerDiskCacheMaxSize) { + when (val size = exoPlayerDiskCacheMaxSize) { ExoPlayerDiskCacheMaxSize.Unlimited -> {} else -> append("(${diskCacheSize * 100 / size.bytes}%)") } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt index ae43337..1d10a01 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt @@ -23,10 +23,10 @@ import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.TextCard import it.vfsfitvnm.vimusic.ui.screens.* -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography -import it.vfsfitvnm.vimusic.utils.LocalPreferences +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.isIgnoringBatteryOptimizations +import it.vfsfitvnm.vimusic.utils.isInvincibilityEnabledKey +import it.vfsfitvnm.vimusic.utils.rememberPreference import it.vfsfitvnm.vimusic.utils.semiBold @@ -53,9 +53,9 @@ fun OtherSettingsScreen() { host { val context = LocalContext.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current - val preferences = LocalPreferences.current + val (colorPalette, typography) = LocalAppearance.current + + var isInvincibilityEnabled by rememberPreference(isInvincibilityEnabledKey, false) var isIgnoringBatteryOptimizations by remember { mutableStateOf(context.isIgnoringBatteryOptimizations) @@ -140,9 +140,9 @@ fun OtherSettingsScreen() { SwitchSettingEntry( title = "Invincible service", text = "When turning off battery optimizations is not enough", - isChecked = preferences.isInvincibilityEnabled, + isChecked = isInvincibilityEnabled, onCheckedChange = { - preferences.isInvincibilityEnabled = it + isInvincibilityEnabled = it } ) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/PlayerSettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/PlayerSettingsScreen.kt index a868b2a..bbfbc17 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/PlayerSettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/PlayerSettingsScreen.kt @@ -10,6 +10,8 @@ import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.BasicText import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext @@ -20,10 +22,8 @@ import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.screens.* -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography -import it.vfsfitvnm.vimusic.utils.LocalPreferences -import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance +import it.vfsfitvnm.vimusic.utils.* @ExperimentalAnimationApi @@ -49,11 +49,13 @@ fun PlayerSettingsScreen() { host { val context = LocalContext.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current - val preferences = LocalPreferences.current + val (colorPalette, typography) = LocalAppearance.current val binder = LocalPlayerServiceBinder.current + var persistentQueue by rememberPreference(persistentQueueKey, false) + var skipSilence by rememberPreference(skipSilenceKey, false) + var volumeNormalization by rememberPreference(volumeNormalizationKey, false) + val activityResultLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { } @@ -96,9 +98,9 @@ fun PlayerSettingsScreen() { SwitchSettingEntry( title = "Persistent queue", text = "Save and restore playing songs", - isChecked = preferences.persistentQueue, + isChecked = persistentQueue, onCheckedChange = { - preferences.persistentQueue = it + persistentQueue = it } ) @@ -107,19 +109,18 @@ fun PlayerSettingsScreen() { SwitchSettingEntry( title = "Skip silence", text = "Skip silent parts during playback", - isChecked = preferences.skipSilence, + isChecked = skipSilence, onCheckedChange = { - binder?.player?.skipSilenceEnabled = it - preferences.skipSilence = it + skipSilence = it } ) SwitchSettingEntry( title = "Loudness normalization", text = "Lower the volume to a standard level", - isChecked = preferences.volumeNormalization, + isChecked = volumeNormalization, onCheckedChange = { - preferences.volumeNormalization = it + volumeNormalization = it } ) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Appearance.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Appearance.kt new file mode 100644 index 0000000..06acdf6 --- /dev/null +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Appearance.kt @@ -0,0 +1,12 @@ +package it.vfsfitvnm.vimusic.ui.styling + +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Shape + +data class Appearance( + val colorPalette: ColorPalette, + val typography: Typography, + val thumbnailShape: Shape +) + +val LocalAppearance = staticCompositionLocalOf { TODO() } \ No newline at end of file diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/ColorPalette.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/ColorPalette.kt index c4ce4c8..ce1b2c7 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/ColorPalette.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/ColorPalette.kt @@ -82,5 +82,3 @@ val LightColorPalette = ColorPalette( // iconOnPrimaryContainer = Color(0xff2e30b8), isDark = false ) - -val LocalColorPalette = staticCompositionLocalOf { LightColorPalette } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Typography.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Typography.kt index ee90103..0db5811 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Typography.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Typography.kt @@ -23,53 +23,3 @@ data class Typography( val m: TextStyle, val l: TextStyle, ) - -val LocalTypography = staticCompositionLocalOf { TODO() } - -@Suppress("DEPRECATION") -@OptIn(ExperimentalTextApi::class) -@Composable -fun rememberTypography(color: Color): Typography { - return remember(color) { - TextStyle( - fontFamily = FontFamily( - Font( - resId = R.font.poppins_w300, - weight = FontWeight.Light - ), - Font( - resId = R.font.poppins_w400, - weight = FontWeight.Normal - ), - Font( - resId = R.font.poppins_w400_italic, - weight = FontWeight.Normal, - style = FontStyle.Italic - ), - Font( - resId = R.font.poppins_w500, - weight = FontWeight.Medium - ), - Font( - resId = R.font.poppins_w600, - weight = FontWeight.SemiBold - ), - Font( - resId = R.font.poppins_w700, - weight = FontWeight.Bold - ), - ), - fontWeight = FontWeight.Normal, - color = color, - platformStyle = PlatformTextStyle(includeFontPadding = false) - ).run { - Typography( - xxs = copy(fontSize = 12.sp), - xs = copy(fontSize = 14.sp), - s = copy(fontSize = 16.sp), - m = copy(fontSize = 18.sp), - l = copy(fontSize = 20.sp), - ) - } - } -} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/CurrentPlaylistView.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/CurrentPlaylistView.kt index 50adb17..b18bceb 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/CurrentPlaylistView.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/CurrentPlaylistView.kt @@ -36,10 +36,7 @@ import it.vfsfitvnm.vimusic.ui.components.BottomSheetState import it.vfsfitvnm.vimusic.ui.components.MusicBars import it.vfsfitvnm.vimusic.ui.components.themed.QueuedMediaItemMenu import it.vfsfitvnm.vimusic.ui.screens.SmallSongItemShimmer -import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LightColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.px +import it.vfsfitvnm.vimusic.ui.styling.* import it.vfsfitvnm.vimusic.utils.PlayerState @@ -53,7 +50,7 @@ fun CurrentPlaylistView( ) { val binder = LocalPlayerServiceBinder.current val hapticFeedback = LocalHapticFeedback.current - val colorPalette = LocalColorPalette.current + val (colorPalette) = LocalAppearance.current val thumbnailSize = Dimensions.thumbnails.song.px diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/LyricsView.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/LyricsView.kt index e4991b5..64070d3 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/LyricsView.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/LyricsView.kt @@ -19,7 +19,7 @@ import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.ui.components.themed.TextCard import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.center import it.vfsfitvnm.vimusic.utils.secondary @@ -32,7 +32,7 @@ fun LyricsView( onLyricsUpdate: (String) -> Unit, nestedScrollConnectionProvider: () -> NestedScrollConnection, ) { - val typography = LocalTypography.current + val (_, typography) = LocalAppearance.current var isEditingLyrics by remember { mutableStateOf(false) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerBottomSheet.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerBottomSheet.kt index c52fdc0..55dc5e4 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerBottomSheet.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerBottomSheet.kt @@ -28,8 +28,7 @@ import it.vfsfitvnm.vimusic.ui.components.BottomSheet import it.vfsfitvnm.vimusic.ui.components.BottomSheetState import it.vfsfitvnm.vimusic.ui.components.HorizontalTabPager import it.vfsfitvnm.vimusic.ui.components.rememberTabPagerState -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.PlayerState import it.vfsfitvnm.vimusic.utils.center import it.vfsfitvnm.vimusic.utils.color @@ -50,8 +49,7 @@ fun PlayerBottomSheet( onGlobalRouteEmitted: () -> Unit, modifier: Modifier = Modifier, ) { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val coroutineScope = rememberCoroutineScope() diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt index ff8888a..92dcf2c 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt @@ -63,8 +63,7 @@ fun PlayerView( ) { val menuState = LocalMenuState.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val binder = LocalPlayerServiceBinder.current val context = LocalContext.current val configuration = LocalConfiguration.current @@ -318,7 +317,7 @@ private fun Thumbnail( song: Song?, modifier: Modifier = Modifier ) { - val typography = LocalTypography.current + val (_, typography) = LocalAppearance.current val context = LocalContext.current val binder = LocalPlayerServiceBinder.current val player = binder?.player ?: return @@ -527,9 +526,7 @@ private fun Controls( song: Song?, modifier: Modifier = Modifier ) { - val typography = LocalTypography.current - val colorPalette = LocalColorPalette.current - val preferences = LocalPreferences.current + val (colorPalette, typography) = LocalAppearance.current val binder = LocalPlayerServiceBinder.current val player = binder?.player ?: return @@ -730,9 +727,8 @@ private fun Controls( player.repeatMode .plus(2) .mod(3) - .let { repeatMode -> - player.repeatMode = repeatMode - preferences.repeatMode = repeatMode + .let { + player.repeatMode = it } } .weight(1f) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlaylistPreviewItem.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlaylistPreviewItem.kt index 81bcafd..de55db1 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlaylistPreviewItem.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlaylistPreviewItem.kt @@ -23,8 +23,7 @@ import coil.compose.AsyncImage import it.vfsfitvnm.vimusic.Database import it.vfsfitvnm.vimusic.models.PlaylistPreview import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.color import it.vfsfitvnm.vimusic.utils.semiBold import it.vfsfitvnm.vimusic.utils.thumbnail @@ -38,8 +37,7 @@ fun PlaylistPreviewItem( modifier: Modifier = Modifier, thumbnailSize: Dp = Dimensions.thumbnails.song, ) { - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current val density = LocalDensity.current val thumbnailSizePx = density.run { diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/SongItem.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/SongItem.kt index 5f35eed..4d881f5 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/SongItem.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/SongItem.kt @@ -26,8 +26,7 @@ import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness import it.vfsfitvnm.vimusic.models.DetailedSong import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.styling.Dimensions -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette -import it.vfsfitvnm.vimusic.ui.styling.LocalTypography +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.secondary import it.vfsfitvnm.vimusic.utils.semiBold import it.vfsfitvnm.vimusic.utils.thumbnail @@ -150,8 +149,7 @@ fun SongItem( trailingContent: (@Composable () -> Unit)? = null ) { val menuState = LocalMenuState.current - val colorPalette = LocalColorPalette.current - val typography = LocalTypography.current + val (colorPalette, typography) = LocalAppearance.current Row( verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Preferences.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Preferences.kt index 7a4fb35..57d35aa 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Preferences.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Preferences.kt @@ -5,145 +5,24 @@ import android.content.SharedPreferences import androidx.compose.runtime.* import androidx.compose.ui.platform.LocalContext import androidx.core.content.edit -import androidx.media3.common.Player -import it.vfsfitvnm.vimusic.enums.* -import it.vfsfitvnm.youtubemusic.YouTube -@Stable -class Preferences( - private val edit: (action: SharedPreferences.Editor.() -> Unit) -> Unit, - initialIsFirstLaunch: Boolean, - initialSongSortBy: SongSortBy, - initialSongSortOrder: SortOrder, - initialColorPaletteMode: ColorPaletteMode, - initialSearchFilter: String, - initialRepeatMode: Int, - initialThumbnailRoundness: ThumbnailRoundness, - initialCoilDiskCacheMaxSize: CoilDiskCacheMaxSize, - initialExoPlayerDiskCacheMaxSize: ExoPlayerDiskCacheMaxSize, - initialSkipSilence: Boolean, - initialVolumeNormalization: Boolean, - initialPersistentQueue: Boolean, - initialIsInvincibilityEnabled: Boolean, - initialIsCachedPlaylistShown: Boolean, -) { - constructor(preferences: SharedPreferences) : this( - edit = { action: SharedPreferences.Editor.() -> Unit -> - preferences.edit(action = action) - }, - initialIsFirstLaunch = preferences.getBoolean(Keys.isFirstLaunch, true), - initialSongSortBy = preferences.getEnum(Keys.songSortBy, SongSortBy.DateAdded), - initialSongSortOrder = preferences.getEnum(Keys.songSortOrder, SortOrder.Descending), - initialColorPaletteMode = preferences.getEnum(Keys.colorPaletteMode, ColorPaletteMode.System), - initialSearchFilter = preferences.getString(Keys.searchFilter, YouTube.Item.Song.Filter.value)!!, - initialRepeatMode = preferences.getInt(Keys.repeatMode, Player.REPEAT_MODE_OFF), - initialThumbnailRoundness = preferences.getEnum(Keys.thumbnailRoundness, ThumbnailRoundness.Light), - initialCoilDiskCacheMaxSize = preferences.getEnum(Keys.coilDiskCacheMaxSize, CoilDiskCacheMaxSize.`128MB`), - initialExoPlayerDiskCacheMaxSize = preferences.getEnum(Keys.exoPlayerDiskCacheMaxSize, ExoPlayerDiskCacheMaxSize.`2GB`), - initialSkipSilence = preferences.getBoolean(Keys.skipSilence, false), - initialVolumeNormalization = preferences.getBoolean(Keys.volumeNormalization, false), - initialPersistentQueue = preferences.getBoolean(Keys.persistentQueue, false), - initialIsInvincibilityEnabled = preferences.getBoolean(Keys.isInvincibilityEnabled, false), - initialIsCachedPlaylistShown = preferences.getBoolean(Keys.isCachedPlaylistShown, false), - ) +const val colorPaletteModeKey = "colorPaletteMode" +const val thumbnailRoundnessKey = "thumbnailRoundness" +const val isCachedPlaylistShownKey = "isCachedPlaylistShown" +const val coilDiskCacheMaxSizeKey = "coilDiskCacheMaxSize" +const val exoPlayerDiskCacheMaxSizeKey = "exoPlayerDiskCacheMaxSize" +const val isInvincibilityEnabledKey = "isInvincibilityEnabled" +const val isFirstLaunchKey = "isFirstLaunch" +const val songSortOrderKey = "songSortOrder" +const val songSortByKey = "songSortBy" +const val searchFilterKey = "searchFilter" +const val repeatModeKey = "repeatMode" +const val skipSilenceKey = "skipSilence" +const val volumeNormalizationKey = "volumeNormalization" +const val persistentQueueKey = "persistentQueue" - var isFirstLaunch = initialIsFirstLaunch - set(value) = edit { putBoolean(Keys.isFirstLaunch, value) } - - var songSortBy = initialSongSortBy - set(value) = edit { putEnum(Keys.songSortBy, value) } - - var songSortOrder = initialSongSortOrder - set(value) = edit { putEnum(Keys.songSortOrder, value) } - - var colorPaletteMode = initialColorPaletteMode - set(value) = edit { putEnum(Keys.colorPaletteMode, value) } - - var searchFilter = initialSearchFilter - set(value) = edit { putString(Keys.searchFilter, value) } - - var repeatMode = initialRepeatMode - set(value) = edit { putInt(Keys.repeatMode, value) } - - var thumbnailRoundness = initialThumbnailRoundness - set(value) = edit { putEnum(Keys.thumbnailRoundness, value) } - - var coilDiskCacheMaxSize = initialCoilDiskCacheMaxSize - set(value) = edit { putEnum(Keys.coilDiskCacheMaxSize, value) } - - var exoPlayerDiskCacheMaxSize = initialExoPlayerDiskCacheMaxSize - set(value) = edit { putEnum(Keys.exoPlayerDiskCacheMaxSize, value) } - - var skipSilence = initialSkipSilence - set(value) = edit { putBoolean(Keys.skipSilence, value) } - - var volumeNormalization = initialVolumeNormalization - set(value) = edit { putBoolean(Keys.volumeNormalization, value) } - - var persistentQueue = initialPersistentQueue - set(value) = edit { putBoolean(Keys.persistentQueue, value) } - - var isInvincibilityEnabled = initialIsInvincibilityEnabled - set(value) = edit { putBoolean(Keys.isInvincibilityEnabled, value) } - - var isCachedPlaylistShown = initialIsCachedPlaylistShown - set(value) = edit { putBoolean(Keys.isCachedPlaylistShown, value) } - - object Keys { - const val isFirstLaunch = "isFirstLaunch" - const val songSortOrder = "songSortOrder" - const val songSortBy = "songSortBy" - const val colorPaletteMode = "colorPaletteMode" - const val searchFilter = "searchFilter" - const val repeatMode = "repeatMode" - const val thumbnailRoundness = "thumbnailRoundness" - const val coilDiskCacheMaxSize = "coilDiskCacheMaxSize" - const val exoPlayerDiskCacheMaxSize = "exoPlayerDiskCacheMaxSize" - const val skipSilence = "skipSilence" - const val volumeNormalization = "volumeNormalization" - const val persistentQueue = "persistentQueue" - const val isInvincibilityEnabled = "isInvincibilityEnabled" - const val isCachedPlaylistShown = "isCachedPlaylistShown" - } - - companion object { - const val fileName = "preferences" - - context(Context) - operator fun invoke() = - Preferences(getSharedPreferences(fileName, Context.MODE_PRIVATE)) - } -} - -val LocalPreferences = staticCompositionLocalOf { TODO() } - -@Composable -fun rememberPreferences(): Preferences { - val context = LocalContext.current - var preferences by remember { - mutableStateOf(context.run { Preferences() }) - } - - DisposableEffect(Unit) { - val holder = context.getSharedPreferences(Preferences.fileName, Context.MODE_PRIVATE) - - val listener = - SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, _ -> - preferences = Preferences(sharedPreferences) - } - - holder.registerOnSharedPreferenceChangeListener(listener) - - onDispose { - holder.unregisterOnSharedPreferenceChangeListener(listener) - } - } - - return preferences -} - -private inline fun > SharedPreferences.getEnum( +inline fun > SharedPreferences.getEnum( key: String, defaultValue: T ): T = @@ -155,6 +34,51 @@ private inline fun > SharedPreferences.getEnum( } } ?: defaultValue -private inline fun > SharedPreferences.Editor.putEnum(key: String, value: T) = +inline fun > SharedPreferences.Editor.putEnum(key: String, value: T) = putString(key, value.name) + +val Context.preferences: SharedPreferences + get() = getSharedPreferences("preferences", Context.MODE_PRIVATE) + + +@Composable +fun rememberPreference(key: String, defaultValue: Boolean): MutableState { + val context = LocalContext.current + return remember { + mutableStatePreferenceOf(context.preferences.getBoolean(key, defaultValue)) { + context.preferences.edit { putBoolean(key, it) } + } + } +} + +@Composable +fun rememberPreference(key: String, defaultValue: String): MutableState { + val context = LocalContext.current + return remember { + mutableStatePreferenceOf(context.preferences.getString(key, null) ?: defaultValue) { + context.preferences.edit { putString(key, it) } + } + } +} + +@Composable +inline fun > rememberPreference(key: String, defaultValue: T): MutableState { + val context = LocalContext.current + return remember { + mutableStatePreferenceOf(context.preferences.getEnum(key, defaultValue)) { + context.preferences.edit { putEnum(key, it) } + } + } +} + +inline fun mutableStatePreferenceOf(value: T, crossinline onStructuralInequality: (newValue: T) -> Unit) = + mutableStateOf( + value = value, + policy = object : SnapshotMutationPolicy { + override fun equivalent(a: T, b: T): Boolean { + val areEquals = a == b + if (!areEquals) onStructuralInequality(b) + return areEquals + } + }) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/TextStyle.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/TextStyle.kt index 6002856..92279b1 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/TextStyle.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/TextStyle.kt @@ -7,7 +7,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign -import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance fun TextStyle.style(style: FontStyle) = copy(fontStyle = style) @@ -35,9 +35,9 @@ inline val TextStyle.center: TextStyle inline val TextStyle.secondary: TextStyle @Composable @ReadOnlyComposable - get() = color(LocalColorPalette.current.textSecondary) + get() = color(LocalAppearance.current.colorPalette.textSecondary) inline val TextStyle.disabled: TextStyle @Composable @ReadOnlyComposable - get() = color(LocalColorPalette.current.textDisabled) + get() = color(LocalAppearance.current.colorPalette.textDisabled)