From 7c6d4c5a2bdc0ff56fc70dbfb1d2bb89efbc49aa Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sat, 1 Jun 2024 15:26:12 +0300 Subject: [PATCH] Replace livedata with flow in WebReaderViewModel --- .../core/database/dao/SavedItemLabelDao.kt | 2 +- .../omnivore/feature/reader/WebReader.kt | 3 +- .../reader/WebReaderLoadingContainer.kt | 17 ++--- .../feature/reader/WebReaderViewModel.kt | 63 +++++++++---------- 4 files changed, 40 insertions(+), 45 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemLabelDao.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemLabelDao.kt index af75d6c0c..b33646e49 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemLabelDao.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemLabelDao.kt @@ -21,7 +21,7 @@ interface SavedItemLabelDao { @Transaction @Query("SELECT * FROM SavedItemLabel WHERE serverSyncStatus != 2 ORDER BY name ASC") - fun getSavedItemLabelsLiveData(): LiveData> + fun getSavedItemLabelsFlow(): Flow> @Transaction @Query("UPDATE SavedItemLabel set savedItemLabelId = :permanentId, serverSyncStatus = :status WHERE savedItemLabelId = :tempId") diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReader.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReader.kt index e0e67ece5..cc3977e2b 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReader.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReader.kt @@ -19,7 +19,6 @@ import android.webkit.WebViewClient import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.runtime.* -import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Modifier import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -38,7 +37,7 @@ fun WebReader( currentTheme: Themes?, modifier: Modifier = Modifier ) { - val javascriptActionLoopUUID: UUID by webReaderViewModel.javascriptActionLoopUUIDLiveData.observeAsState( + val javascriptActionLoopUUID: UUID by webReaderViewModel.javascriptActionLoopUUIDFlow.collectAsStateWithLifecycle( UUID.randomUUID() ) val isDarkMode = isSystemInDarkTheme() diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderLoadingContainer.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderLoadingContainer.kt index cdb28e963..6f124b9f6 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderLoadingContainer.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderLoadingContainer.kt @@ -48,6 +48,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.omnivore.omnivore.MainActivity import app.omnivore.omnivore.R import app.omnivore.omnivore.core.database.entities.SavedItemLabel @@ -132,7 +133,9 @@ fun WebReaderLoadingContainer( labelsViewModel: LabelsViewModel, editInfoViewModel: EditInfoViewModel ) { - val currentThemeKey = webReaderViewModel.currentThemeKey.observeAsState() + val currentThemeKey = webReaderViewModel.currentThemeKey.collectAsStateWithLifecycle( + "System" + ) val currentTheme by remember { derivedStateOf { Themes.entries.find { it.themeKey == currentThemeKey.value } @@ -143,12 +146,12 @@ fun WebReaderLoadingContainer( BottomSheetState.NONE ) - val webReaderParams: WebReaderParams? by webReaderViewModel.webReaderParamsLiveData.observeAsState( + val webReaderParams: WebReaderParams? by webReaderViewModel.webReaderParamsFlow.collectAsStateWithLifecycle( null ) - val shouldPopView: Boolean by webReaderViewModel.shouldPopViewLiveData.observeAsState(false) + val shouldPopView: Boolean by webReaderViewModel.shouldPopViewFlow.collectAsStateWithLifecycle(false) - val labels: List by webReaderViewModel.savedItemLabelsLiveData.observeAsState( + val labels: List by webReaderViewModel.savedItemLabelsFlow.collectAsStateWithLifecycle( listOf() ) @@ -371,16 +374,16 @@ fun ReaderTopAppBar( val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher val isDarkMode = isSystemInDarkTheme() - val currentThemeKey = webReaderViewModel.currentThemeKey.observeAsState() + val currentThemeKey = webReaderViewModel.currentThemeKey.collectAsStateWithLifecycle("System") val currentTheme by remember { derivedStateOf { Themes.entries.find { it.themeKey == currentThemeKey.value } } } - val toolbarHeightPx: Float by webReaderViewModel.currentToolbarHeightLiveData.observeAsState( + val toolbarHeightPx: Float by webReaderViewModel.currentToolbarHeightFlow.collectAsStateWithLifecycle( 0.0f ) - val webReaderParams: WebReaderParams? by webReaderViewModel.webReaderParamsLiveData.observeAsState( + val webReaderParams: WebReaderParams? by webReaderViewModel.webReaderParamsFlow.collectAsStateWithLifecycle( null ) var isMenuExpanded by remember { mutableStateOf(false) } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt index 1c11941e3..abdb71073 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt @@ -8,10 +8,7 @@ import android.net.Uri import android.util.Log import android.widget.Toast import androidx.core.content.ContextCompat.startActivity -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import app.omnivore.omnivore.R import app.omnivore.omnivore.core.analytics.EventTracker @@ -51,6 +48,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -101,13 +99,13 @@ class WebReaderViewModel @Inject constructor( var javascriptDispatchQueue: MutableList = mutableListOf() var maxToolbarHeightPx = 0.0f - val webReaderParamsLiveData = MutableLiveData(null) + val webReaderParamsFlow = MutableStateFlow(null) var annotation: String? = null - val javascriptActionLoopUUIDLiveData = MutableLiveData(lastJavascriptActionLoopUUID) - val shouldPopViewLiveData = MutableLiveData(false) - val hasFetchError = MutableLiveData(false) - val currentToolbarHeightLiveData = MutableLiveData(0.0f) - val savedItemLabelsLiveData = dataService.db.savedItemLabelDao().getSavedItemLabelsLiveData() + val javascriptActionLoopUUIDFlow = MutableStateFlow(lastJavascriptActionLoopUUID) + val shouldPopViewFlow = MutableStateFlow(false) + val hasFetchError = MutableStateFlow(false) + val currentToolbarHeightFlow = MutableStateFlow(0.0f) + val savedItemLabelsFlow = dataService.db.savedItemLabelDao().getSavedItemLabelsFlow() var currentLink: Uri? = null val bottomSheetStateFlow = MutableStateFlow(BottomSheetState.NONE) @@ -117,12 +115,12 @@ class WebReaderViewModel @Inject constructor( private var isLoading = false private var slug: String? = null - private val showHighlightColorPalette = MutableLiveData(false) - val highlightColor = MutableLiveData(HighlightColor()) + private val showHighlightColorPalette = MutableStateFlow(false) + val highlightColor = MutableStateFlow(HighlightColor()) fun loadItem(slug: String?, requestID: String?) { this.slug = slug - if (isLoading || webReaderParamsLiveData.value != null) { + if (isLoading || webReaderParamsFlow.value != null) { return } isLoading = true @@ -147,7 +145,7 @@ class WebReaderViewModel @Inject constructor( } fun showOpenLinkSheet(context: Context, uri: Uri) { - webReaderParamsLiveData.value?.let { + webReaderParamsFlow.value?.let { if (it.item.pageURLString == uri.toString()) { openLink(context, uri) } else { @@ -160,7 +158,7 @@ class WebReaderViewModel @Inject constructor( } fun showShareLinkSheet(context: Context) { - webReaderParamsLiveData.value?.let { + webReaderParamsFlow.value?.let { val sendIntent = Intent(Intent.ACTION_SEND) sendIntent.setType("text/plain") @@ -218,8 +216,8 @@ class WebReaderViewModel @Inject constructor( } fun onScrollChange(delta: Float) { - val newHeight = (currentToolbarHeightLiveData.value ?: 0.0f) + delta - currentToolbarHeightLiveData.value = newHeight.coerceIn(0f, maxToolbarHeightPx) + val newHeight = (currentToolbarHeightFlow.value) + delta + currentToolbarHeightFlow.value = newHeight.coerceIn(0f, maxToolbarHeightPx) } private suspend fun loadItemUsingSlug(slug: String) { @@ -237,7 +235,7 @@ class WebReaderViewModel @Inject constructor( .putValue("originalArticleURL", webReaderParams.item.pageURLString) .putValue("loaded_from", "network") ) - webReaderParamsLiveData.postValue(webReaderParams) + webReaderParamsFlow.update { webReaderParams } isLoading = false } } @@ -256,14 +254,14 @@ class WebReaderViewModel @Inject constructor( .putValue("originalArticleURL", webReaderParams.item.pageURLString) .putValue("loaded_from", "request_id") ) - webReaderParamsLiveData.postValue(webReaderParams) + webReaderParamsFlow.update { (webReaderParams) } isLoading = false } else if (requestCount < 7) { // delay then try again delay(2000L) loadItemUsingRequestID(requestID = requestID, requestCount = requestCount + 1) } else { - hasFetchError.postValue(true) + hasFetchError.update { true } } } @@ -298,7 +296,7 @@ class WebReaderViewModel @Inject constructor( .putValue("originalArticleURL", webReaderParams.item.pageURLString) .putValue("loaded_from", "db") ) - webReaderParamsLiveData.postValue(webReaderParams) + webReaderParamsFlow.update { webReaderParams } } } isLoading = false @@ -363,22 +361,18 @@ class WebReaderViewModel @Inject constructor( } } - private fun popToLibraryView() { - CoroutineScope(Dispatchers.Main).launch { - shouldPopViewLiveData.postValue(true) - } + private fun popToLibraryView() = viewModelScope.launch { + shouldPopViewFlow.update { true } } - fun showHighlightColorPalette() { - CoroutineScope(Dispatchers.Main).launch { - showHighlightColorPalette.postValue(true) - } + fun showHighlightColorPalette() = viewModelScope.launch { + showHighlightColorPalette.update { true } } fun hideHighlightColorPalette() { CoroutineScope(Dispatchers.Main).launch { - showHighlightColorPalette.postValue(false) + showHighlightColorPalette.update { false } } } @@ -387,7 +381,7 @@ class WebReaderViewModel @Inject constructor( when (actionID) { "createHighlight" -> { viewModelScope.launch { - dataService.createWebHighlight(jsonString, highlightColor.value?.name) + dataService.createWebHighlight(jsonString, highlightColor.value.name) } } @@ -436,7 +430,7 @@ class WebReaderViewModel @Inject constructor( } fun resetJavascriptDispatchQueue() { - lastJavascriptActionLoopUUID = javascriptActionLoopUUIDLiveData.value ?: UUID.randomUUID() + lastJavascriptActionLoopUUID = javascriptActionLoopUUIDFlow.value javascriptDispatchQueue = mutableListOf() } @@ -465,13 +459,12 @@ class WebReaderViewModel @Inject constructor( private fun enqueueScript(javascript: String) { javascriptDispatchQueue.add(javascript) - javascriptActionLoopUUIDLiveData.value = UUID.randomUUID() + javascriptActionLoopUUIDFlow.value = UUID.randomUUID() } - val currentThemeKey: LiveData = datastoreRepository + val currentThemeKey: Flow = datastoreRepository .themeKeyFlow .distinctUntilChanged() - .asLiveData() fun storedWebPreferences(isDarkMode: Boolean): WebPreferences = runBlocking { val storedFontSize = datastoreRepository.getInt(preferredWebFontSize) @@ -627,7 +620,7 @@ class WebReaderViewModel @Inject constructor( loadItemFromDB(it) } - webReaderParamsLiveData.value?.item?.title?.let { + webReaderParamsFlow.value?.item?.title?.let { updateItemTitleInWebView(it) } }