Skip to content

Commit 106f9ba

Browse files
committed
Make MessageReceiptRepository getAllByType return a Flow and add a clear function
The `MessageReceiptRepository.getAllByType` function now accepts a `limit` parameter and returns a `Flow<List<MessageReceipt>>` instead of a `suspend` function returning `List<MessageReceipt>`. A new `clear()` function has been added to `MessageReceiptRepository` to delete all receipts from the database.
1 parent 49b61ce commit 106f9ba

File tree

5 files changed

+98
-20
lines changed

5 files changed

+98
-20
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2014-2025 Stream.io Inc. All rights reserved.
3+
*
4+
* Licensed under the Stream License;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.getstream.chat.android.client.persistance.repository
18+
19+
import io.getstream.chat.android.core.internal.InternalStreamChatApi
20+
import io.getstream.chat.android.models.MessageReceipt
21+
import kotlinx.coroutines.flow.Flow
22+
import kotlinx.coroutines.flow.emptyFlow
23+
24+
@InternalStreamChatApi
25+
public interface MessageReceiptRepository {
26+
27+
public suspend fun upsert(receipts: List<MessageReceipt>) { /* no-op */ }
28+
29+
public fun getAllByType(type: String, limit: Int): Flow<List<MessageReceipt>> = emptyFlow()
30+
31+
public suspend fun deleteByMessageIds(messageIds: List<String>) { /* no-op */ }
32+
33+
public suspend fun clear() { /* no-op */ }
34+
}

stream-chat-android-offline/api/stream-chat-android-offline.api

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,10 @@ public final class io/getstream/chat/android/offline/repository/domain/reaction/
190190

