Revert DataStore migration
This commit is contained in:
@@ -88,8 +88,6 @@ dependencies {
|
|||||||
implementation(libs.media3.session)
|
implementation(libs.media3.session)
|
||||||
implementation(libs.media3.exoplayer)
|
implementation(libs.media3.exoplayer)
|
||||||
|
|
||||||
implementation(libs.datastore)
|
|
||||||
|
|
||||||
implementation(libs.room)
|
implementation(libs.room)
|
||||||
kapt(libs.room.compiler)
|
kapt(libs.room.compiler)
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
mediaControllerFuture = MediaController.Builder(this, sessionToken).buildAsync()
|
mediaControllerFuture = MediaController.Builder(this, sessionToken).buildAsync()
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
val preferences by rememberPreferences(dataStore)
|
val preferences = rememberPreferences()
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
|
|
||||||
val (isDarkTheme, colorPalette) = when (preferences.colorPaletteMode) {
|
val (isDarkTheme, colorPalette) = when (preferences.colorPaletteMode) {
|
||||||
@@ -118,9 +118,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
LocalShimmerTheme provides shimmerTheme,
|
LocalShimmerTheme provides shimmerTheme,
|
||||||
LocalTypography provides rememberTypography(colorPalette.text),
|
LocalTypography provides rememberTypography(colorPalette.text),
|
||||||
LocalYoutubePlayer provides rememberYoutubePlayer(mediaControllerFuture) {
|
LocalYoutubePlayer provides rememberYoutubePlayer(mediaControllerFuture) {
|
||||||
if (preferences.isReady) {
|
it.repeatMode = preferences.repeatMode
|
||||||
it.repeatMode = preferences.repeatMode
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
LocalMenuState provides rememberMenuState(),
|
LocalMenuState provides rememberMenuState(),
|
||||||
LocalHapticFeedback provides rememberHapticFeedback()
|
LocalHapticFeedback provides rememberHapticFeedback()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package it.vfsfitvnm.vimusic
|
package it.vfsfitvnm.vimusic
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.ImageLoaderFactory
|
import coil.ImageLoaderFactory
|
||||||
import coil.disk.DiskCache
|
import coil.disk.DiskCache
|
||||||
@@ -13,14 +14,18 @@ class MainApplication : Application(), ImageLoaderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun newImageLoader(): ImageLoader {
|
override fun newImageLoader(): ImageLoader {
|
||||||
return ImageLoader.Builder(this)
|
return defaultCoilImageLoader(1024 * 1024 * 1024)
|
||||||
.crossfade(true)
|
|
||||||
.diskCache(
|
|
||||||
DiskCache.Builder()
|
|
||||||
.directory(filesDir.resolve("coil"))
|
|
||||||
.maxSizeBytes(1024 * 1024 * 1024)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.defaultCoilImageLoader(diskCacheMaxSize: Long): ImageLoader {
|
||||||
|
return ImageLoader.Builder(this)
|
||||||
|
.crossfade(true)
|
||||||
|
.diskCache(
|
||||||
|
DiskCache.Builder()
|
||||||
|
.directory(filesDir.resolve("coil"))
|
||||||
|
.maxSizeBytes(diskCacheMaxSize)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
@@ -80,11 +80,7 @@ fun HomeScreen(
|
|||||||
|
|
||||||
val preferences = LocalPreferences.current
|
val preferences = LocalPreferences.current
|
||||||
|
|
||||||
val songCollection by remember(preferences.isReady, preferences.homePageSongCollection) {
|
val songCollection by remember(preferences.homePageSongCollection) {
|
||||||
if (!preferences.isReady) {
|
|
||||||
return@remember flowOf(emptyList())
|
|
||||||
}
|
|
||||||
|
|
||||||
when (preferences.homePageSongCollection) {
|
when (preferences.homePageSongCollection) {
|
||||||
SongCollection.MostPlayed -> Database.mostPlayed()
|
SongCollection.MostPlayed -> Database.mostPlayed()
|
||||||
SongCollection.Favorites -> Database.favorites()
|
SongCollection.Favorites -> Database.favorites()
|
||||||
@@ -311,21 +307,19 @@ fun HomeScreen(
|
|||||||
val songCollections = enumValues<SongCollection>()
|
val songCollections = enumValues<SongCollection>()
|
||||||
val nextSongCollection = songCollections[(preferences.homePageSongCollection.ordinal + 1) % songCollections.size]
|
val nextSongCollection = songCollections[(preferences.homePageSongCollection.ordinal + 1) % songCollections.size]
|
||||||
|
|
||||||
BasicText(
|
BasicText(
|
||||||
text = when (nextSongCollection) {
|
text = when (nextSongCollection) {
|
||||||
SongCollection.MostPlayed -> "Most played"
|
SongCollection.MostPlayed -> "Most played"
|
||||||
SongCollection.Favorites -> "Favorites"
|
SongCollection.Favorites -> "Favorites"
|
||||||
SongCollection.History -> "History"
|
SongCollection.History -> "History"
|
||||||
},
|
},
|
||||||
style = typography.xxs.secondary.bold,
|
style = typography.xxs.secondary.bold,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(
|
.clickable(
|
||||||
indication = rememberRipple(bounded = true),
|
indication = rememberRipple(bounded = true),
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
) {
|
onClick = {
|
||||||
preferences.onHomePageSongCollectionChange(
|
preferences.homePageSongCollection = nextSongCollection
|
||||||
nextSongCollection
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// .alignByBaseline()
|
// .alignByBaseline()
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
|
|||||||
@@ -80,13 +80,17 @@ fun AppearanceScreen() {
|
|||||||
EnumValueSelectorEntry(
|
EnumValueSelectorEntry(
|
||||||
title = "Theme mode",
|
title = "Theme mode",
|
||||||
selectedValue = preferences.colorPaletteMode,
|
selectedValue = preferences.colorPaletteMode,
|
||||||
onValueSelected = preferences.onColorPaletteModeChange
|
onValueSelected = {
|
||||||
|
preferences.colorPaletteMode = it
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
EnumValueSelectorEntry(
|
EnumValueSelectorEntry(
|
||||||
title = "Thumbnail roundness",
|
title = "Thumbnail roundness",
|
||||||
selectedValue = preferences.thumbnailRoundness,
|
selectedValue = preferences.thumbnailRoundness,
|
||||||
onValueSelected = preferences.onThumbnailRoundnessChange
|
onValueSelected = {
|
||||||
|
preferences.thumbnailRoundness = it
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ fun PlayerView(
|
|||||||
player.mediaController.repeatMode =
|
player.mediaController.repeatMode =
|
||||||
(player.mediaController.repeatMode + 2) % 3
|
(player.mediaController.repeatMode + 2) % 3
|
||||||
|
|
||||||
preferences.onRepeatModeChange(player.mediaController.repeatMode)
|
preferences.repeatMode = player.mediaController.repeatMode
|
||||||
}
|
}
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.size(28.dp)
|
.size(28.dp)
|
||||||
|
|||||||
@@ -1,123 +1,114 @@
|
|||||||
package it.vfsfitvnm.vimusic.utils
|
package it.vfsfitvnm.vimusic.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.datastore.preferences.core.intPreferencesKey
|
import androidx.compose.ui.unit.TextUnit
|
||||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.core.content.edit
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import it.vfsfitvnm.vimusic.enums.ColorPaletteMode
|
import it.vfsfitvnm.vimusic.enums.ColorPaletteMode
|
||||||
import it.vfsfitvnm.vimusic.enums.SongCollection
|
import it.vfsfitvnm.vimusic.enums.SongCollection
|
||||||
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
|
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
|
||||||
import it.vfsfitvnm.youtubemusic.YouTube
|
import it.vfsfitvnm.youtubemusic.YouTube
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import androidx.datastore.preferences.core.Preferences as DataStorePreferences
|
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
class Preferences(holder: SharedPreferences) : SharedPreferences by holder {
|
||||||
|
var colorPaletteMode by preference("colorPaletteMode", ColorPaletteMode.System)
|
||||||
|
var searchFilter by preference("searchFilter", YouTube.Item.Song.Filter.value)
|
||||||
|
var repeatMode by preference("repeatMode", Player.REPEAT_MODE_OFF)
|
||||||
|
var homePageSongCollection by preference("homePageSongCollection", SongCollection.MostPlayed)
|
||||||
|
var thumbnailRoundness by preference("thumbnailRoundness", ThumbnailRoundness.Light)
|
||||||
|
}
|
||||||
|
|
||||||
@Immutable
|
val Context.preferences: Preferences
|
||||||
data class Preferences(
|
get() = Preferences(getSharedPreferences("preferences", Context.MODE_PRIVATE))
|
||||||
val isReady: Boolean,
|
|
||||||
val colorPaletteMode: ColorPaletteMode,
|
|
||||||
val onColorPaletteModeChange: (ColorPaletteMode) -> Unit,
|
|
||||||
val searchFilter: String,
|
|
||||||
val onSearchFilterChange: (String) -> Unit,
|
|
||||||
val repeatMode: Int,
|
|
||||||
val onRepeatModeChange: (Int) -> Unit,
|
|
||||||
val homePageSongCollection: SongCollection,
|
|
||||||
val onHomePageSongCollectionChange: (SongCollection) -> Unit,
|
|
||||||
val thumbnailRoundness: ThumbnailRoundness,
|
|
||||||
val onThumbnailRoundnessChange: (ThumbnailRoundness) -> Unit,
|
|
||||||
) {
|
|
||||||
constructor(
|
|
||||||
isReady: Boolean,
|
|
||||||
colorPaletteMode: ColorPaletteMode? = null,
|
|
||||||
onColorPaletteModeChange: (ColorPaletteMode) -> Unit = {},
|
|
||||||
searchFilter: String? = null,
|
|
||||||
onSearchFilterChange: (String) -> Unit = {},
|
|
||||||
repeatMode: Int? = null,
|
|
||||||
onRepeatModeChange: (Int) -> Unit = {},
|
|
||||||
homePageSongCollection: SongCollection? = null,
|
|
||||||
onHomePageSongCollectionChange: (SongCollection) -> Unit = {},
|
|
||||||
thumbnailRoundness: ThumbnailRoundness? = null,
|
|
||||||
onThumbnailRoundnessChange: (ThumbnailRoundness) -> Unit = {},
|
|
||||||
) : this(
|
|
||||||
isReady = isReady,
|
|
||||||
colorPaletteMode = colorPaletteMode ?: ColorPaletteMode.System,
|
|
||||||
onColorPaletteModeChange = onColorPaletteModeChange,
|
|
||||||
searchFilter = searchFilter ?: YouTube.Item.Song.Filter.value,
|
|
||||||
onSearchFilterChange = onSearchFilterChange,
|
|
||||||
repeatMode = repeatMode ?: Player.REPEAT_MODE_OFF,
|
|
||||||
onRepeatModeChange = onRepeatModeChange,
|
|
||||||
homePageSongCollection = homePageSongCollection ?: SongCollection.MostPlayed,
|
|
||||||
onHomePageSongCollectionChange = onHomePageSongCollectionChange,
|
|
||||||
thumbnailRoundness = thumbnailRoundness ?: ThumbnailRoundness.Light,
|
|
||||||
onThumbnailRoundnessChange = onThumbnailRoundnessChange
|
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
val LocalPreferences = staticCompositionLocalOf<Preferences> { TODO() }
|
||||||
val Default = Preferences(isReady = false)
|
|
||||||
|
@Composable
|
||||||
|
fun rememberPreferences(): Preferences {
|
||||||
|
val context = LocalContext.current
|
||||||
|
return remember {
|
||||||
|
context.preferences
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val LocalPreferences = staticCompositionLocalOf { Preferences.Default }
|
private fun SharedPreferences.preference(key: String, defaultValue: Boolean) =
|
||||||
|
mutableStateOf(value = getBoolean(key, defaultValue)) {
|
||||||
private val colorPaletteModeKey = stringPreferencesKey("colorPaletteMode")
|
edit {
|
||||||
private val searchFilterKey = stringPreferencesKey("searchFilter")
|
putBoolean(key, it)
|
||||||
private val repeatModeKey = intPreferencesKey("repeatMode")
|
|
||||||
private val homePageSongCollectionKey = stringPreferencesKey("homePageSongCollection")
|
|
||||||
private val thumbnailRoundnessKey = stringPreferencesKey("thumbnailRoundness")
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun rememberPreferences(dataStore: DataStore<DataStorePreferences>): State<Preferences> {
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
return remember(dataStore, coroutineScope) {
|
|
||||||
dataStore.data.map { preferences ->
|
|
||||||
Preferences(
|
|
||||||
isReady = true,
|
|
||||||
colorPaletteMode = preferences[colorPaletteModeKey]?.let { enumValueOf<ColorPaletteMode>(it) },
|
|
||||||
onColorPaletteModeChange = { colorPaletteMode ->
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
|
||||||
dataStore.edit { mutablePreferences ->
|
|
||||||
mutablePreferences[colorPaletteModeKey] = colorPaletteMode.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
searchFilter = preferences[searchFilterKey],
|
|
||||||
onSearchFilterChange = { searchFilter ->
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
|
||||||
dataStore.edit { mutablePreferences ->
|
|
||||||
mutablePreferences[searchFilterKey] = searchFilter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
repeatMode = preferences[repeatModeKey],
|
|
||||||
onRepeatModeChange = { repeatMode ->
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
|
||||||
dataStore.edit { mutablePreferences ->
|
|
||||||
mutablePreferences[repeatModeKey] = repeatMode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
homePageSongCollection = preferences[homePageSongCollectionKey]?.let { enumValueOf<SongCollection>(it) },
|
|
||||||
onHomePageSongCollectionChange = { homePageSongCollection ->
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
|
||||||
dataStore.edit { mutablePreferences ->
|
|
||||||
mutablePreferences[homePageSongCollectionKey] = homePageSongCollection.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
thumbnailRoundness = preferences[thumbnailRoundnessKey]?.let { enumValueOf<ThumbnailRoundness>(it) },
|
|
||||||
onThumbnailRoundnessChange = { thumbnailRoundness ->
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
|
||||||
dataStore.edit { mutablePreferences ->
|
|
||||||
mutablePreferences[thumbnailRoundnessKey] = thumbnailRoundness.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}.collectAsState(initial = Preferences.Default, context = Dispatchers.IO)
|
}
|
||||||
}
|
|
||||||
|
private fun SharedPreferences.preference(key: String, defaultValue: Int) =
|
||||||
|
mutableStateOf(value = getInt(key, defaultValue)) {
|
||||||
|
edit {
|
||||||
|
putInt(key, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SharedPreferences.preference(key: String, defaultValue: Long) =
|
||||||
|
mutableStateOf(value = getLong(key, defaultValue)) {
|
||||||
|
edit {
|
||||||
|
putLong(key, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SharedPreferences.preference(key: String, defaultValue: Float) =
|
||||||
|
mutableStateOf(value = getFloat(key, defaultValue)) {
|
||||||
|
edit {
|
||||||
|
putFloat(key, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SharedPreferences.preference(key: String, defaultValue: String) =
|
||||||
|
mutableStateOf(value = getString(key, defaultValue)!!) {
|
||||||
|
edit {
|
||||||
|
putString(key, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SharedPreferences.preference(key: String, defaultValue: Set<String>) =
|
||||||
|
mutableStateOf(value = getStringSet(key, defaultValue)!!) {
|
||||||
|
edit {
|
||||||
|
putStringSet(key, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SharedPreferences.preference(key: String, defaultValue: Dp) =
|
||||||
|
mutableStateOf(value = getFloat(key, defaultValue.value).dp) {
|
||||||
|
edit {
|
||||||
|
putFloat(key, it.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SharedPreferences.preference(key: String, defaultValue: TextUnit) =
|
||||||
|
mutableStateOf(value = getFloat(key, defaultValue.value).sp) {
|
||||||
|
edit {
|
||||||
|
putFloat(key, it.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T : Enum<T>> SharedPreferences.preference(
|
||||||
|
key: String,
|
||||||
|
defaultValue: T
|
||||||
|
) = mutableStateOf(value = enumValueOf<T>(getString(key, defaultValue.name)!!)) {
|
||||||
|
edit {
|
||||||
|
putString(key, it.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> mutableStateOf(value: T, onStructuralInequality: (newValue: T) -> Unit) =
|
||||||
|
mutableStateOf(
|
||||||
|
value = value,
|
||||||
|
policy = object : SnapshotMutationPolicy<T> {
|
||||||
|
override fun equivalent(a: T, b: T): Boolean {
|
||||||
|
val areEquals = a == b
|
||||||
|
if (!areEquals) onStructuralInequality(b)
|
||||||
|
return areEquals
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ dependencyResolutionManagement {
|
|||||||
version("accompanist", "0.24.10-beta")
|
version("accompanist", "0.24.10-beta")
|
||||||
alias("accompanist-systemuicontroller").to("com.google.accompanist", "accompanist-systemuicontroller").versionRef("accompanist")
|
alias("accompanist-systemuicontroller").to("com.google.accompanist", "accompanist-systemuicontroller").versionRef("accompanist")
|
||||||
|
|
||||||
alias("datastore").to("androidx.datastore", "datastore-preferences").version("1.0.0")
|
|
||||||
|
|
||||||
version("room", "2.5.0-alpha01")
|
version("room", "2.5.0-alpha01")
|
||||||
alias("room").to("androidx.room", "room-ktx").versionRef("room")
|
alias("room").to("androidx.room", "room-ktx").versionRef("room")
|
||||||
alias("room-compiler").to("androidx.room", "room-compiler").versionRef("room")
|
alias("room-compiler").to("androidx.room", "room-compiler").versionRef("room")
|
||||||
|
|||||||
Reference in New Issue
Block a user