Merge pull request #661 from mpretty-cyro/fix/deleted-messages-read-state

Fixed a bug where deleted incoming messages could incorrectly be counted as unread
This commit is contained in:
Morgan Pretty 2022-08-16 12:39:11 +10:00 committed by GitHub
commit 6c5d138bd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 47 additions and 7 deletions

View File

@ -644,6 +644,7 @@
FD245C6B2850667400B966DD /* VisibleMessage+Profile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C300A5B12554AF9800555489 /* VisibleMessage+Profile.swift */; };
FD245C6C2850669200B966DD /* MessageReceiveJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A31225574F5200338F3E /* MessageReceiveJob.swift */; };
FD245C6D285066A400B966DD /* NotifyPushServerJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A32E2557549C00338F3E /* NotifyPushServerJob.swift */; };
FD37EA0D28AB2A45003AE748 /* _005_FixDeletedMessageReadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA0C28AB2A45003AE748 /* _005_FixDeletedMessageReadState.swift */; };
FD3AABE928306BBD00E5099A /* ThreadPickerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3AABE828306BBD00E5099A /* ThreadPickerViewModel.swift */; };
FD3C905C27E3FBEF00CD579F /* BatchRequestInfoSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C905B27E3FBEF00CD579F /* BatchRequestInfoSpec.swift */; };
FD3C906027E410F700CD579F /* FileUploadResponseSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C905F27E410F700CD579F /* FileUploadResponseSpec.swift */; };
@ -1683,6 +1684,7 @@
FD245C612850664300B966DD /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListUIUtils.swift; sourceTree = "<group>"; };
FD28A4F527EAD44C00FF65E7 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = "<group>"; };
FD37EA0C28AB2A45003AE748 /* _005_FixDeletedMessageReadState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _005_FixDeletedMessageReadState.swift; sourceTree = "<group>"; };
FD3AABE828306BBD00E5099A /* ThreadPickerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadPickerViewModel.swift; sourceTree = "<group>"; };
FD3C905B27E3FBEF00CD579F /* BatchRequestInfoSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchRequestInfoSpec.swift; sourceTree = "<group>"; };
FD3C905F27E410F700CD579F /* FileUploadResponseSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUploadResponseSpec.swift; sourceTree = "<group>"; };
@ -3454,6 +3456,7 @@
FDF0B7412804EA4F004C14C5 /* _002_SetupStandardJobs.swift */,
FD17D79827F40AB800122BE0 /* _003_YDBToGRDBMigration.swift */,
FDF40CDD2897A1BC006A0CC4 /* _004_RemoveLegacyYDB.swift */,
FD37EA0C28AB2A45003AE748 /* _005_FixDeletedMessageReadState.swift */,
);
path = Migrations;
sourceTree = "<group>";
@ -5191,6 +5194,7 @@
FD716E682850318E00C96BF4 /* CallMode.swift in Sources */,
FD09799527FE7B8E00936362 /* Interaction.swift in Sources */,
FD5C72FF284F0F120029977D /* MessageReceiver+ConfigurationMessages.swift in Sources */,
FD37EA0D28AB2A45003AE748 /* _005_FixDeletedMessageReadState.swift in Sources */,
FDC4380927B31D4E00C60D73 /* OpenGroupAPIError.swift in Sources */,
FDC4382027B36ADC00C60D73 /* SOGSEndpoint.swift in Sources */,
FDC438C927BB706500C60D73 /* SendDirectMessageRequest.swift in Sources */,

View File

@ -435,6 +435,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
return try Interaction
.filter(Interaction.Columns.wasRead == false)
.filter(
// Exclude outgoing and deleted messages from the count
Interaction.Columns.variant != Interaction.Variant.standardOutgoing &&
Interaction.Columns.variant != Interaction.Variant.standardIncomingDeleted
)
.filter(
// Only count mentions if 'onlyNotifyForMentions' is set
thread[.onlyNotifyForMentions] == false ||

View File

@ -15,6 +15,9 @@ public enum SNMessagingKit { // Just to make the external API nice
],
[
_004_RemoveLegacyYDB.self
],
[
_005_FixDeletedMessageReadState.self
]
]
)

