Make link previews work again

pull/313/head
nielsandriesse 4 years ago
parent f7bfa5c4d7
commit d39e155e1c

@ -3753,22 +3753,29 @@ typedef enum : NSUInteger {
message.sentTimestamp = [NSDate millisecondTimestamp];
message.text = text;
message.quote = [SNQuote from:self.inputToolbar.quotedReply];
TSThread *thread = self.thread;
TSOutgoingMessage *tsMessage = [TSOutgoingMessage from:message associatedWith:thread];
[self.conversationViewModel appendUnsavedOutgoingTextMessage:tsMessage];
OWSLinkPreviewDraft *linkPreviewDraft = self.inputToolbar.linkPreviewDraft;
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[tsMessage saveWithTransaction:transaction];
}];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[SNMessageSender send:message withAttachments:@[] inThread:thread usingTransaction:transaction];
[thread setDraft:@"" transaction:transaction];
message.linkPreview = [SNLinkPreview from:linkPreviewDraft using:transaction];
} completion:^{
dispatch_async(dispatch_get_main_queue(), ^{
TSThread *thread = self.thread;
TSOutgoingMessage *tsMessage = [TSOutgoingMessage from:message associatedWith:thread];
[self.conversationViewModel appendUnsavedOutgoingTextMessage:tsMessage];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[tsMessage saveWithTransaction:transaction];
}];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[SNMessageSender send:message withAttachments:@[] inThread:thread usingTransaction:transaction];
[thread setDraft:@"" transaction:transaction];
}];
[self messageWasSent:tsMessage];
[self.inputToolbar clearTextMessageAnimated:YES];
[self resetMentions];
dispatch_async(dispatch_get_main_queue(), ^{
[[weakSelf inputToolbar] toggleDefaultKeyboard];
});
});
}];
[self messageWasSent:tsMessage];
[self.inputToolbar clearTextMessageAnimated:YES];
[self resetMentions];
dispatch_async(dispatch_get_main_queue(), ^{
[[weakSelf inputToolbar] toggleDefaultKeyboard];
});
}
- (void)voiceMemoGestureDidStart

