|  |  |  | import CoreGraphics | 
					
						
							|  |  |  | import SessionUtilitiesKit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public extension VisibleMessage { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @objc(SNAttachment) | 
					
						
							|  |  |  |     class Attachment : NSObject, NSCoding { | 
					
						
							|  |  |  |         public var fileName: String? | 
					
						
							|  |  |  |         public var contentType: String? | 
					
						
							|  |  |  |         public var key: Data? | 
					
						
							|  |  |  |         public var digest: Data? | 
					
						
							|  |  |  |         public var kind: Kind? | 
					
						
							|  |  |  |         public var caption: String? | 
					
						
							|  |  |  |         public var size: CGSize? | 
					
						
							|  |  |  |         public var sizeInBytes: UInt? | 
					
						
							|  |  |  |         public var url: String? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public var isValid: Bool { | 
					
						
							|  |  |  |             // key and digest can be nil for open group attachments | 
					
						
							|  |  |  |             contentType != nil && kind != nil && size != nil && sizeInBytes != nil && url != nil | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public enum Kind : String { | 
					
						
							|  |  |  |             case voiceMessage, generic | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public override init() { super.init() } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public required init?(coder: NSCoder) { | 
					
						
							|  |  |  |             if let fileName = coder.decodeObject(forKey: "fileName") as! String? { self.fileName = fileName } | 
					
						
							|  |  |  |             if let contentType = coder.decodeObject(forKey: "contentType") as! String? { self.contentType = contentType } | 
					
						
							|  |  |  |             if let key = coder.decodeObject(forKey: "key") as! Data? { self.key = key } | 
					
						
							|  |  |  |             if let digest = coder.decodeObject(forKey: "digest") as! Data? { self.digest = digest } | 
					
						
							|  |  |  |             if let rawKind = coder.decodeObject(forKey: "kind") as! String? { self.kind = Kind(rawValue: rawKind) } | 
					
						
							|  |  |  |             if let caption = coder.decodeObject(forKey: "caption") as! String? { self.caption = caption } | 
					
						
							|  |  |  |             if let size = coder.decodeObject(forKey: "size") as! CGSize? { self.size = size } | 
					
						
							|  |  |  |             if let sizeInBytes = coder.decodeObject(forKey: "sizeInBytes") as! UInt? { self.sizeInBytes = sizeInBytes } | 
					
						
							|  |  |  |             if let url = coder.decodeObject(forKey: "url") as! String? { self.url = url } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public func encode(with coder: NSCoder) { | 
					
						
							|  |  |  |             coder.encode(fileName, forKey: "fileName") | 
					
						
							|  |  |  |             coder.encode(contentType, forKey: "contentType") | 
					
						
							|  |  |  |             coder.encode(key, forKey: "key") | 
					
						
							|  |  |  |             coder.encode(digest, forKey: "digest") | 
					
						
							|  |  |  |             coder.encode(kind?.rawValue, forKey: "kind") | 
					
						
							|  |  |  |             coder.encode(caption, forKey: "caption") | 
					
						
							|  |  |  |             coder.encode(size, forKey: "size") | 
					
						
							|  |  |  |             coder.encode(sizeInBytes, forKey: "sizeInBytes") | 
					
						
							|  |  |  |             coder.encode(url, forKey: "url") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public static func fromProto(_ proto: SNProtoAttachmentPointer) -> Attachment? { | 
					
						
							|  |  |  |             let result = Attachment() | 
					
						
							|  |  |  |             result.fileName = proto.fileName | 
					
						
							|  |  |  |             func inferContentType() -> String { | 
					
						
							|  |  |  |                 guard let fileName = result.fileName, let fileExtension = URL(string: fileName)?.pathExtension else { return OWSMimeTypeApplicationOctetStream } | 
					
						
							|  |  |  |                 return MIMETypeUtil.mimeType(forFileExtension: fileExtension) ?? OWSMimeTypeApplicationOctetStream | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             result.contentType = proto.contentType ?? inferContentType() | 
					
						
							|  |  |  |             result.key = proto.key | 
					
						
							|  |  |  |             result.digest = proto.digest | 
					
						
							|  |  |  |             let kind: VisibleMessage.Attachment.Kind | 
					
						
							|  |  |  |             if proto.hasFlags && (proto.flags & UInt32(SNProtoAttachmentPointer.SNProtoAttachmentPointerFlags.voiceMessage.rawValue)) > 0 { | 
					
						
							|  |  |  |                 kind = .voiceMessage | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 kind = .generic | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             result.kind = kind | 
					
						
							|  |  |  |             result.caption = proto.hasCaption ? proto.caption : nil | 
					
						
							|  |  |  |             let size: CGSize | 
					
						
							|  |  |  |             if proto.hasWidth && proto.width > 0 && proto.hasHeight && proto.height > 0 { | 
					
						
							|  |  |  |                 size = CGSize(width: Int(proto.width), height: Int(proto.height)) | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 size = CGSize.zero | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             result.size = size | 
					
						
							|  |  |  |             result.sizeInBytes = proto.size > 0 ? UInt(proto.size) : nil | 
					
						
							|  |  |  |             result.url = proto.url | 
					
						
							|  |  |  |             return result | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public func toProto() -> SNProtoDataMessageQuote? { | 
					
						
							|  |  |  |             fatalError("Not implemented.") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |