From fa6e4d5ccc6273aca647c204da1d8a6d9ead2242 Mon Sep 17 00:00:00 2001 From: Divyesh Canopas Date: Tue, 31 Dec 2024 11:20:56 +0530 Subject: [PATCH] Update encoder decoder to match quill structure --- .../Data/Models/RichAttributes.swift | 14 ++- .../Data/Models/RichText.swift | 93 +++++++++++++++---- 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/Sources/RichEditorSwiftUI/Data/Models/RichAttributes.swift b/Sources/RichEditorSwiftUI/Data/Models/RichAttributes.swift index 24e2d6a..70ad0d5 100644 --- a/Sources/RichEditorSwiftUI/Data/Models/RichAttributes.swift +++ b/Sources/RichEditorSwiftUI/Data/Models/RichAttributes.swift @@ -73,7 +73,12 @@ public struct RichAttributes: Codable { case background = "background" case align = "align" case link = "link" - case image = "image" + /** + Commented as it should not be encode as we follow Quill Architecture so in that image is encoded + in ``RichTextSpan.insert`` of span model + + */ + // case image = "image" } public init(from decoder: Decoder) throws { @@ -96,7 +101,12 @@ public struct RichAttributes: Codable { self.align = try values.decodeIfPresent( RichTextAlignment.self, forKey: .align) self.link = try values.decodeIfPresent(String.self, forKey: .link) - self.image = try values.decodeIfPresent(String.self, forKey: .image) + /** + Commented as it should not be decode as we follow Quill Structure so in that image is decoded + in ``RichTextSpan.insert`` of span's json and we add it by copying it + + */ + // self.image = try values.decodeIfPresent(String.self, forKey: .image) } } diff --git a/Sources/RichEditorSwiftUI/Data/Models/RichText.swift b/Sources/RichEditorSwiftUI/Data/Models/RichText.swift index 9d2f669..1683087 100644 --- a/Sources/RichEditorSwiftUI/Data/Models/RichText.swift +++ b/Sources/RichEditorSwiftUI/Data/Models/RichText.swift @@ -10,28 +10,85 @@ import Foundation typealias RichTextSpans = [RichTextSpan] public struct RichText: Codable { - public let spans: [RichTextSpan] + public let spans: [RichTextSpan] - public init(spans: [RichTextSpan] = []) { - self.spans = spans - } + public init(spans: [RichTextSpan] = []) { + self.spans = spans + } - func encodeToData() throws -> Data { - return try JSONEncoder().encode(self) - } + func encodeToData() throws -> Data { + return try JSONEncoder().encode(self) + } } public struct RichTextSpan: Codable { - // public var id: String = UUID().uuidString - public let insert: String - public let attributes: RichAttributes? - - public init( - insert: String, - attributes: RichAttributes? = nil - ) { - // self.id = id - self.insert = insert - self.attributes = attributes + // public var id: String = UUID().uuidString + public let insert: String + public let attributes: RichAttributes? + + public init( + insert: String, + attributes: RichAttributes? = nil + ) { + // self.id = id + self.insert = insert + self.attributes = attributes + } +} + +extension RichTextSpan { + + // Custom Encoding + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + // If there is an image in the attributes, encode insert as an image object + if let image = attributes?.image { + let richTextImage = RichTextImage(image: image) + try container.encode(richTextImage, forKey: .insert) + } else { + // Otherwise, just encode insert as a simple string + try container.encode(insert, forKey: .insert) } + + try container.encodeIfPresent(attributes, forKey: .attributes) + } + + // Custom Decoding + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + var imageAttribute: String? = nil + // Decode insert as a string and extract image form json's insert if available + if let imageDict = try? container.decode([String: String].self, forKey: .insert), + let image = imageDict["image"] + { + self.insert = " " + // If insert contains an image, set insert to the image URL and set the image attribute + imageAttribute = image + } else { + // If insert is just a string, set insert as usual + self.insert = try container.decode(String.self, forKey: .insert) + } + let attributesInit = try container.decodeIfPresent(RichAttributes.self, forKey: .attributes) + self.attributes = attributesInit?.copy(with: .image(imageAttribute), byAdding: true) + + } + + enum CodingKeys: String, CodingKey { + case insert + case attributes + } +} + +internal struct RichTextImage: Codable { + let image: String + + enum CodingKeys: String, CodingKey { + case image = "image" + } + + init(image: String) { + self.image = image + } }