Migrate to DataStore

This commit is contained in:
vfsfitvnm
2022-06-05 17:35:07 +02:00
parent c808b2a482
commit b9489e5274

View File

@@ -1,112 +1,123 @@
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.compose.ui.platform.LocalContext import androidx.datastore.core.DataStore
import androidx.compose.ui.unit.Dp import androidx.datastore.preferences.core.edit
import androidx.compose.ui.unit.TextUnit import androidx.datastore.preferences.core.intPreferencesKey
import androidx.compose.ui.unit.dp import androidx.datastore.preferences.core.stringPreferencesKey
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 { @Immutable
var colorPaletteMode by preference("colorPaletteMode", ColorPaletteMode.System) data class Preferences(
var searchFilter by preference("searchFilter", YouTube.Item.Song.Filter.value) val isReady: Boolean,
var repeatMode by preference("repeatMode", Player.REPEAT_MODE_OFF) val colorPaletteMode: ColorPaletteMode,
var homePageSongCollection by preference("homePageSongCollection", SongCollection.MostPlayed) val onColorPaletteModeChange: (ColorPaletteMode) -> Unit,
var thumbnailRoundness by preference("thumbnailRoundness", ThumbnailRoundness.Light) 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 Default = Preferences(isReady = false)
}
} }
val LocalPreferences = staticCompositionLocalOf<Preferences> { TODO() } val LocalPreferences = staticCompositionLocalOf { Preferences.Default }
private val colorPaletteModeKey = stringPreferencesKey("colorPaletteMode")
private val searchFilterKey = stringPreferencesKey("searchFilter")
private val repeatModeKey = intPreferencesKey("repeatMode")
private val homePageSongCollectionKey = stringPreferencesKey("homePageSongCollection")
private val thumbnailRoundnessKey = stringPreferencesKey("thumbnailRoundness")
@Composable @Composable
fun rememberPreferences(): Preferences { fun rememberPreferences(dataStore: DataStore<DataStorePreferences>): State<Preferences> {
val context = LocalContext.current val coroutineScope = rememberCoroutineScope()
return remember {
Preferences(context.getSharedPreferences("preferences", Context.MODE_PRIVATE)) 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: Boolean) =
mutableStateOf(value = getBoolean(key, defaultValue)) {
edit {
putBoolean(key, it)
}
}
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
}
})