Update 'new_message' column when adding and removing notifications

This commit is contained in:
cketti 2021-12-10 22:22:50 +01:00
parent 245404d6e4
commit 386dd9073f
9 changed files with 125 additions and 11 deletions

View file

@ -78,6 +78,11 @@ interface MessageStore {
*/
fun setMessageFlag(folderId: Long, messageServerId: String, flag: Flag, set: Boolean)
/**
* Set whether a message should be considered as new.
*/
fun setNewMessageState(folderId: Long, messageServerId: String, newMessage: Boolean)
/**
* Retrieve the server ID for a given message.
*/

View file

@ -43,6 +43,11 @@ class NotifierMessageStore(
notifyChange()
}
override fun setNewMessageState(folderId: Long, messageServerId: String, newMessage: Boolean) {
messageStore.setNewMessageState(folderId, messageServerId, newMessage)
notifyChange()
}
override fun destroyMessages(folderId: Long, messageServerIds: Collection<String>) {
messageStore.destroyMessages(folderId, messageServerIds)
notifyChange()

View file

@ -108,6 +108,7 @@ val coreNotificationModule = module {
NotificationRepository(
notificationStoreProvider = get(),
localStoreProvider = get(),
messageStoreManager = get(),
notificationContentCreator = get()
)
}

View file

@ -3,10 +3,12 @@ package com.fsck.k9.notification
import com.fsck.k9.Account
import com.fsck.k9.controller.MessageReference
import com.fsck.k9.mailstore.LocalStoreProvider
import com.fsck.k9.mailstore.MessageStoreManager
internal class NotificationRepository(
private val notificationStoreProvider: NotificationStoreProvider,
private val localStoreProvider: LocalStoreProvider,
private val messageStoreManager: MessageStoreManager,
private val notificationContentCreator: NotificationContentCreator
) {
private val notificationDataStore = NotificationDataStore()
@ -58,6 +60,34 @@ internal class NotificationRepository(
private fun persistNotificationDataStoreChanges(account: Account, operations: List<NotificationStoreOperation>) {
val notificationStore = notificationStoreProvider.getNotificationStore(account)
notificationStore.persistNotificationChanges(operations)
setNewMessageState(account, operations)
}
private fun setNewMessageState(account: Account, operations: List<NotificationStoreOperation>) {
val messageStore = messageStoreManager.getMessageStore(account)
for (operation in operations) {
when (operation) {
is NotificationStoreOperation.Add -> {
val messageReference = operation.messageReference
messageStore.setNewMessageState(
folderId = messageReference.folderId,
messageServerId = messageReference.uid,
newMessage = true
)
}
is NotificationStoreOperation.Remove -> {
val messageReference = operation.messageReference
messageStore.setNewMessageState(
folderId = messageReference.folderId,
messageServerId = messageReference.uid,
newMessage = false
)
}
else -> Unit
}
}
}
private fun clearNotificationStore(account: Account) {

View file

@ -6,6 +6,7 @@ import com.fsck.k9.controller.MessageReference
import com.fsck.k9.mailstore.LocalMessage
import com.fsck.k9.mailstore.LocalStore
import com.fsck.k9.mailstore.LocalStoreProvider
import com.fsck.k9.mailstore.MessageStoreManager
import com.fsck.k9.mailstore.NotificationMessage
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertNotNull
@ -429,14 +430,18 @@ class NewMailNotificationManagerTest {
}
private fun createNotificationRepository(): NotificationRepository {
val notificationStoreProvider = object : NotificationStoreProvider {
override fun getNotificationStore(account: Account): NotificationStore {
return object : NotificationStore {
override fun persistNotificationChanges(operations: List<NotificationStoreOperation>) = Unit
override fun clearNotifications() = Unit
}
}
val notificationStoreProvider = mock<NotificationStoreProvider> {
on { getNotificationStore(account) } doReturn mock()
}
return NotificationRepository(notificationStoreProvider, localStoreProvider, notificationContentCreator)
val messageStoreManager = mock<MessageStoreManager> {
on { getMessageStore(account) } doReturn mock()
}
return NotificationRepository(
notificationStoreProvider,
localStoreProvider,
messageStoreManager,
notificationContentCreator
)
}
}

View file

@ -33,6 +33,7 @@ class K9MessageStore(
private val copyMessageOperations = CopyMessageOperations(database, attachmentFileManager, threadMessageOperations)
private val moveMessageOperations = MoveMessageOperations(database, threadMessageOperations)
private val flagMessageOperations = FlagMessageOperations(database)
private val updateMessageOperations = UpdateMessageOperations(database)
private val retrieveMessageOperations = RetrieveMessageOperations(database)
private val deleteMessageOperations = DeleteMessageOperations(database, attachmentFileManager)
private val createFolderOperations = CreateFolderOperations(database)
@ -67,6 +68,10 @@ class K9MessageStore(
flagMessageOperations.setMessageFlag(folderId, messageServerId, flag, set)
}
override fun setNewMessageState(folderId: Long, messageServerId: String, newMessage: Boolean) {
updateMessageOperations.setNewMessageState(folderId, messageServerId, newMessage)
}
override fun getMessageServerId(messageId: Long): String {
return retrieveMessageOperations.getMessageServerId(messageId)
}

View file

@ -0,0 +1,22 @@
package com.fsck.k9.storage.messages
import android.content.ContentValues
import com.fsck.k9.mailstore.LockableDatabase
internal class UpdateMessageOperations(private val lockableDatabase: LockableDatabase) {
fun setNewMessageState(folderId: Long, messageServerId: String, newMessage: Boolean) {
lockableDatabase.execute(false) { database ->
val values = ContentValues().apply {
put("new_message", if (newMessage) 1 else 0)
}
database.update(
"messages",
values,
"folder_id = ? AND uid = ?",
arrayOf(folderId.toString(), messageServerId)
)
}
}
}

View file

@ -62,7 +62,8 @@ fun SQLiteDatabase.createMessage(
answered: Boolean = false,
forwarded: Boolean = false,
messagePartId: Long = 0L,
encryptionType: String? = null
encryptionType: String? = null,
newMessage: Boolean = false
): Long {
val values = ContentValues().apply {
put("deleted", if (deleted) 1 else 0)
@ -90,6 +91,7 @@ fun SQLiteDatabase.createMessage(
put("forwarded", if (forwarded) 1 else 0)
put("message_part_id", messagePartId)
put("encryption_type", encryptionType)
put("new_message", if (newMessage) 1 else 0)
}
return insert("messages", null, values)
@ -125,7 +127,8 @@ fun SQLiteDatabase.readMessages(): List<MessageEntry> {
answered = cursor.getIntOrNull("answered"),
forwarded = cursor.getIntOrNull("forwarded"),
messagePartId = cursor.getLongOrNull("message_part_id"),
encryptionType = cursor.getStringOrNull("encryption_type")
encryptionType = cursor.getStringOrNull("encryption_type"),
newMessage = cursor.getIntOrNull("new_message")
)
}
}
@ -157,7 +160,8 @@ data class MessageEntry(
val answered: Int?,
val forwarded: Int?,
val messagePartId: Long?,
val encryptionType: String?
val encryptionType: String?,
val newMessage: Int?
)
fun SQLiteDatabase.createMessagePart(

View file

@ -0,0 +1,37 @@
package com.fsck.k9.storage.messages
import com.fsck.k9.storage.RobolectricTest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
class UpdateMessageOperationsTest : RobolectricTest() {
private val sqliteDatabase = createDatabase()
private val lockableDatabase = createLockableDatabaseMock(sqliteDatabase)
private val updateMessageOperations = UpdateMessageOperations(lockableDatabase)
@Test
fun `mark message as new`() {
sqliteDatabase.createMessage(folderId = 1, uid = "uid1", newMessage = false)
updateMessageOperations.setNewMessageState(folderId = 1, messageServerId = "uid1", newMessage = true)
val messages = sqliteDatabase.readMessages()
assertThat(messages).hasSize(1)
val message = messages.first()
assertThat(message.newMessage).isEqualTo(1)
}
@Test
fun `mark message as not new`() {
sqliteDatabase.createMessage(folderId = 1, uid = "uid1", newMessage = true)
updateMessageOperations.setNewMessageState(folderId = 1, messageServerId = "uid1", newMessage = false)
val messages = sqliteDatabase.readMessages()
assertThat(messages).hasSize(1)
val message = messages.first()
assertThat(message.newMessage).isEqualTo(0)
}
}