From ba89d93ee453f1b8a93f779e32456bf745dac4a6 Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Tue, 24 Aug 2021 16:15:55 -0700 Subject: [PATCH 1/7] Add new database column --- .../sds_config/sds-property_order.json | 1 + ...ngConfigurationUpdateInfoMessage+SDS.swift | 3 +- ...WSVerificationStateChangeMessage+SDS.swift | 3 +- .../Interactions/TSErrorMessage+SDS.swift | 3 +- .../Interactions/TSIncomingMessage+SDS.swift | 3 +- .../Interactions/TSInfoMessage+SDS.swift | 3 +- .../Interactions/TSInteraction+SDS.swift | 18 ++++-- .../Messages/Interactions/TSMessage+SDS.swift | 3 +- .../Interactions/TSOutgoingMessage+SDS.swift | 3 +- .../TSUnreadIndicatorInteraction+SDS.swift | 3 +- ...TSInvalidIdentityKeyErrorMessage+SDS.swift | 3 +- ...IdentityKeyReceivingErrorMessage+SDS.swift | 3 +- ...idIdentityKeySendingErrorMessage+SDS.swift | 3 +- .../OWSAddToContactsOfferMessage+SDS.swift | 3 +- ...ddToProfileWhitelistOfferMessage+SDS.swift | 3 +- .../Messages/OWSGroupCallMessage+SDS.swift | 3 +- ...RecoverableDecryptionPlaceholder+SDS.swift | 3 +- .../OWSRecoverableDecryptionPlaceholder.h | 30 +++++++++ .../OWSRecoverableDecryptionPlaceholder.m | 63 +++++++++++++++++++ ...SUnknownContactBlockOfferMessage+SDS.swift | 3 +- ...OWSUnknownProtocolVersionMessage+SDS.swift | 3 +- .../OWSOutgoingPaymentMessage+SDS.swift | 3 +- .../src/Messages/TSCall+SDS.swift | 3 +- 23 files changed, 146 insertions(+), 23 deletions(-) diff --git a/Scripts/sds_codegen/sds_config/sds-property_order.json b/Scripts/sds_codegen/sds_config/sds-property_order.json index e3ac5f948b..09dcbbc805 100644 --- a/Scripts/sds_codegen/sds_config/sds-property_order.json +++ b/Scripts/sds_codegen/sds_config/sds-property_order.json @@ -81,6 +81,7 @@ "InteractionRecord.hasEnded": 56, "InteractionRecord.hasLegacyMessageState": 22, "InteractionRecord.hasSyncedTranscript": 23, + "InteractionRecord.hiddenUntilTimestamp": 65, "InteractionRecord.infoMessageUserInfo": 50, "InteractionRecord.isFromLinkedDevice": 24, "InteractionRecord.isLocalChange": 25, diff --git a/SignalServiceKit/src/Messages/Interactions/OWSDisappearingConfigurationUpdateInfoMessage+SDS.swift b/SignalServiceKit/src/Messages/Interactions/OWSDisappearingConfigurationUpdateInfoMessage+SDS.swift index e73662959e..c4f924d498 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSDisappearingConfigurationUpdateInfoMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/OWSDisappearingConfigurationUpdateInfoMessage+SDS.swift @@ -125,7 +125,8 @@ class OWSDisappearingConfigurationUpdateInfoMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Interactions/OWSVerificationStateChangeMessage+SDS.swift b/SignalServiceKit/src/Messages/Interactions/OWSVerificationStateChangeMessage+SDS.swift index c5361b58bf..19c6e47d43 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSVerificationStateChangeMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/OWSVerificationStateChangeMessage+SDS.swift @@ -125,7 +125,8 @@ class OWSVerificationStateChangeMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage+SDS.swift b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage+SDS.swift index c0c8769167..c3d63896d6 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage+SDS.swift @@ -125,7 +125,8 @@ class TSErrorMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage+SDS.swift b/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage+SDS.swift index 97f644af8e..562da909f7 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage+SDS.swift @@ -125,7 +125,8 @@ class TSIncomingMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = model.wasViewed let serverGuid: String? = model.serverGuid + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Interactions/TSInfoMessage+SDS.swift b/SignalServiceKit/src/Messages/Interactions/TSInfoMessage+SDS.swift index 9ba59245b0..7a19442fcc 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInfoMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/TSInfoMessage+SDS.swift @@ -125,7 +125,8 @@ class TSInfoMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Interactions/TSInteraction+SDS.swift b/SignalServiceKit/src/Messages/Interactions/TSInteraction+SDS.swift index cd5ca164f1..fccf3fe45e 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInteraction+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/TSInteraction+SDS.swift @@ -92,6 +92,7 @@ public struct InteractionRecord: SDSRecord { public let paymentRequest: Data? public let viewed: Bool? public let serverGuid: String? + public let hiddenUntilTimestamp: UInt64? public enum CodingKeys: String, CodingKey, ColumnExpression, CaseIterable { case id @@ -161,6 +162,7 @@ public struct InteractionRecord: SDSRecord { case paymentRequest case viewed case serverGuid + case hiddenUntilTimestamp } public static func columnName(_ column: InteractionRecord.CodingKeys, fullyQualified: Bool = false) -> String { @@ -251,6 +253,7 @@ public extension InteractionRecord { paymentRequest = row[64] viewed = row[65] serverGuid = row[66] + hiddenUntilTimestamp = row[67] } } @@ -625,6 +628,7 @@ extension TSInteraction { let senderSerialized: Data? = record.sender let sender: SignalServiceAddress? = try SDSDeserialization.optionalUnarchive(senderSerialized, name: "sender") let wasIdentityVerified: Bool = try SDSDeserialization.required(record.wasIdentityVerified, name: "wasIdentityVerified") + let hiddenUntilTimestamp: UInt64 = try SDSDeserialization.required(record.hiddenUntilTimestamp, name: "hiddenUntilTimestamp") return OWSRecoverableDecryptionPlaceholder(grdbId: recordId, uniqueId: uniqueId, @@ -650,7 +654,8 @@ extension TSInteraction { read: read, recipientAddress: recipientAddress, sender: sender, - wasIdentityVerified: wasIdentityVerified) + wasIdentityVerified: wasIdentityVerified, + hiddenUntilTimestamp: hiddenUntilTimestamp) case .unknownContactBlockOfferMessage: @@ -3546,6 +3551,7 @@ extension TSInteraction: DeepCopyable { sender = nil } let wasIdentityVerified: Bool = modelToCopy.wasIdentityVerified + let hiddenUntilTimestamp: UInt64 = modelToCopy.hiddenUntilTimestamp return OWSRecoverableDecryptionPlaceholder(grdbId: id, uniqueId: uniqueId, @@ -3571,7 +3577,8 @@ extension TSInteraction: DeepCopyable { read: read, recipientAddress: recipientAddress, sender: sender, - wasIdentityVerified: wasIdentityVerified) + wasIdentityVerified: wasIdentityVerified, + hiddenUntilTimestamp: hiddenUntilTimestamp) } if let modelToCopy = self as? TSErrorMessage { @@ -3974,6 +3981,7 @@ extension TSInteractionSerializer { static let paymentRequestColumn = SDSColumnMetadata(columnName: "paymentRequest", columnType: .blob, isOptional: true) static let viewedColumn = SDSColumnMetadata(columnName: "viewed", columnType: .int, isOptional: true) static let serverGuidColumn = SDSColumnMetadata(columnName: "serverGuid", columnType: .unicodeString, isOptional: true) + static let hiddenUntilTimestampColumn = SDSColumnMetadata(columnName: "hiddenUntilTimestamp", columnType: .int64, isOptional: true) // TODO: We should decide on a naming convention for // tables that store models. @@ -4046,7 +4054,8 @@ extension TSInteractionSerializer { paymentNotificationColumn, paymentRequestColumn, viewedColumn, - serverGuidColumn + serverGuidColumn, + hiddenUntilTimestampColumn ]) } @@ -4520,8 +4529,9 @@ class TSInteractionSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage+SDS.swift b/SignalServiceKit/src/Messages/Interactions/TSMessage+SDS.swift index f638d6d241..126ca4ccd3 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage+SDS.swift @@ -125,7 +125,8 @@ class TSMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage+SDS.swift b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage+SDS.swift index e765183d47..89810e72ff 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage+SDS.swift @@ -125,7 +125,8 @@ class TSOutgoingMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Interactions/TSUnreadIndicatorInteraction+SDS.swift b/SignalServiceKit/src/Messages/Interactions/TSUnreadIndicatorInteraction+SDS.swift index 5d9d4a02a9..4e9f3e04d9 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSUnreadIndicatorInteraction+SDS.swift +++ b/SignalServiceKit/src/Messages/Interactions/TSUnreadIndicatorInteraction+SDS.swift @@ -125,7 +125,8 @@ class TSUnreadIndicatorInteractionSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage+SDS.swift b/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage+SDS.swift index 6f59a384be..0c0e5885bc 100644 --- a/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage+SDS.swift @@ -125,7 +125,8 @@ class TSInvalidIdentityKeyErrorMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage+SDS.swift b/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage+SDS.swift index ef941ff819..7bf2aba914 100644 --- a/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage+SDS.swift @@ -125,7 +125,8 @@ class TSInvalidIdentityKeyReceivingErrorMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage+SDS.swift b/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage+SDS.swift index a1f24442e3..02591a8b29 100644 --- a/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage+SDS.swift @@ -125,7 +125,8 @@ class TSInvalidIdentityKeySendingErrorMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/OWSAddToContactsOfferMessage+SDS.swift b/SignalServiceKit/src/Messages/OWSAddToContactsOfferMessage+SDS.swift index e6b13bbe0e..281d374e0a 100644 --- a/SignalServiceKit/src/Messages/OWSAddToContactsOfferMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/OWSAddToContactsOfferMessage+SDS.swift @@ -125,7 +125,8 @@ class OWSAddToContactsOfferMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/OWSAddToProfileWhitelistOfferMessage+SDS.swift b/SignalServiceKit/src/Messages/OWSAddToProfileWhitelistOfferMessage+SDS.swift index 8729f2bf7e..9eaa5472e6 100644 --- a/SignalServiceKit/src/Messages/OWSAddToProfileWhitelistOfferMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/OWSAddToProfileWhitelistOfferMessage+SDS.swift @@ -125,7 +125,8 @@ class OWSAddToProfileWhitelistOfferMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/OWSGroupCallMessage+SDS.swift b/SignalServiceKit/src/Messages/OWSGroupCallMessage+SDS.swift index 19af4b0412..4dfe76c455 100644 --- a/SignalServiceKit/src/Messages/OWSGroupCallMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/OWSGroupCallMessage+SDS.swift @@ -125,7 +125,8 @@ class OWSGroupCallMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder+SDS.swift b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder+SDS.swift index 8c8c662466..693b5e11eb 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder+SDS.swift +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder+SDS.swift @@ -125,7 +125,8 @@ class OWSRecoverableDecryptionPlaceholderSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = model.hiddenUntilTimestamp - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.h b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.h index 50b17ce020..d09c179bd8 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.h +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.h @@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN @property (assign, nonatomic, readonly) BOOL isVisible; @property (assign, nonatomic, readonly) BOOL supportsReplacement; +@property (assign, nonatomic, readonly) uint64_t hiddenUntilTimestamp; // Used to resolve timestamp collisions for a long-lived placeholder. // If a placeholder has outlived its eligible replacement period, it will live on as an error message @@ -31,6 +32,35 @@ NS_ASSUME_NONNULL_BEGIN // `sds_codegen.sh`. // clang-format off + +- (instancetype)initWithGrdbId:(int64_t)grdbId + uniqueId:(NSString *)uniqueId + receivedAtTimestamp:(uint64_t)receivedAtTimestamp + sortId:(uint64_t)sortId + timestamp:(uint64_t)timestamp + uniqueThreadId:(NSString *)uniqueThreadId + attachmentIds:(NSArray *)attachmentIds + body:(nullable NSString *)body + bodyRanges:(nullable MessageBodyRanges *)bodyRanges + contactShare:(nullable OWSContact *)contactShare + expireStartedAt:(uint64_t)expireStartedAt + expiresAt:(uint64_t)expiresAt + expiresInSeconds:(unsigned int)expiresInSeconds + isViewOnceComplete:(BOOL)isViewOnceComplete + isViewOnceMessage:(BOOL)isViewOnceMessage + linkPreview:(nullable OWSLinkPreview *)linkPreview + messageSticker:(nullable MessageSticker *)messageSticker + quotedMessage:(nullable TSQuotedMessage *)quotedMessage + storedShouldStartExpireTimer:(BOOL)storedShouldStartExpireTimer + wasRemotelyDeleted:(BOOL)wasRemotelyDeleted + errorType:(TSErrorMessageType)errorType + read:(BOOL)read + recipientAddress:(nullable SignalServiceAddress *)recipientAddress + sender:(nullable SignalServiceAddress *)sender + wasIdentityVerified:(BOOL)wasIdentityVerified + hiddenUntilTimestamp:(uint64_t)hiddenUntilTimestamp +NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(grdbId:uniqueId:receivedAtTimestamp:sortId:timestamp:uniqueThreadId:attachmentIds:body:bodyRanges:contactShare:expireStartedAt:expiresAt:expiresInSeconds:isViewOnceComplete:isViewOnceMessage:linkPreview:messageSticker:quotedMessage:storedShouldStartExpireTimer:wasRemotelyDeleted:errorType:read:recipientAddress:sender:wasIdentityVerified:hiddenUntilTimestamp:)); + // clang-format on // --- CODE GENERATION MARKER diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m index fdbb671e28..2fca2452d6 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m @@ -51,6 +51,69 @@ NS_ASSUME_NONNULL_BEGIN // `sds_codegen.sh`. // clang-format off + +- (instancetype)initWithGrdbId:(int64_t)grdbId + uniqueId:(NSString *)uniqueId + receivedAtTimestamp:(uint64_t)receivedAtTimestamp + sortId:(uint64_t)sortId + timestamp:(uint64_t)timestamp + uniqueThreadId:(NSString *)uniqueThreadId + attachmentIds:(NSArray *)attachmentIds + body:(nullable NSString *)body + bodyRanges:(nullable MessageBodyRanges *)bodyRanges + contactShare:(nullable OWSContact *)contactShare + expireStartedAt:(uint64_t)expireStartedAt + expiresAt:(uint64_t)expiresAt + expiresInSeconds:(unsigned int)expiresInSeconds + isViewOnceComplete:(BOOL)isViewOnceComplete + isViewOnceMessage:(BOOL)isViewOnceMessage + linkPreview:(nullable OWSLinkPreview *)linkPreview + messageSticker:(nullable MessageSticker *)messageSticker + quotedMessage:(nullable TSQuotedMessage *)quotedMessage + storedShouldStartExpireTimer:(BOOL)storedShouldStartExpireTimer + wasRemotelyDeleted:(BOOL)wasRemotelyDeleted + errorType:(TSErrorMessageType)errorType + read:(BOOL)read + recipientAddress:(nullable SignalServiceAddress *)recipientAddress + sender:(nullable SignalServiceAddress *)sender + wasIdentityVerified:(BOOL)wasIdentityVerified + hiddenUntilTimestamp:(uint64_t)hiddenUntilTimestamp +{ + self = [super initWithGrdbId:grdbId + uniqueId:uniqueId + receivedAtTimestamp:receivedAtTimestamp + sortId:sortId + timestamp:timestamp + uniqueThreadId:uniqueThreadId + attachmentIds:attachmentIds + body:body + bodyRanges:bodyRanges + contactShare:contactShare + expireStartedAt:expireStartedAt + expiresAt:expiresAt + expiresInSeconds:expiresInSeconds + isViewOnceComplete:isViewOnceComplete + isViewOnceMessage:isViewOnceMessage + linkPreview:linkPreview + messageSticker:messageSticker + quotedMessage:quotedMessage + storedShouldStartExpireTimer:storedShouldStartExpireTimer + wasRemotelyDeleted:wasRemotelyDeleted + errorType:errorType + read:read + recipientAddress:recipientAddress + sender:sender + wasIdentityVerified:wasIdentityVerified]; + + if (!self) { + return self; + } + + _hiddenUntilTimestamp = hiddenUntilTimestamp; + + return self; +} + // clang-format on // --- CODE GENERATION MARKER diff --git a/SignalServiceKit/src/Messages/OWSUnknownContactBlockOfferMessage+SDS.swift b/SignalServiceKit/src/Messages/OWSUnknownContactBlockOfferMessage+SDS.swift index cc7c7b503c..7a7e73a888 100644 --- a/SignalServiceKit/src/Messages/OWSUnknownContactBlockOfferMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/OWSUnknownContactBlockOfferMessage+SDS.swift @@ -125,7 +125,8 @@ class OWSUnknownContactBlockOfferMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/OWSUnknownProtocolVersionMessage+SDS.swift b/SignalServiceKit/src/Messages/OWSUnknownProtocolVersionMessage+SDS.swift index 3c73565689..17b9bbae5b 100644 --- a/SignalServiceKit/src/Messages/OWSUnknownProtocolVersionMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/OWSUnknownProtocolVersionMessage+SDS.swift @@ -125,7 +125,8 @@ class OWSUnknownProtocolVersionMessageSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/Payments/OWSOutgoingPaymentMessage+SDS.swift b/SignalServiceKit/src/Messages/Payments/OWSOutgoingPaymentMessage+SDS.swift index f361ca4b29..70f1354840 100644 --- a/SignalServiceKit/src/Messages/Payments/OWSOutgoingPaymentMessage+SDS.swift +++ b/SignalServiceKit/src/Messages/Payments/OWSOutgoingPaymentMessage+SDS.swift @@ -125,7 +125,8 @@ class OWSOutgoingPaymentMessageSerializer: SDSSerializer { let paymentRequest: Data? = optionalArchive(model.paymentRequest) let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } diff --git a/SignalServiceKit/src/Messages/TSCall+SDS.swift b/SignalServiceKit/src/Messages/TSCall+SDS.swift index 949524a3cf..e58e9bf7b9 100644 --- a/SignalServiceKit/src/Messages/TSCall+SDS.swift +++ b/SignalServiceKit/src/Messages/TSCall+SDS.swift @@ -125,7 +125,8 @@ class TSCallSerializer: SDSSerializer { let paymentRequest: Data? = nil let viewed: Bool? = nil let serverGuid: String? = nil + let hiddenUntilTimestamp: UInt64? = nil - return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid) + return InteractionRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, receivedAtTimestamp: receivedAtTimestamp, timestamp: timestamp, threadUniqueId: threadUniqueId, attachmentIds: attachmentIds, authorId: authorId, authorPhoneNumber: authorPhoneNumber, authorUUID: authorUUID, body: body, callType: callType, configurationDurationSeconds: configurationDurationSeconds, configurationIsEnabled: configurationIsEnabled, contactShare: contactShare, createdByRemoteName: createdByRemoteName, createdInExistingGroup: createdInExistingGroup, customMessage: customMessage, envelopeData: envelopeData, errorType: errorType, expireStartedAt: expireStartedAt, expiresAt: expiresAt, expiresInSeconds: expiresInSeconds, groupMetaMessage: groupMetaMessage, hasLegacyMessageState: hasLegacyMessageState, hasSyncedTranscript: hasSyncedTranscript, isFromLinkedDevice: isFromLinkedDevice, isLocalChange: isLocalChange, isViewOnceComplete: isViewOnceComplete, isViewOnceMessage: isViewOnceMessage, isVoiceMessage: isVoiceMessage, legacyMessageState: legacyMessageState, legacyWasDelivered: legacyWasDelivered, linkPreview: linkPreview, messageId: messageId, messageSticker: messageSticker, messageType: messageType, mostRecentFailureText: mostRecentFailureText, preKeyBundle: preKeyBundle, protocolVersion: protocolVersion, quotedMessage: quotedMessage, read: read, recipientAddress: recipientAddress, recipientAddressStates: recipientAddressStates, sender: sender, serverTimestamp: serverTimestamp, sourceDeviceId: sourceDeviceId, storedMessageState: storedMessageState, storedShouldStartExpireTimer: storedShouldStartExpireTimer, unregisteredAddress: unregisteredAddress, verificationState: verificationState, wasReceivedByUD: wasReceivedByUD, infoMessageUserInfo: infoMessageUserInfo, wasRemotelyDeleted: wasRemotelyDeleted, bodyRanges: bodyRanges, offerType: offerType, serverDeliveryTimestamp: serverDeliveryTimestamp, eraId: eraId, hasEnded: hasEnded, creatorUuid: creatorUuid, joinedMemberUuids: joinedMemberUuids, wasIdentityVerified: wasIdentityVerified, paymentCancellation: paymentCancellation, paymentNotification: paymentNotification, paymentRequest: paymentRequest, viewed: viewed, serverGuid: serverGuid, hiddenUntilTimestamp: hiddenUntilTimestamp) } } From 86310a18558de1418eed5e2a2cbea4a6b232717f Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Tue, 24 Aug 2021 23:01:49 -0700 Subject: [PATCH 2/7] Handling of invisible interactions --- .../CV/CVMessageMapping.swift | 12 ++- .../Notifications/AppNotifications.swift | 2 + SignalServiceKit/src/Contacts/TSThread.m | 2 +- .../Messages/Interactions/TSErrorMessage.h | 5 ++ .../Messages/Interactions/TSErrorMessage.m | 32 ++++--- .../Messages/Interactions/TSInteraction.swift | 42 ++-------- .../src/Messages/OWSMessageDecrypter.swift | 53 ++++++++++++ .../OWSRecoverableDecryptionPlaceholder.h | 9 +- .../OWSRecoverableDecryptionPlaceholder.m | 21 ++--- .../Database/Records/InteractionFinder.swift | 84 +++++++++++++++---- SignalServiceKit/src/Util/Date+SSK.swift | 12 +++ 11 files changed, 186 insertions(+), 88 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift b/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift index 4e13f09466..4390efe4d2 100644 --- a/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift +++ b/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift @@ -163,8 +163,8 @@ public class CVMessageMapping: NSObject { owsAssertDebug(count > 0) let count = max(1, min(count, maxInteractionCount)) - // The number of interactions currently in the conversation. - let conversationSize = interactionFinder.count(transaction: transaction) + // The number of visible interactions currently in the conversation. + let conversationSize = interactionFinder.count(includingHiddenInteractions: false, transaction: transaction) guard conversationSize > 0 else { self.loadedInteractions = [] updateCanLoadMore(fetchIndexSet: IndexSet(), conversationSize: conversationSize) @@ -190,7 +190,10 @@ public class CVMessageMapping: NSObject { // the distance from the oldest message, since most of the time the user will // be scrolled towards the bottom of the conversation. The further you scroll // from the bottom of the conversation, the more expensive this query will get. - guard let distanceFromLatest = try self.interactionFinder.distanceFromLatest(interactionUniqueId: interactionUniqueId, transaction: transaction) else { + guard let distanceFromLatest = try self.interactionFinder.distanceFromLatest( + interactionUniqueId: interactionUniqueId, + countHidden: false, + transaction: transaction) else { throw OWSAssertionError("viewIndex was unexpectedly nil") } return Int(conversationSize - distanceFromLatest - 1) @@ -474,6 +477,7 @@ public class CVMessageMapping: NSObject { var newItems: [TSInteraction] = [] try self.interactionFinder.enumerateInteractions(range: nsRange, + includeHidden: false, transaction: transaction) { (interaction: TSInteraction, _) in newItems.append(interaction) } @@ -483,7 +487,7 @@ public class CVMessageMapping: NSObject { // Loading the mapping from the cache has the following steps: // // 1. Fetch the uniqueIds for the interactions in the load window/mapping. - let interactionIds = try interactionFinder.interactionIds(inRange: nsRange, transaction: transaction) + let interactionIds = try interactionFinder.interactionIds(inRange: nsRange, includeHidden: false, transaction: transaction) guard !interactionIds.isEmpty else { return [] } diff --git a/SignalMessaging/Notifications/AppNotifications.swift b/SignalMessaging/Notifications/AppNotifications.swift index 6ef19deab1..b868874296 100644 --- a/SignalMessaging/Notifications/AppNotifications.swift +++ b/SignalMessaging/Notifications/AppNotifications.swift @@ -692,6 +692,8 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { } public func notifyUser(for errorMessage: TSErrorMessage, thread: TSThread, transaction: SDSAnyWriteTransaction) { + guard (errorMessage is OWSRecoverableDecryptionPlaceholder) == false else { return } + switch errorMessage.errorType { case .noSession, .wrongTrustedIdentityKey, diff --git a/SignalServiceKit/src/Contacts/TSThread.m b/SignalServiceKit/src/Contacts/TSThread.m index e9f36f50f0..c681a61fa7 100644 --- a/SignalServiceKit/src/Contacts/TSThread.m +++ b/SignalServiceKit/src/Contacts/TSThread.m @@ -357,7 +357,7 @@ lastVisibleSortIdOnScreenPercentageObsolete:(double)lastVisibleSortIdOnScreenPer - (NSUInteger)numberOfInteractionsWithTransaction:(SDSAnyReadTransaction *)transaction { OWSAssertDebug(transaction); - return [[[InteractionFinder alloc] initWithThreadUniqueId:self.uniqueId] countWithTransaction:transaction]; + return [[[InteractionFinder alloc] initWithThreadUniqueId:self.uniqueId] countIncludingHiddenInteractions:YES transaction:transaction]; } - (nullable TSInteraction *)lastInteractionForInboxWithTransaction:(SDSAnyReadTransaction *)transaction diff --git a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.h b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.h index 7f82bcf8d4..b561007fde 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.h @@ -129,6 +129,11 @@ NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(grdbId:uniqueId:receivedAtTimestamp groupId:(nullable NSData *)groupId withTransaction:(SDSAnyWriteTransaction *)transaction; ++ (instancetype)failedDecryptionForSender:(nullable SignalServiceAddress *)sender + thread:(TSThread *)thread + timestamp:(uint64_t)timestamp + transaction:(SDSAnyWriteTransaction *)transaction; + @property (nonatomic, readonly) TSErrorMessageType errorType; @property (nullable, nonatomic, readonly) SignalServiceAddress *sender; @property (nullable, nonatomic, readonly) SignalServiceAddress *recipientAddress; diff --git a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m index d80d1a31fd..fa952b6ef8 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m @@ -232,11 +232,15 @@ NSUInteger TSErrorMessageSchemaVersion = 2; return NSLocalizedString( @"ERROR_MESSAGE_SESSION_REFRESH", @"Text notifying the user that their secure session has been reset"); case TSErrorMessageDecryptionFailure: { - NSString *formatString = NSLocalizedString(@"ERROR_MESSAGE_DECRYPTION_FAILURE", - @"Error message for a decryption failure. Embeds {{sender short name}}."); - NSString *senderName = [self.contactsManager shortDisplayNameForAddress:self.sender - transaction:transaction]; - return [[NSString alloc] initWithFormat:formatString, senderName]; + if (self.sender) { + NSString *formatString = NSLocalizedString(@"ERROR_MESSAGE_DECRYPTION_FAILURE", + @"Error message for a decryption failure. Embeds {{sender short name}}."); + NSString *senderName = [self.contactsManager shortDisplayNameForAddress:self.sender + transaction:transaction]; + return [[NSString alloc] initWithFormat:formatString, senderName]; + } else { + return NSLocalizedString(@"ERROR_MESSAGE_DECRYPTION_FAILURE_UNKNOWN_SENDER", @"Error message for a decryption failure."); + } } default: OWSFailDebug(@"failure: unknown error type"); @@ -296,6 +300,18 @@ NSUInteger TSErrorMessageSchemaVersion = 2; return [builder build]; } ++ (instancetype)failedDecryptionForSender:(nullable SignalServiceAddress *)sender + thread:(TSThread *)thread + timestamp:(uint64_t)timestamp + transaction:(SDSAnyWriteTransaction *)transaction +{ + TSErrorMessageBuilder *builder = + [TSErrorMessageBuilder errorMessageBuilderWithThread:thread errorType:TSErrorMessageDecryptionFailure]; + builder.senderAddress = sender; + builder.timestamp = timestamp; + return [builder build]; +} + + (instancetype)failedDecryptionForEnvelope:(SSKProtoEnvelope *)envelope groupId:(nullable NSData *)groupId withTransaction:(SDSAnyWriteTransaction *)transaction @@ -318,11 +334,7 @@ NSUInteger TSErrorMessageSchemaVersion = 2; if (!thread) { return nil; } - TSErrorMessageBuilder *builder = - [TSErrorMessageBuilder errorMessageBuilderWithThread:thread errorType:TSErrorMessageDecryptionFailure]; - builder.senderAddress = sender; - builder.timestamp = envelope.timestamp; - return [builder build]; + return [self failedDecryptionForSender:sender thread:thread timestamp:envelope.timestamp transaction:transaction]; } #pragma mark - OWSReadTracking diff --git a/SignalServiceKit/src/Messages/Interactions/TSInteraction.swift b/SignalServiceKit/src/Messages/Interactions/TSInteraction.swift index 01e6e06f0c..bbe9df47ee 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInteraction.swift +++ b/SignalServiceKit/src/Messages/Interactions/TSInteraction.swift @@ -56,10 +56,9 @@ extension TSInteraction { // there was no meaningful interaction. return false case .decryptionFailure: - if let replaceableInteraction = errorMessage as? OWSRecoverableDecryptionPlaceholder { - // Replaceable interactions may be temporarily hidden if we expect we'll be - // able to recover - return replaceableInteraction.isVisible + if errorMessage is OWSRecoverableDecryptionPlaceholder { + // Replaceable interactions should never be shown to the user + return false } else { return true } @@ -119,40 +118,9 @@ extension TSInteraction { if placeholder.supportsReplacement { placeholder.replaceWithInteraction(self, writeTx: transaction) return true - } else if placeholder.uniqueThreadId == uniqueThreadId { - // We've found the placeholder for the replacement message, but it is no longer eligible - // for replacement. We now want to preserve this placeholder as a permanent error message. - // - // In many places we assume interaction timestamps are unique for a thread. So we adjust the timestamp - // to preserve this uniqueness. It's likely nothing will collide, but we walk back over a small window - // to find an opening just in case. - let timestampWindow = (placeholder.timestamp - 10 ..< placeholder.timestamp).reversed() - - let newTimestamp = timestampWindow.first { candidate in - guard candidate > 0 else { return false } - - do { - return try InteractionFinder.interactions(withTimestamp: candidate, filter: { interaction in - interaction.uniqueThreadId == placeholder.uniqueThreadId - }, transaction: transaction).isEmpty - } catch { - owsFailDebug("\(error)") - return false - } - } - - if let newTimestamp = newTimestamp, newTimestamp > 0 { - Logger.info("Placeholder not eligible for replacement. Updating timestamp") - placeholder.anyUpdate(transaction: transaction) { interaction in - (interaction as? OWSRecoverableDecryptionPlaceholder)?.adjustTimestamp(newTimestamp) - } - } else { - Logger.warn("Placeholder not eligible for replacement. Failed to find free timestamp. Deleting placeholder.") - placeholder.anyRemove(transaction: transaction) - } - return false } else { - Logger.info("Placeholder not eligible for replacement. No need to adjust timestamp") + Logger.info("Placeholder not eligible for replacement, deleting.") + placeholder.anyRemove(transaction: transaction) return false } } diff --git a/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift b/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift index 80c193b1e7..ce0f3cf578 100644 --- a/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift +++ b/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift @@ -51,6 +51,9 @@ public class OWSMessageDecryptResult: NSObject { public class OWSMessageDecrypter: OWSMessageHandler { private var senderIdsResetDuringCurrentBatch = NSMutableSet() + private var placeholderCleanupTimer: Timer? { + didSet { oldValue?.invalidate() } + } public override init() { super.init() @@ -63,6 +66,10 @@ public class OWSMessageDecrypter: OWSMessageHandler { name: MessageProcessor.messageProcessorDidFlushQueue, object: nil ) + + AppReadiness.runNowOrWhenAppDidBecomeReadySync { [weak self] in + self?.schedulePlaceholderCleanup() + } } public func decryptEnvelope(_ envelope: SSKProtoEnvelope, envelopeData: Data, transaction: SDSAnyWriteTransaction) -> Result { @@ -768,6 +775,52 @@ public class OWSMessageDecrypter: OWSMessageHandler { return error } } + + func schedulePlaceholderCleanup() { + databaseStorage.read { readTx in + guard let oldestPlaceholder = GRDBInteractionFinder.oldestPlaceholderInteraction(transaction: readTx.unwrapGrdbRead) else { return } + + if oldestPlaceholder.expirationDate.isBeforeNow { + Logger.info("Oldest placeholder expirationDate: \(oldestPlaceholder.expirationDate). Will perform cleanup...") + placeholderCleanupTimer = nil + cleanupExpiredPlaceholders() + + } else if (placeholderCleanupTimer?.fireDate ?? .distantFuture).isAfter(oldestPlaceholder.expirationDate) { + Logger.info("Oldest placeholder expirationDate: \(oldestPlaceholder.expirationDate). Scheduling timer...") + + placeholderCleanupTimer = Timer.scheduledTimer( + withTimeInterval: oldestPlaceholder.expirationDate.timeIntervalSinceNow, + repeats: false, + block: { [weak self] timer in + self?.cleanupExpiredPlaceholders() + }) + } + } + } + + func cleanupExpiredPlaceholders() { + databaseStorage.asyncWrite { writeTx in + Logger.info("Performing placeholder cleanup") + GRDBInteractionFinder.enumeratePlaceholders(transaction: writeTx.unwrapGrdbWrite) { placeholder, _ in + if placeholder.expirationDate.isBeforeNow { + let thread = placeholder.thread(transaction: writeTx) + + let errorMessage = TSErrorMessage.failedDecryption( + forSender: placeholder.sender, + thread: thread, + timestamp: placeholder.timestamp, + transaction: writeTx) + + placeholder.anyRemove(transaction: writeTx) + errorMessage.anyInsert(transaction: writeTx) + + self.notificationsManager?.notifyUser(for: errorMessage, + thread: thread, + transaction: writeTx) + } + } + } + } } private extension SSKProtoEnvelope { diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.h b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.h index d09c179bd8..e9d3aa66f2 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.h +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.h @@ -18,13 +18,8 @@ NS_ASSUME_NONNULL_BEGIN @property (assign, nonatomic, readonly) BOOL supportsReplacement; @property (assign, nonatomic, readonly) uint64_t hiddenUntilTimestamp; -// Used to resolve timestamp collisions for a long-lived placeholder. -// If a placeholder has outlived its eligible replacement period, it will live on as an error message -// even after the replacement content has been received. -// -// Since we need to persist *both* the error and the replacement message, we adjust the placeholder's timestamp -// slightly to resolve the timestamp collision. -- (void)adjustTimestamp:(uint64_t)timestamp; +/// After this date, the placeholder is no longer eligible for replacement with the original content. +@property (strong, nonatomic, readonly) NSDate *expirationDate; // --- CODE GENERATION MARKER diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m index 2fca2452d6..6c3646f820 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m @@ -37,7 +37,11 @@ NS_ASSUME_NONNULL_BEGIN builder.timestamp = envelope.timestamp; builder.senderAddress = sender; - return [super initErrorMessageWithBuilder:builder]; + self = [super initErrorMessageWithBuilder:builder]; + if (self) { + _hiddenUntilTimestamp = [NSDate distantFutureMillisecondTimestamp]; + } + return self; } - (nullable instancetype)initWithCoder:(NSCoder *)coder @@ -120,26 +124,17 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Methods -- (void)adjustTimestamp:(uint64_t)timestamp +- (NSDate *)expirationDate { - OWSAssert(timestamp > 0); - self.timestamp = timestamp; -} - -- (BOOL)isVisible -{ - // If this interaction has ever been seen or the recovery period has elapsed, we should make - // this visible to the user. NSTimeInterval expirationInterval = [RemoteConfig replaceableInteractionExpiration]; OWSAssertDebug(expirationInterval >= 0); - NSDate *expiration = [self.receivedAtDate dateByAddingTimeInterval:MAX(0, expirationInterval)]; - return [expiration isBeforeNow] || self.wasRead; + return [self.receivedAtDate dateByAddingTimeInterval:MAX(0, expirationInterval)]; } - (BOOL)supportsReplacement { - return !self.isVisible; + return [self.expirationDate isAfterNow] && !self.wasRead; } - (NSString *)previewTextWithTransaction:(SDSAnyReadTransaction *)transaction diff --git a/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift b/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift index daf59104fe..1bee80cc49 100644 --- a/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift +++ b/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift @@ -39,12 +39,12 @@ protocol InteractionFinderAdapter { func earliestKnownInteractionRowId(transaction: ReadTransaction) -> Int? - func distanceFromLatest(interactionUniqueId: String, transaction: ReadTransaction) throws -> UInt? - func count(transaction: ReadTransaction) -> UInt + func distanceFromLatest(interactionUniqueId: String, countHidden: Bool, transaction: ReadTransaction) throws -> UInt? + func count(includingHiddenInteractions: Bool, transaction: ReadTransaction) -> UInt func enumerateInteractionIds(transaction: ReadTransaction, block: @escaping (String, UnsafeMutablePointer) throws -> Void) throws func enumerateRecentInteractions(transaction: ReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws - func enumerateInteractions(range: NSRange, transaction: ReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws - func interactionIds(inRange range: NSRange, transaction: ReadTransaction) throws -> [String] + func enumerateInteractions(range: NSRange, includeHidden: Bool, transaction: ReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws + func interactionIds(inRange range: NSRange, includeHidden: Bool, transaction: ReadTransaction) throws -> [String] func existsOutgoingMessage(transaction: ReadTransaction) -> Bool func outgoingMessageCount(transaction: ReadTransaction) -> UInt @@ -287,20 +287,20 @@ public class InteractionFinder: NSObject, InteractionFinderAdapter { } } - public func distanceFromLatest(interactionUniqueId: String, transaction: SDSAnyReadTransaction) throws -> UInt? { + public func distanceFromLatest(interactionUniqueId: String, countHidden: Bool = true, transaction: SDSAnyReadTransaction) throws -> UInt? { return try Bench(title: "InteractionFinder.distanceFromLatest") { switch transaction.readTransaction { case .grdbRead(let grdbRead): - return try grdbAdapter.distanceFromLatest(interactionUniqueId: interactionUniqueId, transaction: grdbRead) + return try grdbAdapter.distanceFromLatest(interactionUniqueId: interactionUniqueId, countHidden: countHidden, transaction: grdbRead) } } } @objc - public func count(transaction: SDSAnyReadTransaction) -> UInt { + public func count(includingHiddenInteractions includeHidden: Bool = true, transaction: SDSAnyReadTransaction) -> UInt { switch transaction.readTransaction { case .grdbRead(let grdbRead): - return grdbAdapter.count(transaction: grdbRead) + return grdbAdapter.count(includingHiddenInteractions: includeHidden, transaction: grdbRead) } } @@ -351,17 +351,17 @@ public class InteractionFinder: NSObject, InteractionFinderAdapter { } } - public func enumerateInteractions(range: NSRange, transaction: SDSAnyReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws { + public func enumerateInteractions(range: NSRange, includeHidden: Bool = true, transaction: SDSAnyReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws { switch transaction.readTransaction { case .grdbRead(let grdbRead): - return try grdbAdapter.enumerateInteractions(range: range, transaction: grdbRead, block: block) + return try grdbAdapter.enumerateInteractions(range: range, includeHidden: includeHidden, transaction: grdbRead, block: block) } } - public func interactionIds(inRange range: NSRange, transaction: SDSAnyReadTransaction) throws -> [String] { + public func interactionIds(inRange range: NSRange, includeHidden: Bool = true, transaction: SDSAnyReadTransaction) throws -> [String] { switch transaction.readTransaction { case .grdbRead(let grdbRead): - return try grdbAdapter.interactionIds(inRange: range, transaction: grdbRead) + return try grdbAdapter.interactionIds(inRange: range, includeHidden: includeHidden, transaction: grdbRead) } } @@ -849,6 +849,48 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { return interactions } + static func oldestPlaceholderInteraction(transaction: GRDBReadTransaction) -> OWSRecoverableDecryptionPlaceholder? { + let sql = """ + SELECT * + FROM \(InteractionRecord.databaseTableName) + WHERE \(interactionColumn: .recordType) IS \(SDSRecordType.recoverableDecryptionPlaceholder.rawValue) + ORDER BY \(interactionColumn: .id) ASC + LIMIT 1 + """ + let result = TSInteraction.grdbFetchOne(sql: sql, transaction: transaction) + if let result = result as? OWSRecoverableDecryptionPlaceholder { + return result + } else { + owsFailDebug("Unexpected type: \(type(of: result))") + return nil + } + } + + static func enumeratePlaceholders(transaction: GRDBReadTransaction, block: (OWSRecoverableDecryptionPlaceholder, UnsafeMutablePointer) -> Void) { + let sql = """ + SELECT * + FROM \(InteractionRecord.databaseTableName) + WHERE \(interactionColumn: .recordType) IS \(SDSRecordType.recoverableDecryptionPlaceholder.rawValue) + ORDER BY \(interactionColumn: .id) ASC + """ + do { + let cursor = TSInteraction.grdbFetchCursor(sql: sql, transaction: transaction) + while let result = try cursor.next() { + if let placeholder = result as? OWSRecoverableDecryptionPlaceholder { + var stop: ObjCBool = false + block(placeholder, &stop) + if stop.boolValue { + return + } + } else { + owsFailDebug("Unexpected type: \(type(of: result))") + } + } + } catch { + owsFailDebug("unexpected error \(error)") + } + } + // MARK: - instance methods public func profileUpdateInteractions(afterSortId sortId: UInt64, transaction: GRDBReadTransaction) -> [TSInfoMessage] { @@ -965,11 +1007,14 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { return try? Int.fetchOne(transaction.database, sql: sql, arguments: arguments) } - func distanceFromLatest(interactionUniqueId: String, transaction: GRDBReadTransaction) throws -> UInt? { + func distanceFromLatest(interactionUniqueId: String, countHidden: Bool = true, transaction: GRDBReadTransaction) throws -> UInt? { + let hiddenInteractionFilterClause = "AND \(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970)" + guard let interactionId = try UInt.fetchOne(transaction.database, sql: """ SELECT id FROM \(InteractionRecord.databaseTableName) WHERE \(interactionColumn: .uniqueId) = ? + \(countHidden ? "" : hiddenInteractionFilterClause) """, arguments: [interactionUniqueId]) else { owsFailDebug("failed to find id for interaction \(interactionUniqueId)") return nil @@ -980,6 +1025,7 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { FROM \(InteractionRecord.databaseTableName) WHERE \(interactionColumn: .threadUniqueId) = ? AND \(interactionColumn: .id) >= ? + \(countHidden ? "" : hiddenInteractionFilterClause) ORDER BY \(interactionColumn: .id) DESC """, arguments: [threadUniqueId, interactionId]) else { owsFailDebug("failed to find distance from latest message") @@ -989,13 +1035,15 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { return distanceFromLatest } - func count(transaction: GRDBReadTransaction) -> UInt { + func count(includingHiddenInteractions includeHidden: Bool, transaction: GRDBReadTransaction) -> UInt { do { + let hiddenInteractionFilterClause = "AND \(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970)" guard let count = try UInt.fetchOne(transaction.database, sql: """ SELECT COUNT(*) FROM \(InteractionRecord.databaseTableName) WHERE \(interactionColumn: .threadUniqueId) = ? + \(includeHidden ? "" : hiddenInteractionFilterClause) """, arguments: [threadUniqueId]) else { throw OWSAssertionError("count was unexpectedly nil") @@ -1046,11 +1094,13 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { } } - func enumerateInteractions(range: NSRange, transaction: GRDBReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws { + func enumerateInteractions(range: NSRange, includeHidden: Bool = true, transaction: GRDBReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws { + let hiddenInteractionFilterClause = "AND \(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970)" let sql = """ SELECT * FROM \(InteractionRecord.databaseTableName) WHERE \(interactionColumn: .threadUniqueId) = ? + \(includeHidden ? "" : hiddenInteractionFilterClause) ORDER BY \(interactionColumn: .id) LIMIT \(range.length) OFFSET \(range.location) @@ -1069,11 +1119,13 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { } } - func interactionIds(inRange range: NSRange, transaction: GRDBReadTransaction) throws -> [String] { + func interactionIds(inRange range: NSRange, includeHidden: Bool = true, transaction: GRDBReadTransaction) throws -> [String] { + let hiddenInteractionFilterClause = "AND \(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970)" let sql = """ SELECT \(interactionColumn: .uniqueId) FROM \(InteractionRecord.databaseTableName) WHERE \(interactionColumn: .threadUniqueId) = ? + \(includeHidden ? "" : hiddenInteractionFilterClause) ORDER BY \(interactionColumn: .id) LIMIT \(range.length) OFFSET \(range.location) diff --git a/SignalServiceKit/src/Util/Date+SSK.swift b/SignalServiceKit/src/Util/Date+SSK.swift index 180d258d15..f49c5bc299 100644 --- a/SignalServiceKit/src/Util/Date+SSK.swift +++ b/SignalServiceKit/src/Util/Date+SSK.swift @@ -32,6 +32,14 @@ public extension NSDate { var ows_millisecondsSince1970: UInt64 { return NSDate.ows_millisecondsSince1970(for: self as Date) } + + static var distantFutureForMillisecondTimestamp: Date { + Date.distantFutureForMillisecondTimestamp + } + + static var distantFutureMillisecondTimestamp: UInt64 { + Date.distantFutureMillisecondTimestamp + } } public extension Date { @@ -63,6 +71,10 @@ public extension Date { return result } + static var distantFutureMillisecondTimestamp: UInt64 { + distantFutureForMillisecondTimestamp.ows_millisecondsSince1970 + } + func isBefore(_ date: Date) -> Bool { (self as NSDate).is(before: date) } From ee85ecc96562044f9e9fdbca5700b6fad2b698fe Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Wed, 25 Aug 2021 01:29:29 -0700 Subject: [PATCH 3/7] Migrations, renames, more aggressive scheduling of cleanup --- .../CV/CVMessageMapping.swift | 7 +++-- SignalServiceKit/Resources/schema.sql | 1 + .../src/Messages/OWSMessageDecrypter.swift | 9 +++++- .../src/Messages/OWSOutgoingResendResponse.m | 15 ++++----- .../OWSRecoverableDecryptionPlaceholder.m | 25 +++++++++++++++ .../Storage/Database/GRDBSchemaMigrator.swift | 11 +++++++ .../Database/Records/InteractionFinder.swift | 31 ++++++++++--------- SignalServiceKit/src/Util/FeatureFlags.swift | 20 ++++++++++-- 8 files changed, 93 insertions(+), 26 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift b/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift index 4390efe4d2..fef9dc49a6 100644 --- a/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift +++ b/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift @@ -477,7 +477,7 @@ public class CVMessageMapping: NSObject { var newItems: [TSInteraction] = [] try self.interactionFinder.enumerateInteractions(range: nsRange, - includeHidden: false, + includingHiddenInteractions: DebugFlags.showFailedDecryptionPlaceholders.get(), transaction: transaction) { (interaction: TSInteraction, _) in newItems.append(interaction) } @@ -487,7 +487,10 @@ public class CVMessageMapping: NSObject { // Loading the mapping from the cache has the following steps: // // 1. Fetch the uniqueIds for the interactions in the load window/mapping. - let interactionIds = try interactionFinder.interactionIds(inRange: nsRange, includeHidden: false, transaction: transaction) + let interactionIds = try interactionFinder.interactionIds( + inRange: nsRange, + includingHiddenInteractions: DebugFlags.showFailedDecryptionPlaceholders.get(), + transaction: transaction) guard !interactionIds.isEmpty else { return [] } diff --git a/SignalServiceKit/Resources/schema.sql b/SignalServiceKit/Resources/schema.sql index 59681ab0be..006ef390f4 100644 --- a/SignalServiceKit/Resources/schema.sql +++ b/SignalServiceKit/Resources/schema.sql @@ -115,6 +115,7 @@ CREATE ,"paymentRequest" BLOB ,"viewed" BOOLEAN ,"serverGuid" TEXT + ,"hiddenUntilTimestamp" INTEGER ) ; diff --git a/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift b/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift index ce0f3cf578..f694cccc34 100644 --- a/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift +++ b/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift @@ -68,7 +68,9 @@ public class OWSMessageDecrypter: OWSMessageHandler { ) AppReadiness.runNowOrWhenAppDidBecomeReadySync { [weak self] in - self?.schedulePlaceholderCleanup() + self?.databaseStorage.read { [weak self] readTx in + self?.schedulePlaceholderCleanup(transaction: readTx) + } } } @@ -819,7 +821,12 @@ public class OWSMessageDecrypter: OWSMessageHandler { transaction: writeTx) } } + } completion: { + self.databaseStorage.read { readTx in + self.schedulePlaceholderCleanup(transaction: readTx) + } } + } } diff --git a/SignalServiceKit/src/Messages/OWSOutgoingResendResponse.m b/SignalServiceKit/src/Messages/OWSOutgoingResendResponse.m index c64a4f42de..1fa6c020a2 100644 --- a/SignalServiceKit/src/Messages/OWSOutgoingResendResponse.m +++ b/SignalServiceKit/src/Messages/OWSOutgoingResendResponse.m @@ -24,18 +24,19 @@ { OWSAssertDebug(address); OWSAssertDebug(transaction); - - Payload *payloadRecord = [MessageSendLog fetchPayloadWithAddress:address - deviceId:deviceId - timestamp:failedTimestamp - transaction:transaction]; - - TSThread *originalThread = [TSThread anyFetchWithUniqueId:payloadRecord.uniqueThreadId transaction:transaction]; TSThread *targetThread = [TSContactThread getOrCreateThreadWithContactAddress:address transaction:transaction]; TSOutgoingMessageBuilder *builder = [TSOutgoingMessageBuilder outgoingMessageBuilderWithThread:targetThread]; + Payload *_Nullable payloadRecord = [MessageSendLog fetchPayloadWithAddress:address + deviceId:deviceId + timestamp:failedTimestamp + transaction:transaction]; + + TSThread *_Nullable originalThread = nil; if (payloadRecord) { OWSLogInfo(@"Found an MSL record for resend request: %lli", failedTimestamp); + originalThread = [TSThread anyFetchWithUniqueId:payloadRecord.uniqueThreadId transaction:transaction]; + // We should inherit the timestamp of the failed message. This allows the recipient of this message // to correlate the resend response with the original failed message. builder.timestamp = payloadRecord.sentTimestamp; diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m index 6c3646f820..efb560b449 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m @@ -129,6 +129,10 @@ NS_ASSUME_NONNULL_BEGIN NSTimeInterval expirationInterval = [RemoteConfig replaceableInteractionExpiration]; OWSAssertDebug(expirationInterval >= 0); + if (SSKDebugFlags.fastPlaceholderExpiration.value) { + expirationInterval = min(expirationInterval, 5.0); + } + return [self.receivedAtDate dateByAddingTimeInterval:MAX(0, expirationInterval)]; } @@ -145,6 +149,27 @@ NS_ASSUME_NONNULL_BEGIN return [[NSString alloc] initWithFormat:formatString, senderName]; } +- (void)anyDidInsertWithTransaction:(SDSAnyWriteTransaction *)transaction +{ + [self.messageDecrypter schedulePlaceholderCleanupWithTransaction:transaction]; +} + +- (void)anyDidRemoveWithTransaction:(SDSAnyWriteTransaction *)transaction +{ + [self.messageDecrypter schedulePlaceholderCleanupWithTransaction:transaction]; +} + +#pragma mark - + +- (void)markAsReadAtTimestamp:(uint64_t)readTimestamp + thread:(TSThread *)thread + circumstance:(OWSReceiptCircumstance)circumstance + transaction:(SDSAnyWriteTransaction *)transaction +{ + OWSLogInfo(@"Marking placeholder as read. No longer eligible for inline replacement."); + [super markAsReadAtTimestamp:readTimestamp thread:thread circumstance:circumstance transaction:transaction]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Storage/Database/GRDBSchemaMigrator.swift b/SignalServiceKit/src/Storage/Database/GRDBSchemaMigrator.swift index 0527ed1ea0..98be019c25 100644 --- a/SignalServiceKit/src/Storage/Database/GRDBSchemaMigrator.swift +++ b/SignalServiceKit/src/Storage/Database/GRDBSchemaMigrator.swift @@ -111,6 +111,7 @@ public class GRDBSchemaMigrator: NSObject { case addSendCompletionToMessageSendLog case addExclusiveProcessIdentifierAndHighPriorityToJobRecord case updateMessageSendLogColumnTypes + case addHiddenInteractionColumn // NOTE: Every time we add a migration id, consider // incrementing grdbSchemaVersionLatest. @@ -1398,6 +1399,16 @@ public class GRDBSchemaMigrator: NSObject { } } + migrator.registerMigration(MigrationId.addHiddenInteractionColumn.rawValue) { db in + do { + try db.alter(table: "model_TSInteraction") { (table: TableAlteration) -> Void in + table.add(column: "hiddenUntilTimestamp", .integer) + } + } catch { + owsFail("Error: \(error)") + } + } + // MARK: - Schema Migration Insertion Point } diff --git a/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift b/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift index 1bee80cc49..5cfa8c6f5e 100644 --- a/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift +++ b/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift @@ -43,8 +43,8 @@ protocol InteractionFinderAdapter { func count(includingHiddenInteractions: Bool, transaction: ReadTransaction) -> UInt func enumerateInteractionIds(transaction: ReadTransaction, block: @escaping (String, UnsafeMutablePointer) throws -> Void) throws func enumerateRecentInteractions(transaction: ReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws - func enumerateInteractions(range: NSRange, includeHidden: Bool, transaction: ReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws - func interactionIds(inRange range: NSRange, includeHidden: Bool, transaction: ReadTransaction) throws -> [String] + func enumerateInteractions(range: NSRange, includingHiddenInteractions: Bool, transaction: ReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws + func interactionIds(inRange range: NSRange, includingHiddenInteractions: Bool, transaction: ReadTransaction) throws -> [String] func existsOutgoingMessage(transaction: ReadTransaction) -> Bool func outgoingMessageCount(transaction: ReadTransaction) -> UInt @@ -351,17 +351,17 @@ public class InteractionFinder: NSObject, InteractionFinderAdapter { } } - public func enumerateInteractions(range: NSRange, includeHidden: Bool = true, transaction: SDSAnyReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws { + public func enumerateInteractions(range: NSRange, includingHiddenInteractions includeHidden: Bool = true, transaction: SDSAnyReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws { switch transaction.readTransaction { case .grdbRead(let grdbRead): - return try grdbAdapter.enumerateInteractions(range: range, includeHidden: includeHidden, transaction: grdbRead, block: block) + return try grdbAdapter.enumerateInteractions(range: range, includingHiddenInteractions: includeHidden, transaction: grdbRead, block: block) } } - public func interactionIds(inRange range: NSRange, includeHidden: Bool = true, transaction: SDSAnyReadTransaction) throws -> [String] { + public func interactionIds(inRange range: NSRange, includingHiddenInteractions includeHidden: Bool = true, transaction: SDSAnyReadTransaction) throws -> [String] { switch transaction.readTransaction { case .grdbRead(let grdbRead): - return try grdbAdapter.interactionIds(inRange: range, includeHidden: includeHidden, transaction: grdbRead) + return try grdbAdapter.interactionIds(inRange: range, includingHiddenInteractions: includeHidden, transaction: grdbRead) } } @@ -860,9 +860,11 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { let result = TSInteraction.grdbFetchOne(sql: sql, transaction: transaction) if let result = result as? OWSRecoverableDecryptionPlaceholder { return result - } else { + } else if let result = result { owsFailDebug("Unexpected type: \(type(of: result))") return nil + } else { + return nil } } @@ -1008,7 +1010,7 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { } func distanceFromLatest(interactionUniqueId: String, countHidden: Bool = true, transaction: GRDBReadTransaction) throws -> UInt? { - let hiddenInteractionFilterClause = "AND \(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970)" + let hiddenInteractionFilterClause = "AND (\(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970) OR \(interactionColumn: .hiddenUntilTimestamp) IS NULL)" guard let interactionId = try UInt.fetchOne(transaction.database, sql: """ SELECT id @@ -1035,9 +1037,9 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { return distanceFromLatest } - func count(includingHiddenInteractions includeHidden: Bool, transaction: GRDBReadTransaction) -> UInt { + func count(includingHiddenInteractions includeHidden: Bool = true, transaction: GRDBReadTransaction) -> UInt { do { - let hiddenInteractionFilterClause = "AND \(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970)" + let hiddenInteractionFilterClause = "AND (\(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970) OR \(interactionColumn: .hiddenUntilTimestamp) IS NULL)" guard let count = try UInt.fetchOne(transaction.database, sql: """ SELECT COUNT(*) @@ -1094,8 +1096,8 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { } } - func enumerateInteractions(range: NSRange, includeHidden: Bool = true, transaction: GRDBReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws { - let hiddenInteractionFilterClause = "AND \(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970)" + func enumerateInteractions(range: NSRange, includingHiddenInteractions includeHidden: Bool = true, transaction: GRDBReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws { + let hiddenInteractionFilterClause = "AND (\(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970) OR \(interactionColumn: .hiddenUntilTimestamp) IS NULL)" let sql = """ SELECT * FROM \(InteractionRecord.databaseTableName) @@ -1119,8 +1121,9 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { } } - func interactionIds(inRange range: NSRange, includeHidden: Bool = true, transaction: GRDBReadTransaction) throws -> [String] { - let hiddenInteractionFilterClause = "AND \(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970)" + func interactionIds(inRange range: NSRange, includingHiddenInteractions includeHidden: Bool = true, transaction: GRDBReadTransaction) throws -> [String] { + let hiddenInteractionFilterClause = "AND (\(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970) OR \(interactionColumn: .hiddenUntilTimestamp) IS NULL)" + let sql = """ SELECT \(interactionColumn: .uniqueId) FROM \(InteractionRecord.databaseTableName) diff --git a/SignalServiceKit/src/Util/FeatureFlags.swift b/SignalServiceKit/src/Util/FeatureFlags.swift index 473868cd00..d2541d20ca 100644 --- a/SignalServiceKit/src/Util/FeatureFlags.swift +++ b/SignalServiceKit/src/Util/FeatureFlags.swift @@ -501,9 +501,22 @@ public class DebugFlags: BaseFlags { @objc public static let delayedMessageResend = TestableFlag(false, - title: LocalizationNotNeeded("Delayed message resend"), + title: LocalizationNotNeeded("Sender Key: Delayed message resend"), details: LocalizationNotNeeded("Waits 10s before responding to a resend request.")) + @objc + public static let showFailedDecryptionPlaceholders = TestableFlag(false, + title: LocalizationNotNeeded("Sender Key: Show failed decryption placeholders"), + details: LocalizationNotNeeded("Shows placeholder interactions in the conversation list.")) + + @objc + public static let fastPlaceholderExpiration = TestableFlag(false, + title: LocalizationNotNeeded("Sender Key: Early placeholder expiration"), + details: LocalizationNotNeeded("Shortens the valid window for message resend+recovery."), + toggleHandler: { _ in + databaseStorage.read { messageDecrypter.schedulePlaceholderCleanup(transaction: $0)} + }) + public static func buildFlagMap() -> [String: Any] { BaseFlags.buildFlagMap(for: DebugFlags.self) { (key: String) -> Any? in DebugFlags.value(forKey: key) @@ -586,16 +599,19 @@ public class TestableFlag: NSObject { private let flag: AtomicBool public let title: String public let details: String + public let toggleHandler: ((Bool) -> Void)? fileprivate init(_ defaultValue: Bool, title: String, details: String, - affectsCapabilities: Bool = false) { + affectsCapabilities: Bool = false, + toggleHandler: ((Bool) -> Void)? = nil) { self.defaultValue = defaultValue self.title = title self.details = details self.affectsCapabilities = affectsCapabilities self.flag = AtomicBool(defaultValue) + self.toggleHandler = toggleHandler super.init() From 276837b62e70e5b49494c367d32c06d281a8e6de Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Wed, 25 Aug 2021 01:58:39 -0700 Subject: [PATCH 4/7] Bug fixes around cleanup scheduling --- .../CV/CVMessageMapping.swift | 2 +- .../src/Messages/OWSMessageDecrypter.swift | 20 ++++++++++--------- .../OWSRecoverableDecryptionPlaceholder.m | 19 +++++++++--------- .../Database/Records/InteractionFinder.swift | 8 ++++---- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift b/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift index fef9dc49a6..6ef6e16075 100644 --- a/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift +++ b/Signal/src/ViewControllers/ConversationView/CV/CVMessageMapping.swift @@ -192,7 +192,7 @@ public class CVMessageMapping: NSObject { // from the bottom of the conversation, the more expensive this query will get. guard let distanceFromLatest = try self.interactionFinder.distanceFromLatest( interactionUniqueId: interactionUniqueId, - countHidden: false, + includingHiddenInteractions: false, transaction: transaction) else { throw OWSAssertionError("viewIndex was unexpectedly nil") } diff --git a/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift b/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift index f694cccc34..13728cacbb 100644 --- a/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift +++ b/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift @@ -778,24 +778,25 @@ public class OWSMessageDecrypter: OWSMessageHandler { } } - func schedulePlaceholderCleanup() { - databaseStorage.read { readTx in - guard let oldestPlaceholder = GRDBInteractionFinder.oldestPlaceholderInteraction(transaction: readTx.unwrapGrdbRead) else { return } + @objc + func schedulePlaceholderCleanup(transaction readTx: SDSAnyReadTransaction) { + guard let oldestPlaceholder = GRDBInteractionFinder.oldestPlaceholderInteraction(transaction: readTx.unwrapGrdbRead) else { return } + DispatchQueue.main.async { if oldestPlaceholder.expirationDate.isBeforeNow { Logger.info("Oldest placeholder expirationDate: \(oldestPlaceholder.expirationDate). Will perform cleanup...") - placeholderCleanupTimer = nil - cleanupExpiredPlaceholders() + self.placeholderCleanupTimer = nil + self.cleanupExpiredPlaceholders() - } else if (placeholderCleanupTimer?.fireDate ?? .distantFuture).isAfter(oldestPlaceholder.expirationDate) { + } else if (self.placeholderCleanupTimer?.fireDate ?? .distantFuture).isAfter(oldestPlaceholder.expirationDate) { Logger.info("Oldest placeholder expirationDate: \(oldestPlaceholder.expirationDate). Scheduling timer...") - placeholderCleanupTimer = Timer.scheduledTimer( + self.placeholderCleanupTimer = Timer.scheduledTimer( withTimeInterval: oldestPlaceholder.expirationDate.timeIntervalSinceNow, repeats: false, block: { [weak self] timer in self?.cleanupExpiredPlaceholders() - }) + }) } } } @@ -805,8 +806,9 @@ public class OWSMessageDecrypter: OWSMessageHandler { Logger.info("Performing placeholder cleanup") GRDBInteractionFinder.enumeratePlaceholders(transaction: writeTx.unwrapGrdbWrite) { placeholder, _ in if placeholder.expirationDate.isBeforeNow { - let thread = placeholder.thread(transaction: writeTx) + Logger.info("replacing placeholder \(placeholder.timestamp) with error message") + let thread = placeholder.thread(transaction: writeTx) let errorMessage = TSErrorMessage.failedDecryption( forSender: placeholder.sender, thread: thread, diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m index efb560b449..398e8bf8fb 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m @@ -130,7 +130,7 @@ NS_ASSUME_NONNULL_BEGIN OWSAssertDebug(expirationInterval >= 0); if (SSKDebugFlags.fastPlaceholderExpiration.value) { - expirationInterval = min(expirationInterval, 5.0); + expirationInterval = MIN(expirationInterval, 5.0); } return [self.receivedAtDate dateByAddingTimeInterval:MAX(0, expirationInterval)]; @@ -143,19 +143,20 @@ NS_ASSUME_NONNULL_BEGIN - (NSString *)previewTextWithTransaction:(SDSAnyReadTransaction *)transaction { - NSString *formatString = NSLocalizedString( - @"ERROR_MESSAGE_DECRYPTION_FAILURE", @"Error message for a decryption failure. Embeds {{sender short name}}."); NSString *senderName = [self.contactsManager shortDisplayNameForAddress:self.sender transaction:transaction]; - return [[NSString alloc] initWithFormat:formatString, senderName]; + if (SSKDebugFlags.showFailedDecryptionPlaceholders.value) { + return [[NSString alloc] initWithFormat:@"Placeholder for timestamp: %llu from sender: %@", self.timestamp, senderName]; + } else { + OWSFailDebug(@"Should not be directly surfaced to user"); + NSString *formatString = NSLocalizedString( + @"ERROR_MESSAGE_DECRYPTION_FAILURE", @"Error message for a decryption failure. Embeds {{sender short name}}."); + return [[NSString alloc] initWithFormat:formatString, senderName]; + } } - (void)anyDidInsertWithTransaction:(SDSAnyWriteTransaction *)transaction { - [self.messageDecrypter schedulePlaceholderCleanupWithTransaction:transaction]; -} - -- (void)anyDidRemoveWithTransaction:(SDSAnyWriteTransaction *)transaction -{ + [super anyDidInsertWithTransaction:transaction]; [self.messageDecrypter schedulePlaceholderCleanupWithTransaction:transaction]; } diff --git a/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift b/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift index 5cfa8c6f5e..e825678a3a 100644 --- a/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift +++ b/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift @@ -39,7 +39,7 @@ protocol InteractionFinderAdapter { func earliestKnownInteractionRowId(transaction: ReadTransaction) -> Int? - func distanceFromLatest(interactionUniqueId: String, countHidden: Bool, transaction: ReadTransaction) throws -> UInt? + func distanceFromLatest(interactionUniqueId: String, includingHiddenInteractions countHidden: Bool, transaction: ReadTransaction) throws -> UInt? func count(includingHiddenInteractions: Bool, transaction: ReadTransaction) -> UInt func enumerateInteractionIds(transaction: ReadTransaction, block: @escaping (String, UnsafeMutablePointer) throws -> Void) throws func enumerateRecentInteractions(transaction: ReadTransaction, block: @escaping (TSInteraction, UnsafeMutablePointer) -> Void) throws @@ -287,11 +287,11 @@ public class InteractionFinder: NSObject, InteractionFinderAdapter { } } - public func distanceFromLatest(interactionUniqueId: String, countHidden: Bool = true, transaction: SDSAnyReadTransaction) throws -> UInt? { + public func distanceFromLatest(interactionUniqueId: String, includingHiddenInteractions countHidden: Bool = true, transaction: SDSAnyReadTransaction) throws -> UInt? { return try Bench(title: "InteractionFinder.distanceFromLatest") { switch transaction.readTransaction { case .grdbRead(let grdbRead): - return try grdbAdapter.distanceFromLatest(interactionUniqueId: interactionUniqueId, countHidden: countHidden, transaction: grdbRead) + return try grdbAdapter.distanceFromLatest(interactionUniqueId: interactionUniqueId, includingHiddenInteractions: countHidden, transaction: grdbRead) } } } @@ -1009,7 +1009,7 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { return try? Int.fetchOne(transaction.database, sql: sql, arguments: arguments) } - func distanceFromLatest(interactionUniqueId: String, countHidden: Bool = true, transaction: GRDBReadTransaction) throws -> UInt? { + func distanceFromLatest(interactionUniqueId: String, includingHiddenInteractions countHidden: Bool = true, transaction: GRDBReadTransaction) throws -> UInt? { let hiddenInteractionFilterClause = "AND (\(interactionColumn: .hiddenUntilTimestamp) < \(Date().ows_millisecondsSince1970) OR \(interactionColumn: .hiddenUntilTimestamp) IS NULL)" guard let interactionId = try UInt.fetchOne(transaction.database, sql: """ From 79af7036d6aacd5985527f32acf7175618f4fc03 Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Wed, 25 Aug 2021 09:29:32 -0700 Subject: [PATCH 5/7] Don't inherit timestamp from placeholder --- Signal/translations/en.lproj/Localizable.strings | 3 +++ SignalServiceKit/src/Contacts/TSThread.m | 4 +++- .../src/Messages/Interactions/TSErrorMessage.m | 7 ++++--- .../src/Messages/OWSMessageDecrypter.swift | 4 ++-- .../OWSRecoverableDecryptionPlaceholder.m | 15 +++++++++++---- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index b06aef6f42..267e711724 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -1663,6 +1663,9 @@ /* Error message for a decryption failure. Embeds {{sender short name}}. */ "ERROR_MESSAGE_DECRYPTION_FAILURE" = "A message from %@ could not be delivered"; +/* Error message for a decryption failure. */ +"ERROR_MESSAGE_DECRYPTION_FAILURE_UNKNOWN_SENDER" = "A message could not be delivered"; + /* No comment provided by engineer. */ "ERROR_MESSAGE_DUPLICATE_MESSAGE" = "Received a duplicate message."; diff --git a/SignalServiceKit/src/Contacts/TSThread.m b/SignalServiceKit/src/Contacts/TSThread.m index c681a61fa7..ca93f5b977 100644 --- a/SignalServiceKit/src/Contacts/TSThread.m +++ b/SignalServiceKit/src/Contacts/TSThread.m @@ -357,7 +357,9 @@ lastVisibleSortIdOnScreenPercentageObsolete:(double)lastVisibleSortIdOnScreenPer - (NSUInteger)numberOfInteractionsWithTransaction:(SDSAnyReadTransaction *)transaction { OWSAssertDebug(transaction); - return [[[InteractionFinder alloc] initWithThreadUniqueId:self.uniqueId] countIncludingHiddenInteractions:YES transaction:transaction]; + return + [[[InteractionFinder alloc] initWithThreadUniqueId:self.uniqueId] countIncludingHiddenInteractions:YES + transaction:transaction]; } - (nullable TSInteraction *)lastInteractionForInboxWithTransaction:(SDSAnyReadTransaction *)transaction diff --git a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m index fa952b6ef8..1bf73eee71 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m @@ -234,12 +234,13 @@ NSUInteger TSErrorMessageSchemaVersion = 2; case TSErrorMessageDecryptionFailure: { if (self.sender) { NSString *formatString = NSLocalizedString(@"ERROR_MESSAGE_DECRYPTION_FAILURE", - @"Error message for a decryption failure. Embeds {{sender short name}}."); + @"Error message for a decryption failure. Embeds {{sender short name}}."); NSString *senderName = [self.contactsManager shortDisplayNameForAddress:self.sender transaction:transaction]; return [[NSString alloc] initWithFormat:formatString, senderName]; } else { - return NSLocalizedString(@"ERROR_MESSAGE_DECRYPTION_FAILURE_UNKNOWN_SENDER", @"Error message for a decryption failure."); + return NSLocalizedString( + @"ERROR_MESSAGE_DECRYPTION_FAILURE_UNKNOWN_SENDER", @"Error message for a decryption failure."); } } default: @@ -306,7 +307,7 @@ NSUInteger TSErrorMessageSchemaVersion = 2; transaction:(SDSAnyWriteTransaction *)transaction { TSErrorMessageBuilder *builder = - [TSErrorMessageBuilder errorMessageBuilderWithThread:thread errorType:TSErrorMessageDecryptionFailure]; + [TSErrorMessageBuilder errorMessageBuilderWithThread:thread errorType:TSErrorMessageDecryptionFailure]; builder.senderAddress = sender; builder.timestamp = timestamp; return [builder build]; diff --git a/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift b/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift index 13728cacbb..26827c6d2d 100644 --- a/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift +++ b/SignalServiceKit/src/Messages/OWSMessageDecrypter.swift @@ -794,7 +794,7 @@ public class OWSMessageDecrypter: OWSMessageHandler { self.placeholderCleanupTimer = Timer.scheduledTimer( withTimeInterval: oldestPlaceholder.expirationDate.timeIntervalSinceNow, repeats: false, - block: { [weak self] timer in + block: { [weak self] _ in self?.cleanupExpiredPlaceholders() }) } @@ -812,7 +812,7 @@ public class OWSMessageDecrypter: OWSMessageHandler { let errorMessage = TSErrorMessage.failedDecryption( forSender: placeholder.sender, thread: thread, - timestamp: placeholder.timestamp, + timestamp: NSDate.ows_millisecondTimeStamp(), transaction: writeTx) placeholder.anyRemove(transaction: writeTx) diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m index 398e8bf8fb..bd9cea36be 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m @@ -143,14 +143,21 @@ NS_ASSUME_NONNULL_BEGIN - (NSString *)previewTextWithTransaction:(SDSAnyReadTransaction *)transaction { - NSString *senderName = [self.contactsManager shortDisplayNameForAddress:self.sender transaction:transaction]; + NSString *_Nullable senderName = nil; + if (self.sender) { + senderName = [self.contactsManager shortDisplayNameForAddress:self.sender transaction:transaction]; + } + if (SSKDebugFlags.showFailedDecryptionPlaceholders.value) { return [[NSString alloc] initWithFormat:@"Placeholder for timestamp: %llu from sender: %@", self.timestamp, senderName]; - } else { + } else if (senderName) { OWSFailDebug(@"Should not be directly surfaced to user"); - NSString *formatString = NSLocalizedString( - @"ERROR_MESSAGE_DECRYPTION_FAILURE", @"Error message for a decryption failure. Embeds {{sender short name}}."); + NSString *formatString = NSLocalizedString(@"ERROR_MESSAGE_DECRYPTION_FAILURE", + @"Error message for a decryption failure. Embeds {{sender short name}}."); return [[NSString alloc] initWithFormat:formatString, senderName]; + } else { + return NSLocalizedString( + @"ERROR_MESSAGE_DECRYPTION_FAILURE_UNKNOWN_SENDER", @"Error message for a decryption failure."); } } From 3f39745135a0027817d2207f59883a30a55fc374 Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Wed, 25 Aug 2021 15:55:14 -0700 Subject: [PATCH 6/7] Unrelated bug fix: ModelReadCache holding stale placeholders It checks to see if any updated models have a valid sortId before deciding whether or not to update the cache. Since we'll eventually inherit a sortId from our grdbId, let's just explicitly set it to satisfy the ModelReadCache. --- .../Messages/OWSRecoverableDecryptionPlaceholder+Replace.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder+Replace.swift b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder+Replace.swift index 9ab06a4b58..bd4664d5dc 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder+Replace.swift +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder+Replace.swift @@ -10,7 +10,9 @@ extension OWSRecoverableDecryptionPlaceholder { func replaceWithInteraction(_ interaction: TSInteraction, writeTx: SDSAnyWriteTransaction) { Logger.info("Replacing placeholder with recovered interaction: \(interaction.timestamp)") guard let inheritedId = grdbId?.int64Value else { return owsFailDebug("Missing rowId") } + interaction.replaceRowId(inheritedId, uniqueId: uniqueId) + interaction.replaceSortId(UInt64(inheritedId)) interaction.anyOverwritingUpdate(transaction: writeTx) } From 1407a36370300b4fabac85ce0e7465edd04e21c2 Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Wed, 25 Aug 2021 16:23:28 -0700 Subject: [PATCH 7/7] Lint --- .../src/Messages/OWSRecoverableDecryptionPlaceholder.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m index bd9cea36be..66ffe96244 100644 --- a/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m +++ b/SignalServiceKit/src/Messages/OWSRecoverableDecryptionPlaceholder.m @@ -149,13 +149,15 @@ NS_ASSUME_NONNULL_BEGIN } if (SSKDebugFlags.showFailedDecryptionPlaceholders.value) { - return [[NSString alloc] initWithFormat:@"Placeholder for timestamp: %llu from sender: %@", self.timestamp, senderName]; + return [[NSString alloc] + initWithFormat:@"Placeholder for timestamp: %llu from sender: %@", self.timestamp, senderName]; } else if (senderName) { OWSFailDebug(@"Should not be directly surfaced to user"); NSString *formatString = NSLocalizedString(@"ERROR_MESSAGE_DECRYPTION_FAILURE", @"Error message for a decryption failure. Embeds {{sender short name}}."); return [[NSString alloc] initWithFormat:formatString, senderName]; } else { + OWSFailDebug(@"Should not be directly surfaced to user"); return NSLocalizedString( @"ERROR_MESSAGE_DECRYPTION_FAILURE_UNKNOWN_SENDER", @"Error message for a decryption failure."); }