From f5db5c39c38b34be49967ce0be11d9f2085c92ef Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 15 May 2022 19:43:01 +0300 Subject: [PATCH] Add deleted_at db columns --- .../kotatsu/core/backup/RestoreRepository.kt | 11 ++-- .../core/db/DatabasePrePopulateCallback.kt | 4 +- .../koitharu/kotatsu/core/db/MangaDatabase.kt | 5 +- .../core/db/migrations/Migration11To12.kt | 13 +++++ .../favourites/data/FavouriteCategoriesDao.kt | 23 ++++---- .../data/FavouriteCategoryEntity.kt | 1 + .../favourites/data/FavouriteEntity.kt | 3 +- .../kotatsu/favourites/data/FavouritesDao.kt | 54 ++++++++++++------- .../favourites/domain/FavouritesRepository.kt | 38 +++---------- .../kotatsu/history/data/HistoryDao.kt | 31 ++++++----- .../kotatsu/history/data/HistoryEntity.kt | 3 +- .../history/domain/HistoryRepository.kt | 1 + .../kotatsu/sync/data/SyncInterceptor.kt | 2 + 13 files changed, 106 insertions(+), 83 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/RestoreRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/backup/RestoreRepository.kt index 57fd4d6ee..f4db32cd0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/backup/RestoreRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/backup/RestoreRepository.kt @@ -79,14 +79,14 @@ class RestoreRepository(private val db: MangaDatabase) { largeCoverUrl = json.getStringOrNull("large_cover_url"), state = json.getStringOrNull("state"), author = json.getStringOrNull("author"), - source = json.getString("source") + source = json.getString("source"), ) private fun parseTag(json: JSONObject) = TagEntity( id = json.getLong("id"), title = json.getString("title"), key = json.getString("key"), - source = json.getString("source") + source = json.getString("source"), ) private fun parseHistory(json: JSONObject) = HistoryEntity( @@ -95,7 +95,8 @@ class RestoreRepository(private val db: MangaDatabase) { updatedAt = json.getLong("updated_at"), chapterId = json.getLong("chapter_id"), page = json.getInt("page"), - scroll = json.getDouble("scroll").toFloat() + scroll = json.getDouble("scroll").toFloat(), + deletedAt = 0L, ) private fun parseCategory(json: JSONObject) = FavouriteCategoryEntity( @@ -105,11 +106,13 @@ class RestoreRepository(private val db: MangaDatabase) { title = json.getString("title"), order = json.getStringOrNull("order") ?: SortOrder.NEWEST.name, track = json.getBooleanOrDefault("track", true), + deletedAt = 0L, ) private fun parseFavourite(json: JSONObject) = FavouriteEntity( mangaId = json.getLong("manga_id"), categoryId = json.getLong("category_id"), - createdAt = json.getLong("created_at") + createdAt = json.getLong("created_at"), + deletedAt = 0L, ) } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt index 6257a8456..1afe800a7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt @@ -10,8 +10,8 @@ class DatabasePrePopulateCallback(private val resources: Resources) : RoomDataba override fun onCreate(db: SupportSQLiteDatabase) { db.execSQL( - "INSERT INTO favourite_categories (created_at, sort_key, title, `order`, track) VALUES (?,?,?,?,?)", - arrayOf(System.currentTimeMillis(), 1, resources.getString(R.string.read_later), SortOrder.NEWEST.name, 1) + "INSERT INTO favourite_categories (created_at, sort_key, title, `order`, `track`, `deleted_at`) VALUES (?,?,?,?,?,?)", + arrayOf(System.currentTimeMillis(), 1, resources.getString(R.string.read_later), SortOrder.NEWEST.name, 1, 0L) ) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt index 0714c0fcc..2f0184a8f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt @@ -18,13 +18,15 @@ import org.koitharu.kotatsu.history.data.HistoryEntity import org.koitharu.kotatsu.suggestions.data.SuggestionDao import org.koitharu.kotatsu.suggestions.data.SuggestionEntity +const val DATABASE_VERSION = 12 + @Database( entities = [ MangaEntity::class, TagEntity::class, HistoryEntity::class, MangaTagsEntity::class, FavouriteCategoryEntity::class, FavouriteEntity::class, MangaPrefsEntity::class, TrackEntity::class, TrackLogEntity::class, SuggestionEntity::class, BookmarkEntity::class, ], - version = 11, + version = DATABASE_VERSION, ) abstract class MangaDatabase : RoomDatabase() { @@ -64,6 +66,7 @@ fun MangaDatabase(context: Context): MangaDatabase = Room.databaseBuilder( Migration8To9(), Migration9To10(), Migration10To11(), + Migration11To12(), ).addCallback( DatabasePrePopulateCallback(context.resources) ).build() \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt new file mode 100644 index 000000000..18704cbce --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt @@ -0,0 +1,13 @@ +package org.koitharu.kotatsu.core.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration11To12 : Migration(11, 12) { + + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE favourite_categories ADD COLUMN `deleted_at` INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE favourites ADD COLUMN `deleted_at` INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE history ADD COLUMN `deleted_at` INTEGER NOT NULL DEFAULT 0") + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt index 148dfd820..1e80daba5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt @@ -6,16 +6,16 @@ import kotlinx.coroutines.flow.Flow @Dao abstract class FavouriteCategoriesDao { - @Query("SELECT * FROM favourite_categories WHERE category_id = :id") + @Query("SELECT * FROM favourite_categories WHERE category_id = :id AND deleted_at = 0") abstract suspend fun find(id: Int): FavouriteCategoryEntity - @Query("SELECT * FROM favourite_categories ORDER BY sort_key") + @Query("SELECT * FROM favourite_categories WHERE deleted_at = 0 ORDER BY sort_key") abstract suspend fun findAll(): List - @Query("SELECT * FROM favourite_categories ORDER BY sort_key") + @Query("SELECT * FROM favourite_categories WHERE deleted_at = 0 ORDER BY sort_key") abstract fun observeAll(): Flow> - @Query("SELECT * FROM favourite_categories WHERE category_id = :id") + @Query("SELECT * FROM favourite_categories WHERE category_id = :id AND deleted_at = 0") abstract fun observe(id: Long): Flow @Insert(onConflict = OnConflictStrategy.ABORT) @@ -24,11 +24,8 @@ abstract class FavouriteCategoriesDao { @Update abstract suspend fun update(category: FavouriteCategoryEntity): Int - @Query("DELETE FROM favourite_categories WHERE category_id = :id") - abstract suspend fun delete(id: Long) - - @Query("UPDATE favourite_categories SET title = :title WHERE category_id = :id") - abstract suspend fun updateTitle(id: Long, title: String) + @Query("UPDATE favourite_categories SET deleted_at = :now WHERE category_id = :id") + abstract suspend fun delete(id: Long, now: Long = System.currentTimeMillis()) @Query("UPDATE favourite_categories SET title = :title, `order` = :order, `track` = :tracker WHERE category_id = :id") abstract suspend fun update(id: Long, title: String, order: String, tracker: Boolean) @@ -36,13 +33,13 @@ abstract class FavouriteCategoriesDao { @Query("UPDATE favourite_categories SET `order` = :order WHERE category_id = :id") abstract suspend fun updateOrder(id: Long, order: String) - @Query("UPDATE favourite_categories SET `track` = :isEnabled WHERE category_id = :id") - abstract suspend fun updateTracking(id: Long, isEnabled: Boolean) - @Query("UPDATE favourite_categories SET sort_key = :sortKey WHERE category_id = :id") abstract suspend fun updateSortKey(id: Long, sortKey: Int) - @Query("SELECT MAX(sort_key) FROM favourite_categories") + @Query("DELETE FROM favourite_categories WHERE deleted_at != 0") + abstract suspend fun gc() + + @Query("SELECT MAX(sort_key) FROM favourite_categories WHERE deleted_at = 0") protected abstract suspend fun getMaxSortKey(): Int? suspend fun getNextSortKey(): Int { diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt index 08cbd7b62..abf480bed 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt @@ -14,4 +14,5 @@ class FavouriteCategoryEntity( @ColumnInfo(name = "title") val title: String, @ColumnInfo(name = "order") val order: String, @ColumnInfo(name = "track") val track: Boolean, + @ColumnInfo(name = "deleted_at") val deletedAt: Long, ) \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt index a13e54230..4fdf1e943 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt @@ -27,5 +27,6 @@ import org.koitharu.kotatsu.core.db.entity.MangaEntity class FavouriteEntity( @ColumnInfo(name = "manga_id", index = true) val mangaId: Long, @ColumnInfo(name = "category_id", index = true) val categoryId: Long, - @ColumnInfo(name = "created_at") val createdAt: Long + @ColumnInfo(name = "created_at") val createdAt: Long, + @ColumnInfo(name = "deleted_at") val deletedAt: Long, ) \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt index 89fcc92fb..3ac780436 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt @@ -4,6 +4,7 @@ import androidx.room.* import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SupportSQLiteQuery import kotlinx.coroutines.flow.Flow +import org.intellij.lang.annotations.Language import org.koitharu.kotatsu.core.db.entity.MangaEntity import org.koitharu.kotatsu.parsers.model.SortOrder @@ -11,53 +12,67 @@ import org.koitharu.kotatsu.parsers.model.SortOrder abstract class FavouritesDao { @Transaction - @Query("SELECT * FROM favourites GROUP BY manga_id ORDER BY created_at DESC") + @Query("SELECT * FROM favourites WHERE deleted_at = 0 GROUP BY manga_id ORDER BY created_at DESC") abstract suspend fun findAll(): List fun observeAll(order: SortOrder): Flow> { val orderBy = getOrderBy(order) - val query = SimpleSQLiteQuery( - "SELECT * FROM favourites LEFT JOIN manga ON favourites.manga_id = manga.manga_id GROUP BY favourites.manga_id ORDER BY $orderBy", + @Language("RoomSql") val query = SimpleSQLiteQuery( + "SELECT * FROM favourites LEFT JOIN manga ON favourites.manga_id = manga.manga_id " + + "WHERE favourites.deleted_at = 0 GROUP BY favourites.manga_id ORDER BY $orderBy", ) return observeAllRaw(query) } @Transaction - @Query("SELECT * FROM favourites GROUP BY manga_id ORDER BY created_at DESC LIMIT :limit OFFSET :offset") + @Query( + "SELECT * FROM favourites WHERE deleted_at = 0 " + + "GROUP BY manga_id ORDER BY created_at DESC LIMIT :limit OFFSET :offset" + ) abstract suspend fun findAll(offset: Int, limit: Int): List @Transaction - @Query("SELECT * FROM favourites WHERE category_id = :categoryId GROUP BY manga_id ORDER BY created_at DESC") + @Query( + "SELECT * FROM favourites WHERE category_id = :categoryId AND deleted_at = 0 " + + "GROUP BY manga_id ORDER BY created_at DESC" + ) abstract suspend fun findAll(categoryId: Long): List fun observeAll(categoryId: Long, order: SortOrder): Flow> { val orderBy = getOrderBy(order) - val query = SimpleSQLiteQuery( - "SELECT * FROM favourites LEFT JOIN manga ON favourites.manga_id = manga.manga_id WHERE category_id = ? GROUP BY favourites.manga_id ORDER BY $orderBy", + @Language("RoomSql") val query = SimpleSQLiteQuery( + "SELECT * FROM favourites LEFT JOIN manga ON favourites.manga_id = manga.manga_id " + + "WHERE category_id = ? AND deleted_at = 0 GROUP BY favourites.manga_id ORDER BY $orderBy", arrayOf(categoryId), ) return observeAllRaw(query) } @Transaction - @Query("SELECT * FROM favourites WHERE category_id = :categoryId GROUP BY manga_id ORDER BY created_at DESC LIMIT :limit OFFSET :offset") + @Query( + "SELECT * FROM favourites WHERE category_id = :categoryId AND deleted_at = 0 " + + "GROUP BY manga_id ORDER BY created_at DESC LIMIT :limit OFFSET :offset" + ) abstract suspend fun findAll(categoryId: Long, offset: Int, limit: Int): List - @Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM favourites WHERE category_id = :categoryId)") + @Query( + "SELECT * FROM manga WHERE manga_id IN " + + "(SELECT manga_id FROM favourites WHERE category_id = :categoryId AND deleted_at = 0)" + ) abstract suspend fun findAllManga(categoryId: Int): List - @Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM favourites)") + @Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM favourites WHERE deleted_at = 0)") abstract suspend fun findAllManga(): List @Transaction - @Query("SELECT * FROM favourites WHERE manga_id = :id GROUP BY manga_id") + @Query("SELECT * FROM favourites WHERE manga_id = :id AND deleted_at = 0 GROUP BY manga_id") abstract suspend fun find(id: Long): FavouriteManga? @Transaction - @Query("SELECT * FROM favourites WHERE manga_id = :id GROUP BY manga_id") + @Query("SELECT * FROM favourites WHERE manga_id = :id AND deleted_at = 0 GROUP BY manga_id") abstract fun observe(id: Long): Flow - @Query("SELECT DISTINCT category_id FROM favourites WHERE manga_id = :id") + @Query("SELECT DISTINCT category_id FROM favourites WHERE manga_id = :id AND deleted_at = 0") abstract fun observeIds(id: Long): Flow> @Insert(onConflict = OnConflictStrategy.IGNORE) @@ -66,11 +81,14 @@ abstract class FavouritesDao { @Update abstract suspend fun update(favourite: FavouriteEntity): Int - @Query("DELETE FROM favourites WHERE manga_id = :mangaId") - abstract suspend fun delete(mangaId: Long) + @Query("UPDATE favourites SET deleted_at = :now WHERE manga_id = :mangaId") + abstract suspend fun delete(mangaId: Long, now: Long = System.currentTimeMillis()) - @Query("DELETE FROM favourites WHERE manga_id = :mangaId AND category_id = :categoryId") - abstract suspend fun delete(categoryId: Long, mangaId: Long) + @Query("UPDATE favourites SET deleted_at = :now WHERE manga_id = :mangaId AND category_id = :categoryId") + abstract suspend fun delete(categoryId: Long, mangaId: Long, now: Long = System.currentTimeMillis()) + + @Query("DELETE FROM favourites WHERE deleted_at != 0") + abstract suspend fun gc() @Transaction open suspend fun upsert(entity: FavouriteEntity) { @@ -83,7 +101,7 @@ abstract class FavouritesDao { @RawQuery(observedEntities = [FavouriteEntity::class]) protected abstract fun observeAllRaw(query: SupportSQLiteQuery): Flow> - private fun getOrderBy(sortOrder: SortOrder) = when(sortOrder) { + private fun getOrderBy(sortOrder: SortOrder) = when (sortOrder) { SortOrder.RATING -> "rating DESC" SortOrder.NEWEST, SortOrder.UPDATED -> "created_at DESC" diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt index 13a4c92c4..a1cbf8cf9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt @@ -54,12 +54,6 @@ class FavouritesRepository( .map { it?.toFavouriteCategory() } } - fun observeCategories(mangaId: Long): Flow> { - return db.favouritesDao.observe(mangaId).map { entity -> - entity?.categories?.map { it.toFavouriteCategory() }.orEmpty() - }.distinctUntilChanged() - } - fun observeCategoriesIds(mangaId: Long): Flow> { return db.favouritesDao.observeIds(mangaId).map { it.toSet() } } @@ -76,6 +70,7 @@ class FavouritesRepository( categoryId = 0, order = sortOrder.name, track = isTrackerEnabled, + deletedAt = 0L, ) val id = db.favouriteCategoriesDao.insert(entity) val category = entity.toFavouriteCategory(id) @@ -87,26 +82,6 @@ class FavouritesRepository( db.favouriteCategoriesDao.update(id, title, sortOrder.name, isTrackerEnabled) } - suspend fun addCategory(title: String): FavouriteCategory { - val entity = FavouriteCategoryEntity( - title = title, - createdAt = System.currentTimeMillis(), - sortKey = db.favouriteCategoriesDao.getNextSortKey(), - categoryId = 0, - order = SortOrder.NEWEST.name, - track = true, - ) - val id = db.favouriteCategoriesDao.insert(entity) - val category = entity.toFavouriteCategory(id) - channels.createChannel(category) - return category - } - - suspend fun renameCategory(id: Long, title: String) { - db.favouriteCategoriesDao.updateTitle(id, title) - channels.renameChannel(id, title) - } - suspend fun removeCategory(id: Long) { db.favouriteCategoriesDao.delete(id) channels.deleteChannel(id) @@ -116,10 +91,6 @@ class FavouritesRepository( db.favouriteCategoriesDao.updateOrder(id, order.name) } - suspend fun setCategoryTracking(id: Long, isEnabled: Boolean) { - db.favouriteCategoriesDao.updateTracking(id, isEnabled) - } - suspend fun reorderCategories(orderedIds: List) { val dao = db.favouriteCategoriesDao db.withTransaction { @@ -135,7 +106,12 @@ class FavouritesRepository( val tags = manga.tags.toEntities() db.tagsDao.upsert(tags) db.mangaDao.upsert(manga.toEntity(), tags) - val entity = FavouriteEntity(manga.id, categoryId, System.currentTimeMillis()) + val entity = FavouriteEntity( + mangaId = manga.id, + categoryId = categoryId, + createdAt = System.currentTimeMillis(), + deletedAt = 0L, + ) db.favouritesDao.insert(entity) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryDao.kt b/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryDao.kt index bfd1f9598..cc176a057 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryDao.kt @@ -9,46 +9,50 @@ import org.koitharu.kotatsu.core.db.entity.TagEntity abstract class HistoryDao { @Transaction - @Query("SELECT * FROM history ORDER BY updated_at DESC LIMIT :limit OFFSET :offset") + @Query("SELECT * FROM history WHERE deleted_at = 0 ORDER BY updated_at DESC LIMIT :limit OFFSET :offset") abstract suspend fun findAll(offset: Int, limit: Int): List @Transaction - @Query("SELECT * FROM history WHERE manga_id IN (:ids)") + @Query("SELECT * FROM history WHERE deleted_at = 0 AND manga_id IN (:ids)") abstract suspend fun findAll(ids: Collection): List @Transaction - @Query("SELECT * FROM history ORDER BY updated_at DESC") + @Query("SELECT * FROM history WHERE deleted_at = 0 ORDER BY updated_at DESC") abstract fun observeAll(): Flow> - @Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM history)") + @Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM history WHERE deleted_at = 0)") abstract suspend fun findAllManga(): List @Query( """SELECT tags.* FROM tags LEFT JOIN manga_tags ON tags.tag_id = manga_tags.tag_id INNER JOIN history ON history.manga_id = manga_tags.manga_id + WHERE history.deleted_at = 0 GROUP BY manga_tags.tag_id ORDER BY COUNT(manga_tags.manga_id) DESC LIMIT :limit""" ) abstract suspend fun findPopularTags(limit: Int): List - @Query("SELECT * FROM history WHERE manga_id = :id") + @Query("SELECT * FROM history WHERE manga_id = :id AND deleted_at = 0") abstract suspend fun find(id: Long): HistoryEntity? - @Query("SELECT * FROM history WHERE manga_id = :id") + @Query("SELECT * FROM history WHERE manga_id = :id AND deleted_at = 0") abstract fun observe(id: Long): Flow - @Query("SELECT COUNT(*) FROM history") + @Query("SELECT COUNT(*) FROM history WHERE deleted_at = 0") abstract fun observeCount(): Flow - @Query("DELETE FROM history") - abstract suspend fun clear() + @Query("UPDATE history SET deleted_at = :now WHERE deleted_at = 0") + abstract suspend fun clear(now: Long = System.currentTimeMillis()) @Insert(onConflict = OnConflictStrategy.IGNORE) abstract suspend fun insert(entity: HistoryEntity): Long - @Query("UPDATE history SET page = :page, chapter_id = :chapterId, scroll = :scroll, updated_at = :updatedAt WHERE manga_id = :mangaId") + @Query( + "UPDATE history SET page = :page, chapter_id = :chapterId, scroll = :scroll, updated_at = :updatedAt " + + "WHERE manga_id = :mangaId" + ) abstract suspend fun update( mangaId: Long, page: Int, @@ -57,8 +61,11 @@ abstract class HistoryDao { updatedAt: Long ): Int - @Query("DELETE FROM history WHERE manga_id = :mangaId") - abstract suspend fun delete(mangaId: Long) + @Query("UPDATE history SET deleted_at = :now WHERE manga_id = :mangaId") + abstract suspend fun delete(mangaId: Long, now: Long = System.currentTimeMillis()) + + @Query("DELETE FROM history WHERE deleted_at != 0") + abstract suspend fun gc() suspend fun update(entity: HistoryEntity) = update(entity.mangaId, entity.page, entity.chapterId, entity.scroll, entity.updatedAt) diff --git a/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryEntity.kt b/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryEntity.kt index 95edf3d9c..6ce1492e3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryEntity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryEntity.kt @@ -21,9 +21,10 @@ import org.koitharu.kotatsu.core.db.entity.MangaEntity class HistoryEntity( @PrimaryKey(autoGenerate = false) @ColumnInfo(name = "manga_id") val mangaId: Long, - @ColumnInfo(name = "created_at") val createdAt: Long = System.currentTimeMillis(), + @ColumnInfo(name = "created_at") val createdAt: Long, @ColumnInfo(name = "updated_at") val updatedAt: Long, @ColumnInfo(name = "chapter_id") val chapterId: Long, @ColumnInfo(name = "page") val page: Int, @ColumnInfo(name = "scroll") val scroll: Float, + @ColumnInfo(name = "deleted_at") val deletedAt: Long, ) \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt b/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt index a4b2ab772..8ae569729 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt @@ -75,6 +75,7 @@ class HistoryRepository( chapterId = chapterId, page = page, scroll = scroll.toFloat(), // we migrate to int, but decide to not update database + deletedAt = 0L, ) ) trackingRepository.upsert(manga) diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt b/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt index 2d96b5dcb..0a9cc0db4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt @@ -7,6 +7,7 @@ import okhttp3.Interceptor import okhttp3.Response import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.db.DATABASE_VERSION class SyncInterceptor( context: Context, @@ -23,6 +24,7 @@ class SyncInterceptor( requestBuilder.header("Authorization", "Bearer $token") } requestBuilder.header("X-App-Version", BuildConfig.VERSION_CODE.toString()) + requestBuilder.header("X-Db-Version", DATABASE_VERSION.toString()) return chain.proceed(requestBuilder.build()) } } \ No newline at end of file