diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/HighlightChangesDao.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/HighlightChangesDao.kt new file mode 100644 index 000000000..b1e08984a --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/HighlightChangesDao.kt @@ -0,0 +1,19 @@ +package app.omnivore.omnivore.core.database.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import app.omnivore.omnivore.core.database.entities.HighlightChange + +@Dao +interface HighlightChangesDao { + @Query("SELECT * FROM highlightChange WHERE serverSyncStatus != 0 ORDER BY updatedAt ASC") + fun getUnSynced(): List + + @Query("DELETE FROM highlightChange WHERE highlightId = :highlightId") + fun deleteById(highlightId: String) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertAll(items: List) +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/HighlightDao.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/HighlightDao.kt new file mode 100644 index 000000000..aa8fc2bb6 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/HighlightDao.kt @@ -0,0 +1,31 @@ +package app.omnivore.omnivore.core.database.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Update +import app.omnivore.omnivore.core.data.model.ServerSyncStatus +import app.omnivore.omnivore.core.database.entities.Highlight + +@Dao +interface HighlightDao { + @Query("SELECT * FROM highlight WHERE serverSyncStatus != 0") + fun getUnSynced(): List + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertAll(items: List) + + @Query("DELETE FROM highlight WHERE highlightId = :highlightId") + fun deleteById(highlightId: String) + + @Query("SELECT * FROM highlight WHERE highlightId = :highlightId") + fun findById(highlightId: String): Highlight? + + // Server sync status is passed in here to work around Room compile-time query rules, but should always be NEEDS_UPDATE + @Query("UPDATE highlight SET annotation = :note, serverSyncStatus = :serverSyncStatus WHERE highlightId = :highlightId") + fun updateNote(highlightId: String, note: String, serverSyncStatus: Int = ServerSyncStatus.NEEDS_UPDATE.rawValue) + + @Update + fun update(highlight: Highlight) +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemAndSavedItemLabelCrossRefDao.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemAndSavedItemLabelCrossRefDao.kt new file mode 100644 index 000000000..0e34b4a4c --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemAndSavedItemLabelCrossRefDao.kt @@ -0,0 +1,16 @@ +package app.omnivore.omnivore.core.database.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import app.omnivore.omnivore.core.database.entities.SavedItemAndSavedItemLabelCrossRef + +@Dao +interface SavedItemAndSavedItemLabelCrossRefDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(items: List) + + @Query("DELETE FROM savedItemAndSavedItemLabelCrossRef WHERE savedItemId = :savedItemId") + suspend fun deleteRefsBySavedItemId(savedItemId: String) +} 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 new file mode 100644 index 000000000..af75d6c0c --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemLabelDao.kt @@ -0,0 +1,35 @@ +package app.omnivore.omnivore.core.database.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Transaction +import app.omnivore.omnivore.core.data.model.ServerSyncStatus +import app.omnivore.omnivore.core.database.entities.SavedItemLabel +import kotlinx.coroutines.flow.Flow + +@Dao +interface SavedItemLabelDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(items: List) + + @Transaction + @Query("SELECT * FROM SavedItemLabel WHERE serverSyncStatus != 2 ORDER BY name ASC") + fun getSavedItemLabels(): Flow> + + @Transaction + @Query("SELECT * FROM SavedItemLabel WHERE serverSyncStatus != 2 ORDER BY name ASC") + fun getSavedItemLabelsLiveData(): LiveData> + + @Transaction + @Query("UPDATE SavedItemLabel set savedItemLabelId = :permanentId, serverSyncStatus = :status WHERE savedItemLabelId = :tempId") + fun updateTempLabel( + tempId: String, permanentId: String, status: ServerSyncStatus = ServerSyncStatus.IS_SYNCED + ) + + @Transaction + @Query("SELECT * FROM SavedItemLabel WHERE name in (:names) ORDER BY name ASC") + suspend fun namedLabels(names: List): List +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemWithLabelsAndHighlightsDao.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemWithLabelsAndHighlightsDao.kt new file mode 100644 index 000000000..45f9f45c0 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/database/dao/SavedItemWithLabelsAndHighlightsDao.kt @@ -0,0 +1,70 @@ +package app.omnivore.omnivore.core.database.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Transaction +import app.omnivore.omnivore.core.database.entities.Highlight +import app.omnivore.omnivore.core.database.entities.SavedItem +import app.omnivore.omnivore.core.database.entities.SavedItemAndHighlightCrossRef +import app.omnivore.omnivore.core.database.entities.SavedItemAndSavedItemLabelCrossRef +import app.omnivore.omnivore.core.database.entities.SavedItemLabel +import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights + +@Dao +abstract class SavedItemWithLabelsAndHighlightsDao { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun insertSavedItems(items: List) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun insertLabelCrossRefs(items: List) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun insertLabels(items: List) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun insertHighlights(items: List) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun insertHighlightCrossRefs(items: List) + + @Transaction + open suspend fun insertAll(savedItems: List) { + insertSavedItems(savedItems.map { it.savedItem }) + + val labels: MutableList = mutableListOf() + val highlights: MutableList = mutableListOf() + + val labelCrossRefs: MutableList = mutableListOf() + val highlightCrossRefs: MutableList = mutableListOf() + + for (searchItem in savedItems) { + labels.addAll(searchItem.labels) + highlights.addAll(searchItem.highlights) + + val newLabelCrossRefs = searchItem.labels.map { + SavedItemAndSavedItemLabelCrossRef( + savedItemLabelId = it.savedItemLabelId, + savedItemId = searchItem.savedItem.savedItemId + ) + } + + val newHighlightCrossRefs = searchItem.highlights.map { + SavedItemAndHighlightCrossRef( + highlightId = it.highlightId, + savedItemId = searchItem.savedItem.savedItemId + ) + } + + labelCrossRefs.addAll(newLabelCrossRefs) + highlightCrossRefs.addAll(newHighlightCrossRefs) + } + + insertLabels(labels) + insertLabelCrossRefs(labelCrossRefs) + + insertHighlights(highlights) + insertHighlightCrossRefs(highlightCrossRefs) + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/di/DaosModule.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/di/DaosModule.kt index f2175bb1f..aa11efbb8 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/di/DaosModule.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/di/DaosModule.kt @@ -1,7 +1,12 @@ package app.omnivore.omnivore.di import app.omnivore.omnivore.core.database.OmnivoreDatabase +import app.omnivore.omnivore.core.database.dao.HighlightChangesDao +import app.omnivore.omnivore.core.database.dao.HighlightDao +import app.omnivore.omnivore.core.database.dao.SavedItemAndSavedItemLabelCrossRefDao import app.omnivore.omnivore.core.database.dao.SavedItemDao +import app.omnivore.omnivore.core.database.dao.SavedItemLabelDao +import app.omnivore.omnivore.core.database.dao.SavedItemWithLabelsAndHighlightsDao import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -15,4 +20,29 @@ object DaosModule { fun providesSavedItemDao( database: OmnivoreDatabase, ): SavedItemDao = database.savedItemDao() + + @Provides + fun providesSavedItemLabelDao( + database: OmnivoreDatabase, + ): SavedItemLabelDao = database.savedItemLabelDao() + + @Provides + fun providesHighlightDao( + database: OmnivoreDatabase, + ): HighlightDao = database.highlightDao() + + @Provides + fun providesHighlightChangesDao( + database: OmnivoreDatabase, + ): HighlightChangesDao = database.highlightChangesDao() + + @Provides + fun providesSavedItemWithLabelsAndHighlightsDao( + database: OmnivoreDatabase, + ): SavedItemWithLabelsAndHighlightsDao = database.savedItemWithLabelsAndHighlightsDao() + + @Provides + fun providesSavedItemAndSavedItemLabelCrossRefDao( + database: OmnivoreDatabase, + ): SavedItemAndSavedItemLabelCrossRefDao = database.savedItemAndSavedItemLabelCrossRefDao() }