From cc9ae629ece361d1684d4bf89b76b09afe6d3c77 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 20 Jul 2018 13:06:38 +0300 Subject: [PATCH] no message --- Postbox/Coding.swift | 18 ++ Postbox/MediaBox.swift | 346 +----------------------------- Postbox/MediaBoxFile.swift | 16 +- Postbox/MediaResource.swift | 13 ++ Postbox/MessageHistoryTable.swift | 22 +- 5 files changed, 70 insertions(+), 345 deletions(-) diff --git a/Postbox/Coding.swift b/Postbox/Coding.swift index c9238a6334..ff3091c278 100644 --- a/Postbox/Coding.swift +++ b/Postbox/Coding.swift @@ -892,6 +892,24 @@ public final class PostboxDecoder { } } + public func decodeAnyObjectForKey(_ key: StaticString, decoder: (PostboxDecoder) -> Any?) -> Any? { + if PostboxDecoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Object) { + var typeHash: Int32 = 0 + memcpy(&typeHash, self.buffer.memory + self.offset, 4) + self.offset += 4 + + var length: Int32 = 0 + memcpy(&length, self.buffer.memory + self.offset, 4) + + let innerDecoder = PostboxDecoder(buffer: ReadBuffer(memory: self.buffer.memory + (self.offset + 4), length: Int(length), freeWhenDone: false)) + self.offset += 4 + Int(length) + + return decoder(innerDecoder) + } else { + return nil + } + } + public func decodeObjectForKeyThrowing(_ key: StaticString, decoder: (PostboxDecoder) throws -> Any) throws -> Any? { if PostboxDecoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Object) { var typeHash: Int32 = 0 diff --git a/Postbox/MediaBox.swift b/Postbox/MediaBox.swift index 670b8d5acf..5cc494fabd 100644 --- a/Postbox/MediaBox.swift +++ b/Postbox/MediaBox.swift @@ -117,8 +117,8 @@ public final class MediaBox { private var fileContexts: [WrappedMediaResourceId: MediaBoxFileContext] = [:] - private var wrappedFetchResource = Promise<(MediaResource, Signal, MediaResourceFetchTag?) -> Signal>() - public var fetchResource: ((MediaResource, Signal, MediaResourceFetchTag?) -> Signal)? { + private var wrappedFetchResource = Promise<(MediaResource, Signal, MediaResourceFetchParameters?) -> Signal>() + public var fetchResource: ((MediaResource, Signal, MediaResourceFetchParameters?) -> Signal)? { didSet { if let fetchResource = self.fetchResource { wrappedFetchResource.set(.single(fetchResource)) @@ -224,6 +224,7 @@ public final class MediaBox { let statusQueue = self.statusQueue self.dataQueue.async { if let fileContext = self.fileContext(for: resource) { + //let reference = fileContext.addReference() statusUpdateDisposable.set(fileContext.status(next: { [weak statusContext] value in statusQueue.async { if let current = self.statusContexts[resourceId], current === statusContext, current.status != value { @@ -454,7 +455,7 @@ public final class MediaBox { } } - public func fetchedResourceData(_ resource: MediaResource, in range: Range, tag: MediaResourceFetchTag?) -> Signal { + public func fetchedResourceData(_ resource: MediaResource, in range: Range, parameters: MediaResourceFetchParameters?) -> Signal { return Signal { subscriber in let disposable = MetaDisposable() @@ -464,7 +465,7 @@ public final class MediaBox { let fetchResource = self.wrappedFetchResource.get() let fetchedDisposable = fileContext?.fetched(range: Int32(range.lowerBound) ..< Int32(range.upperBound), fetch: { ranges in return fetchResource |> mapToSignal { fetch in - return fetch(resource, ranges, tag) + return fetch(resource, ranges, parameters) } }, completed: { subscriber.putCompletion() @@ -536,7 +537,7 @@ public final class MediaBox { } } - public func fetchedResource(_ resource: MediaResource, tag: MediaResourceFetchTag?, implNext: Bool = false) -> Signal { + public func fetchedResource(_ resource: MediaResource, parameters: MediaResourceFetchParameters?, implNext: Bool = false) -> Signal { return Signal { subscriber in let disposable = MetaDisposable() @@ -553,7 +554,7 @@ public final class MediaBox { let fetchResource = self.wrappedFetchResource.get() let fetchedDisposable = fileContext.fetchedFullRange(fetch: { ranges in return fetchResource |> mapToSignal { fetch in - return fetch(resource, ranges, tag) + return fetch(resource, ranges, parameters) } }, completed: { if implNext { @@ -563,318 +564,6 @@ public final class MediaBox { }) disposable.set(fetchedDisposable) } - /* - let currentSize = fileSize(paths.partial) ?? 0 - let dataContext: ResourceDataContext - if let current = self.dataContexts[resourceId] { - dataContext = current - } else { - dataContext = ResourceDataContext(data: MediaResourceData(path: paths.partial, offset: 0, size: currentSize, complete: false)) - self.dataContexts[resourceId] = dataContext - } - - let index: Bag.Index = dataContext.fetchSubscribers.add(Void()) - - if dataContext.fetchDisposable == nil { - let status: MediaResourceStatus - if let resourceSize = resource.size { - status = .Fetching(isActive: true, progress: Float(currentSize) / Float(resourceSize)) - } else { - status = .Fetching(isActive: true, progress: 0.0) - } - self.statusQueue.async { - if let statusContext = self.statusContexts[resourceId] { - statusContext.status = status - for subscriber in statusContext.subscribers.copyItems() { - subscriber(status) - } - } - } - - var offset = currentSize - let file = Atomic(value: nil) - let dataQueue = self.dataQueue - dataContext.fetchDisposable = ((self.wrappedFetchResource.get() |> take(1) |> mapToSignal { fetch -> Signal in - var ranges = IndexSet() - ranges.insert(integersIn: currentSize ..< Int.max) - return fetch(resource, .single(ranges), tag) - }) |> afterDisposed { - dataQueue.async { - let _ = file.modify { current in - return nil - } - } - }).start(next: { resultOption in - self.dataQueue.async { - let _ = self.ensureDirectoryCreated - - switch resultOption { - case .resourceSizeUpdated: - break - case let .dataPart(_, data, dataRange, complete): - var currentFile: ManagedFile? - let _ = file.modify { current in - if let current = current { - currentFile = current - return current - } else { - let newFile = ManagedFile(queue: self.dataQueue, path: paths.partial, mode: .append) - currentFile = newFile - return newFile - } - } - - if let currentFile = currentFile { - if !dataRange.isEmpty { - let writeResult = data.withUnsafeBytes { bytes -> Int in - return currentFile.write(bytes.advanced(by: dataRange.lowerBound), count: dataRange.count) - } - if writeResult != dataRange.count { - assertionFailure("write error \(errno)") - } - } - - offset += dataRange.count - let updatedSize = offset - - let updatedData: MediaResourceData - if complete { - let linkResult = link(paths.partial, paths.complete) - //assert(linkResult == 0) - updatedData = MediaResourceData(path: paths.complete, offset: 0, size: updatedSize, complete: true) - } else { - updatedData = MediaResourceData(path: paths.partial, offset: 0, size: updatedSize, complete: false) - } - - dataContext.data = updatedData - - let hadProcessedFetch = dataContext.processedFetch - dataContext.processedFetch = true - - for (_, subscriber) in dataContext.progresiveDataSubscribers.copyItems() { - subscriber(updatedData) - } - - if updatedData.complete { - for (_, subscriber) in dataContext.completeDataSubscribers.copyItems() { - subscriber(updatedData) - } - } else if !hadProcessedFetch { - for (waitUntilFetchStatus, subscriber) in dataContext.completeDataSubscribers.copyItems() { - if waitUntilFetchStatus { - subscriber(updatedData) - } - } - } - - let status: MediaResourceStatus - if updatedData.complete { - status = .Local - if implNext { - subscriber.putNext(.remote) - } - subscriber.putCompletion() - } else { - if let resourceSize = resource.size { - status = .Fetching(isActive: true, progress: Float(updatedSize) / Float(resourceSize)) - } else { - status = .Fetching(isActive: true, progress: 0.0) - } - } - - self.statusQueue.async { - if let statusContext = self.statusContexts[resourceId] { - statusContext.status = status - for subscriber in statusContext.subscribers.copyItems() { - subscriber(status) - } - } - } - } - case let .replaceHeader(data, dataRange): - let currentFile = ManagedFile(queue: self.dataQueue, path: paths.partial, mode: .readwrite) - let _ = file.modify { _ in - return nil - } - - if let currentFile = currentFile { - if !dataRange.isEmpty { - currentFile.seek(position: 0) - let writeResult = data.withUnsafeBytes { bytes -> Int in - return currentFile.write(bytes.advanced(by: dataRange.lowerBound), count: dataRange.count) - } - currentFile.seek(position: Int64(offset)) - if writeResult != dataRange.count { - assertionFailure("write error \(errno)") - } - } - } - case .reset: - var currentFile: ManagedFile? - let _ = file.modify { current in - if let current = current { - currentFile = current - return current - } else { - let newFile = ManagedFile(queue: self.dataQueue, path: paths.partial, mode: .append) - currentFile = newFile - return newFile - } - } - - if let currentFile = currentFile { - currentFile.truncate(count: 0) - currentFile.seek(position: 0) - } else { - assertionFailure() - } - - offset = 0 - let updatedSize = offset - - let updatedData: MediaResourceData - updatedData = MediaResourceData(path: paths.partial, offset: 0, size: updatedSize, complete: false) - - dataContext.data = updatedData - - let hadProcessedFetch = dataContext.processedFetch - dataContext.processedFetch = true - - for (_, subscriber) in dataContext.progresiveDataSubscribers.copyItems() { - subscriber(updatedData) - } - - if updatedData.complete { - for (_, subscriber) in dataContext.completeDataSubscribers.copyItems() { - subscriber(updatedData) - } - } else if !hadProcessedFetch { - for (waitUntilFetchStatus, subscriber) in dataContext.completeDataSubscribers.copyItems() { - if waitUntilFetchStatus { - subscriber(updatedData) - } - } - } - - let status: MediaResourceStatus - if updatedData.complete { - status = .Local - } else { - if let resourceSize = resource.size { - status = .Fetching(isActive: true, progress: Float(updatedSize) / Float(resourceSize)) - } else { - status = .Fetching(isActive: true, progress: 0.0) - } - } - - self.statusQueue.async { - if let statusContext = self.statusContexts[resourceId] { - statusContext.status = status - for subscriber in statusContext.subscribers.copyItems() { - subscriber(status) - } - } - } - case let .moveLocalFile(tempPath): - let _ = file.modify { _ in - return nil - } - - unlink(paths.partial) - do { - try FileManager.default.moveItem(atPath: tempPath, toPath: paths.partial) - } catch { - assertionFailure() - } - - guard let offset = fileSize(paths.partial) else { - assertionFailure() - return - } - let updatedSize = offset - - let updatedData: MediaResourceData - let linkResult = link(paths.partial, paths.complete) - assert(linkResult == 0) - updatedData = MediaResourceData(path: paths.complete, offset: 0, size: updatedSize, complete: true) - - dataContext.data = updatedData - - let hadProcessedFetch = dataContext.processedFetch - dataContext.processedFetch = true - - for (_, subscriber) in dataContext.progresiveDataSubscribers.copyItems() { - subscriber(updatedData) - } - - if updatedData.complete { - for (_, subscriber) in dataContext.completeDataSubscribers.copyItems() { - subscriber(updatedData) - } - } else if !hadProcessedFetch { - for (waitUntilFetchStatus, subscriber) in dataContext.completeDataSubscribers.copyItems() { - if waitUntilFetchStatus { - subscriber(updatedData) - } - } - } - - let status: MediaResourceStatus - if updatedData.complete { - status = .Local - } else { - if let resourceSize = resource.size { - status = .Fetching(isActive: true, progress: Float(updatedSize) / Float(resourceSize)) - } else { - status = .Fetching(isActive: true, progress: 0.0) - } - } - - self.statusQueue.async { - if let statusContext = self.statusContexts[resourceId] { - statusContext.status = status - for subscriber in statusContext.subscribers.copyItems() { - subscriber(status) - } - } - } - } - } - }) - } - - disposable.set(ActionDisposable { - self.dataQueue.async { - if let dataContext = self.dataContexts[resourceId] { - dataContext.fetchSubscribers.remove(index) - - if dataContext.fetchSubscribers.isEmpty { - dataContext.fetchDisposable?.dispose() - dataContext.fetchDisposable = nil - - let status: MediaResourceStatus - if dataContext.data.complete { - status = .Local - } else { - status = .Remote - } - - self.statusQueue.async { - if let statusContext = self.statusContexts[resourceId], statusContext.status != status { - statusContext.status = status - for subscriber in statusContext.subscribers.copyItems() { - subscriber(status) - } - } - } - } - - if dataContext.completeDataSubscribers.isEmpty && dataContext.progresiveDataSubscribers.isEmpty && dataContext.fetchSubscribers.isEmpty { - self.dataContexts.removeValue(forKey: resourceId) - } - } - } - })*/ } } @@ -887,27 +576,6 @@ public final class MediaBox { if let fileContext = self.fileContext(for: resource) { fileContext.cancelFullRangeFetches() } - /*let resourceId = WrappedMediaResourceId(resource.id) - if let dataContext = self.dataContexts[resourceId], dataContext.fetchDisposable != nil { - dataContext.fetchDisposable?.dispose() - dataContext.fetchDisposable = nil - - let status: MediaResourceStatus - if dataContext.data.complete { - status = .Local - } else { - status = .Remote - } - - self.statusQueue.async { - if let statusContext = self.statusContexts[resourceId], statusContext.status != status { - statusContext.status = status - for subscriber in statusContext.subscribers.copyItems() { - subscriber(status) - } - } - } - }*/ } } diff --git a/Postbox/MediaBoxFile.swift b/Postbox/MediaBoxFile.swift index 7c08e76123..517e7ffbc6 100644 --- a/Postbox/MediaBoxFile.swift +++ b/Postbox/MediaBoxFile.swift @@ -294,7 +294,7 @@ final class MediaBoxPartialFile { } self.statusRequests.removeAll() - self.completed(self.fileMap.sum) + self.completed(Int32(size)) } else { assertionFailure() } @@ -740,6 +740,12 @@ final class MediaBoxFileContext { private var content: MediaBoxFileContent + private let references = CounterBag() + + var isEmpty: Bool { + return self.references.isEmpty + } + init?(queue: Queue, path: String, partialPath: String) { assert(queue.isCurrent()) @@ -770,6 +776,14 @@ final class MediaBoxFileContext { assert(self.queue.isCurrent()) } + func addReference() -> Int { + return self.references.add() + } + + func removeReference(_ index: Int) { + self.references.remove(index) + } + func data(range: Range, waitUntilAfterInitialFetch: Bool, next: @escaping (MediaResourceData) -> Void) -> Disposable { switch self.content { case let .complete(path, size): diff --git a/Postbox/MediaResource.swift b/Postbox/MediaResource.swift index 4a4983f0be..2aa8ea119b 100644 --- a/Postbox/MediaResource.swift +++ b/Postbox/MediaResource.swift @@ -54,3 +54,16 @@ public protocol CachedMediaResourceRepresentation { public protocol MediaResourceFetchTag { } + +public protocol MediaResourceFetchInfo { +} + +public struct MediaResourceFetchParameters { + public let tag: MediaResourceFetchTag? + public let info: MediaResourceFetchInfo? + + public init(tag: MediaResourceFetchTag?, info: MediaResourceFetchInfo?) { + self.tag = tag + self.info = info + } +} diff --git a/Postbox/MessageHistoryTable.swift b/Postbox/MessageHistoryTable.swift index b2cbf72f80..d3d96fae8e 100644 --- a/Postbox/MessageHistoryTable.swift +++ b/Postbox/MessageHistoryTable.swift @@ -572,7 +572,7 @@ final class MessageHistoryTable: Table { processIndexOperationsCommitAccumulatedRemoveIndices(peerId: peerId, accumulatedRemoveIndices: &accumulatedRemoveIndices, updatedCombinedState: &updatedCombinedState, invalidateReadState: &invalidateReadState, unsentMessageOperations: &unsentMessageOperations, outputOperations: &outputOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations) var updatedGroupInfos: [MessageId: MessageGroupInfo] = [:] - if let (message, previousTags) = self.justUpdate(index, message: storeMessage, sharedKey: sharedKey, sharedBuffer: sharedBuffer, sharedEncoder: sharedEncoder, unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations) { + if let (message, previousTags) = self.justUpdate(index, message: storeMessage, sharedKey: sharedKey, sharedBuffer: sharedBuffer, sharedEncoder: sharedEncoder, unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations, updatedMedia: &updatedMedia) { outputOperations.append(.Remove([(index, true, previousTags)])) outputOperations.append(.InsertMessage(message)) if !updatedGroupInfos.isEmpty { @@ -591,7 +591,7 @@ final class MessageHistoryTable: Table { processIndexOperationsCommitAccumulatedRemoveIndices(peerId: peerId, accumulatedRemoveIndices: &accumulatedRemoveIndices, updatedCombinedState: &updatedCombinedState, invalidateReadState: &invalidateReadState, unsentMessageOperations: &unsentMessageOperations, outputOperations: &outputOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations) var updatedGroupInfos: [MessageId: MessageGroupInfo] = [:] - let tagsAndGlobalTags = self.justUpdateTimestamp(index, timestamp: timestamp, unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations) + let tagsAndGlobalTags = self.justUpdateTimestamp(index, timestamp: timestamp, unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations, updatedMedia: &updatedMedia) outputOperations.append(.UpdateTimestamp(index, timestamp)) if !updatedGroupInfos.isEmpty { outputOperations.append(.UpdateGroupInfos(updatedGroupInfos)) @@ -1628,8 +1628,10 @@ final class MessageHistoryTable: Table { }) } - private func justUpdate(_ index: MessageIndex, message: InternalStoreMessage, sharedKey: ValueBoxKey, sharedBuffer: WriteBuffer, sharedEncoder: PostboxEncoder, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], updatedGroupInfos: inout [MessageId: MessageGroupInfo], groupFeedOperations: inout [PeerGroupId : [GroupFeedIndexOperation]], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) -> (IntermediateMessage, MessageTags)? { + private func justUpdate(_ index: MessageIndex, message: InternalStoreMessage, sharedKey: ValueBoxKey, sharedBuffer: WriteBuffer, sharedEncoder: PostboxEncoder, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], updatedGroupInfos: inout [MessageId: MessageGroupInfo], groupFeedOperations: inout [PeerGroupId : [GroupFeedIndexOperation]], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: inout [MediaId: Media?]) -> (IntermediateMessage, MessageTags)? { if let previousMessage = self.getMessage(index) { + var mediaToUpdate: [Media] = [] + var previousEmbeddedMediaWithIds: [(MediaId, Media)] = [] if previousMessage.embeddedMediaData.length > 4 { var embeddedMediaCount: Int32 = 0 @@ -1898,6 +1900,9 @@ final class MessageHistoryTable: Table { embeddedMedia.append(media) case .Reference: referencedMedia.append(mediaId) + if let currentMedia = self.messageMediaTable.get(mediaId, embedded: { _, _ in nil }), !currentMedia.isEqual(media) { + mediaToUpdate.append(media) + } } } else { embeddedMedia.append(media) @@ -1942,6 +1947,13 @@ final class MessageHistoryTable: Table { } } + for media in mediaToUpdate { + if let id = media.id { + var operationsByPeerId: [PeerId: [MessageHistoryOperation]] = [:] + self.updateMedia(id, media: media, operationsByPeerId: &operationsByPeerId, updatedMedia: &updatedMedia) + } + } + return result } else { return nil @@ -1962,7 +1974,7 @@ final class MessageHistoryTable: Table { } } - private func justUpdateTimestamp(_ index: MessageIndex, timestamp: Int32, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], updatedGroupInfos: inout [MessageId: MessageGroupInfo], groupFeedOperations: inout [PeerGroupId : [GroupFeedIndexOperation]], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) -> (MessageTags, GlobalMessageTags)? { + private func justUpdateTimestamp(_ index: MessageIndex, timestamp: Int32, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], updatedGroupInfos: inout [MessageId: MessageGroupInfo], groupFeedOperations: inout [PeerGroupId : [GroupFeedIndexOperation]], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: inout [MediaId: Media?]) -> (MessageTags, GlobalMessageTags)? { if let previousMessage = self.getMessage(index) { var storeForwardInfo: StoreMessageForwardInfo? if let forwardInfo = previousMessage.forwardInfo { @@ -2010,7 +2022,7 @@ final class MessageHistoryTable: Table { let updatedIndex = MessageIndex(id: index.id, timestamp: timestamp) - let _ = self.justUpdate(index, message: InternalStoreMessage(id: previousMessage.id, timestamp: timestamp, globallyUniqueId: previousMessage.globallyUniqueId, groupingKey: previousMessage.groupingKey, flags: StoreMessageFlags(previousMessage.flags), tags: previousMessage.tags, globalTags: previousMessage.globalTags, localTags: previousMessage.localTags, forwardInfo: storeForwardInfo, authorId: previousMessage.authorId, text: previousMessage.text, attributes: parsedAttributes, media: parsedMedia), sharedKey: self.key(updatedIndex), sharedBuffer: WriteBuffer(), sharedEncoder: PostboxEncoder(), unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations) + let _ = self.justUpdate(index, message: InternalStoreMessage(id: previousMessage.id, timestamp: timestamp, globallyUniqueId: previousMessage.globallyUniqueId, groupingKey: previousMessage.groupingKey, flags: StoreMessageFlags(previousMessage.flags), tags: previousMessage.tags, globalTags: previousMessage.globalTags, localTags: previousMessage.localTags, forwardInfo: storeForwardInfo, authorId: previousMessage.authorId, text: previousMessage.text, attributes: parsedAttributes, media: parsedMedia), sharedKey: self.key(updatedIndex), sharedBuffer: WriteBuffer(), sharedEncoder: PostboxEncoder(), unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations, updatedMedia: &updatedMedia) return (previousMessage.tags, previousMessage.globalTags)