@@ -58,7 +58,110 @@ extension ChatControllerImpl {
5858 return
5959 }
6060
61- var richTextDraft : ( document: RichTextAttachmentScreen . Document ? , media: [ String : Media ] , emojiFiles: [ Int64 : TelegramMediaFile ] ) ?
61+ struct RichTextDraft : Codable {
62+ enum LoadError : Error {
63+ case generic
64+ }
65+
66+ private enum CodingKeys : String , CodingKey {
67+ case document
68+ case mediaKeys
69+ case mediaValues
70+ case emojiFilesKeys
71+ case emojiFilesValues
72+ }
73+
74+ let document : RichTextAttachmentScreen . Document
75+ let media : [ String : Media ]
76+ let emojiFiles : [ Int64 : TelegramMediaFile ]
77+
78+ init ( document: RichTextAttachmentScreen . Document , media: [ String : Media ] , emojiFiles: [ Int64 : TelegramMediaFile ] ) {
79+ self . document = document
80+ self . media = media
81+ self . emojiFiles = emojiFiles
82+ }
83+
84+ init ( from decoder: Decoder ) throws {
85+ let container = try decoder. container ( keyedBy: CodingKeys . self)
86+
87+ let documentData = try container. decode ( Data . self, forKey: . document)
88+ self . document = try JSONDecoder ( ) . decode ( RichTextAttachmentScreen . Document. self, from: documentData)
89+
90+ // `Media`/`TelegramMediaFile` are Postbox-coded (not `Codable`), so each value is stored as a
91+ // self-describing root object (its concrete type is recovered from the embedded type hash).
92+ let mediaKeys = try container. decode ( [ String ] . self, forKey: . mediaKeys)
93+ let mediaValues = try container. decode ( [ Data ] . self, forKey: . mediaValues)
94+ if mediaKeys. count != mediaValues. count {
95+ throw LoadError . generic
96+ }
97+ var media : [ String : Media ] = [ : ]
98+ for i in 0 ..< mediaKeys. count {
99+ guard let mediaValue = PostboxDecoder ( buffer: MemoryBuffer ( data: mediaValues [ i] ) ) . decodeRootObject ( ) as? Media else {
100+ throw LoadError . generic
101+ }
102+ media [ mediaKeys [ i] ] = mediaValue
103+ }
104+ self . media = media
105+
106+ let emojiFilesKeys = try container. decode ( [ Int64 ] . self, forKey: . emojiFilesKeys)
107+ let emojiFilesValues = try container. decode ( [ Data ] . self, forKey: . emojiFilesValues)
108+ if emojiFilesKeys. count != emojiFilesValues. count {
109+ throw LoadError . generic
110+ }
111+ var emojiFiles : [ Int64 : TelegramMediaFile ] = [ : ]
112+ for i in 0 ..< emojiFilesKeys. count {
113+ guard let emojiFileValue = PostboxDecoder ( buffer: MemoryBuffer ( data: emojiFilesValues [ i] ) ) . decodeRootObject ( ) as? TelegramMediaFile else {
114+ throw LoadError . generic
115+ }
116+ emojiFiles [ emojiFilesKeys [ i] ] = emojiFileValue
117+ }
118+ self . emojiFiles = emojiFiles
119+ }
120+
121+ func encode( to encoder: Encoder ) throws {
122+ var container = encoder. container ( keyedBy: CodingKeys . self)
123+
124+ let documentData = try JSONEncoder ( ) . encode ( self . document)
125+ try container. encode ( documentData, forKey: . document)
126+
127+ var mediaKeys : [ String ] = [ ]
128+ var mediaValues : [ Data ] = [ ]
129+ for (key, value) in self . media {
130+ let mediaEncoder = PostboxEncoder ( )
131+ mediaEncoder. encodeRootObject ( value)
132+ mediaKeys. append ( key)
133+ mediaValues. append ( mediaEncoder. makeData ( ) )
134+ }
135+ try container. encode ( mediaKeys, forKey: . mediaKeys)
136+ try container. encode ( mediaValues, forKey: . mediaValues)
137+
138+ var emojiFilesKeys : [ Int64 ] = [ ]
139+ var emojiFilesValues : [ Data ] = [ ]
140+ for (key, value) in self . emojiFiles {
141+ let fileEncoder = PostboxEncoder ( )
142+ fileEncoder. encodeRootObject ( value)
143+ emojiFilesKeys. append ( key)
144+ emojiFilesValues. append ( fileEncoder. makeData ( ) )
145+ }
146+ try container. encode ( emojiFilesKeys, forKey: . emojiFilesKeys)
147+ try container. encode ( emojiFilesValues, forKey: . emojiFilesValues)
148+ }
149+ }
150+
151+ var richTextDraft : RichTextDraft ?
152+
153+ var richTextDraftKey : EngineDataBuffer ?
154+ if let peerId = self . chatLocation. peerId {
155+ let key = EngineDataBuffer ( length: 8 + 8 )
156+ key. setInt64 ( 0 , value: peerId. toInt64 ( ) )
157+ key. setInt64 ( 8 , value: self . chatLocation. threadId ?? 0 )
158+ richTextDraftKey = key
159+ if let entry = await self . context. engine. data. get (
160+ TelegramEngine . EngineData. Item. ItemCache. Item ( collectionId: Namespaces . CachedItemCollection. richTextComposerDrafts, id: key)
161+ ) . get ( ) {
162+ richTextDraft = entry. get ( RichTextDraft . self)
163+ }
164+ }
62165
63166 let context = self . context
64167 let inputIsActive = self . presentationInterfaceState. inputMode == . text
@@ -852,9 +955,11 @@ extension ChatControllerImpl {
852955 return
853956 }
854957
855- //TODO:clear draft in db
856958 richTextDraft = nil
857-
959+ if let richTextDraftKey {
960+ let _ = strongSelf. context. engine. itemCache. remove ( collectionId: Namespaces . CachedItemCollection. richTextComposerDrafts, id: richTextDraftKey) . start ( )
961+ }
962+
858963 let text : String
859964 let attributes : [ EngineMessage . Attribute ]
860965 if sendWithoutFormatting {
@@ -918,8 +1023,11 @@ extension ChatControllerImpl {
9181023 guard let self else {
9191024 return
9201025 }
921- let _ = self
922- richTextDraft = ( document, media, emojiFiles)
1026+ let draft = RichTextDraft ( document: document, media: media, emojiFiles: emojiFiles)
1027+ richTextDraft = draft
1028+ if let richTextDraftKey {
1029+ let _ = self . context. engine. itemCache. put ( collectionId: Namespaces . CachedItemCollection. richTextComposerDrafts, id: richTextDraftKey, item: draft) . start ( )
1030+ }
9231031 } ,
9241032 presentAttachmentMenu: { [ weak self] photoVideoOnly, completion in
9251033 guard let self else {
0 commit comments