session-ios/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Quote.swift

110 lines
3.8 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtilitiesKit
public extension VisibleMessage {
struct VMQuote: Codable {
public let timestamp: UInt64?
public let publicKey: String?
public let text: String?
public let attachmentId: String?
public var isValid: Bool { timestamp != nil && publicKey != nil }
// MARK: - Initialization
internal init(timestamp: UInt64, publicKey: String, text: String?, attachmentId: String?) {
self.timestamp = timestamp
self.publicKey = publicKey
self.text = text
self.attachmentId = attachmentId
}
// MARK: - Proto Conversion
public static func fromProto(_ proto: SNProtoDataMessageQuote) -> VMQuote? {
return VMQuote(
timestamp: proto.id,
publicKey: proto.author,
text: proto.text,
attachmentId: nil
)
}
public func toProto() -> SNProtoDataMessageQuote? {
preconditionFailure("Use toProto(_:) instead.")
}
public func toProto(_ db: Database) -> SNProtoDataMessageQuote? {
guard let timestamp = timestamp, let publicKey = publicKey else {
SNLog("Couldn't construct quote proto from: \(self).")
return nil
}
let quoteProto = SNProtoDataMessageQuote.builder(id: timestamp, author: publicKey)
if let text = text { quoteProto.setText(text) }
addAttachmentsIfNeeded(db, to: quoteProto)
do {
return try quoteProto.build()
} catch {
SNLog("Couldn't construct quote proto from: \(self).")
return nil
}
}
private func addAttachmentsIfNeeded(_ db: Database, to quoteProto: SNProtoDataMessageQuote.SNProtoDataMessageQuoteBuilder) {
guard let attachmentId = attachmentId else { return }
guard
let attachment: Attachment = try? Attachment.fetchOne(db, id: attachmentId),
attachment.state == .uploaded
else {
#if DEBUG
preconditionFailure("Sending a message before all associated attachments have been uploaded.")
#else
return
#endif
}
let quotedAttachmentProto = SNProtoDataMessageQuoteQuotedAttachment.builder()
quotedAttachmentProto.setContentType(attachment.contentType)
if let fileName = attachment.sourceFilename { quotedAttachmentProto.setFileName(fileName) }
guard let attachmentProto = attachment.buildProto() else {
return SNLog("Ignoring invalid attachment for quoted message.")
}
quotedAttachmentProto.setThumbnail(attachmentProto)
do {
try quoteProto.addAttachments(quotedAttachmentProto.build())
} catch {
SNLog("Couldn't construct quoted attachment proto from: \(self).")
}
}
// MARK: - Description
public var description: String {
"""
Quote(
timestamp: \(timestamp?.description ?? "null"),
publicKey: \(publicKey ?? "null"),
text: \(text ?? "null"),
attachmentId: \(attachmentId ?? "null")
)
"""
}
}
}
// MARK: - Database Type Conversion
public extension VisibleMessage.VMQuote {
static func from(_ db: Database, quote: Quote) -> VisibleMessage.VMQuote {
return VisibleMessage.VMQuote(
timestamp: UInt64(quote.timestampMs),
publicKey: quote.authorId,
text: quote.body,
attachmentId: quote.attachmentId
)
}
}