View File

@ -0,0 +1,25 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtilitiesKit
/// This migration fixes a bug where certain message variants could incorrectly be counted as unread messages
enum _005_FixDeletedMessageReadState: Migration {
static let target: TargetMigrations.Identifier = .messagingKit
static let identifier: String = "FixDeletedMessageReadState"
static let needsConfigSync: Bool = false
static let minExpectedRunDuration: TimeInterval = 0.1
static func migrate(_ db: Database) throws {
_ = try Interaction
.filter(
Interaction.Columns.variant == Interaction.Variant.standardIncomingDeleted ||
Interaction.Columns.variant == Interaction.Variant.standardOutgoing ||
Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate
)
.updateAll(db, Interaction.Columns.wasRead.set(to: true))
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -208,7 +208,7 @@ public class SMKDisappearingMessagesConfiguration: NSObject {
body: config.messageInfoString(with: nil),
timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000))
)
.saved(db)
.inserted(db)
try MessageSender.send(
db,

View File

@ -262,7 +262,7 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
self.body = body
self.timestampMs = timestampMs
self.receivedAtTimestampMs = receivedAtTimestampMs
self.wasRead = wasRead
self.wasRead = (wasRead && variant.canBeUnread)
self.hasMention = hasMention
self.expiresInSeconds = expiresInSeconds
self.expiresStartedAtMs = expiresStartedAtMs
@ -304,7 +304,7 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
default: return timestampMs
}
}()
self.wasRead = wasRead
self.wasRead = (wasRead && variant.canBeUnread)
self.hasMention = hasMention
self.expiresInSeconds = expiresInSeconds
self.expiresStartedAtMs = expiresStartedAtMs
@ -497,8 +497,6 @@ public extension Interaction {
.filter(Interaction.Columns.threadId == threadId)
.filter(Interaction.Columns.timestampMs <= interactionInfo.timestampMs)
.filter(Interaction.Columns.wasRead == false)
// The `wasRead` flag doesn't apply to `standardOutgoing` or `standardIncomingDeleted`
.filter(Columns.variant != Variant.standardOutgoing && Columns.variant != Variant.standardIncomingDeleted)
let interactionIdsToMarkAsRead: [Int64] = try interactionQuery
.select(.id)
.asRequest(of: Int64.self)
@ -600,7 +598,7 @@ public extension Interaction {
body: nil,
timestampMs: timestampMs,
receivedAtTimestampMs: receivedAtTimestampMs,
wasRead: wasRead,
wasRead: (wasRead && Variant.standardIncomingDeleted.canBeUnread),
hasMention: hasMention,
expiresInSeconds: expiresInSeconds,
expiresStartedAtMs: expiresStartedAtMs,

View File

@ -241,7 +241,7 @@ public class SMKOpenGroup: NSObject {
.fetchOne(db),
linkPreviewUrl: urlString
)
.saved(db)
.inserted(db)
try MessageSender.send(
db,

View File

@ -193,6 +193,7 @@ extension MessageReceiver {
)
)
.inserted(db)
try MessageSender
.sendNonDurably(
db,

View File

@ -346,6 +346,8 @@ public extension SessionThreadViewModel {
// MARK: --SessionThreadViewModel
public extension SessionThreadViewModel {
/// **Note:** This query **will not** include deleted incoming messages in it's unread count (they should never be marked as unread
/// but including this warning just in case there is a discrepancy)
static func baseQuery(
userPublicKey: String,
filterSQL: SQL,
@ -610,6 +612,8 @@ public extension SessionThreadViewModel {
// MARK: - ConversationVC
public extension SessionThreadViewModel {
/// **Note:** This query **will** include deleted incoming messages in it's unread count (they should never be marked as unread
/// but including this warning just in case there is a discrepancy)
static func conversationQuery(threadId: String, userPublicKey: String) -> AdaptedFetchRequest<SQLRequest<SessionThreadViewModel>> {
let thread: TypedTableAlias<SessionThread> = TypedTableAlias()
let contact: TypedTableAlias<Contact> = TypedTableAlias()