From fdae9552885d2c417c070e5a4ba3449a4a7764f4 Mon Sep 17 00:00:00 2001 From: Ryan ZHAO <> Date: Tue, 13 Feb 2024 15:40:08 +1100 Subject: [PATCH] fix data extraction message DaR --- ...isappearingMessagesSettingsViewModel.swift | 1 + Session/Meta/Session-Info.plist | 4 +- .../DisappearingMessageConfiguration.swift | 5 +- .../Message+DisappearingMessages.swift | 121 ++++++++++++++++++ .../MessageReceiver+Calls.swift | 3 +- ...eReceiver+DataExtractionNotification.swift | 39 ++++-- .../MessageReceiver+ExpirationTimers.swift | 38 +++++- .../MessageReceiver+VisibleMessages.swift | 13 +- .../Sending & Receiving/MessageReceiver.swift | 6 +- 9 files changed, 203 insertions(+), 27 deletions(-) create mode 100644 SessionMessagingKit/Messages/Message+DisappearingMessages.swift diff --git a/Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift b/Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift index 67d967cd1..895e1873e 100644 --- a/Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift +++ b/Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift @@ -486,6 +486,7 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, Naviga authorId: userPublicKey, timestampMs: currentTimestampMs, serverHash: nil, + serverExpirationTimestamp: nil, updatedConfiguration: updatedConfig ) diff --git a/Session/Meta/Session-Info.plist b/Session/Meta/Session-Info.plist index 6a0190a1d..452f90504 100644 --- a/Session/Meta/Session-Info.plist +++ b/Session/Meta/Session-Info.plist @@ -57,6 +57,8 @@ NSAppTransportSecurity + NSAllowsArbitraryLoads + NSExceptionDomains seed1.getsession.org @@ -85,7 +87,7 @@ NSCameraUsageDescription Session needs camera access to take pictures and scan QR codes. NSFaceIDUsageDescription - Session's Screen Lock feature uses Face ID. + Session's Screen Lock feature uses Face ID. NSHumanReadableCopyright com.loki-project.loki-messenger NSMicrophoneUsageDescription diff --git a/SessionMessagingKit/Database/Models/DisappearingMessageConfiguration.swift b/SessionMessagingKit/Database/Models/DisappearingMessageConfiguration.swift index cbfafa8aa..d5b06100f 100644 --- a/SessionMessagingKit/Database/Models/DisappearingMessageConfiguration.swift +++ b/SessionMessagingKit/Database/Models/DisappearingMessageConfiguration.swift @@ -253,8 +253,7 @@ public extension DisappearingMessagesConfiguration { openGroup: nil ) ) - let messageExpirationInfo: MessageReceiver.MessageExpirationInfo = MessageReceiver.getMessageExpirationInfo( - db, + let messageExpirationInfo: Message.MessageExpirationInfo = Message.getMessageExpirationInfo( wasRead: wasRead, serverExpirationTimestamp: serverExpirationTimestamp, expiresInSeconds: (updatedConfiguration.type == .disappearAfterSend) ? Double(timestampMs) : nil, @@ -276,7 +275,7 @@ public extension DisappearingMessagesConfiguration { ).inserted(db) if messageExpirationInfo.shouldUpdateExpiry { - MessageReceiver.updateExpiryForDisappearAfterReadMessages( + Message.updateExpiryForDisappearAfterReadMessages( db, threadId: threadId, serverHash: serverHash, diff --git a/SessionMessagingKit/Messages/Message+DisappearingMessages.swift b/SessionMessagingKit/Messages/Message+DisappearingMessages.swift new file mode 100644 index 000000000..1e99a21b8 --- /dev/null +++ b/SessionMessagingKit/Messages/Message+DisappearingMessages.swift @@ -0,0 +1,121 @@ +// Copyright © 2024 Rangeproof Pty Ltd. All rights reserved. + +import Foundation +import GRDB +import SessionSnodeKit +import SessionUIKit +import SessionUtilitiesKit + +extension Message { + public struct MessageExpirationInfo { + let expiresStartedAtMs: Double? + let expiresInSeconds: TimeInterval? + let shouldUpdateExpiry: Bool + } + + public static func getMessageExpirationInfo( + wasRead: Bool, + serverExpirationTimestamp: TimeInterval?, + expiresInSeconds: TimeInterval?, + expiresStartedAtMs: Double? + ) -> MessageExpirationInfo { + var shouldUpdateExpiry: Bool = false + let expiresStartedAtMs: Double? = { + // Disappear after sent + guard expiresStartedAtMs == nil else { + return expiresStartedAtMs + } + + // Disappear after read + guard + let expiresInSeconds: TimeInterval = expiresInSeconds, + expiresInSeconds > 0, + wasRead, + let serverExpirationTimestamp: TimeInterval = serverExpirationTimestamp + else { + return nil + } + + let nowMs: Double = Double(SnodeAPI.currentOffsetTimestampMs()) + let serverExpirationTimestampMs: Double = serverExpirationTimestamp * 1000 + let expiresInMs: Double = expiresInSeconds * 1000 + + if serverExpirationTimestampMs <= (nowMs + expiresInMs) { + // seems to have been shortened already + return (serverExpirationTimestampMs - expiresInMs) + } else { + // consider that message unread + shouldUpdateExpiry = true + return (nowMs + expiresInSeconds) + } + }() + + return MessageExpirationInfo( + expiresStartedAtMs: expiresStartedAtMs, + expiresInSeconds: expiresInSeconds, + shouldUpdateExpiry: shouldUpdateExpiry + ) + } + + public static func getExpirationForOutgoingDisappearingMessages( + _ db: Database, + threadId: String, + variant: Interaction.Variant, + serverHash: String?, + expireInSeconds: TimeInterval? + ) { + guard + variant == .standardOutgoing, + let serverHash: String = serverHash, + let expireInSeconds: TimeInterval = expireInSeconds, + expireInSeconds > 0 + else { + return + } + + let startedAtTimestampMs: Double = Double(SnodeAPI.currentOffsetTimestampMs()) + + JobRunner.add( + db, + job: Job( + variant: .getExpiration, + behaviour: .runOnce, + threadId: threadId, + details: GetExpirationJob.Details( + expirationInfo: [serverHash: expireInSeconds], + startedAtTimestampMs: startedAtTimestampMs + ) + ) + ) + } + + public static func updateExpiryForDisappearAfterReadMessages( + _ db: Database, + threadId: String, + serverHash: String?, + expiresInSeconds: TimeInterval?, + expiresStartedAtMs: Double? + ) { + guard + let serverHash: String = serverHash, + let expiresInSeconds: TimeInterval = expiresInSeconds, + let expiresStartedAtMs: Double = expiresStartedAtMs + else { + return + } + + let expirationTimestampMs: Int64 = Int64(expiresStartedAtMs + expiresInSeconds * 1000) + JobRunner.add( + db, + job: Job( + variant: .expirationUpdate, + behaviour: .runOnce, + threadId: threadId, + details: ExpirationUpdateJob.Details( + serverHashes: [serverHash], + expirationTimestampMs: expirationTimestampMs + ) + ) + ) + } +} diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+Calls.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+Calls.swift index 2c1f8d07d..0c0fdb9c0 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+Calls.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+Calls.swift @@ -11,8 +11,7 @@ extension MessageReceiver { _ db: Database, threadId: String, threadVariant: SessionThread.Variant, - message: CallMessage, - serverExpirationTimestamp: TimeInterval? + message: CallMessage ) throws { // Only support calls from contact threads guard threadVariant == .contact else { return } diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+DataExtractionNotification.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+DataExtractionNotification.swift index c09dfa082..9b0842849 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+DataExtractionNotification.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+DataExtractionNotification.swift @@ -10,7 +10,8 @@ extension MessageReceiver { _ db: Database, threadId: String, threadVariant: SessionThread.Variant, - message: DataExtractionNotification + message: DataExtractionNotification, + serverExpirationTimestamp: TimeInterval? ) throws { guard threadVariant == .contact, @@ -22,6 +23,20 @@ extension MessageReceiver { message.sentTimestamp.map { Int64($0) } ?? SnodeAPI.currentOffsetTimestampMs() ) + + let wasRead: Bool = SessionUtil.timestampAlreadyRead( + threadId: threadId, + threadVariant: threadVariant, + timestampMs: (timestampMs * 1000), + userPublicKey: getUserHexEncodedPublicKey(db), + openGroup: nil + ) + let messageExpirationInfo: Message.MessageExpirationInfo = Message.getMessageExpirationInfo( + wasRead: wasRead, + serverExpirationTimestamp: serverExpirationTimestamp, + expiresInSeconds: message.expiresInSeconds, + expiresStartedAtMs: message.expiresStartedAtMs + ) _ = try Interaction( serverHash: message.serverHash, threadId: threadId, @@ -33,16 +48,20 @@ extension MessageReceiver { } }(), timestampMs: timestampMs, - wasRead: SessionUtil.timestampAlreadyRead( - threadId: threadId, - threadVariant: threadVariant, - timestampMs: (timestampMs * 1000), - userPublicKey: getUserHexEncodedPublicKey(db), - openGroup: nil - ), - expiresInSeconds: message.expiresInSeconds, - expiresStartedAtMs: message.expiresStartedAtMs + wasRead: wasRead, + expiresInSeconds: messageExpirationInfo.expiresInSeconds, + expiresStartedAtMs: messageExpirationInfo.expiresStartedAtMs ) .inserted(db) + + if messageExpirationInfo.shouldUpdateExpiry { + Message.updateExpiryForDisappearAfterReadMessages( + db, + threadId: threadId, + serverHash: message.serverHash, + expiresInSeconds: messageExpirationInfo.expiresInSeconds, + expiresStartedAtMs: messageExpirationInfo.expiresStartedAtMs + ) + } } } diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift index 90cd48c75..0199bceb6 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift @@ -197,11 +197,47 @@ extension MessageReceiver { threadVariant: threadVariant, authorId: sender, timestampMs: Int64(timestampMs), - serverHash: message.serverHash, + serverHash: message.serverHash, + serverExpirationTimestamp: serverExpirationTimestamp, updatedConfiguration: updatedConfig ) default: return } } + + public static func updateContactDisappearingMessagesVersionIfNeeded( + _ db: Database, + messageVariant: Message.Variant?, + contactId: String?, + version: FeatureVersion? + ) { + guard + let messageVariant: Message.Variant = messageVariant, + let contactId: String = contactId, + let version: FeatureVersion = version + else { + return + } + + guard [ .visibleMessage, .expirationTimerUpdate ].contains(messageVariant) else { return } + + _ = try? Contact + .filter(id: contactId) + .updateAllAndConfig( + db, + Contact.Columns.lastKnownClientVersion.set(to: version) + ) + + guard Features.useNewDisappearingMessagesConfig else { return } + + if contactId == getUserHexEncodedPublicKey(db) { + switch version { + case .legacyDisappearingMessages: + TopBannerController.show(warning: .outdatedUserConfig) + case .newDisappearingMessages: + TopBannerController.hide() + } + } + } } diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+VisibleMessages.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+VisibleMessages.swift index cac4b1cc5..2c621e5d3 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+VisibleMessages.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+VisibleMessages.swift @@ -151,8 +151,7 @@ extension MessageReceiver { openGroup: maybeOpenGroup ) ) - let messageExpirationInfo: MessageExpirationInfo = getMessageExpirationInfo( - db, + let messageExpirationInfo: Message.MessageExpirationInfo = Message.getMessageExpirationInfo( wasRead: wasRead, serverExpirationTimestamp: serverExpirationTimestamp, expiresInSeconds: message.expiresInSeconds, @@ -217,7 +216,7 @@ extension MessageReceiver { syncTarget: message.syncTarget ) - getExpirationForOutgoingDisappearingMessages( + Message.getExpirationForOutgoingDisappearingMessages( db, threadId: threadId, variant: variant, @@ -244,16 +243,16 @@ extension MessageReceiver { ) if messageExpirationInfo.shouldUpdateExpiry { - updateExpiryForDisappearAfterReadMessages( + Message.updateExpiryForDisappearAfterReadMessages( db, threadId: threadId, serverHash: message.serverHash, - expiresInSeconds: messageExpirationInfo.expiresInSeconds, - expiresStartedAtMs: messageExpirationInfo.expiresStartedAtMs + expiresInSeconds: message.expiresInSeconds, + expiresStartedAtMs: message.expiresStartedAtMs ) } - getExpirationForOutgoingDisappearingMessages( + Message.getExpirationForOutgoingDisappearingMessages( db, threadId: threadId, variant: variant, diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index 79895d953..bf9b6890f 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -248,7 +248,8 @@ public enum MessageReceiver { db, threadId: threadId, threadVariant: threadVariant, - message: message + message: message, + serverExpirationTimestamp: serverExpirationTimestamp ) case let message as ExpirationTimerUpdate: @@ -281,8 +282,7 @@ public enum MessageReceiver { db, threadId: threadId, threadVariant: threadVariant, - message: message, - serverExpirationTimestamp: serverExpirationTimestamp + message: message ) case let message as MessageRequestResponse: