From dc97ea7b780054d652448d2563548a0b03e78e64 Mon Sep 17 00:00:00 2001 From: William Brawner Date: Wed, 21 Aug 2024 20:53:26 -0600 Subject: [PATCH 1/3] Persist preference for Lock Swiping --- .../simplemarkdown/MarkdownViewModel.kt | 18 +++++++++++++++++- .../wbrawner/simplemarkdown/ui/MainScreen.kt | 11 ++++++++--- .../simplemarkdown/utility/PreferenceHelper.kt | 16 ++-------------- .../simplemarkdown/FakePreferenceHelper.kt | 18 ++++++++++++++---- .../simplemarkdown/MarkdownViewModelTest.kt | 14 ++++++++++++++ 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownViewModel.kt b/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownViewModel.kt index c2d0955..f20312a 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownViewModel.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownViewModel.kt @@ -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(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, diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/ui/MainScreen.kt b/app/src/main/java/com/wbrawner/simplemarkdown/ui/MainScreen.kt index 62a39d0..5cef4d2 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/ui/MainScreen.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/ui/MainScreen.kt @@ -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 }) } diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/utility/PreferenceHelper.kt b/app/src/main/java/com/wbrawner/simplemarkdown/utility/PreferenceHelper.kt index 747da2f..d26a3a5 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/utility/PreferenceHelper.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/utility/PreferenceHelper.kt @@ -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) } \ No newline at end of file diff --git a/app/src/test/java/com/wbrawner/simplemarkdown/FakePreferenceHelper.kt b/app/src/test/java/com/wbrawner/simplemarkdown/FakePreferenceHelper.kt index bd00a9c..a600129 100644 --- a/app/src/test/java/com/wbrawner/simplemarkdown/FakePreferenceHelper.kt +++ b/app/src/test/java/com/wbrawner/simplemarkdown/FakePreferenceHelper.kt @@ -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() - override fun get(preference: Preference): Any? = preferences[preference]?: preference.default + private val preferenceFlows = mutableMapOf>() + + 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 observe(preference: Preference): StateFlow { - TODO("Not yet implemented") - } + override fun observe(preference: Preference): StateFlow = + preferenceFlow(preference) as StateFlow } \ No newline at end of file diff --git a/app/src/test/java/com/wbrawner/simplemarkdown/MarkdownViewModelTest.kt b/app/src/test/java/com/wbrawner/simplemarkdown/MarkdownViewModelTest.kt index 44fe955..f4e0a88 100644 --- a/app/src/test/java/com/wbrawner/simplemarkdown/MarkdownViewModelTest.kt +++ b/app/src/test/java/com/wbrawner/simplemarkdown/MarkdownViewModelTest.kt @@ -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) + } } \ No newline at end of file -- 2.45.2 From 90ab7f93971065eaec29a13f2eae28bd0dde8535 Mon Sep 17 00:00:00 2001 From: William Brawner Date: Wed, 21 Aug 2024 22:12:25 -0600 Subject: [PATCH 2/3] Enable gestures on nav drawer when open --- .../com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt b/app/src/main/java/com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt index 0551b0c..34765d5 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt @@ -30,7 +30,7 @@ fun MarkdownNavigationDrawer( val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val coroutineScope = rememberCoroutineScope() DismissibleNavigationDrawer( - gesturesEnabled = false, + gesturesEnabled = drawerState.isOpen, drawerState = drawerState, drawerContent = { DismissibleDrawerSheet { -- 2.45.2 From 094ac1fccffedb7ef5de8977ab2b4ad502811b17 Mon Sep 17 00:00:00 2001 From: William Brawner Date: Wed, 21 Aug 2024 22:20:25 -0600 Subject: [PATCH 3/3] Close navigation drawer on back press --- .../wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt b/app/src/main/java/com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt index 34765d5..da43067 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/ui/MarkdownNavigationDrawer.kt @@ -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,6 +30,11 @@ fun MarkdownNavigationDrawer( ) { val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val coroutineScope = rememberCoroutineScope() + BackHandler(enabled = drawerState.isOpen) { + coroutineScope.launch { + drawerState.close() + } + } DismissibleNavigationDrawer( gesturesEnabled = drawerState.isOpen, drawerState = drawerState, -- 2.45.2