191191
public final class io/getstream/chat/android/offline/repository/domain/receipts/MessageReceiptDao_Impl : io/getstream/chat/android/offline/repository/domain/receipts/MessageReceiptDao {
192192
public fun <init> (Landroidx/room/RoomDatabase;)V
193+
public fun deleteAll (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
193194
public fun deleteByMessageIds (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
194195
public static fun getRequiredConverters ()Ljava/util/List;
195-
public fun selectAllByType (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
196+
public fun selectAllByType (Ljava/lang/String;I)Lkotlinx/coroutines/flow/Flow;
196197
public fun upsert (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
197198
}
198199

stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/receipts/MessageReceiptDao.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,25 @@ import androidx.room.Dao
44
import androidx.room.Insert
55
import androidx.room.OnConflictStrategy
66
import androidx.room.Query
7+
import kotlinx.coroutines.flow.Flow
78

89
@Dao
910
internal interface MessageReceiptDao {
1011

1112
@Insert(onConflict = OnConflictStrategy.REPLACE)
1213
suspend fun upsert(receipts: List<MessageReceiptEntity>)
1314

14-
@Query("SELECT * FROM stream_chat_message_receipt WHERE type = :type ORDER BY createdAt ASC")
15-
suspend fun selectAllByType(type: String): List<MessageReceiptEntity>
15+
@Query(
16+
"SELECT * FROM stream_chat_message_receipt " +
17+
"WHERE type = :type " +
18+
"ORDER BY createdAt ASC " +
19+
"LIMIT :limit"
20+
)
21+
fun selectAllByType(type: String, limit: Int): Flow<List<MessageReceiptEntity>>
1622

1723
@Query("DELETE FROM stream_chat_message_receipt WHERE messageId IN (:messageIds)")
1824
suspend fun deleteByMessageIds(messageIds: List<String>)
25+
26+
@Query("DELETE FROM stream_chat_message_receipt")
27+
suspend fun deleteAll()
1928
}

stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/receipts/MessageReceiptRepositoryImpl.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package io.getstream.chat.android.offline.repository.domain.receipts
22

33
import io.getstream.chat.android.client.persistance.repository.MessageReceiptRepository
44
import io.getstream.chat.android.models.MessageReceipt
5+
import kotlinx.coroutines.flow.Flow
6+
import kotlinx.coroutines.flow.map
57

68
internal class MessageReceiptRepositoryImpl(
79
private val dao: MessageReceiptDao,
@@ -11,10 +13,17 @@ internal class MessageReceiptRepositoryImpl(
1113
dao.upsert(receipts.map(MessageReceipt::toEntity))
1214
}
1315

14-
override suspend fun getAllByType(type: String): List<MessageReceipt> =
15-
dao.selectAllByType(type).map(MessageReceiptEntity::toModel)
16+
override fun getAllByType(type: String, limit: Int): Flow<List<MessageReceipt>> =
17+
dao.selectAllByType(type, limit)
18+
.map { receipts ->
19+
receipts.map(MessageReceiptEntity::toModel)
20+
}
1621

1722
override suspend fun deleteByMessageIds(messageIds: List<String>) {
1823
dao.deleteByMessageIds(messageIds)
1924
}
25+
26+
override suspend fun clear() {
27+
dao.deleteAll()
28+
}
2029
}

stream-chat-android-offline/src/test/java/io/getstream/chat/android/offline/repository/domain/receipts/MessageReceiptRepositoryImplTest.kt

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package io.getstream.chat.android.offline.repository.domain.receipts
22

3+
import app.cash.turbine.test
34
import io.getstream.chat.android.models.MessageReceipt
45
import io.getstream.chat.android.offline.randomMessageReceiptEntity
6+
import io.getstream.chat.android.randomInt
57
import io.getstream.chat.android.randomMessageReceipt
68
import io.getstream.chat.android.randomString
9+
import kotlinx.coroutines.flow.MutableStateFlow
710
import kotlinx.coroutines.test.runTest
811
import org.junit.Test
912
import org.junit.jupiter.api.Assertions.assertEquals
@@ -31,31 +34,35 @@ internal class MessageReceiptRepositoryImplTest {
3134
cid = receipt.cid,
3235
)
3336
)
34-
fixture.verifyUpsert(expectedReceipts)
37+
fixture.verifyUpsertCalled(expectedReceipts)
3538
}
3639

3740
@Test
3841
fun `get receipts by type`() = runTest {
3942
val type = randomString()
43+
val limit = randomInt()
4044
val receipt = randomMessageReceiptEntity()
4145
val fixture = Fixture()
4246
.givenReceiptsByType(
4347
type = type,
48+
limit = limit,
4449
receipts = listOf(receipt),
4550
)
4651
val sut = fixture.get()
4752

48-
val actual = sut.getAllByType(type)
53+
sut.getAllByType(type, limit).test {
54+
val actual = awaitItem()
4955

50-
val expected = listOf(
51-
MessageReceipt(
52-
messageId = receipt.messageId,
53-
type = receipt.type,
54-
createdAt = receipt.createdAt,
55-
cid = receipt.cid,
56+
val expected = listOf(
57+
MessageReceipt(
58+
messageId = receipt.messageId,
59+
type = receipt.type,
60+
createdAt = receipt.createdAt,
61+
cid = receipt.cid,
62+
)
5663
)
57-
)
58-
assertEquals(expected, actual)
64+
assertEquals(expected, actual)
65+
}
5966
}
6067

6168
@Test
@@ -66,27 +73,45 @@ internal class MessageReceiptRepositoryImplTest {
6673

6774
sut.deleteByMessageIds(messageIds)
6875

69-
fixture.verifyDeleteByMessageIds(messageIds)
76+
fixture.verifyDeleteByMessageIdsCalled(messageIds)
77+
}
78+
79+
@Test
80+
fun `clear receipts`() = runTest {
81+
val fixture = Fixture()
82+
val sut = fixture.get()
83+
84+
sut.clear()
85+
86+
fixture.verifyDeleteAllCalled()
7087
}
7188

7289
private class Fixture {
90+
91+
private val receiptsStateFlow = MutableStateFlow<List<MessageReceiptEntity>>(emptyList())
92+
7393
private val mockDao = mock<MessageReceiptDao> {
7494
onBlocking { upsert(any()) } doReturn Unit
7595
onBlocking { deleteByMessageIds(any()) } doReturn Unit
7696
}
7797

78-
fun givenReceiptsByType(type: String, receipts: List<MessageReceiptEntity>) = apply {
79-
wheneverBlocking { mockDao.selectAllByType(type) } doReturn receipts
98+
fun givenReceiptsByType(type: String, limit: Int, receipts: List<MessageReceiptEntity>) = apply {
99+
wheneverBlocking { mockDao.selectAllByType(type, limit) } doReturn
100+
receiptsStateFlow.apply { value = receipts }
80101
}
81102

82-
fun verifyUpsert(receipts: List<MessageReceiptEntity>) {
103+
fun verifyUpsertCalled(receipts: List<MessageReceiptEntity>) {
83104
verifyBlocking(mockDao) { upsert(receipts) }
84105
}
85106

86-
fun verifyDeleteByMessageIds(messageIds: List<String>) {
107+
fun verifyDeleteByMessageIdsCalled(messageIds: List<String>) {
87108
verifyBlocking(mockDao) { deleteByMessageIds(messageIds) }
88109
}
89110

111+
fun verifyDeleteAllCalled() {
112+
verifyBlocking(mockDao) { deleteAll() }
113+
}
114+
90115
fun get() = MessageReceiptRepositoryImpl(dao = mockDao)
91116
}
92117
}

0 commit comments

Comments
 (0)