Persist preference for Lock Swiping

This commit is contained in:
William Brawner 2024-08-21 20:53:26 -06:00
parent 9b6a5ba2be
commit dc97ea7b78
5 changed files with 55 additions and 22 deletions

View file

@ -11,6 +11,8 @@ import com.wbrawner.simplemarkdown.utility.PreferenceHelper
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
@ -31,6 +33,7 @@ data class EditorState(
* a new file * a new file
*/ */
val reloadToggle: Int = 0, val reloadToggle: Int = 0,
val lockSwiping: Boolean = false,
private val initialMarkdown: String = "", private val initialMarkdown: String = "",
) { ) {
val dirty: Boolean val dirty: Boolean
@ -49,6 +52,11 @@ class MarkdownViewModel(
viewModelScope.launch { viewModelScope.launch {
load(null) load(null)
} }
preferenceHelper.observe<Boolean>(Preference.LOCK_SWIPING)
.onEach {
_state.value = _state.value.copy(lockSwiping = it)
}
.launchIn(viewModelScope)
} }
fun updateMarkdown(markdown: String?) { fun updateMarkdown(markdown: String?) {
@ -210,11 +218,19 @@ class MarkdownViewModel(
return return
} }
_state.value = _state.value =
EditorState(fileName = untitledFileName, reloadToggle = _state.value.reloadToggle.inv()) EditorState(
fileName = untitledFileName,
reloadToggle = _state.value.reloadToggle.inv(),
lockSwiping = preferenceHelper[Preference.LOCK_SWIPING] as Boolean
)
Timber.i("Removing autosave uri from shared prefs") Timber.i("Removing autosave uri from shared prefs")
preferenceHelper[Preference.AUTOSAVE_URI] = null preferenceHelper[Preference.AUTOSAVE_URI] = null
} }
fun setLockSwiping(enabled: Boolean) {
preferenceHelper[Preference.LOCK_SWIPING] = enabled
}
companion object { companion object {
fun factory( fun factory(
fileHelper: FileHelper, fileHelper: FileHelper,

View file

@ -86,6 +86,7 @@ fun MainScreen(
val dirty by viewModel.collectAsState(EditorState::dirty, false) val dirty by viewModel.collectAsState(EditorState::dirty, false)
val alert by viewModel.collectAsState(EditorState::alert, null) val alert by viewModel.collectAsState(EditorState::alert, null)
val saveCallback by viewModel.collectAsState(EditorState::saveCallback, null) val saveCallback by viewModel.collectAsState(EditorState::saveCallback, null)
val lockSwiping by viewModel.collectAsState(EditorState::lockSwiping, false)
LaunchedEffect(enableAutosave) { LaunchedEffect(enableAutosave) {
if (!enableAutosave) return@LaunchedEffect if (!enableAutosave) return@LaunchedEffect
while (isActive) { while (isActive) {
@ -101,6 +102,8 @@ fun MainScreen(
initialMarkdown = initialMarkdown, initialMarkdown = initialMarkdown,
markdown = markdown, markdown = markdown,
setMarkdown = viewModel::updateMarkdown, setMarkdown = viewModel::updateMarkdown,
lockSwiping = lockSwiping,
toggleLockSwiping = viewModel::setLockSwiping,
message = toast?.stringRes(), message = toast?.stringRes(),
dismissMessage = viewModel::dismissToast, dismissMessage = viewModel::dismissToast,
alert = alert, alert = alert,
@ -137,6 +140,8 @@ private fun MainScreen(
initialMarkdown: String = "", initialMarkdown: String = "",
markdown: String = "", markdown: String = "",
setMarkdown: (String) -> Unit = {}, setMarkdown: (String) -> Unit = {},
lockSwiping: Boolean,
toggleLockSwiping: (Boolean) -> Unit,
message: String? = null, message: String? = null,
dismissMessage: () -> Unit = {}, dismissMessage: () -> Unit = {},
alert: AlertDialogModel? = null, alert: AlertDialogModel? = null,
@ -150,7 +155,6 @@ private fun MainScreen(
enableWideLayout: Boolean = false, enableWideLayout: Boolean = false,
enableReadability: Boolean = false enableReadability: Boolean = false
) { ) {
var lockSwiping by remember { mutableStateOf(true) }
val openFileLauncher = val openFileLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
loadFile(it) loadFile(it)
@ -250,10 +254,11 @@ private fun MainScreen(
Text(stringResource(R.string.action_lock_swipe)) Text(stringResource(R.string.action_lock_swipe))
Checkbox( Checkbox(
checked = lockSwiping, checked = lockSwiping,
onCheckedChange = { lockSwiping = !lockSwiping }) onCheckedChange = toggleLockSwiping
)
} }
}, onClick = { }, onClick = {
lockSwiping = !lockSwiping toggleLockSwiping(!lockSwiping)
menuExpanded = false menuExpanded = false
}) })
} }

View file

@ -1,19 +1,14 @@
package com.wbrawner.simplemarkdown.utility package com.wbrawner.simplemarkdown.utility
import android.content.Context import android.content.Context
import android.net.Uri
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException
interface PreferenceHelper { interface PreferenceHelper {
operator fun get(preference: Preference): Any? operator fun get(preference: Preference): Any?
@ -25,15 +20,7 @@ interface PreferenceHelper {
class AndroidPreferenceHelper(context: Context, private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO)): PreferenceHelper { class AndroidPreferenceHelper(context: Context, private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO)): PreferenceHelper {
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
private val states = mapOf( private val states = Preference.entries.associateWith { MutableStateFlow(get(it)) }
Preference.ANALYTICS_ENABLED to MutableStateFlow(get(Preference.ANALYTICS_ENABLED)),
Preference.AUTOSAVE_ENABLED to MutableStateFlow(get(Preference.AUTOSAVE_ENABLED)),
Preference.AUTOSAVE_URI to MutableStateFlow(get(Preference.AUTOSAVE_URI)),
Preference.CUSTOM_CSS to MutableStateFlow(get(Preference.CUSTOM_CSS)),
Preference.DARK_MODE to MutableStateFlow(get(Preference.DARK_MODE)),
Preference.ERROR_REPORTS_ENABLED to MutableStateFlow(get(Preference.ERROR_REPORTS_ENABLED)),
Preference.READABILITY_ENABLED to MutableStateFlow(get(Preference.READABILITY_ENABLED)),
)
override fun get(preference: Preference): Any? = sharedPreferences.all[preference.key]?: preference.default override fun get(preference: Preference): Any? = sharedPreferences.all[preference.key]?: preference.default
@ -63,5 +50,6 @@ enum class Preference(val key: String, val default: Any?) {
CUSTOM_CSS("pref.custom_css", null), CUSTOM_CSS("pref.custom_css", null),
DARK_MODE("darkMode", "Auto"), DARK_MODE("darkMode", "Auto"),
ERROR_REPORTS_ENABLED("acra.enable", true), ERROR_REPORTS_ENABLED("acra.enable", true),
LOCK_SWIPING("lockSwiping", false),
READABILITY_ENABLED("readability.enable", false) READABILITY_ENABLED("readability.enable", false)
} }

View file

@ -2,17 +2,27 @@ package com.wbrawner.simplemarkdown
import com.wbrawner.simplemarkdown.utility.Preference import com.wbrawner.simplemarkdown.utility.Preference
import com.wbrawner.simplemarkdown.utility.PreferenceHelper import com.wbrawner.simplemarkdown.utility.PreferenceHelper
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
class FakePreferenceHelper: PreferenceHelper { class FakePreferenceHelper: PreferenceHelper {
val preferences = mutableMapOf<Preference, Any?>() val preferences = mutableMapOf<Preference, Any?>()
override fun get(preference: Preference): Any? = preferences[preference]?: preference.default private val preferenceFlows = mutableMapOf<Preference, MutableStateFlow<Any?>>()
private fun preferenceFlow(preference: Preference) = preferenceFlows.getOrPut(preference) {
MutableStateFlow(preference.default)
}
override fun get(preference: Preference): Any? =
(preferences[preference] ?: preference.default).also {
preferenceFlow(preference)
}
override fun set(preference: Preference, value: Any?) { override fun set(preference: Preference, value: Any?) {
preferenceFlow(preference).value = value
preferences[preference] = value preferences[preference] = value
} }
override fun <T> observe(preference: Preference): StateFlow<T> { override fun <T> observe(preference: Preference): StateFlow<T> =
TODO("Not yet implemented") preferenceFlow(preference) as StateFlow<T>
}
} }

View file

@ -288,4 +288,18 @@ class MarkdownViewModelTest {
viewModel.autosave() viewModel.autosave()
assertEquals(2, fileHelper.savedData.count()) assertEquals(2, fileHelper.savedData.count())
} }
@Test
fun testSetLockSwiping() = runTest {
preferenceHelper[Preference.LOCK_SWIPING] = false
assertFalse(viewModel.state.value.lockSwiping)
viewModel.setLockSwiping(true)
viewModelScope.advanceUntilIdle()
assertTrue(preferenceHelper.preferences[Preference.LOCK_SWIPING] as Boolean)
assertTrue(viewModel.state.value.lockSwiping)
viewModel.setLockSwiping(false)
viewModelScope.advanceUntilIdle()
assertFalse(preferenceHelper.preferences[Preference.LOCK_SWIPING] as Boolean)
assertFalse(viewModel.state.value.lockSwiping)
}
} }