Migrate to DataStore
This commit is contained in:
parent
c808b2a482
commit
b9489e5274
1 changed files with 109 additions and 98 deletions
|
@ -1,112 +1,123 @@
|
|||
package it.vfsfitvnm.vimusic.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.edit
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.intPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.media3.common.Player
|
||||
import it.vfsfitvnm.vimusic.enums.ColorPaletteMode
|
||||
import it.vfsfitvnm.vimusic.enums.SongCollection
|
||||
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
|
||||
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
|
||||
data class Preferences(
|
||||
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 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
|
||||
fun rememberPreferences(): Preferences {
|
||||
val context = LocalContext.current
|
||||
return remember {
|
||||
Preferences(context.getSharedPreferences("preferences", Context.MODE_PRIVATE))
|
||||
}
|
||||
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: 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
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue