diff --git a/capy/src/main/java/com/jocmp/capy/persistence/ArticleRecords.kt b/capy/src/main/java/com/jocmp/capy/persistence/ArticleRecords.kt index 6056b201b..ee93110ae 100644 --- a/capy/src/main/java/com/jocmp/capy/persistence/ArticleRecords.kt +++ b/capy/src/main/java/com/jocmp/capy/persistence/ArticleRecords.kt @@ -159,7 +159,7 @@ class ArticleRecords( val updated = updatedAt.toEpochSecond() database.transactionWithErrorHandling { - articleIDs.forEach { articleID -> + articleIDs.distinct().forEach { articleID -> database.articlesQueries.upsertUnread( articleID = articleID, updatedAt = updated @@ -174,7 +174,7 @@ class ArticleRecords( val updated = updatedAt.toEpochSecond() database.transactionWithErrorHandling { - articleIDs.forEach { articleID -> + articleIDs.distinct().forEach { articleID -> database.articlesQueries.upsertStarred( articleID = articleID, updatedAt = updated diff --git a/capy/src/main/sqldelight/com/jocmp/capy/db/articles.sq b/capy/src/main/sqldelight/com/jocmp/capy/db/articles.sq index 15e3fc9a1..5e402a77c 100644 --- a/capy/src/main/sqldelight/com/jocmp/capy/db/articles.sq +++ b/capy/src/main/sqldelight/com/jocmp/capy/db/articles.sq @@ -147,7 +147,7 @@ upsertUnread { last_read_at = excluded.last_read_at, read = excluded.read; - INSERT INTO excluded_statuses( + INSERT OR IGNORE INTO excluded_statuses( article_id, type ) @@ -186,7 +186,7 @@ upsertStarred { SET starred = excluded.starred; - INSERT INTO excluded_statuses( + INSERT OR IGNORE INTO excluded_statuses( article_id, type ) diff --git a/capy/src/test/java/com/jocmp/capy/persistence/ArticleRecordsTest.kt b/capy/src/test/java/com/jocmp/capy/persistence/ArticleRecordsTest.kt index 97e78680a..ab20097f5 100644 --- a/capy/src/test/java/com/jocmp/capy/persistence/ArticleRecordsTest.kt +++ b/capy/src/test/java/com/jocmp/capy/persistence/ArticleRecordsTest.kt @@ -373,6 +373,52 @@ class ArticleRecordsTest { assertTrue(articleRecords.find(readArticle.id)!!.read) } + @Test + fun markAllUnread_withDuplicateIDs() = runTest { + val articleIDs = 3.repeated { RandomUUID.generate() } + val readArticle = articleFixture.create(read = false) + + articleIDs.forEach { id -> + articleFixture.create(id = id, read = true) + } + + articleRecords.markAllUnread(articleIDs + articleIDs.first()) + + val articles = articleIDs.map { articleRecords.find(it)!! } + + assertTrue(articles.none { it.read }) + assertTrue(articleRecords.find(readArticle.id)!!.read) + } + + @Test + fun markAllStarred_withDuplicateIDs() = runTest { + val articleIDs = 3.repeated { RandomUUID.generate() } + + articleIDs.forEach { id -> + articleFixture.create(id = id) + } + + articleRecords.markAllStarred(articleIDs + articleIDs.first()) + + val articles = articleIDs.map { articleRecords.find(it)!! } + + assertTrue(articles.all { it.starred }) + } + + @Test + fun upsertUnread_ignoresRepeatedMarkers() = runTest { + val article = articleFixture.create(read = true) + val updatedAt = nowUTC().toEpochSecond() + + database.transaction { + database.articlesQueries.upsertUnread(articleID = article.id, updatedAt = updatedAt) + database.articlesQueries.upsertUnread(articleID = article.id, updatedAt = updatedAt) + database.articlesQueries.updateStaleUnreads() + } + + assertFalse(articleRecords.find(article.id)!!.read) + } + @Test fun deleteOldArticles() = runTest { val oldPublishedAt = nowUTC().minusMonths(4).toEpochSecond()