no message

This commit is contained in:
Peter 2018-07-20 13:06:38 +03:00
parent ec83f35663
commit cc9ae629ec
5 changed files with 70 additions and 345 deletions

View File

@ -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

View File

@ -117,8 +117,8 @@ public final class MediaBox {
private var fileContexts: [WrappedMediaResourceId: MediaBoxFileContext] = [:]
private var wrappedFetchResource = Promise<(MediaResource, Signal<IndexSet, NoError>, MediaResourceFetchTag?) -> Signal<MediaResourceDataFetchResult, NoError>>()
public var fetchResource: ((MediaResource, Signal<IndexSet, NoError>, MediaResourceFetchTag?) -> Signal<MediaResourceDataFetchResult, NoError>)? {
private var wrappedFetchResource = Promise<(MediaResource, Signal<IndexSet, NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, NoError>>()
public var fetchResource: ((MediaResource, Signal<IndexSet, NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, NoError>)? {
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<Int>, tag: MediaResourceFetchTag?) -> Signal<Void, NoError> {
public func fetchedResourceData(_ resource: MediaResource, in range: Range<Int>, parameters: MediaResourceFetchParameters?) -> Signal<Void, NoError> {
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<FetchResourceSourceType, NoError> {
public func fetchedResource(_ resource: MediaResource, parameters: MediaResourceFetchParameters?, implNext: Bool = false) -> Signal<FetchResourceSourceType, NoError> {
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<Void>.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<ManagedFile?>(value: nil)
let dataQueue = self.dataQueue
dataContext.fetchDisposable = ((self.wrappedFetchResource.get() |> take(1) |> mapToSignal { fetch -> Signal<MediaResourceDataFetchResult, NoError> 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)
}
}
}
}*/
}
}

View File

@ -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<Int32>, waitUntilAfterInitialFetch: Bool, next: @escaping (MediaResourceData) -> Void) -> Disposable {
switch self.content {
case let .complete(path, size):

View File

@ -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
}
}

View File

@ -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)