@ -31,11 +31,11 @@ extension Storage {
}
/// Returns the ID of the `TSIncomingMessage` that was constructed.
public func persist(_ message: VisibleMessage, withQuotedMessage quotedMessage: TSQuotedMessage?, groupPublicKey: String?, using transaction: Any) -> String? {
public func persist(_ message: VisibleMessage, quotedMessage: TSQuotedMessage?, linkPreview: OWSLinkPreview?, groupPublicKey: String?, using transaction: Any) -> String? {
let transaction = transaction as! YapDatabaseReadWriteTransaction
guard let threadID = getOrCreateThread(for: message.sender!, groupPublicKey: groupPublicKey, using: transaction),
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return nil }
let message = TSIncomingMessage.from(message, withQuotedMessage: quotedMessage, associatedWith: thread)
let message = TSIncomingMessage.from(message, quotedMessage: quotedMessage, linkPreview: linkPreview, associatedWith: thread)
message.save(with: transaction)
DispatchQueue.main.async { message.touch() } // FIXME: Hack for a thread updating issue
return message.uniqueId!

@ -1,7 +1,7 @@
public extension TSIncomingMessage {
static func from(_ visibleMessage: VisibleMessage, withQuotedMessage quotedMessage: TSQuotedMessage?, associatedWith thread: TSThread) -> TSIncomingMessage {
static func from(_ visibleMessage: VisibleMessage, quotedMessage: TSQuotedMessage?, linkPreview: OWSLinkPreview?, associatedWith thread: TSThread) -> TSIncomingMessage {
let sender = visibleMessage.sender!
var expiration: UInt32 = 0
Storage.read { transaction in
@ -16,7 +16,7 @@ public extension TSIncomingMessage {
attachmentIds: visibleMessage.attachmentIDs,
expiresInSeconds: expiration,
quotedMessage: quotedMessage,
linkPreview: OWSLinkPreview.from(visibleMessage.linkPreview),
linkPreview: linkPreview,
serverTimestamp: nil,
wasReceivedByUD: true
)

@ -6,37 +6,49 @@ public extension VisibleMessage {
class LinkPreview : NSObject, NSCoding {
public var title: String?
public var url: String?
public var attachmentID: String?
public var isValid: Bool { title != nil && url != nil }
public var isValid: Bool { title != nil && url != nil && attachmentID != nil }
internal init(title: String?, url: String) {
internal init(title: String?, url: String, attachmentID: String?) {
self.title = title
self.url = url
self.attachmentID = attachmentID
}
public required init?(coder: NSCoder) {
if let title = coder.decodeObject(forKey: "title") as! String? { self.title = title }
if let url = coder.decodeObject(forKey: "urlString") as! String? { self.url = url }
if let attachmentID = coder.decodeObject(forKey: "attachmentID") as! String? { self.attachmentID = attachmentID }
}
public func encode(with coder: NSCoder) {
coder.encode(title, forKey: "title")
coder.encode(url, forKey: "urlString")
coder.encode(attachmentID, forKey: "attachmentID")
}
public static func fromProto(_ proto: SNProtoDataMessagePreview) -> LinkPreview? {
let title = proto.title
let url = proto.url
return LinkPreview(title: title, url: url)
return LinkPreview(title: title, url: url, attachmentID: nil)
}
public func toProto() -> SNProtoDataMessagePreview? {
preconditionFailure("Use toProto(using:) instead.")
}
public func toProto(using transaction: YapDatabaseReadWriteTransaction) -> SNProtoDataMessagePreview? {
guard let url = url else {
SNLog("Couldn't construct link preview proto from: \(self).")
return nil
}
let linkPreviewProto = SNProtoDataMessagePreview.builder(url: url)
if let title = title { linkPreviewProto.setTitle(title) }
if let attachmentID = attachmentID, let stream = TSAttachmentStream.fetch(uniqueId: attachmentID, transaction: transaction),
let attachmentProto = stream.buildProto() {
linkPreviewProto.setImage(attachmentProto)
}
do {
return try linkPreviewProto.build()
} catch {

@ -60,17 +60,27 @@ public final class VisibleMessage : Message {
public func toProto(using transaction: YapDatabaseReadWriteTransaction) -> SNProtoContent? {
let proto = SNProtoContent.builder()
var attachmentIDs = self.attachmentIDs
let dataMessage: SNProtoDataMessage.SNProtoDataMessageBuilder
// Profile
if let profile = profile, let profileProto = profile.toProto() {
dataMessage = profileProto.asBuilder()
} else {
dataMessage = SNProtoDataMessage.builder()
}
// Text
if let text = text { dataMessage.setBody(text) }
var attachmentIDs = self.attachmentIDs
// Quote
if let quotedAttachmentID = quote?.attachmentID, let index = attachmentIDs.firstIndex(of: quotedAttachmentID) {
attachmentIDs.remove(at: index)
}
if let quote = quote, let quoteProto = quote.toProto(using: transaction) { dataMessage.setQuote(quoteProto) }
// Link preview
if let linkPreviewAttachmentID = linkPreview?.attachmentID, let index = attachmentIDs.firstIndex(of: linkPreviewAttachmentID) {
attachmentIDs.remove(at: index)
}
if let linkPreview = linkPreview, let linkPreviewProto = linkPreview.toProto(using: transaction) { dataMessage.setPreview([ linkPreviewProto ]) }
// Attachments
let attachments = attachmentIDs.compactMap { TSAttachmentStream.fetch(uniqueId: $0, transaction: transaction) }
if !attachments.allSatisfy({ $0.isUploaded }) {
#if DEBUG
@ -79,9 +89,8 @@ public final class VisibleMessage : Message {
}
let attachmentProtos = attachments.compactMap { $0.buildProto() }
dataMessage.setAttachments(attachmentProtos)
if let quote = quote, let quoteProto = quote.toProto(using: transaction) { dataMessage.setQuote(quoteProto) }
if let linkPreview = linkPreview, let linkPreviewProto = linkPreview.toProto() { dataMessage.setPreview([ linkPreviewProto ]) }
// TODO: Contact
// Build
do {
proto.setDataMessage(try dataMessage.build())
return try proto.build()

@ -2,6 +2,21 @@
extension OWSLinkPreview {
public static func from(_ linkPreview: VisibleMessage.LinkPreview?) -> OWSLinkPreview? {
return nil // TODO: Implement
guard let linkPreview = linkPreview else { return nil }
return OWSLinkPreview(urlString: linkPreview.url!, title: linkPreview.title, imageAttachmentId: linkPreview.attachmentID)
}
}
extension VisibleMessage.LinkPreview {
@objc(from:using:)
public static func from(_ linkPreview: OWSLinkPreviewDraft?, using transaction: YapDatabaseReadWriteTransaction) -> VisibleMessage.LinkPreview? {
guard let linkPreview = linkPreview else { return nil }
do {
let linkPreview = try OWSLinkPreview.buildValidatedLinkPreview(fromInfo: linkPreview, transaction: transaction)
return VisibleMessage.LinkPreview(title: linkPreview.title, url: linkPreview.urlString!, attachmentID: linkPreview.imageAttachmentId)
} catch {
return nil
}
}
}

@ -167,8 +167,17 @@ extension MessageReceiver {
attachmentIDs.append(id)
}
}
// Parse link preview if needed
var owsLinkPreview: OWSLinkPreview?
if message.linkPreview != nil && proto.dataMessage?.preview.isEmpty == false {
owsLinkPreview = try? OWSLinkPreview.buildValidatedLinkPreview(dataMessage: proto.dataMessage!, body: message.text, transaction: transaction)
if let id = owsLinkPreview?.imageAttachmentId {
attachmentIDs.append(id)
}
}
// Persist the message
guard let tsIncomingMessageID = storage.persist(message, withQuotedMessage: tsQuotedMessage, groupPublicKey: message.groupPublicKey, using: transaction) else { throw Error.noThread }
guard let tsIncomingMessageID = storage.persist(message, quotedMessage: tsQuotedMessage, linkPreview: owsLinkPreview,
groupPublicKey: message.groupPublicKey, using: transaction) else { throw Error.noThread }
message.threadID = threadID
// Start attachment downloads if needed
storage.withAsync({ transaction in

@ -76,7 +76,7 @@ public protocol SessionMessagingKitStorageProtocol {
/// Returns the ID of the thread.
func getOrCreateThread(for publicKey: String, groupPublicKey: String?, using transaction: Any) -> String?
/// Returns the ID of the `TSIncomingMessage` that was constructed.
func persist(_ message: VisibleMessage, withQuotedMessage quotedMessage: TSQuotedMessage?, groupPublicKey: String?, using transaction: Any) -> String?
func persist(_ message: VisibleMessage, quotedMessage: TSQuotedMessage?, linkPreview: OWSLinkPreview?, groupPublicKey: String?, using transaction: Any) -> String?
/// Returns the IDs of the saved attachments.
func persist(_ attachments: [VisibleMessage.Attachment], using transaction: Any) -> [String]
/// Also touches the associated message.

@ -21,12 +21,15 @@ extension MessageSender : SharedSenderKeysDelegate {
stream.save(with: transaction)
}
tsMessage.quotedMessage?.createThumbnailAttachmentsIfNecessary(with: transaction)
if let linkPreviewAttachmentID = tsMessage.linkPreview?.imageAttachmentId,
let stream = TSAttachment.fetch(uniqueId: linkPreviewAttachmentID, transaction: transaction) as? TSAttachmentStream {
var linkPreviewAttachmentID: String?
if let id = tsMessage.linkPreview?.imageAttachmentId,
let stream = TSAttachment.fetch(uniqueId: id, transaction: transaction) as? TSAttachmentStream {
linkPreviewAttachmentID = id
streams.append(stream)
}
message.attachmentIDs = streams.map { $0.uniqueId! }
tsMessage.attachmentIds.addObjects(from: message.attachmentIDs)
if let id = linkPreviewAttachmentID { tsMessage.attachmentIds.remove(id) }
tsMessage.save(with: transaction)
}

Loading…
Cancel
Save