diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/DataService.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/DataService.kt index d85be98cf..6b561c864 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/DataService.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/DataService.kt @@ -3,14 +3,10 @@ package app.omnivore.omnivore import android.content.Context import android.util.Log import androidx.room.Room -import app.omnivore.omnivore.networking.Networker -import app.omnivore.omnivore.networking.savedItem -import app.omnivore.omnivore.networking.savedItemUpdates +import app.omnivore.omnivore.models.ServerSyncStatus +import app.omnivore.omnivore.networking.* import app.omnivore.omnivore.persistence.AppDatabase -import app.omnivore.omnivore.persistence.entities.SavedItem -import app.omnivore.omnivore.persistence.entities.SavedItemAndHighlightCrossRef -import app.omnivore.omnivore.persistence.entities.SavedItemAndSavedItemLabelCrossRef -import app.omnivore.omnivore.persistence.entities.SavedItemLabel +import app.omnivore.omnivore.persistence.entities.* import javax.inject.Inject class DataService @Inject constructor( @@ -116,7 +112,67 @@ suspend fun DataService.syncSavedItemContent(slug: String) { } suspend fun DataService.syncOfflineItemsWithServerIfNeeded() { - // TODO: implement this + val unSyncedSavedItems = db.savedItemDao().getUnSynced() + val unSyncedHighlights = db.highlightDao().getUnSynced() + + for (savedItem in unSyncedSavedItems) { + syncSavedItem(savedItem) + } + + for (highlight in unSyncedHighlights) { + syncHighlight(highlight) + } +} + +private suspend fun DataService.syncSavedItem(item: SavedItem) { + fun updateSyncStatus(status: ServerSyncStatus) { + item.serverSyncStatus = status.rawValue + db.savedItemDao().update(item) + } + + when (item.serverSyncStatus) { + ServerSyncStatus.NEEDS_DELETION.rawValue -> { + updateSyncStatus(ServerSyncStatus.IS_SYNCING) + + val isDeletedOnServer = networker.deleteSavedItem(item.savedItemId) + + if (isDeletedOnServer) { + db.savedItemDao().deleteById(item.savedItemId) + } else { + updateSyncStatus(ServerSyncStatus.NEEDS_DELETION) + } + } + ServerSyncStatus.NEEDS_UPDATE.rawValue -> { + updateSyncStatus(ServerSyncStatus.IS_SYNCING) + + val isArchiveServerSynced = networker.updateArchiveStatusSavedItem(itemID = item.savedItemId, setAsArchived = item.isArchived) + + val isReadingProgressSynced = networker.updateReadingProgress( + ReadingProgressParams( + id = item.savedItemId, + readingProgressPercent = item.readingProgress, + readingProgressAnchorIndex = item.readingProgressAnchor + ) + ) + + if (isArchiveServerSynced && isReadingProgressSynced) { + updateSyncStatus(ServerSyncStatus.IS_SYNCED) + } else { + updateSyncStatus(ServerSyncStatus.NEEDS_UPDATE) + } + } + ServerSyncStatus.NEEDS_CREATION.rawValue -> { + // TODO: implement when we are able to create content on device + // updateSyncStatus(ServerSyncStatus.IS_SYNCING) + // send update to server + // update db + } + else -> return + } +} + +private suspend fun DataService.syncHighlight(item: Highlight) { + // TODO: update } data class SavedItemSyncResult( diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/networking/SavedItemMutations.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/networking/SavedItemMutations.kt index 67ead474e..391124e2e 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/networking/SavedItemMutations.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/networking/SavedItemMutations.kt @@ -23,7 +23,7 @@ suspend fun Networker.unarchiveSavedItem(itemID: String): Boolean { return updateArchiveStatusSavedItem(itemID, false) } -private suspend fun Networker.updateArchiveStatusSavedItem(itemID: String, setAsArchived: Boolean): Boolean { +suspend fun Networker.updateArchiveStatusSavedItem(itemID: String, setAsArchived: Boolean): Boolean { return try { val input = ArchiveLinkInput(setAsArchived, itemID) val result = authenticatedApolloClient().mutation(SetLinkArchivedMutation(input)).execute() diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/persistence/entities/Highlight.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/persistence/entities/Highlight.kt index 0c4588741..c734af753 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/persistence/entities/Highlight.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/persistence/entities/Highlight.kt @@ -2,8 +2,7 @@ package app.omnivore.omnivore.persistence.entities import androidx.room.* import app.omnivore.omnivore.models.ServerSyncStatus -import java.time.LocalDate -import java.util.Date + @Entity data class Highlight( @@ -73,6 +72,12 @@ data class SavedItemWithLabelsAndHighlights( @Dao interface HighlightDao { + @Query("SELECT * FROM highlight WHERE serverSyncStatus != 0") + fun getUnSynced(): List + @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertAll(items: List) + + @Update + fun update(highlight: Highlight) } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/persistence/entities/SavedItem.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/persistence/entities/SavedItem.kt index 440ed2461..00965a85d 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/persistence/entities/SavedItem.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/persistence/entities/SavedItem.kt @@ -36,7 +36,7 @@ data class SavedItem( val onDeviceImageURLString: String? = null, val originalHtml: String? = null, @ColumnInfo(typeAffinity = ColumnInfo.BLOB) val pdfData: ByteArray? = null, - val serverSyncStatus: Int = 0, + var serverSyncStatus: Int = 0, val tempPDFURL: String? = null // hasMany highlights @@ -92,6 +92,9 @@ interface SavedItemDao { @Query("SELECT * FROM savedItem") fun getAll(): List + @Query("SELECT * FROM savedItem WHERE serverSyncStatus != 0") + fun getUnSynced(): List + @Query("SELECT * FROM savedItem WHERE slug = :slug") fun getSavedItemWithLabelsAndHighlights(slug: String): SavedItemWithLabelsAndHighlights? @@ -104,6 +107,9 @@ interface SavedItemDao { @Query("DELETE FROM savedItem WHERE savedItemId = :itemID") fun deleteById(itemID: String) + @Update + fun update(savedItem: SavedItem) + @Transaction @Query("SELECT savedItemId, slug, publisherURLString, title, author, imageURLString, isArchived, pageURLString, contentReader FROM SavedItem ORDER BY savedAt DESC") fun getLibraryLiveDataWithLabels(): LiveData>