add saved item flow in library view model

This commit is contained in:
Stefano Sansone
2024-02-21 00:01:02 +00:00
parent 9d800366c2
commit e61df9d02e
9 changed files with 81 additions and 49 deletions

View File

@ -1,6 +1,6 @@
package app.omnivore.omnivore.core.data
import app.omnivore.omnivore.core.database.AppDatabase
import app.omnivore.omnivore.core.database.OmnivoreDatabase
import app.omnivore.omnivore.core.database.entities.SavedItem
import app.omnivore.omnivore.core.network.Networker
import kotlinx.coroutines.CoroutineScope
@ -11,11 +11,11 @@ import javax.inject.Inject
class DataService @Inject constructor(
val networker: Networker,
appDatabase: AppDatabase
omnivoreDatabase: OmnivoreDatabase
) {
val savedItemSyncChannel = Channel<SavedItem>(capacity = Channel.UNLIMITED)
val db = appDatabase
val db = omnivoreDatabase
init {
CoroutineScope(Dispatchers.IO).launch {

View File

@ -19,25 +19,24 @@ import app.omnivore.omnivore.core.database.entities.Viewer
import app.omnivore.omnivore.core.database.entities.ViewerDao
@Database(
entities = [
Viewer::class,
SavedItem::class,
SavedItemLabel::class,
Highlight::class,
HighlightChange::class,
SavedItemAndSavedItemLabelCrossRef::class,
SavedItemAndHighlightCrossRef::class
],
version = 24,
exportSchema = false
entities = [
Viewer::class,
SavedItem::class,
SavedItemLabel::class,
Highlight::class,
HighlightChange::class,
SavedItemAndSavedItemLabelCrossRef::class,
SavedItemAndHighlightCrossRef::class],
version = 24,
exportSchema = true
)
abstract class AppDatabase : RoomDatabase() {
abstract fun viewerDao(): ViewerDao
abstract fun savedItemDao(): SavedItemDao
abstract fun highlightDao(): HighlightDao
abstract fun highlightChangesDao(): HighlightChangesDao
abstract fun savedItemLabelDao(): SavedItemLabelDao
abstract fun savedItemWithLabelsAndHighlightsDao(): SavedItemWithLabelsAndHighlightsDao
abstract fun savedItemAndSavedItemLabelCrossRefDao(): SavedItemAndSavedItemLabelCrossRefDao
abstract fun savedItemAndHighlightCrossRefDao(): SavedItemAndHighlightCrossRefDao
abstract class OmnivoreDatabase : RoomDatabase() {
abstract fun viewerDao(): ViewerDao
abstract fun savedItemDao(): SavedItemDao
abstract fun highlightDao(): HighlightDao
abstract fun highlightChangesDao(): HighlightChangesDao
abstract fun savedItemLabelDao(): SavedItemLabelDao
abstract fun savedItemWithLabelsAndHighlightsDao(): SavedItemWithLabelsAndHighlightsDao
abstract fun savedItemAndSavedItemLabelCrossRefDao(): SavedItemAndSavedItemLabelCrossRefDao
abstract fun savedItemAndHighlightCrossRefDao(): SavedItemAndHighlightCrossRefDao
}

View File

@ -13,7 +13,6 @@ import kotlinx.coroutines.flow.Flow
@Dao
interface SavedItemDao {
@Transaction
@Query("SELECT * FROM savedItem")
fun getAll(): Flow<List<SavedItem>>

View File

@ -73,7 +73,20 @@ data class SavedItemWithLabelsAndHighlights(
associateBy = Junction(SavedItemAndHighlightCrossRef::class)
)
val highlights: List<Highlight>
)
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as SavedItemWithLabelsAndHighlights
return savedItem.savedItemId == other.savedItem.savedItemId
}
override fun hashCode(): Int {
return savedItem.savedItemId.hashCode()
}
}
@Dao
interface HighlightDao {

View File

@ -3,7 +3,7 @@ package app.omnivore.omnivore.di
import android.content.Context
import app.omnivore.omnivore.core.analytics.EventTracker
import app.omnivore.omnivore.core.data.DataService
import app.omnivore.omnivore.core.database.AppDatabase
import app.omnivore.omnivore.core.database.OmnivoreDatabase
import app.omnivore.omnivore.core.datastore.DatastoreRepository
import app.omnivore.omnivore.core.datastore.OmnivoreDatastore
import app.omnivore.omnivore.core.network.Networker
@ -35,8 +35,8 @@ object AppModule {
@Singleton
@Provides
fun provideDataService(
networker: Networker,
appDatabase: AppDatabase
) = DataService(networker, appDatabase)
networker: Networker,
omnivoreDatabase: OmnivoreDatabase
) = DataService(networker, omnivoreDatabase)
}

View File

@ -1,6 +1,6 @@
package app.omnivore.omnivore.di
import app.omnivore.omnivore.core.database.AppDatabase
import app.omnivore.omnivore.core.database.OmnivoreDatabase
import app.omnivore.omnivore.core.database.dao.SavedItemDao
import dagger.Module
import dagger.Provides
@ -10,8 +10,9 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
object DaosModule {
@Provides
fun providesTopicsDao(
database: AppDatabase,
fun providesSavedItemDao(
database: OmnivoreDatabase,
): SavedItemDao = database.savedItemDao()
}

View File

@ -2,7 +2,7 @@ package app.omnivore.omnivore.di
import android.content.Context
import androidx.room.Room
import app.omnivore.omnivore.core.database.AppDatabase
import app.omnivore.omnivore.core.database.OmnivoreDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -17,9 +17,9 @@ object DatabaseModule {
@Singleton
fun providesOmnivoreDatabase(
@ApplicationContext context: Context,
): AppDatabase = Room.databaseBuilder(
): OmnivoreDatabase = Room.databaseBuilder(
context,
AppDatabase::class.java,
OmnivoreDatabase::class.java,
"omnivore-database",
).build()
}

View File

@ -20,7 +20,6 @@ import androidx.compose.material.DismissValue
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.FractionalThreshold
import androidx.compose.material.Icon
import androidx.compose.material.Scaffold
import androidx.compose.material.ScaffoldState
import androidx.compose.material.SwipeToDismiss
import androidx.compose.material.icons.Icons
@ -36,6 +35,7 @@ import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@ -45,6 +45,7 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -127,7 +128,6 @@ internal fun LibraryView(
}
Scaffold(
scaffoldState = scaffoldState,
topBar = {
LibraryNavigationBar(
savedItemViewModel = viewModel,
@ -334,8 +334,7 @@ fun LibraryViewContent(
val swipeThreshold = 0.45f
val currentThresholdFraction = remember { mutableStateOf(0f) }
//val currentItem by rememberUpdatedState(cardDataWithLabels.savedItem)
val currentItem = cardDataWithLabels.savedItem
val currentItem by rememberUpdatedState(cardDataWithLabels.savedItem)
val swipeState = rememberDismissState(
confirmStateChange = {
when(it) {
@ -412,10 +411,15 @@ fun LibraryViewContent(
dismissContent = {
val selected =
currentItem.savedItemId == selectedItem?.savedItem?.savedItemId
val test = SavedItemWithLabelsAndHighlights(
savedItem = cardDataWithLabels.savedItem,
labels = listOf(),
highlights = listOf()
)
SavedItemCard(
selected = selected,
savedItemViewModel = libraryViewModel,
savedItem = cardDataWithLabels,
savedItem = test,
onClickHandler = {
libraryViewModel.actionsMenuItemLiveData.postValue(null)
val activityClass =

View File

@ -33,22 +33,16 @@ import com.apollographql.apollo3.api.Optional
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.time.Instant
import javax.inject.Inject
@OptIn(ExperimentalCoroutinesApi::class)
@HiltViewModel
class LibraryViewModel @Inject constructor(
private val networker: Networker,
@ -75,16 +69,33 @@ class LibraryViewModel @Inject constructor(
)
)
val uiState: StateFlow<LibraryUiState> = _libraryQuery.flatMapLatest { query ->
// Correct way - but not working
/* val uiState: StateFlow<LibraryUiState> = _libraryQuery.flatMapLatest { query ->
libraryRepository.getSavedItems(query)
}
.map(LibraryUiState::Success)
.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
started = SharingStarted.Lazily,
initialValue = LibraryUiState.Loading
)
)*/
// This approach needs to be replaced with the StateFlow above after fixing Room Flow
private val _uiState = MutableStateFlow<LibraryUiState>(LibraryUiState.Loading)
val uiState: StateFlow<LibraryUiState> = _uiState
init {
loadSavedItems()
}
private fun loadSavedItems() {
viewModelScope.launch {
libraryRepository.getSavedItems(_libraryQuery.value)
.collect { favoriteNews ->
_uiState.value = LibraryUiState.Success(favoriteNews)
}
}
}
private val itemsLiveData = MediatorLiveData<List<SavedItemWithLabelsAndHighlights>>()
val appliedFilterLiveData = MutableLiveData(SavedItemFilter.INBOX)
@ -259,6 +270,7 @@ class LibraryViewModel @Inject constructor(
excludedLabels = excludeLabels,
allowedContentReaders = allowedContentReaders
)
loadSavedItems()
}
}
@ -338,13 +350,17 @@ class LibraryViewModel @Inject constructor(
SavedItemAction.MarkRead -> {
viewModelScope.launch {
_uiState.value = LibraryUiState.Success(emptyList())
libraryRepository.updateReadingProgress(itemID, 100.0, 0)
loadSavedItems()
}
}
SavedItemAction.MarkUnread -> {
viewModelScope.launch {
_uiState.value = LibraryUiState.Success(emptyList())
libraryRepository.updateReadingProgress(itemID, 0.0, 0)
loadSavedItems()
}
}
}