mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: Add "Mark all as read" and unread message count indicators (#4720)
This commit is contained in:
parent
6a1a612c38
commit
b0258d0cf1
10 changed files with 131 additions and 26 deletions
|
|
@ -77,6 +77,9 @@ constructor(
|
|||
override suspend fun getUnreadCount(contact: String): Int =
|
||||
withContext(dispatchers.io) { dbManager.currentDb.value.packetDao().getUnreadCount(contact) }
|
||||
|
||||
override fun getUnreadCountFlow(contact: String): Flow<Int> =
|
||||
dbManager.currentDb.flatMapLatest { db -> db.packetDao().getUnreadCountFlow(contact) }
|
||||
|
||||
override fun getFirstUnreadMessageUuid(contact: String): Flow<Long?> =
|
||||
dbManager.currentDb.flatMapLatest { db -> db.packetDao().getFirstUnreadMessageUuid(contact) }
|
||||
|
||||
|
|
@ -89,6 +92,9 @@ constructor(
|
|||
override suspend fun clearUnreadCount(contact: String, timestamp: Long) =
|
||||
withContext(dispatchers.io) { dbManager.currentDb.value.packetDao().clearUnreadCount(contact, timestamp) }
|
||||
|
||||
override suspend fun clearAllUnreadCounts() =
|
||||
withContext(dispatchers.io) { dbManager.currentDb.value.packetDao().clearAllUnreadCounts() }
|
||||
|
||||
override suspend fun updateLastReadMessage(contact: String, messageUuid: Long, lastReadTimestamp: Long) =
|
||||
withContext(dispatchers.io) {
|
||||
val dao = dbManager.currentDb.value.packetDao()
|
||||
|
|
|
|||
|
|
@ -158,6 +158,26 @@ class PacketDaoTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_getUnreadCount_excludesFiltered() = runBlocking {
|
||||
val filteredContactKey = "0!filteredonly"
|
||||
val filteredPacket =
|
||||
Packet(
|
||||
uuid = 0L,
|
||||
myNodeNum = myNodeNum,
|
||||
port_num = 1,
|
||||
contact_key = filteredContactKey,
|
||||
received_time = nowMillis,
|
||||
read = false,
|
||||
filtered = true,
|
||||
data = DataPacket(DataPacket.ID_BROADCAST, 0, "Filtered message"),
|
||||
)
|
||||
packetDao.insert(filteredPacket)
|
||||
|
||||
val unreadCount = packetDao.getUnreadCount(filteredContactKey)
|
||||
assertEquals(0, unreadCount)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_clearUnreadCount() = runBlocking {
|
||||
val timestamp = nowMillis
|
||||
|
|
|
|||
|
|
@ -94,16 +94,25 @@ interface PacketDao {
|
|||
"""
|
||||
SELECT COUNT(*) FROM packet
|
||||
WHERE (myNodeNum = 0 OR myNodeNum = (SELECT myNodeNum FROM my_node))
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0 AND filtered = 0
|
||||
""",
|
||||
)
|
||||
suspend fun getUnreadCount(contact: String): Int
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT COUNT(*) FROM packet
|
||||
WHERE (myNodeNum = 0 OR myNodeNum = (SELECT myNodeNum FROM my_node))
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0 AND filtered = 0
|
||||
""",
|
||||
)
|
||||
fun getUnreadCountFlow(contact: String): Flow<Int>
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT uuid FROM packet
|
||||
WHERE (myNodeNum = 0 OR myNodeNum = (SELECT myNodeNum FROM my_node))
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0 AND filtered = 0
|
||||
ORDER BY received_time ASC
|
||||
LIMIT 1
|
||||
""",
|
||||
|
|
@ -114,7 +123,7 @@ interface PacketDao {
|
|||
"""
|
||||
SELECT COUNT(*) > 0 FROM packet
|
||||
WHERE (myNodeNum = 0 OR myNodeNum = (SELECT myNodeNum FROM my_node))
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0 AND filtered = 0
|
||||
""",
|
||||
)
|
||||
fun hasUnreadMessages(contact: String): Flow<Boolean>
|
||||
|
|
@ -123,7 +132,7 @@ interface PacketDao {
|
|||
"""
|
||||
SELECT COUNT(*) FROM packet
|
||||
WHERE (myNodeNum = 0 OR myNodeNum = (SELECT myNodeNum FROM my_node))
|
||||
AND port_num = 1 AND read = 0
|
||||
AND port_num = 1 AND read = 0 AND filtered = 0
|
||||
""",
|
||||
)
|
||||
fun getUnreadCountTotal(): Flow<Int>
|
||||
|
|
@ -133,11 +142,21 @@ interface PacketDao {
|
|||
UPDATE packet
|
||||
SET read = 1
|
||||
WHERE (myNodeNum = 0 OR myNodeNum = (SELECT myNodeNum FROM my_node))
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0 AND received_time <= :timestamp
|
||||
AND port_num = 1 AND contact_key = :contact AND read = 0 AND filtered = 0 AND received_time <= :timestamp
|
||||
""",
|
||||
)
|
||||
suspend fun clearUnreadCount(contact: String, timestamp: Long)
|
||||
|
||||
@Query(
|
||||
"""
|
||||
UPDATE packet
|
||||
SET read = 1
|
||||
WHERE (myNodeNum = 0 OR myNodeNum = (SELECT myNodeNum FROM my_node))
|
||||
AND port_num = 1 AND read = 0 AND filtered = 0
|
||||
""",
|
||||
)
|
||||
suspend fun clearAllUnreadCounts()
|
||||
|
||||
@Upsert suspend fun insert(packet: Packet)
|
||||
|
||||
@Transaction
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ interface PacketRepository {
|
|||
/** Returns the count of unread messages in a conversation. */
|
||||
suspend fun getUnreadCount(contact: String): Int
|
||||
|
||||
/** Reactive flow of the unread message count in a conversation. */
|
||||
fun getUnreadCountFlow(contact: String): Flow<Int>
|
||||
|
||||
/** Reactive flow of the UUID of the first unread message in a conversation. */
|
||||
fun getFirstUnreadMessageUuid(contact: String): Flow<Long?>
|
||||
|
||||
|
|
@ -61,6 +64,9 @@ interface PacketRepository {
|
|||
/** Clears the unread status for messages in a conversation up to the given timestamp. */
|
||||
suspend fun clearUnreadCount(contact: String, timestamp: Long)
|
||||
|
||||
/** Clears the unread status for all messages across all conversations. */
|
||||
suspend fun clearAllUnreadCounts()
|
||||
|
||||
/** Updates the identifier of the last read message in a conversation. */
|
||||
suspend fun updateLastReadMessage(contact: String, messageUuid: Long, lastReadTimestamp: Long)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import androidx.compose.material.icons.rounded.ContentCopy
|
|||
import androidx.compose.material.icons.rounded.Delete
|
||||
import androidx.compose.material.icons.rounded.Edit
|
||||
import androidx.compose.material.icons.rounded.Folder
|
||||
import androidx.compose.material.icons.rounded.MarkChatRead
|
||||
import androidx.compose.material.icons.rounded.MoreVert
|
||||
import androidx.compose.material.icons.rounded.QrCode2
|
||||
import androidx.compose.material.icons.rounded.Refresh
|
||||
|
|
@ -81,5 +82,8 @@ val MeshtasticIcons.SelectAll: ImageVector
|
|||
val MeshtasticIcons.ThumbUp: ImageVector
|
||||
get() = Icons.Rounded.ThumbUp
|
||||
|
||||
val MeshtasticIcons.MarkChatRead: ImageVector
|
||||
get() = Icons.Rounded.MarkChatRead
|
||||
|
||||
val MeshtasticIcons.QrCode2: ImageVector
|
||||
get() = Icons.Rounded.QrCode2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue