|  |  |  | import SessionUtilitiesKit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public extension VisibleMessage { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @objc(SNQuote) | 
					
						
							|  |  |  |     class Quote : NSObject, NSCoding { | 
					
						
							|  |  |  |         public var timestamp: UInt64? | 
					
						
							|  |  |  |         public var publicKey: String? | 
					
						
							|  |  |  |         public var text: String? | 
					
						
							|  |  |  |         public var attachmentID: String? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public var isValid: Bool { timestamp != nil && publicKey != nil } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public override init() { super.init() } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         internal init(timestamp: UInt64, publicKey: String, text: String?, attachmentID: String?) { | 
					
						
							|  |  |  |             self.timestamp = timestamp | 
					
						
							|  |  |  |             self.publicKey = publicKey | 
					
						
							|  |  |  |             self.text = text | 
					
						
							|  |  |  |             self.attachmentID = attachmentID | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public required init?(coder: NSCoder) { | 
					
						
							|  |  |  |             if let timestamp = coder.decodeObject(forKey: "timestamp") as! UInt64? { self.timestamp = timestamp } | 
					
						
							|  |  |  |             if let publicKey = coder.decodeObject(forKey: "authorId") as! String? { self.publicKey = publicKey } | 
					
						
							|  |  |  |             if let text = coder.decodeObject(forKey: "body") as! String? { self.text = text } | 
					
						
							|  |  |  |             if let attachmentID = coder.decodeObject(forKey: "attachmentID") as! String? { self.attachmentID = attachmentID } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public func encode(with coder: NSCoder) { | 
					
						
							|  |  |  |             coder.encode(timestamp, forKey: "timestamp") | 
					
						
							|  |  |  |             coder.encode(publicKey, forKey: "authorId") | 
					
						
							|  |  |  |             coder.encode(text, forKey: "body") | 
					
						
							|  |  |  |             coder.encode(attachmentID, forKey: "attachmentID") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public static func fromProto(_ proto: SNProtoDataMessageQuote) -> Quote? { | 
					
						
							|  |  |  |             let timestamp = proto.id | 
					
						
							|  |  |  |             let publicKey = proto.author | 
					
						
							|  |  |  |             let text = proto.text | 
					
						
							|  |  |  |             return Quote(timestamp: timestamp, publicKey: publicKey, text: text, attachmentID: nil) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public func toProto() -> SNProtoDataMessageQuote? { | 
					
						
							|  |  |  |             preconditionFailure("Use toProto(using:) instead.") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public func toProto(using transaction: YapDatabaseReadWriteTransaction) -> 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(to: quoteProto, using: transaction) | 
					
						
							|  |  |  |             do { | 
					
						
							|  |  |  |                 return try quoteProto.build() | 
					
						
							|  |  |  |             } catch { | 
					
						
							|  |  |  |                 SNLog("Couldn't construct quote proto from: \(self).") | 
					
						
							|  |  |  |                 return nil | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private func addAttachmentsIfNeeded(to quoteProto: SNProtoDataMessageQuote.SNProtoDataMessageQuoteBuilder, using transaction: YapDatabaseReadWriteTransaction) { | 
					
						
							|  |  |  |             guard let attachmentID = attachmentID else { return } | 
					
						
							|  |  |  |             guard let stream = TSAttachment.fetch(uniqueId: attachmentID, transaction: transaction) as? TSAttachmentStream, stream.isUploaded else { | 
					
						
							|  |  |  |                 #if DEBUG | 
					
						
							|  |  |  |                 preconditionFailure("Sending a message before all associated attachments have been uploaded.") | 
					
						
							|  |  |  |                 #else | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |                 #endif | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             let quotedAttachmentProto = SNProtoDataMessageQuoteQuotedAttachment.builder() | 
					
						
							|  |  |  |             quotedAttachmentProto.setContentType(stream.contentType) | 
					
						
							|  |  |  |             if let fileName = stream.sourceFilename { quotedAttachmentProto.setFileName(fileName) } | 
					
						
							|  |  |  |             guard let attachmentProto = stream.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 override var description: String { | 
					
						
							|  |  |  |             """
 | 
					
						
							|  |  |  |             Quote( | 
					
						
							|  |  |  |                 timestamp: \(timestamp?.description ?? "null"), | 
					
						
							|  |  |  |                 publicKey: \(publicKey ?? "null"), | 
					
						
							|  |  |  |                 text: \(text ?? "null"), | 
					
						
							|  |  |  |                 attachmentID: \(attachmentID ?? "null") | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             """
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |