diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 9d7c469a1..1b513ff95 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -532,16 +532,34 @@ extension ConversationVC: let insertedInteraction: Interaction = try optimisticData.interaction.inserted(db) self?.viewModel.associate(optimisticMessageId: optimisticData.id, to: insertedInteraction.id) - // If there is a LinkPreview and it doesn't match an existing one then add it now - if - let linkPreviewDraft: LinkPreviewDraft = optimisticData.linkPreviewDraft, - (try? insertedInteraction.linkPreview.isEmpty(db)) == true - { - try LinkPreview( - url: linkPreviewDraft.urlString, - title: linkPreviewDraft.title, - attachmentId: try optimisticData.linkPreviewAttachment?.inserted(db).id - ).insert(db) + // If there is a LinkPreview draft then check the state of any existing link previews and + // insert a new one if needed + if let linkPreviewDraft: LinkPreviewDraft = optimisticData.linkPreviewDraft { + let invalidLinkPreviewAttachmentStates: [Attachment.State] = [ + .failedDownload, .pendingDownload, .downloading, .failedUpload, .invalid + ] + let linkPreviewAttachmentId: String? = try? insertedInteraction.linkPreview + .select(.attachmentId) + .asRequest(of: String.self) + .fetchOne(db) + let linkPreviewAttachmentState: Attachment.State = linkPreviewAttachmentId + .map { + try? Attachment + .filter(id: $0) + .select(.state) + .asRequest(of: Attachment.State.self) + .fetchOne(db) + } + .defaulting(to: .invalid) + + // If we don't have a "valid" existing link preview then upsert a new one + if invalidLinkPreviewAttachmentStates.contains(linkPreviewAttachmentState) { + try LinkPreview( + url: linkPreviewDraft.urlString, + title: linkPreviewDraft.title, + attachmentId: try optimisticData.linkPreviewAttachment?.inserted(db).id + ).save(db) + } } // If there is a Quote the insert it now diff --git a/Session/Conversations/ConversationViewModel.swift b/Session/Conversations/ConversationViewModel.swift index 0bfef4254..7698a6f25 100644 --- a/Session/Conversations/ConversationViewModel.swift +++ b/Session/Conversations/ConversationViewModel.swift @@ -265,6 +265,24 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { .allCases .filter { $0 != .wasRead } ), + PagedData.ObservedChanges( + table: Attachment.self, + columns: [.state], + joinToPagedType: { + let interaction: TypedTableAlias = TypedTableAlias() + let linkPreview: TypedTableAlias = TypedTableAlias() + let linkPreviewAttachment: TypedTableAlias = TypedTableAlias() + + return SQL(""" + LEFT JOIN \(LinkPreview.self) ON ( + \(linkPreview[.url]) = \(interaction[.linkPreviewUrl]) AND + \(Interaction.linkPreviewFilterLiteral()) + ) + LEFT JOIN \(linkPreviewAttachment) ON \(linkPreviewAttachment[.id]) = \(linkPreview[.attachmentId]) + """ + ) + }() + ), PagedData.ObservedChanges( table: Contact.self, columns: [.isTrusted], diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index c264472ea..e1670ea30 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -467,7 +467,6 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { subview.removeFromSuperview() } albumView = nil - albumView = nil bodyTappableLabel = nil // Handle the deleted state first (it's much simpler than the others) diff --git a/SessionMessagingKit/Database/Models/LinkPreview.swift b/SessionMessagingKit/Database/Models/LinkPreview.swift index b214bc78d..c87740015 100644 --- a/SessionMessagingKit/Database/Models/LinkPreview.swift +++ b/SessionMessagingKit/Database/Models/LinkPreview.swift @@ -77,7 +77,7 @@ public struct LinkPreview: Codable, Equatable, Hashable, FetchableRecord, Persis // MARK: - Protobuf public extension LinkPreview { - init?(_ db: Database, proto: SNProtoDataMessage, body: String?, sentTimestampMs: TimeInterval) throws { + init?(_ db: Database, proto: SNProtoDataMessage, sentTimestampMs: TimeInterval) throws { guard let previewProto = proto.preview.first else { throw LinkPreviewError.noPreview } guard URL(string: previewProto.url) != nil else { throw LinkPreviewError.invalidInput } guard LinkPreview.isValidLinkUrl(previewProto.url) else { throw LinkPreviewError.invalidInput } @@ -86,9 +86,7 @@ public extension LinkPreview { let timestamp: TimeInterval = LinkPreview.timestampFor(sentTimestampMs: sentTimestampMs) let maybeLinkPreview: LinkPreview? = try? LinkPreview .filter(LinkPreview.Columns.url == previewProto.url) - .filter(LinkPreview.Columns.timestamp == LinkPreview.timestampFor( - sentTimestampMs: Double(proto.timestamp) - )) + .filter(LinkPreview.Columns.timestamp == timestamp) .fetchOne(db) if let linkPreview: LinkPreview = maybeLinkPreview { diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+VisibleMessages.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+VisibleMessages.swift index 520002125..3f80ebe04 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+VisibleMessages.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+VisibleMessages.swift @@ -276,7 +276,6 @@ extension MessageReceiver { let linkPreview: LinkPreview? = try? LinkPreview( db, proto: dataMessage, - body: message.text, sentTimestampMs: (messageSentTimestamp * 1000) )?.saved(db)