package com.vgmlr.varnish
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.MutablePreferences
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import java.io.IOException
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
private val Context.varnishStore: DataStore<Preferences> by preferencesDataStore(name = "varnish")
data class VarnishSettings(
val scan: ScanMode = ScanMode.FILES,
val types: FileTypes = FileTypes.BOTH,
val showHidden: Boolean = false,
val confirmDelete: Boolean = true,
val editorPkg: String = "",
val playerPkg: String = "",
val folderImg: Int = VarnishConfig.FOLDER_IMG_DEFAULT,
val gridCols: Int = VarnishConfig.GRID_DEFAULT,
val outFormat: OutFormat = OutFormat.JPG,
val quality: Int = VarnishConfig.QUALITY_DEFAULT,
val keepExif: Boolean = false,
val sort: SortMode = SortMode.AZ,
val saveView: Boolean = true
)
class VarnishPrefs(context: Context) {
private val store = context.applicationContext.varnishStore
val settings: Flow<VarnishSettings> = store.data
.catch { if (it is IOException) emit(emptyPreferences()) else throw it }
.map(::read)
suspend fun update(block: (VarnishSettings) -> VarnishSettings) {
store.edit { p -> write(p, block(read(p))) }
}
private fun read(p: Preferences) = VarnishSettings(
scan = enumOr(p[SCAN], ScanMode.FILES),
types = enumOr(p[TYPES], FileTypes.BOTH),
showHidden = p[HIDDEN] ?: false,
confirmDelete = p[CONFIRM] ?: true,
editorPkg = p[EDITOR] ?: "",
playerPkg = p[PLAYER] ?: "",
folderImg = (p[FOLDER_IMG] ?: VarnishConfig.FOLDER_IMG_DEFAULT)
.coerceIn(VarnishConfig.FOLDER_IMG_MIN, VarnishConfig.FOLDER_IMG_MAX),
gridCols = (p[GRID] ?: VarnishConfig.GRID_DEFAULT).coerceIn(2, 6),
outFormat = enumOr(p[FORMAT], OutFormat.JPG),
quality = (p[QUALITY] ?: VarnishConfig.QUALITY_DEFAULT).coerceIn(10, 100),
keepExif = p[EXIF] ?: false,
sort = enumOr(p[SORT], SortMode.AZ),
saveView = p[SAVE_VIEW] ?: true
)
private fun write(p: MutablePreferences, s: VarnishSettings) {
p[SCAN] = s.scan.name
p[TYPES] = s.types.name
p[HIDDEN] = s.showHidden
p[CONFIRM] = s.confirmDelete
p[EDITOR] = s.editorPkg
p[PLAYER] = s.playerPkg
p[FOLDER_IMG] = s.folderImg
p[GRID] = s.gridCols
p[FORMAT] = s.outFormat.name
p[QUALITY] = s.quality
p[EXIF] = s.keepExif
p[SORT] = s.sort.name
p[SAVE_VIEW] = s.saveView
}
private companion object {
val SCAN = stringPreferencesKey("scan")
val TYPES = stringPreferencesKey("types")
val HIDDEN = booleanPreferencesKey("show_hidden")
val CONFIRM = booleanPreferencesKey("confirm_delete")
val EDITOR = stringPreferencesKey("editor_pkg")
val PLAYER = stringPreferencesKey("player_pkg")
val FOLDER_IMG = intPreferencesKey("folder_img")
val GRID = intPreferencesKey("grid_cols")
val FORMAT = stringPreferencesKey("out_format")
val QUALITY = intPreferencesKey("quality")
val EXIF = booleanPreferencesKey("keep_exif")
val SORT = stringPreferencesKey("sort")
val SAVE_VIEW = booleanPreferencesKey("save_view")
}
}
private inline fun <reified T : Enum<T>> enumOr(name: String?, def: T): T =
name?.let { runCatching { enumValueOf<T>(it) }.getOrNull() } ?: def