mirror of
https://github.com/signalapp/Signal-iOS.git
synced 2025-12-05 01:10:41 +00:00
De-protocolize & de-shim EditManager
This commit is contained in:
@@ -811,7 +811,6 @@
|
||||
66062E712E43F83600D5F8C1 /* OWSSequentialProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66062E702E43F83200D5F8C1 /* OWSSequentialProgress.swift */; };
|
||||
66076B4C2BC053290043D547 /* LinkPreviewBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66076B4B2BC053290043D547 /* LinkPreviewBuilder.swift */; };
|
||||
66076B4E2BC056980043D547 /* LinkPreviewBuilderImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66076B4D2BC056980043D547 /* LinkPreviewBuilderImpl.swift */; };
|
||||
66076B5C2BC06CA70043D547 /* EditManagerAttachmentsShims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66076B582BC06CA70043D547 /* EditManagerAttachmentsShims.swift */; };
|
||||
66076B5D2BC06CA70043D547 /* MockEditManagerAttachments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66076B592BC06CA70043D547 /* MockEditManagerAttachments.swift */; };
|
||||
66076B5E2BC06CA70043D547 /* EditManagerAttachmentsImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66076B5A2BC06CA70043D547 /* EditManagerAttachmentsImpl.swift */; };
|
||||
66076B5F2BC06CA70043D547 /* EditManagerAttachments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66076B5B2BC06CA70043D547 /* EditManagerAttachments.swift */; };
|
||||
@@ -4791,7 +4790,6 @@
|
||||
66062E702E43F83200D5F8C1 /* OWSSequentialProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSSequentialProgress.swift; sourceTree = "<group>"; };
|
||||
66076B4B2BC053290043D547 /* LinkPreviewBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreviewBuilder.swift; sourceTree = "<group>"; };
|
||||
66076B4D2BC056980043D547 /* LinkPreviewBuilderImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreviewBuilderImpl.swift; sourceTree = "<group>"; };
|
||||
66076B582BC06CA70043D547 /* EditManagerAttachmentsShims.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditManagerAttachmentsShims.swift; sourceTree = "<group>"; };
|
||||
66076B592BC06CA70043D547 /* MockEditManagerAttachments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockEditManagerAttachments.swift; sourceTree = "<group>"; };
|
||||
66076B5A2BC06CA70043D547 /* EditManagerAttachmentsImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditManagerAttachmentsImpl.swift; sourceTree = "<group>"; };
|
||||
66076B5B2BC06CA70043D547 /* EditManagerAttachments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditManagerAttachments.swift; sourceTree = "<group>"; };
|
||||
@@ -9430,7 +9428,6 @@
|
||||
children = (
|
||||
66076B5B2BC06CA70043D547 /* EditManagerAttachments.swift */,
|
||||
66076B5A2BC06CA70043D547 /* EditManagerAttachmentsImpl.swift */,
|
||||
66076B582BC06CA70043D547 /* EditManagerAttachmentsShims.swift */,
|
||||
66076B592BC06CA70043D547 /* MockEditManagerAttachments.swift */,
|
||||
);
|
||||
path = Attachments;
|
||||
@@ -18042,7 +18039,6 @@
|
||||
C1DB22C329C9F95500757380 /* EditManager.swift in Sources */,
|
||||
66076B5F2BC06CA70043D547 /* EditManagerAttachments.swift in Sources */,
|
||||
66076B5E2BC06CA70043D547 /* EditManagerAttachmentsImpl.swift in Sources */,
|
||||
66076B5C2BC06CA70043D547 /* EditManagerAttachmentsShims.swift in Sources */,
|
||||
668B30092BBDD9A20001FD25 /* EditManagerImpl.swift in Sources */,
|
||||
C1C4AA3329E7038D000CE9D3 /* EditManagerShims.swift in Sources */,
|
||||
C167387529E8397B0068EA92 /* EditMessageStore.swift in Sources */,
|
||||
|
||||
@@ -64,10 +64,10 @@ final class BackupArchiveTSMessageEditHistoryArchiver<MessageType: TSMessage>
|
||||
private typealias ArchiveFrameError = BackupArchive.ArchiveFrameError<BackupArchive.InteractionUniqueId>
|
||||
private typealias RestoreFrameError = BackupArchive.RestoreFrameError<BackupArchive.ChatItemId>
|
||||
|
||||
private let editMessageStore: any EditMessageStore
|
||||
private let editMessageStore: EditMessageStore
|
||||
|
||||
init(
|
||||
editMessageStore: any EditMessageStore
|
||||
editMessageStore: EditMessageStore
|
||||
) {
|
||||
self.editMessageStore = editMessageStore
|
||||
}
|
||||
|
||||
@@ -786,18 +786,16 @@ extension AppSetup.GlobalsContinuation {
|
||||
linkPreviewSettingStore: linkPreviewSettingStore
|
||||
)
|
||||
|
||||
let editMessageStore = EditMessageStoreImpl()
|
||||
let editMessageStore = EditMessageStore()
|
||||
let editManager = EditManagerImpl(
|
||||
context: .init(
|
||||
attachmentContentValidator: attachmentContentValidator,
|
||||
attachmentStore: attachmentStore,
|
||||
dataStore: EditManagerImpl.Wrappers.DataStore(),
|
||||
editManagerAttachments: EditManagerAttachmentsImpl(
|
||||
attachmentManager: attachmentManager,
|
||||
attachmentStore: attachmentStore,
|
||||
attachmentValidator: attachmentContentValidator,
|
||||
linkPreviewManager: linkPreviewManager,
|
||||
tsMessageStore: EditManagerAttachmentsImpl.Wrappers.TSMessageStore()
|
||||
),
|
||||
editMessageStore: editMessageStore,
|
||||
receiptManagerShim: EditManagerImpl.Wrappers.ReceiptManager(receiptManager: receiptManager)
|
||||
|
||||
@@ -11,20 +11,17 @@ public class EditManagerAttachmentsImpl: EditManagerAttachments {
|
||||
private let attachmentStore: AttachmentStore
|
||||
private let attachmentValidator: AttachmentContentValidator
|
||||
private let linkPreviewManager: LinkPreviewManager
|
||||
private let tsMessageStore: EditManagerAttachmentsImpl.Shims.TSMessageStore
|
||||
|
||||
public init(
|
||||
attachmentManager: AttachmentManager,
|
||||
attachmentStore: AttachmentStore,
|
||||
attachmentValidator: AttachmentContentValidator,
|
||||
linkPreviewManager: LinkPreviewManager,
|
||||
tsMessageStore: EditManagerAttachmentsImpl.Shims.TSMessageStore
|
||||
) {
|
||||
self.attachmentManager = attachmentManager
|
||||
self.attachmentStore = attachmentStore
|
||||
self.attachmentValidator = attachmentValidator
|
||||
self.linkPreviewManager = linkPreviewManager
|
||||
self.tsMessageStore = tsMessageStore
|
||||
}
|
||||
|
||||
public func reconcileAttachments<EditTarget: EditMessageWrapper>(
|
||||
@@ -102,7 +99,7 @@ public class EditManagerAttachmentsImpl: EditManagerAttachments {
|
||||
|
||||
if let quotedReplyPriorToEdit {
|
||||
// If we had a quoted reply, always keep it on the prior revision.
|
||||
tsMessageStore.update(priorRevision, with: quotedReplyPriorToEdit, tx: tx)
|
||||
priorRevision.update(with: quotedReplyPriorToEdit, transaction: tx)
|
||||
}
|
||||
if let attachmentReferencePriorToEdit {
|
||||
// IMPORTANT: we MUST assign the prior revision owner BEFORE removing
|
||||
@@ -129,7 +126,7 @@ public class EditManagerAttachmentsImpl: EditManagerAttachments {
|
||||
case .keep:
|
||||
if let quotedReplyPriorToEdit {
|
||||
// The latest revision keeps the prior revision's quoted reply.
|
||||
tsMessageStore.update(latestRevision, with: quotedReplyPriorToEdit, tx: tx)
|
||||
latestRevision.update(with: quotedReplyPriorToEdit, transaction: tx)
|
||||
}
|
||||
|
||||
if let attachmentReferencePriorToEdit {
|
||||
@@ -175,7 +172,7 @@ public class EditManagerAttachmentsImpl: EditManagerAttachments {
|
||||
|
||||
if let linkPreviewPriorToEdit {
|
||||
// If we had a link preview, always keep it on the prior revision.
|
||||
tsMessageStore.update(priorRevision, with: linkPreviewPriorToEdit, tx: tx)
|
||||
priorRevision.update(with: linkPreviewPriorToEdit, transaction: tx)
|
||||
}
|
||||
if let attachmentReferencePriorToEdit {
|
||||
// IMPORTANT: we MUST assign the prior revision owner BEFORE removing
|
||||
@@ -220,7 +217,7 @@ public class EditManagerAttachmentsImpl: EditManagerAttachments {
|
||||
builder: builder,
|
||||
tx: tx
|
||||
)
|
||||
tsMessageStore.update(latestRevision, with: builder.info, tx: tx)
|
||||
latestRevision.update(with: builder.info, transaction: tx)
|
||||
try builder.finalize(
|
||||
owner: .messageLinkPreview(.init(
|
||||
messageRowId: latestRevisionRowId,
|
||||
@@ -252,7 +249,7 @@ public class EditManagerAttachmentsImpl: EditManagerAttachments {
|
||||
} catch let error {
|
||||
throw error
|
||||
}
|
||||
tsMessageStore.update(latestRevision, with: linkPreviewBuilder.info, tx: tx)
|
||||
latestRevision.update(with: linkPreviewBuilder.info, transaction: tx)
|
||||
try linkPreviewBuilder.finalize(
|
||||
owner: .messageLinkPreview(.init(
|
||||
messageRowId: latestRevisionRowId,
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
//
|
||||
// Copyright 2023 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import LibSignalClient
|
||||
|
||||
extension EditManagerAttachmentsImpl {
|
||||
public enum Shims {
|
||||
public typealias TSMessageStore = _EditManagerAttachmentsImpl_TSMessageStoreShim
|
||||
}
|
||||
|
||||
public enum Wrappers {
|
||||
public typealias TSMessageStore = _EditManagerAttachmentsImpl_TSMessageStoreWrapper
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - EditManager.TSMessageStore
|
||||
|
||||
public protocol _EditManagerAttachmentsImpl_TSMessageStoreShim {
|
||||
|
||||
func update(
|
||||
_ message: TSMessage,
|
||||
with quotedReply: TSQuotedMessage,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
|
||||
func update(
|
||||
_ message: TSMessage,
|
||||
with linkPreview: OWSLinkPreview,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
}
|
||||
|
||||
public class _EditManagerAttachmentsImpl_TSMessageStoreWrapper: EditManagerAttachmentsImpl.Shims.TSMessageStore {
|
||||
|
||||
public init() {}
|
||||
|
||||
public func update(
|
||||
_ message: TSMessage,
|
||||
with quotedReply: TSQuotedMessage,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
message.update(with: quotedReply, transaction: tx)
|
||||
}
|
||||
|
||||
public func update(
|
||||
_ message: TSMessage,
|
||||
with linkPreview: OWSLinkPreview,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
message.update(with: linkPreview, transaction: tx)
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,6 @@ public class EditManagerImpl: EditManager {
|
||||
public struct Context {
|
||||
let attachmentContentValidator: AttachmentContentValidator
|
||||
let attachmentStore: AttachmentStore
|
||||
let dataStore: EditManagerImpl.Shims.DataStore
|
||||
let editManagerAttachments: EditManagerAttachments
|
||||
let editMessageStore: EditMessageStore
|
||||
let receiptManagerShim: EditManagerImpl.Shims.ReceiptManager
|
||||
@@ -40,14 +39,12 @@ public class EditManagerImpl: EditManager {
|
||||
public init(
|
||||
attachmentContentValidator: AttachmentContentValidator,
|
||||
attachmentStore: AttachmentStore,
|
||||
dataStore: EditManagerImpl.Shims.DataStore,
|
||||
editManagerAttachments: EditManagerAttachments,
|
||||
editMessageStore: EditMessageStore,
|
||||
receiptManagerShim: EditManagerImpl.Shims.ReceiptManager
|
||||
) {
|
||||
self.attachmentContentValidator = attachmentContentValidator
|
||||
self.attachmentStore = attachmentStore
|
||||
self.dataStore = dataStore
|
||||
self.editManagerAttachments = editManagerAttachments
|
||||
self.editMessageStore = editMessageStore
|
||||
self.receiptManagerShim = receiptManagerShim
|
||||
@@ -143,17 +140,16 @@ public class EditManagerImpl: EditManager {
|
||||
// MARK: - Edit UI Validation
|
||||
|
||||
public func canShowEditMenu(interaction: TSInteraction, thread: TSThread) -> Bool {
|
||||
return Self.validateCanShowEditMenu(interaction: interaction, thread: thread, dataStore: context.dataStore) == nil
|
||||
return Self.validateCanShowEditMenu(interaction: interaction, thread: thread) == nil
|
||||
}
|
||||
|
||||
private static func validateCanShowEditMenu(
|
||||
interaction: TSInteraction,
|
||||
thread: TSThread,
|
||||
dataStore: EditManagerImpl.Shims.DataStore
|
||||
) -> EditSendValidationError? {
|
||||
guard let message = interaction as? TSOutgoingMessage else { return .messageTypeNotSupported }
|
||||
|
||||
if !Self.editMessageTypeSupported(message: message, dataStore: dataStore) {
|
||||
if !Self.editMessageTypeSupported(message: message) {
|
||||
return .messageTypeNotSupported
|
||||
}
|
||||
|
||||
@@ -193,7 +189,7 @@ public class EditManagerImpl: EditManager {
|
||||
|
||||
let targetMessage = targetMessageWrapper.message
|
||||
|
||||
if let error = Self.validateCanShowEditMenu(interaction: targetMessage, thread: thread, dataStore: context.dataStore) {
|
||||
if let error = Self.validateCanShowEditMenu(interaction: targetMessage, thread: thread) {
|
||||
return error
|
||||
}
|
||||
|
||||
@@ -238,11 +234,11 @@ public class EditManagerImpl: EditManager {
|
||||
tx: tx
|
||||
)
|
||||
|
||||
let outgoingEditMessage = context.dataStore.createOutgoingEditMessage(
|
||||
let outgoingEditMessage = OutgoingEditMessage(
|
||||
thread: thread,
|
||||
targetMessageTimestamp: targetMessage.timestamp,
|
||||
editMessage: editedMessage,
|
||||
tx: tx
|
||||
transaction: tx
|
||||
)
|
||||
|
||||
return outgoingEditMessage
|
||||
@@ -276,7 +272,7 @@ public class EditManagerImpl: EditManager {
|
||||
edits: editsToApply,
|
||||
tx: tx
|
||||
)
|
||||
context.dataStore.overwritingUpdate(latestRevisionMessage, tx: tx)
|
||||
latestRevisionMessage.anyOverwritingUpdate(transaction: tx)
|
||||
let latestRevisionRowId = latestRevisionMessage.sqliteRowId!
|
||||
|
||||
/// Create and insert a clone of the original message, preserving all
|
||||
@@ -292,10 +288,9 @@ public class EditManagerImpl: EditManager {
|
||||
)
|
||||
let priorRevisionMessage = EditTarget.build(
|
||||
priorRevisionMessageBuilder,
|
||||
dataStore: context.dataStore,
|
||||
tx: tx
|
||||
)
|
||||
context.dataStore.insert(priorRevisionMessage, tx: tx)
|
||||
priorRevisionMessage.anyInsert(transaction: tx)
|
||||
let priorRevisionRowId = priorRevisionMessage.sqliteRowId!
|
||||
|
||||
try context.editManagerAttachments.reconcileAttachments(
|
||||
@@ -314,7 +309,6 @@ public class EditManagerImpl: EditManager {
|
||||
// Update the newly inserted message with any data that needs to be
|
||||
// copied from the original message
|
||||
editTargetWrapper.updateMessageCopy(
|
||||
dataStore: context.dataStore,
|
||||
newMessageCopy: priorRevisionMessage,
|
||||
tx: tx
|
||||
)
|
||||
@@ -356,7 +350,6 @@ public class EditManagerImpl: EditManager {
|
||||
|
||||
let editedMessage = EditTarget.build(
|
||||
editedMessageBuilder,
|
||||
dataStore: context.dataStore,
|
||||
tx: tx
|
||||
)
|
||||
|
||||
@@ -422,7 +415,7 @@ public class EditManagerImpl: EditManager {
|
||||
}
|
||||
}
|
||||
|
||||
if !Self.editMessageTypeSupported(message: targetMessage, dataStore: context.dataStore) {
|
||||
if !Self.editMessageTypeSupported(message: targetMessage) {
|
||||
throw OWSAssertionError("Edit of message type not supported")
|
||||
}
|
||||
|
||||
@@ -446,7 +439,6 @@ public class EditManagerImpl: EditManager {
|
||||
|
||||
private static func editMessageTypeSupported(
|
||||
message: TSMessage,
|
||||
dataStore: EditManagerImpl.Shims.DataStore
|
||||
) -> Bool {
|
||||
// Skip remotely deleted
|
||||
if message.wasRemotelyDeleted {
|
||||
@@ -464,7 +456,7 @@ public class EditManagerImpl: EditManager {
|
||||
}
|
||||
|
||||
// Skip contact shares
|
||||
if dataStore.isMessageContactShare(message) {
|
||||
if message.contactShare != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -8,104 +8,14 @@ import LibSignalClient
|
||||
|
||||
extension EditManagerImpl {
|
||||
public enum Shims {
|
||||
public typealias DataStore = _EditManagerImpl_DataStore
|
||||
public typealias ReceiptManager = _EditManagerImpl_ReceiptManagerShim
|
||||
}
|
||||
|
||||
public enum Wrappers {
|
||||
public typealias DataStore = _EditManagerImpl_DataStoreWrapper
|
||||
public typealias ReceiptManager = _EditManagerImpl_ReceiptManagerWrapper
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - EditManager.DataStore
|
||||
|
||||
public protocol _EditManagerImpl_DataStore {
|
||||
|
||||
func build(
|
||||
_ builder: TSOutgoingMessageBuilder,
|
||||
tx: DBReadTransaction
|
||||
) -> TSOutgoingMessage
|
||||
|
||||
func createOutgoingEditMessage(
|
||||
thread: TSThread,
|
||||
targetMessageTimestamp: UInt64,
|
||||
editMessage: TSOutgoingMessage,
|
||||
tx: DBReadTransaction
|
||||
) -> OutgoingEditMessage
|
||||
|
||||
func isMessageContactShare(_ message: TSMessage) -> Bool
|
||||
|
||||
func update(
|
||||
_ message: TSOutgoingMessage,
|
||||
withRecipientAddressStates: [SignalServiceAddress: TSOutgoingMessageRecipientState]?,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
|
||||
func insert(
|
||||
_ message: TSMessage,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
|
||||
func overwritingUpdate(
|
||||
_ message: TSMessage,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
}
|
||||
|
||||
public class _EditManagerImpl_DataStoreWrapper: EditManagerImpl.Shims.DataStore {
|
||||
|
||||
public func createOutgoingEditMessage(
|
||||
thread: TSThread,
|
||||
targetMessageTimestamp: UInt64,
|
||||
editMessage: TSOutgoingMessage,
|
||||
tx: DBReadTransaction
|
||||
) -> OutgoingEditMessage {
|
||||
return OutgoingEditMessage(
|
||||
thread: thread,
|
||||
targetMessageTimestamp: targetMessageTimestamp,
|
||||
editMessage: editMessage,
|
||||
transaction: tx
|
||||
)
|
||||
}
|
||||
|
||||
public func build(
|
||||
_ builder: TSOutgoingMessageBuilder,
|
||||
tx: DBReadTransaction
|
||||
) -> TSOutgoingMessage {
|
||||
return builder.build(transaction: tx)
|
||||
}
|
||||
|
||||
public func isMessageContactShare(_ message: TSMessage) -> Bool {
|
||||
return message.contactShare != nil
|
||||
}
|
||||
|
||||
public func update(
|
||||
_ message: TSOutgoingMessage,
|
||||
withRecipientAddressStates recipientAddressStates: [SignalServiceAddress: TSOutgoingMessageRecipientState]?,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
message.updateWithRecipientAddressStates(
|
||||
recipientAddressStates,
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
|
||||
public func insert(
|
||||
_ message: TSMessage,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
message.anyInsert(transaction: tx)
|
||||
}
|
||||
|
||||
public func overwritingUpdate(
|
||||
_ message: TSMessage,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
message.anyOverwritingUpdate(transaction: tx)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - OWSReceiptManager
|
||||
|
||||
public protocol _EditManagerImpl_ReceiptManagerShim {
|
||||
|
||||
@@ -21,76 +21,12 @@ public enum EditMessageTarget {
|
||||
}
|
||||
}
|
||||
|
||||
public protocol EditMessageStore {
|
||||
|
||||
// MARK: - Reads
|
||||
|
||||
func editTarget(
|
||||
timestamp: UInt64,
|
||||
authorAci: Aci?,
|
||||
tx: DBReadTransaction
|
||||
) -> EditMessageTarget?
|
||||
|
||||
func findMessage(
|
||||
fromEdit edit: TSMessage,
|
||||
tx: DBReadTransaction
|
||||
) -> TSMessage?
|
||||
|
||||
func numberOfEdits(
|
||||
for message: TSMessage,
|
||||
tx: DBReadTransaction
|
||||
) -> Int
|
||||
|
||||
/// Fetches all past revisions for the given most-recent-revision message.
|
||||
///
|
||||
/// - Returns
|
||||
/// An edit record and message instance (if one is found) for each past
|
||||
/// revision, from newest to oldest.
|
||||
func findEditHistory<MessageType: TSMessage>(
|
||||
forMostRecentRevision message: MessageType,
|
||||
tx: DBReadTransaction
|
||||
) throws -> [(record: EditRecord, message: MessageType?)]
|
||||
|
||||
/// Fetches all EditRecords related to `message`.
|
||||
///
|
||||
/// The `message` may be the latest revision or a past revision.
|
||||
///
|
||||
/// The EditRecords are fetched "recursively", meaning that every EditRecord
|
||||
/// that references a message ID which is referenced by any element of the
|
||||
/// result will be returned. This is useful when deleting messages because
|
||||
/// it allows us to maintain invariants required by FOREIGN KEY constraints.
|
||||
///
|
||||
/// For example, if the revision "graph" is well-formed, we'll return
|
||||
/// EditRecords with distinct pastRevisionIds (e.g., 102, 103) which all
|
||||
/// refer to the same latestRevisionId (e.g., 101), and we'll return this
|
||||
/// exact same result regardless of whether `message` refers to a past
|
||||
/// revision (e.g., 102) or the latest revision (e.g., 101).
|
||||
///
|
||||
/// If the revision "graph" isn't well-formed, we must fetch extra
|
||||
/// EditRecords to ensure we delete all the EditRecords that reference the
|
||||
/// messages that are about to be deleted.
|
||||
func findEditRecords(
|
||||
relatedTo message: TSMessage,
|
||||
tx: DBReadTransaction
|
||||
) throws -> [EditRecord]
|
||||
|
||||
// MARK: - Writes
|
||||
|
||||
func insert(
|
||||
_ editRecord: EditRecord,
|
||||
tx: DBWriteTransaction
|
||||
) throws
|
||||
|
||||
func update(
|
||||
_ editRecord: EditRecord,
|
||||
tx: DBWriteTransaction
|
||||
) throws
|
||||
}
|
||||
|
||||
public class EditMessageStoreImpl: EditMessageStore {
|
||||
public struct EditMessageStore {
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: - Reads
|
||||
|
||||
public func editTarget(
|
||||
timestamp: UInt64,
|
||||
authorAci: Aci?,
|
||||
@@ -190,6 +126,11 @@ public class EditMessageStoreImpl: EditMessageStore {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches all past revisions for the given most-recent-revision message.
|
||||
///
|
||||
/// - Returns
|
||||
/// An edit record and message instance (if one is found) for each past
|
||||
/// revision, from newest to oldest.
|
||||
public func findEditHistory<MessageType: TSMessage>(
|
||||
forMostRecentRevision message: MessageType,
|
||||
tx: DBReadTransaction
|
||||
@@ -224,6 +165,24 @@ public class EditMessageStoreImpl: EditMessageStore {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches all EditRecords related to `message`.
|
||||
///
|
||||
/// The `message` may be the latest revision or a past revision.
|
||||
///
|
||||
/// The EditRecords are fetched "recursively", meaning that every EditRecord
|
||||
/// that references a message ID which is referenced by any element of the
|
||||
/// result will be returned. This is useful when deleting messages because
|
||||
/// it allows us to maintain invariants required by FOREIGN KEY constraints.
|
||||
///
|
||||
/// For example, if the revision "graph" is well-formed, we'll return
|
||||
/// EditRecords with distinct pastRevisionIds (e.g., 102, 103) which all
|
||||
/// refer to the same latestRevisionId (e.g., 101), and we'll return this
|
||||
/// exact same result regardless of whether `message` refers to a past
|
||||
/// revision (e.g., 102) or the latest revision (e.g., 101).
|
||||
///
|
||||
/// If the revision "graph" isn't well-formed, we must fetch extra
|
||||
/// EditRecords to ensure we delete all the EditRecords that reference the
|
||||
/// messages that are about to be deleted.
|
||||
public func findEditRecords(
|
||||
relatedTo message: TSMessage,
|
||||
tx: DBReadTransaction
|
||||
@@ -253,6 +212,8 @@ public class EditMessageStoreImpl: EditMessageStore {
|
||||
return editRecords.removingDuplicates(uniquingElementsBy: { $0.id! })
|
||||
}
|
||||
|
||||
// MARK: - Writes
|
||||
|
||||
public func insert(
|
||||
_ editRecord: EditRecord,
|
||||
tx: DBWriteTransaction
|
||||
|
||||
@@ -32,12 +32,10 @@ public protocol EditMessageWrapper {
|
||||
|
||||
static func build(
|
||||
_ builder: MessageBuilderType,
|
||||
dataStore: EditManagerImpl.Shims.DataStore,
|
||||
tx: DBReadTransaction
|
||||
) -> MessageType
|
||||
|
||||
func updateMessageCopy(
|
||||
dataStore: EditManagerImpl.Shims.DataStore,
|
||||
newMessageCopy: MessageType,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
@@ -173,14 +171,12 @@ public struct IncomingEditMessageWrapper: EditMessageWrapper {
|
||||
|
||||
public static func build(
|
||||
_ builder: TSIncomingMessageBuilder,
|
||||
dataStore: EditManagerImpl.Shims.DataStore,
|
||||
tx: DBReadTransaction
|
||||
) -> TSIncomingMessage {
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
public func updateMessageCopy(
|
||||
dataStore: EditManagerImpl.Shims.DataStore,
|
||||
newMessageCopy: TSIncomingMessage,
|
||||
tx: DBWriteTransaction
|
||||
) {}
|
||||
@@ -266,22 +262,19 @@ public struct OutgoingEditMessageWrapper: EditMessageWrapper {
|
||||
|
||||
public static func build(
|
||||
_ builder: TSOutgoingMessageBuilder,
|
||||
dataStore: EditManagerImpl.Shims.DataStore,
|
||||
tx: DBReadTransaction
|
||||
) -> TSOutgoingMessage {
|
||||
return dataStore.build(builder, tx: tx)
|
||||
return builder.build(transaction: tx)
|
||||
}
|
||||
|
||||
public func updateMessageCopy(
|
||||
dataStore: EditManagerImpl.Shims.DataStore,
|
||||
newMessageCopy: TSOutgoingMessage,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
// Need to copy over the recipient address from the old message
|
||||
// This is needed when procesing sync messages.
|
||||
dataStore.update(
|
||||
newMessageCopy,
|
||||
withRecipientAddressStates: message.recipientAddressStates,
|
||||
newMessageCopy.updateWithRecipientAddressStates(
|
||||
message.recipientAddressStates,
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
|
||||
@@ -49,23 +49,22 @@ class EditManagerTests: SSKBaseTest {
|
||||
}
|
||||
|
||||
let editMessage = createEditDataMessage { $0.setBody("FOO") }
|
||||
let dataStoreMock = EditManagerDataStoreMock(targetMessage: targetMessage)
|
||||
let editMessageStoreMock = EditMessageStoreMock()
|
||||
let editManager = EditManagerImpl(context:
|
||||
.init(
|
||||
attachmentContentValidator: AttachmentContentValidatorMock(),
|
||||
attachmentStore: AttachmentStoreMock(),
|
||||
dataStore: dataStoreMock,
|
||||
editManagerAttachments: MockEditManagerAttachments(),
|
||||
editMessageStore: editMessageStoreMock,
|
||||
editMessageStore: EditMessageStore(),
|
||||
receiptManagerShim: ReceiptManagerMock()
|
||||
)
|
||||
)
|
||||
|
||||
var newMessage: TSMessage!
|
||||
try db.write { tx in
|
||||
_ = try editManager.processIncomingEditMessage(
|
||||
targetMessage.anyInsert(transaction: tx)
|
||||
newMessage = try editManager.processIncomingEditMessage(
|
||||
editMessage,
|
||||
serverTimestamp: 1,
|
||||
serverTimestamp: 2,
|
||||
serverGuid: UUID().uuidString,
|
||||
serverDeliveryTimestamp: 1234,
|
||||
thread: thread,
|
||||
@@ -76,15 +75,20 @@ class EditManagerTests: SSKBaseTest {
|
||||
)),
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
|
||||
try db.read { tx in
|
||||
// Inserted edit
|
||||
compare(
|
||||
dataStoreMock.editMessageCopy,
|
||||
newMessage,
|
||||
targetMessage,
|
||||
propertyList: editPropertyList
|
||||
)
|
||||
|
||||
// original
|
||||
let dbOriginal = try InteractionFinder.fetchInteractions(timestamp: targetMessage.timestamp, transaction: tx).first!
|
||||
compare(
|
||||
dataStoreMock.oldMessageCopy,
|
||||
dbOriginal,
|
||||
targetMessage,
|
||||
propertyList: originalPropetyList
|
||||
)
|
||||
@@ -97,15 +101,12 @@ class EditManagerTests: SSKBaseTest {
|
||||
builder.isViewOnceMessage = true
|
||||
}
|
||||
let editMessage = createEditDataMessage { _ in }
|
||||
let dataStoreMock = EditManagerDataStoreMock(targetMessage: targetMessage)
|
||||
let editMessageStoreMock = EditMessageStoreMock()
|
||||
let editManager = EditManagerImpl(context:
|
||||
.init(
|
||||
attachmentContentValidator: AttachmentContentValidatorMock(),
|
||||
attachmentStore: AttachmentStoreMock(),
|
||||
dataStore: dataStoreMock,
|
||||
editManagerAttachments: MockEditManagerAttachments(),
|
||||
editMessageStore: editMessageStoreMock,
|
||||
editMessageStore: EditMessageStore(),
|
||||
receiptManagerShim: ReceiptManagerMock()
|
||||
)
|
||||
)
|
||||
@@ -139,24 +140,20 @@ class EditManagerTests: SSKBaseTest {
|
||||
func testContactShareEditMessageFails() {
|
||||
let targetMessage = createIncomingMessage(with: thread) { builder in
|
||||
builder.authorAci = authorAci
|
||||
builder.contactShare = OWSContact(name: .init(givenName: "Test"))
|
||||
}
|
||||
|
||||
let editMessage = createEditDataMessage { _ in }
|
||||
let dataStoreMock = EditManagerDataStoreMock(targetMessage: targetMessage)
|
||||
let editMessageStoreMock = EditMessageStoreMock()
|
||||
let editManager = EditManagerImpl(context:
|
||||
.init(
|
||||
attachmentContentValidator: AttachmentContentValidatorMock(),
|
||||
attachmentStore: AttachmentStoreMock(),
|
||||
dataStore: dataStoreMock,
|
||||
editManagerAttachments: MockEditManagerAttachments(),
|
||||
editMessageStore: editMessageStoreMock,
|
||||
editMessageStore: EditMessageStore(),
|
||||
receiptManagerShim: ReceiptManagerMock()
|
||||
)
|
||||
)
|
||||
|
||||
dataStoreMock.isContactShare = true
|
||||
|
||||
db.write { tx in
|
||||
do {
|
||||
OWSAssertionError.test_skipAssertions = true
|
||||
@@ -188,16 +185,12 @@ class EditManagerTests: SSKBaseTest {
|
||||
builder.authorAci = authorAci
|
||||
}
|
||||
let editMessage = createEditDataMessage { _ in }
|
||||
let dataStoreMock = EditManagerDataStoreMock(targetMessage: targetMessage)
|
||||
let editMessageStoreMock = EditMessageStoreMock()
|
||||
|
||||
let editManager = EditManagerImpl(context:
|
||||
.init(
|
||||
attachmentContentValidator: AttachmentContentValidatorMock(),
|
||||
attachmentStore: AttachmentStoreMock(),
|
||||
dataStore: dataStoreMock,
|
||||
editManagerAttachments: MockEditManagerAttachments(),
|
||||
editMessageStore: editMessageStoreMock,
|
||||
editMessageStore: EditMessageStore(),
|
||||
receiptManagerShim: ReceiptManagerMock()
|
||||
)
|
||||
)
|
||||
@@ -237,16 +230,12 @@ class EditManagerTests: SSKBaseTest {
|
||||
builder.serverTimestamp = bigInt
|
||||
}
|
||||
let editMessage = createEditDataMessage { _ in }
|
||||
let dataStoreMock = EditManagerDataStoreMock(targetMessage: targetMessage)
|
||||
let editMessageStoreMock = EditMessageStoreMock()
|
||||
|
||||
let editManager = EditManagerImpl(context:
|
||||
.init(
|
||||
attachmentContentValidator: AttachmentContentValidatorMock(),
|
||||
attachmentStore: AttachmentStoreMock(),
|
||||
dataStore: dataStoreMock,
|
||||
editManagerAttachments: MockEditManagerAttachments(),
|
||||
editMessageStore: editMessageStoreMock,
|
||||
editMessageStore: EditMessageStore(),
|
||||
receiptManagerShim: ReceiptManagerMock()
|
||||
)
|
||||
)
|
||||
@@ -363,107 +352,11 @@ class EditManagerTests: SSKBaseTest {
|
||||
)
|
||||
messageBuilder.serverTimestamp = 1
|
||||
customizeBlock(messageBuilder)
|
||||
let targetMessage = messageBuilder.build()
|
||||
targetMessage.replaceRowId(1, uniqueId: "1")
|
||||
return targetMessage
|
||||
return messageBuilder.build()
|
||||
}
|
||||
|
||||
// MARK: - Test Mocks
|
||||
|
||||
private class EditManagerDataStoreMock: EditManagerImpl.Shims.DataStore {
|
||||
func createOutgoingEditMessage(
|
||||
thread: TSThread,
|
||||
targetMessageTimestamp: UInt64,
|
||||
editMessage: TSOutgoingMessage,
|
||||
tx: DBReadTransaction
|
||||
) -> OutgoingEditMessage {
|
||||
return try! OutgoingEditMessage(dictionary: [:])
|
||||
}
|
||||
|
||||
func build(
|
||||
_ builder: TSOutgoingMessageBuilder,
|
||||
tx: DBReadTransaction
|
||||
) -> TSOutgoingMessage {
|
||||
return builder.build(transaction: tx)
|
||||
}
|
||||
|
||||
var isContactShare = false
|
||||
|
||||
func isMessageContactShare(_ message: TSMessage) -> Bool {
|
||||
return isContactShare
|
||||
}
|
||||
|
||||
func update(
|
||||
_ message: TSOutgoingMessage,
|
||||
withRecipientAddressStates: [SignalServiceAddress: TSOutgoingMessageRecipientState]?,
|
||||
tx: DBWriteTransaction
|
||||
) {}
|
||||
|
||||
let targetMessage: TSMessage?
|
||||
var editMessageCopy: TSMessage?
|
||||
var oldMessageCopy: TSMessage?
|
||||
|
||||
init(targetMessage: TSMessage?) {
|
||||
self.targetMessage = targetMessage
|
||||
}
|
||||
|
||||
func insert(_ message: TSMessage, tx: DBWriteTransaction) {
|
||||
oldMessageCopy = message
|
||||
message.replaceRowId(2, uniqueId: message.uniqueId)
|
||||
}
|
||||
|
||||
func overwritingUpdate(_ message: TSMessage, tx: DBWriteTransaction) {
|
||||
editMessageCopy = message
|
||||
}
|
||||
}
|
||||
|
||||
private class EditMessageStoreMock: EditMessageStore {
|
||||
func editTarget(
|
||||
timestamp: UInt64,
|
||||
authorAci: Aci?,
|
||||
tx: DBReadTransaction
|
||||
) -> EditMessageTarget? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func findMessage(
|
||||
fromEdit edit: TSMessage,
|
||||
tx: DBReadTransaction
|
||||
) -> TSMessage? {
|
||||
nil
|
||||
}
|
||||
|
||||
func numberOfEdits(
|
||||
for message: TSMessage,
|
||||
tx: DBReadTransaction
|
||||
) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func findEditHistory<MessageType: TSMessage>(
|
||||
forMostRecentRevision message: MessageType,
|
||||
tx: DBReadTransaction
|
||||
) throws -> [(record: EditRecord, message: MessageType?)] {
|
||||
return []
|
||||
}
|
||||
|
||||
func findEditRecords(
|
||||
relatedTo message: TSMessage,
|
||||
tx: DBReadTransaction
|
||||
) throws -> [EditRecord] {
|
||||
return []
|
||||
}
|
||||
|
||||
var editRecord: EditRecord?
|
||||
|
||||
func insert(_ editRecord: EditRecord, tx: DBWriteTransaction) {
|
||||
self.editRecord = editRecord
|
||||
}
|
||||
|
||||
func update(_ editRecord: EditRecord, tx: DBWriteTransaction) throws {}
|
||||
|
||||
}
|
||||
|
||||
private class ReceiptManagerMock: EditManagerImpl.Shims.ReceiptManager {
|
||||
func messageWasRead(
|
||||
_ message: TSIncomingMessage,
|
||||
@@ -489,11 +382,11 @@ class EditManagerTests: SSKBaseTest {
|
||||
"isOutgoing": .unchanged,
|
||||
"editState": .changed,
|
||||
"body": .changed,
|
||||
"bodyRanges": .changed,
|
||||
"bodyRanges": .ignore, // MessageBodyRanges are not equatable, so ignore
|
||||
"expiresInSeconds": .unchanged,
|
||||
"expireTimerVersion": .unchanged,
|
||||
"expireStartedAt": .unchanged,
|
||||
"schemaVersion": .unchanged,
|
||||
"schemaVersion": .ignore,
|
||||
"quotedMessage": .unchanged,
|
||||
"contactShare": .unchanged,
|
||||
"linkPreview": .unchanged,
|
||||
@@ -527,11 +420,11 @@ class EditManagerTests: SSKBaseTest {
|
||||
"isOutgoing": .unchanged,
|
||||
"editState": .changed,
|
||||
"body": .unchanged,
|
||||
"bodyRanges": .unchanged,
|
||||
"bodyRanges": .ignore,
|
||||
"expiresInSeconds": .unchanged,
|
||||
"expireTimerVersion": .unchanged,
|
||||
"expireStartedAt": .unchanged,
|
||||
"schemaVersion": .unchanged,
|
||||
"schemaVersion": .ignore,
|
||||
"quotedMessage": .unchanged,
|
||||
"contactShare": .unchanged,
|
||||
"linkPreview": .unchanged,
|
||||
|
||||
Reference in New Issue
Block a user