From feb19c4eb5a44544faba801cccce3a4e6f4b0ee4 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Thu, 21 Jul 2022 11:15:08 +0300 Subject: [PATCH] Fix favourites and history deletion --- .../favourites/data/FavouriteCategoriesDao.kt | 10 +++-- .../kotatsu/favourites/data/FavouritesDao.kt | 37 ++++++++++++++----- .../favourites/domain/FavouritesRepository.kt | 19 +++++++--- .../FavouritesCategoriesViewModel.kt | 4 +- .../kotatsu/history/data/HistoryDao.kt | 19 ++++++---- .../history/domain/HistoryRepository.kt | 2 +- 6 files changed, 61 insertions(+), 30 deletions(-) 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 6788a641d..83d5ab0d3 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 @@ -24,8 +24,7 @@ abstract class FavouriteCategoriesDao { @Update abstract suspend fun update(category: FavouriteCategoryEntity): Int - @Query("UPDATE favourite_categories SET deleted_at = :now WHERE category_id = :id") - abstract suspend fun delete(id: Long, now: Long = System.currentTimeMillis()) + suspend fun delete(id: Long) = setDeletedAt(id, 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) @@ -33,8 +32,8 @@ 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 `track` = :isEnabled WHERE category_id = :id") + // abstract suspend fun updateTracking(id: Long, isEnabled: Boolean) @Query("UPDATE favourite_categories SET `show_in_lib` = :isEnabled WHERE category_id = :id") abstract suspend fun updateLibVisibility(id: Long, isEnabled: Boolean) @@ -58,4 +57,7 @@ abstract class FavouriteCategoriesDao { insert(entity) } } + + @Query("UPDATE favourite_categories SET deleted_at = :deletedAt WHERE category_id = :id") + protected abstract suspend fun setDeletedAt(id: Long, deletedAt: Long) } 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 9820e2d49..e6fdd5a8c 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 @@ -11,6 +11,8 @@ import org.koitharu.kotatsu.parsers.model.SortOrder @Dao abstract class FavouritesDao { + /** SELECT **/ + @Transaction @Query("SELECT * FROM favourites WHERE deleted_at = 0 GROUP BY manga_id ORDER BY created_at DESC") abstract suspend fun findAll(): List @@ -61,12 +63,12 @@ abstract class FavouritesDao { ) abstract suspend fun findAllManga(categoryId: Int): List - suspend fun findCovers(categoryId: Long, order: SortOrder, limit: Int): List { + suspend fun findCovers(categoryId: Long, order: SortOrder): List { val orderBy = getOrderBy(order) @Language("RoomSql") val query = SimpleSQLiteQuery( "SELECT m.cover_url FROM favourites AS f LEFT JOIN manga AS m ON f.manga_id = m.manga_id " + - "WHERE f.category_id = ? AND deleted_at = 0 ORDER BY $orderBy LIMIT ?", - arrayOf(categoryId, limit), + "WHERE f.category_id = ? AND deleted_at = 0 ORDER BY $orderBy", + arrayOf(categoryId), ) return findCoversImpl(query) } @@ -85,25 +87,33 @@ abstract class FavouritesDao { @Query("SELECT DISTINCT category_id FROM favourites WHERE manga_id = :id AND deleted_at = 0") abstract fun observeIds(id: Long): Flow> + /** INSERT **/ + @Insert(onConflict = OnConflictStrategy.REPLACE) abstract suspend fun insert(favourite: FavouriteEntity) + /** UPDATE **/ + @Update abstract suspend fun update(favourite: FavouriteEntity): Int - @Query("UPDATE favourites SET deleted_at = :now WHERE manga_id = :mangaId") - abstract suspend fun delete(mangaId: Long, now: Long = System.currentTimeMillis()) + /** DELETE **/ - @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()) + suspend fun delete(mangaId: Long) = setDeletedAt(mangaId, System.currentTimeMillis()) - suspend fun recover(mangaId: Long) = delete(mangaId, 0L) + suspend fun delete(mangaId: Long, categoryId: Long) = setDeletedAt(mangaId, categoryId, System.currentTimeMillis()) - suspend fun recover(categoryId: Long, mangaId: Long) = delete(categoryId, mangaId, 0L) + suspend fun deleteAll(categoryId: Long) = setDeletedAtAll(categoryId, System.currentTimeMillis()) + + suspend fun recover(mangaId: Long) = setDeletedAt(mangaId, 0L) + + suspend fun recover(mangaId: Long, categoryId: Long) = setDeletedAt(categoryId, mangaId, 0L) @Query("DELETE FROM favourites WHERE deleted_at != 0 AND deleted_at < :maxDeletionTime") abstract suspend fun gc(maxDeletionTime: Long) + /** TOOLS **/ + @Transaction open suspend fun upsert(entity: FavouriteEntity) { if (update(entity) == 0) { @@ -118,6 +128,15 @@ abstract class FavouritesDao { @RawQuery protected abstract suspend fun findCoversImpl(query: SupportSQLiteQuery): List + @Query("UPDATE favourites SET deleted_at = :deletedAt WHERE manga_id = :mangaId") + protected abstract suspend fun setDeletedAt(mangaId: Long, deletedAt: Long) + + @Query("UPDATE favourites SET deleted_at = :deletedAt WHERE manga_id = :mangaId AND category_id = :categoryId") + abstract suspend fun setDeletedAt(mangaId: Long, categoryId: Long, deletedAt: Long) + + @Query("UPDATE favourites SET deleted_at = :deletedAt WHERE category_id = :categoryId AND deleted_at = 0") + protected abstract suspend fun setDeletedAtAll(categoryId: Long, deletedAt: Long) + private fun getOrderBy(sortOrder: SortOrder) = when (sortOrder) { SortOrder.RATING -> "rating DESC" SortOrder.NEWEST, 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 6ff525817..871ae5329 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 @@ -51,7 +51,7 @@ class FavouritesRepository( }.distinctUntilChanged() } - fun observeCategoriesWithCovers(coversLimit: Int): Flow>> { + fun observeCategoriesWithCovers(): Flow>> { return db.favouriteCategoriesDao.observeAll() .map { db.withTransaction { @@ -61,7 +61,6 @@ class FavouritesRepository( res[cat] = db.favouritesDao.findCovers( categoryId = cat.id, order = cat.order, - limit = coversLimit, ) } res @@ -108,16 +107,24 @@ class FavouritesRepository( } suspend fun removeCategory(id: Long) { - db.favouriteCategoriesDao.delete(id) + db.withTransaction { + db.favouriteCategoriesDao.delete(id) + db.favouritesDao.deleteAll(id) + } channels.deleteChannel(id) } suspend fun removeCategories(ids: Collection) { db.withTransaction { for (id in ids) { - removeCategory(id) + db.favouriteCategoriesDao.delete(id) + db.favouritesDao.deleteAll(id) } } + // run after transaction success + for (id in ids) { + channels.deleteChannel(id) + } } suspend fun setCategoryOrder(id: Long, order: SortOrder) { @@ -179,7 +186,7 @@ class FavouritesRepository( private suspend fun recoverToFavourites(ids: Collection) { db.withTransaction { for (id in ids) { - db.favouritesDao.recover(id) + db.favouritesDao.recover(mangaId = id) } } } @@ -187,7 +194,7 @@ class FavouritesRepository( private suspend fun recoverToCategory(categoryId: Long, ids: Collection) { db.withTransaction { for (id in ids) { - db.favouritesDao.recover(categoryId, id) + db.favouritesDao.recover(mangaId = id, categoryId = categoryId) } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt index 5efe8dc2b..0b2268c20 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt @@ -39,13 +39,13 @@ class FavouritesCategoriesViewModel( }.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) val detalizedCategories = combine( - repository.observeCategoriesWithCovers(coversLimit = 3), + repository.observeCategoriesWithCovers(), isReorder, ) { list, reordering -> list.map { (category, covers) -> CategoryListModel( mangaCount = covers.size, - covers = covers, + covers = covers.take(3), category = category, isReorderMode = reordering, ) 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 10a912494..f96d728c7 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 @@ -43,9 +43,6 @@ abstract class HistoryDao { @Query("SELECT COUNT(*) FROM history WHERE deleted_at = 0") abstract fun observeCount(): Flow - @Query("UPDATE history SET deleted_at = :now WHERE deleted_at = 0") - abstract suspend fun clear(now: Long = System.currentTimeMillis()) - @Query("SELECT percent FROM history WHERE manga_id = :id AND deleted_at = 0") abstract suspend fun findProgress(id: Long): Float? @@ -62,16 +59,16 @@ abstract class HistoryDao { updatedAt: Long, ): Int - @Query("UPDATE history SET deleted_at = :now WHERE manga_id = :mangaId") - abstract suspend fun delete(mangaId: Long, now: Long = System.currentTimeMillis()) + suspend fun delete(mangaId: Long) = setDeletedAt(mangaId, System.currentTimeMillis()) - suspend fun recover(mangaId: Long) = delete(mangaId, 0L) + suspend fun recover(mangaId: Long) = setDeletedAt(mangaId, 0L) @Query("DELETE FROM history WHERE deleted_at != 0 AND deleted_at < :maxDeletionTime") abstract suspend fun gc(maxDeletionTime: Long) - @Query("DELETE FROM history WHERE created_at >= :minDate") - abstract suspend fun deleteAfter(minDate: Long) + suspend fun deleteAfter(minDate: Long) = setDeletedAtAfter(minDate, System.currentTimeMillis()) + + suspend fun clear() = setDeletedAtAfter(0L, System.currentTimeMillis()) suspend fun update(entity: HistoryEntity) = update( mangaId = entity.mangaId, @@ -98,4 +95,10 @@ abstract class HistoryDao { } } } + + @Query("UPDATE history SET deleted_at = :deletedAt WHERE manga_id = :mangaId") + protected abstract suspend fun setDeletedAt(mangaId: Long, deletedAt: Long) + + @Query("UPDATE history SET deleted_at = :deletedAt WHERE created_at >= :minDate AND deleted_at = 0") + protected abstract suspend fun setDeletedAtAfter(minDate: Long, deletedAt: Long) } 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 52a34fd91..7b226e8bc 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 @@ -109,7 +109,7 @@ class HistoryRepository( } suspend fun deleteAfter(minDate: Long) { - db.historyDao.delete(minDate) + db.historyDao.deleteAfter(minDate) } suspend fun delete(ids: Collection): ReversibleHandle {