Persist preference for Lock Swiping #26

Merged
wbrawner merged 3 commits from persist-lock-swiping into main 2024-08-22 06:06:08 +00:00
6 changed files with 62 additions and 23 deletions

View file

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

View file

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

View file

@ -1,5 +1,6 @@
package com.wbrawner.simplemarkdown.ui
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
@ -29,8 +30,13 @@ fun MarkdownNavigationDrawer(
) {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val coroutineScope = rememberCoroutineScope()
BackHandler(enabled = drawerState.isOpen) {
coroutineScope.launch {
drawerState.close()
}
}
DismissibleNavigationDrawer(
gesturesEnabled = false,
gesturesEnabled = drawerState.isOpen,
drawerState = drawerState,
drawerContent = {
DismissibleDrawerSheet {

View file

@ -1,19 +1,14 @@
package com.wbrawner.simplemarkdown.utility
import android.content.Context
import android.net.Uri
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException
interface PreferenceHelper {
operator fun get(preference: Preference): Any?
@ -25,15 +20,7 @@ interface PreferenceHelper {
class AndroidPreferenceHelper(context: Context, private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO)): PreferenceHelper {
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
private val states = mapOf(
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)),
)
private val states = Preference.entries.associateWith { MutableStateFlow(get(it)) }
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),
DARK_MODE("darkMode", "Auto"),
ERROR_REPORTS_ENABLED("acra.enable", true),
LOCK_SWIPING("lockSwiping", 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.PreferenceHelper
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
class FakePreferenceHelper: PreferenceHelper {
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?) {
preferenceFlow(preference).value = value
preferences[preference] = value
}
override fun <T> observe(preference: Preference): StateFlow<T> {
TODO("Not yet implemented")
}
override fun <T> observe(preference: Preference): StateFlow<T> =
preferenceFlow(preference) as StateFlow<T>
}

View file

@ -288,4 +288,18 @@ class MarkdownViewModelTest {
viewModel.autosave()
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)
}
}