2019-11-01 17:11:12 +04:00

295 lines
12 KiB
Swift

import Postbox
private enum RichTextTypes: Int32 {
case empty = 0
case plain = 1
case bold = 2
case italic = 3
case underline = 4
case strikethrough = 5
case fixed = 6
case url = 7
case email = 8
case concat = 9
case `subscript` = 10
case superscript = 11
case marked = 12
case phone = 13
case image = 14
case anchor = 15
}
public indirect enum RichText: PostboxCoding, Equatable {
case empty
case plain(String)
case bold(RichText)
case italic(RichText)
case underline(RichText)
case strikethrough(RichText)
case fixed(RichText)
case url(text: RichText, url: String, webpageId: MediaId?)
case email(text: RichText, email: String)
case concat([RichText])
case `subscript`(RichText)
case superscript(RichText)
case marked(RichText)
case phone(text: RichText, phone: String)
case image(id: MediaId, dimensions: PixelDimensions)
case anchor(text: RichText, name: String)
public init(decoder: PostboxDecoder) {
switch decoder.decodeInt32ForKey("r", orElse: 0) {
case RichTextTypes.empty.rawValue:
self = .empty
case RichTextTypes.plain.rawValue:
self = .plain(decoder.decodeStringForKey("s", orElse: ""))
case RichTextTypes.bold.rawValue:
self = .bold(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case RichTextTypes.italic.rawValue:
self = .italic(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case RichTextTypes.underline.rawValue:
self = .underline(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case RichTextTypes.strikethrough.rawValue:
self = .strikethrough(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case RichTextTypes.fixed.rawValue:
self = .fixed(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case RichTextTypes.url.rawValue:
let webpageIdNamespace: Int32? = decoder.decodeOptionalInt32ForKey("w.n")
let webpageIdId: Int64? = decoder.decodeOptionalInt64ForKey("w.i")
var webpageId: MediaId?
if let webpageIdNamespace = webpageIdNamespace, let webpageIdId = webpageIdId {
webpageId = MediaId(namespace: webpageIdNamespace, id: webpageIdId)
}
self = .url(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, url: decoder.decodeStringForKey("u", orElse: ""), webpageId: webpageId)
case RichTextTypes.email.rawValue:
self = .email(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, email: decoder.decodeStringForKey("e", orElse: ""))
case RichTextTypes.concat.rawValue:
self = .concat(decoder.decodeObjectArrayWithDecoderForKey("a"))
case RichTextTypes.subscript.rawValue:
self = .subscript(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case RichTextTypes.superscript.rawValue:
self = .superscript(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case RichTextTypes.marked.rawValue:
self = .marked(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case RichTextTypes.phone.rawValue:
self = .phone(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, phone: decoder.decodeStringForKey("p", orElse: ""))
case RichTextTypes.image.rawValue:
self = .image(id: MediaId(namespace: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt64ForKey("i.i", orElse: 0)), dimensions: PixelDimensions(width: decoder.decodeInt32ForKey("sw", orElse: 0), height: decoder.decodeInt32ForKey("sh", orElse: 0)))
case RichTextTypes.anchor.rawValue:
self = .anchor(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, name: decoder.decodeStringForKey("n", orElse: ""))
default:
self = .empty
}
}
public func encode(_ encoder: PostboxEncoder) {
switch self {
case .empty:
encoder.encodeInt32(RichTextTypes.empty.rawValue, forKey: "r")
case let .plain(string):
encoder.encodeInt32(RichTextTypes.plain.rawValue, forKey: "r")
encoder.encodeString(string, forKey: "s")
case let .bold(text):
encoder.encodeInt32(RichTextTypes.bold.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
case let .italic(text):
encoder.encodeInt32(RichTextTypes.italic.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
case let .underline(text):
encoder.encodeInt32(RichTextTypes.underline.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
case let .strikethrough(text):
encoder.encodeInt32(RichTextTypes.strikethrough.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
case let .fixed(text):
encoder.encodeInt32(RichTextTypes.fixed.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
case let .url(text, url, webpageId):
encoder.encodeInt32(RichTextTypes.url.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
encoder.encodeString(url, forKey: "u")
if let webpageId = webpageId {
encoder.encodeInt32(webpageId.namespace, forKey: "w.n")
encoder.encodeInt64(webpageId.id, forKey: "w.i")
} else {
encoder.encodeNil(forKey: "w.n")
encoder.encodeNil(forKey: "w.i")
}
case let .email(text, email):
encoder.encodeInt32(RichTextTypes.email.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
encoder.encodeString(email, forKey: "e")
case let .concat(texts):
encoder.encodeInt32(RichTextTypes.concat.rawValue, forKey: "r")
encoder.encodeObjectArray(texts, forKey: "a")
case let .subscript(text):
encoder.encodeInt32(RichTextTypes.subscript.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
case let .superscript(text):
encoder.encodeInt32(RichTextTypes.superscript.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
case let .marked(text):
encoder.encodeInt32(RichTextTypes.marked.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
case let .phone(text, phone):
encoder.encodeInt32(RichTextTypes.phone.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
encoder.encodeString(phone, forKey: "p")
case let .image(id, dimensions):
encoder.encodeInt32(RichTextTypes.image.rawValue, forKey: "r")
encoder.encodeInt32(id.namespace, forKey: "i.n")
encoder.encodeInt64(id.id, forKey: "i.i")
encoder.encodeInt32(Int32(dimensions.width), forKey: "sw")
encoder.encodeInt32(Int32(dimensions.height), forKey: "sh")
case let .anchor(text, name):
encoder.encodeInt32(RichTextTypes.anchor.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
encoder.encodeString(name, forKey: "n")
}
}
public static func ==(lhs: RichText, rhs: RichText) -> Bool {
switch lhs {
case .empty:
if case .empty = rhs {
return true
} else {
return false
}
case let .plain(string):
if case .plain(string) = rhs {
return true
} else {
return false
}
case let .bold(text):
if case .bold(text) = rhs {
return true
} else {
return false
}
case let .italic(text):
if case .italic(text) = rhs {
return true
} else {
return false
}
case let .underline(text):
if case .underline(text) = rhs {
return true
} else {
return false
}
case let .strikethrough(text):
if case .strikethrough(text) = rhs {
return true
} else {
return false
}
case let .fixed(text):
if case .fixed(text) = rhs {
return true
} else {
return false
}
case let .url(lhsText, lhsUrl, lhsWebpageId):
if case let .url(rhsText, rhsUrl, rhsWebpageId) = rhs, lhsText == rhsText && lhsUrl == rhsUrl && lhsWebpageId == rhsWebpageId {
return true
} else {
return false
}
case let .email(text, email):
if case .email(text, email) = rhs {
return true
} else {
return false
}
case let .concat(lhsTexts):
if case let .concat(rhsTexts) = rhs, lhsTexts == rhsTexts {
return true
} else {
return false
}
case let .subscript(text):
if case .subscript(text) = rhs {
return true
} else {
return false
}
case let .superscript(text):
if case .superscript(text) = rhs {
return true
} else {
return false
}
case let .marked(text):
if case .marked(text) = rhs {
return true
} else {
return false
}
case let .phone(text, phone):
if case .phone(text, phone) = rhs {
return true
} else {
return false
}
case let .image(id, dimensions):
if case .image(id, dimensions) = rhs {
return true
} else {
return false
}
case let .anchor(text, name):
if case .anchor(text, name) = rhs {
return true
} else {
return false
}
}
}
}
public extension RichText {
var plainText: String {
switch self {
case .empty:
return ""
case let .plain(string):
return string
case let .bold(text):
return text.plainText
case let .italic(text):
return text.plainText
case let .underline(text):
return text.plainText
case let .strikethrough(text):
return text.plainText
case let .fixed(text):
return text.plainText
case let .url(text, _, _):
return text.plainText
case let .email(text, _):
return text.plainText
case let .concat(texts):
var string = ""
for text in texts {
string += text.plainText
}
return string
case let .subscript(text):
return text.plainText
case let .superscript(text):
return text.plainText
case let .marked(text):
return text.plainText
case let .phone(text, _):
return text.plainText
case .image:
return ""
case let .anchor(text, _):
return text.plainText
}
}
}