mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-02-03 18:13:41 +00:00
no message
This commit is contained in:
@@ -132,7 +132,6 @@
|
||||
D0B844051DAB91B5005F29E1 /* MediaBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = D055BD321B7D3D2D00F06C0A /* MediaBox.swift */; };
|
||||
D0B844061DAB91B5005F29E1 /* MediaResourceStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05F09A51C9E9F9300BB6F96 /* MediaResourceStatus.swift */; };
|
||||
D0B844071DAB91B5005F29E1 /* MediaResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0CE63F51CA1CCB2002BC462 /* MediaResource.swift */; };
|
||||
D0B844081DAB91B5005F29E1 /* CachedMediaResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DE76F81D9293B8002B8809 /* CachedMediaResource.swift */; };
|
||||
D0B8440A1DAB91B5005F29E1 /* RandomAccessMediaResourceContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09ADF091D2E89F300C8208D /* RandomAccessMediaResourceContext.swift */; };
|
||||
D0B844511DAC04FE005F29E1 /* PeerPresence.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B844501DAC04FE005F29E1 /* PeerPresence.swift */; };
|
||||
D0C07F6A1B67DB4800966E43 /* SwiftSignalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0C07F691B67DB4800966E43 /* SwiftSignalKit.framework */; };
|
||||
@@ -151,7 +150,6 @@
|
||||
D0D511041D64D91C00A97B8A /* IpcNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = D0D511031D64D75200A97B8A /* IpcNotifier.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D0D949F31D35302600740E02 /* RandomAccessResourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D949F21D35302600740E02 /* RandomAccessResourceTests.swift */; };
|
||||
D0D949F51D35353900740E02 /* MappedFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D949F41D35353900740E02 /* MappedFile.swift */; };
|
||||
D0DE76F91D9293B8002B8809 /* CachedMediaResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DE76F81D9293B8002B8809 /* CachedMediaResource.swift */; };
|
||||
D0DF0C8F1D81A350008AEB01 /* PeerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DF0C8E1D81A350008AEB01 /* PeerView.swift */; };
|
||||
D0E1DE151C5E1C6900C7826E /* ViewTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E1DE141C5E1C6900C7826E /* ViewTracker.swift */; };
|
||||
D0E3A7501B28A7E300A402D9 /* Postbox.h in Headers */ = {isa = PBXBuildFile; fileRef = D0E3A74F1B28A7E300A402D9 /* Postbox.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -259,7 +257,6 @@
|
||||
D0D511031D64D75200A97B8A /* IpcNotifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IpcNotifier.h; sourceTree = "<group>"; };
|
||||
D0D949F21D35302600740E02 /* RandomAccessResourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomAccessResourceTests.swift; sourceTree = "<group>"; };
|
||||
D0D949F41D35353900740E02 /* MappedFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MappedFile.swift; sourceTree = "<group>"; };
|
||||
D0DE76F81D9293B8002B8809 /* CachedMediaResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachedMediaResource.swift; sourceTree = "<group>"; };
|
||||
D0DF0C8E1D81A350008AEB01 /* PeerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerView.swift; sourceTree = "<group>"; };
|
||||
D0E1DE141C5E1C6900C7826E /* ViewTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewTracker.swift; sourceTree = "<group>"; };
|
||||
D0E3A74A1B28A7E300A402D9 /* Postbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Postbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -320,7 +317,6 @@
|
||||
D055BD321B7D3D2D00F06C0A /* MediaBox.swift */,
|
||||
D05F09A51C9E9F9300BB6F96 /* MediaResourceStatus.swift */,
|
||||
D0CE63F51CA1CCB2002BC462 /* MediaResource.swift */,
|
||||
D0DE76F81D9293B8002B8809 /* CachedMediaResource.swift */,
|
||||
D09ADF091D2E89F300C8208D /* RandomAccessMediaResourceContext.swift */,
|
||||
);
|
||||
name = "Media Box";
|
||||
@@ -749,7 +745,6 @@
|
||||
D0B4185C1D7DFE2F004562A4 /* MurMurHash32.m in Sources */,
|
||||
D0B418241D7DFE0C004562A4 /* SimpleSet.swift in Sources */,
|
||||
D03C53601DAD5C9C004C17B3 /* ChatListHole.swift in Sources */,
|
||||
D0B844081DAB91B5005F29E1 /* CachedMediaResource.swift in Sources */,
|
||||
D0B4184C1D7DFE20004562A4 /* ContactPeerIdsView.swift in Sources */,
|
||||
D0B843EC1DAB91A0005F29E1 /* GlobalMessageIdsTable.swift in Sources */,
|
||||
D0B4184F1D7DFE20004562A4 /* ChatListHolesView.swift in Sources */,
|
||||
@@ -835,7 +830,6 @@
|
||||
D08C713C1C51283C00779C0F /* MessageHistoryIndexTable.swift in Sources */,
|
||||
D0F9E86D1C5A0E5D00037222 /* MetadataTable.swift in Sources */,
|
||||
D0E3A7841B28AE0900A402D9 /* Peer.swift in Sources */,
|
||||
D0DE76F91D9293B8002B8809 /* CachedMediaResource.swift in Sources */,
|
||||
D0D510F61D63BBE100A97B8A /* MessageHistoryOperation.swift in Sources */,
|
||||
D0AB0B901D65D4AB002C78E7 /* UnsentMessageIndicesView.swift in Sources */,
|
||||
D03120F81DA53FF4006A2A60 /* PeerPresenceTable.swift in Sources */,
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
public protocol CachedMediaResource {
|
||||
var id: String { get }
|
||||
}
|
||||
@@ -20,6 +20,10 @@ public struct ItemCollectionViewEntryIndex: Comparable {
|
||||
return lhs.collectionIndex < rhs.collectionIndex
|
||||
}
|
||||
}
|
||||
|
||||
public static func lowerBound(collectionIndex: Int32, collectionId: ItemCollectionId) -> ItemCollectionViewEntryIndex {
|
||||
return ItemCollectionViewEntryIndex(collectionIndex: collectionIndex, collectionId: collectionId, itemIndex: ItemCollectionItemIndex(index: 0, id: 0))
|
||||
}
|
||||
}
|
||||
|
||||
public struct ItemCollectionViewEntry {
|
||||
|
||||
@@ -87,7 +87,6 @@ private final class CachedMediaResourceRepresentationContext {
|
||||
|
||||
public final class MediaBox {
|
||||
let basePath: String
|
||||
let buffer = WriteBuffer()
|
||||
|
||||
private let statusQueue = Queue()
|
||||
private let concurrentQueue = Queue.concurrentDefaultQueue()
|
||||
@@ -243,7 +242,6 @@ public final class MediaBox {
|
||||
assert(pathExtension == nil)
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.concurrentQueue.async {
|
||||
let paths = self.storePathsForId(resource.id)
|
||||
if let completeSize = fileSize(paths.complete) {
|
||||
|
||||
@@ -77,12 +77,16 @@ public struct MessageId: Hashable, Comparable, CustomStringConvertible {
|
||||
}
|
||||
|
||||
public func ==(lhs: MessageId, rhs: MessageId) -> Bool {
|
||||
return lhs.id == rhs.id && lhs.namespace == rhs.namespace
|
||||
return lhs.id == rhs.id && lhs.namespace == rhs.namespace && lhs.peerId == rhs.peerId
|
||||
}
|
||||
|
||||
public func <(lhs: MessageId, rhs: MessageId) -> Bool {
|
||||
if lhs.namespace == rhs.namespace {
|
||||
return lhs.id < rhs.id
|
||||
if lhs.id == rhs.id {
|
||||
return lhs.peerId < rhs.peerId
|
||||
} else {
|
||||
return lhs.id < rhs.id
|
||||
}
|
||||
} else {
|
||||
return lhs.namespace < rhs.namespace
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ enum MessageHistoryIndexOperation {
|
||||
case InsertHole(MessageHistoryHole)
|
||||
case Remove(MessageIndex)
|
||||
case Update(MessageIndex, InternalStoreMessage)
|
||||
case UpdateTimestamp(MessageIndex, Int32)
|
||||
}
|
||||
|
||||
private let HistoryEntryTypeMask: Int8 = 1
|
||||
@@ -96,6 +97,15 @@ private func readHistoryIndexEntry(_ peerId: PeerId, namespace: MessageId.Namesp
|
||||
}
|
||||
}
|
||||
|
||||
private func modifyHistoryIndexEntryTimestamp(value: ReadBuffer, timestamp: Int32) -> MemoryBuffer {
|
||||
let buffer = WriteBuffer()
|
||||
buffer.write(value.memory.advanced(by: 0), offset: 0, length: 1)
|
||||
var varTimestamp: Int32 = timestamp
|
||||
buffer.write(&varTimestamp, offset: 0, length: 4)
|
||||
buffer.write(value.memory.advanced(by: 5), offset: 0, length: value.length - 5)
|
||||
return buffer
|
||||
}
|
||||
|
||||
final class MessageHistoryIndexTable: Table {
|
||||
let globalMessageIdsNamespace: Int32
|
||||
let globalMessageIdsTable: GlobalMessageIdsTable
|
||||
@@ -355,6 +365,16 @@ final class MessageHistoryIndexTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
func updateTimestamp(_ id: MessageId, timestamp: Int32, operations: inout [MessageHistoryIndexOperation]) {
|
||||
if let previousData = self.valueBox.get(self.tableId, key: self.key(id)), let previousEntry = self.get(id), case let .Message(previousIndex) = previousEntry, previousIndex.timestamp != timestamp {
|
||||
let updatedEntry = modifyHistoryIndexEntryTimestamp(value: previousData, timestamp: timestamp)
|
||||
self.valueBox.remove(self.tableId, key: self.key(id))
|
||||
self.valueBox.set(self.tableId, key: self.key(id), value: updatedEntry)
|
||||
|
||||
operations.append(.UpdateTimestamp(MessageIndex(id: id, timestamp: previousIndex.timestamp), timestamp))
|
||||
}
|
||||
}
|
||||
|
||||
func fillHole(_ id: MessageId, fillType: HoleFill, tagMask: MessageTags?, messages: [InternalStoreMessage], operations: inout [MessageHistoryIndexOperation]) {
|
||||
self.ensureInitialized(id.peerId, operations: &operations)
|
||||
|
||||
|
||||
@@ -6,4 +6,5 @@ enum MessageHistoryOperation {
|
||||
case Remove([MessageIndex])
|
||||
case UpdateReadState(CombinedPeerReadState)
|
||||
case UpdateEmbeddedMedia(MessageIndex, ReadBuffer)
|
||||
case UpdateTimestamp(MessageIndex, Int32)
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ final class MessageHistoryTable: Table {
|
||||
let message = self.justInsertMessage(storeMessage, sharedKey: sharedKey, sharedBuffer: sharedBuffer, sharedEncoder: sharedEncoder)
|
||||
outputOperations.append(.InsertMessage(message))
|
||||
if message.flags.contains(.Unsent) && !message.flags.contains(.Failed) {
|
||||
self.unsentTable.add(MessageIndex(message), operations: &unsentMessageOperations)
|
||||
self.unsentTable.add(message.id, operations: &unsentMessageOperations)
|
||||
}
|
||||
let tags = message.tags.rawValue
|
||||
if tags != 0 {
|
||||
@@ -174,6 +174,13 @@ final class MessageHistoryTable: Table {
|
||||
if let message = self.justUpdate(index, message: storeMessage, sharedKey: sharedKey, sharedBuffer: sharedBuffer, sharedEncoder: sharedEncoder, unsentMessageOperations: &unsentMessageOperations) {
|
||||
outputOperations.append(.InsertMessage(message))
|
||||
}
|
||||
case let .UpdateTimestamp(index, timestamp):
|
||||
if accumulatedRemoveIndices.count != 0 {
|
||||
outputOperations.append(.Remove(accumulatedRemoveIndices))
|
||||
accumulatedRemoveIndices.removeAll()
|
||||
}
|
||||
self.justUpdateTimestamp(index, timestamp: timestamp)
|
||||
outputOperations.append(.UpdateTimestamp(index, timestamp))
|
||||
}
|
||||
}
|
||||
if accumulatedRemoveIndices.count != 0 {
|
||||
@@ -272,6 +279,12 @@ final class MessageHistoryTable: Table {
|
||||
self.processIndexOperations(id.peerId, operations: operations, processedOperationsByPeerId: &operationsByPeerId, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations)
|
||||
}
|
||||
|
||||
func updateMessageTimestamp(_ id: MessageId, timestamp: Int32, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedPeerReadStateOperations: inout [PeerId: PeerReadStateSynchronizationOperation?]) {
|
||||
var operations: [MessageHistoryIndexOperation] = []
|
||||
self.messageHistoryIndexTable.updateTimestamp(id, timestamp: timestamp, operations: &operations)
|
||||
self.processIndexOperations(id.peerId, operations: operations, processedOperationsByPeerId: &operationsByPeerId, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations)
|
||||
}
|
||||
|
||||
func updateMedia(_ id: MediaId, media: Media?, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], updatedMedia: inout [MediaId: Media?]) {
|
||||
if let previousMedia = self.messageMediaTable.get(id, embedded: { index, id in
|
||||
return self.embeddedMediaForIndex(index, id: id)
|
||||
@@ -410,6 +423,14 @@ final class MessageHistoryTable: Table {
|
||||
return nil
|
||||
}
|
||||
|
||||
func offsetPendingMessagesTimestamps(lowerBound: MessageId, timestamp: Int32, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedPeerReadStateOperations: inout [PeerId: PeerReadStateSynchronizationOperation?]) {
|
||||
for messageId in self.unsentTable.get() {
|
||||
if messageId.peerId == lowerBound.peerId && messageId.namespace == lowerBound.namespace && messageId.id > lowerBound.id {
|
||||
self.updateMessageTimestamp(messageId, timestamp: timestamp, operationsByPeerId: &operationsByPeerId, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func justInsertMessage(_ message: InternalStoreMessage, sharedKey: ValueBoxKey, sharedBuffer: WriteBuffer, sharedEncoder: Encoder) -> IntermediateMessage {
|
||||
sharedBuffer.reset()
|
||||
|
||||
@@ -567,7 +588,7 @@ final class MessageHistoryTable: Table {
|
||||
}
|
||||
|
||||
if message.flags.contains(.Unsent) && !message.flags.contains(.Failed) {
|
||||
self.unsentTable.remove(index, operations: &unsentMessageOperations)
|
||||
self.unsentTable.remove(index.id, operations: &unsentMessageOperations)
|
||||
}
|
||||
|
||||
let tags = message.tags.rawValue
|
||||
@@ -705,6 +726,47 @@ final class MessageHistoryTable: Table {
|
||||
|
||||
private func justUpdate(_ index: MessageIndex, message: InternalStoreMessage, sharedKey: ValueBoxKey, sharedBuffer: WriteBuffer, sharedEncoder: Encoder, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation]) -> IntermediateMessage? {
|
||||
if let previousMessage = self.getMessage(index) {
|
||||
var previousEmbeddedMediaWithIds: [(MediaId, Media)] = []
|
||||
if previousMessage.embeddedMediaData.length > 4 {
|
||||
var embeddedMediaCount: Int32 = 0
|
||||
let previousEmbeddedMediaData = previousMessage.embeddedMediaData
|
||||
previousEmbeddedMediaData.read(&embeddedMediaCount, offset: 0, length: 4)
|
||||
for _ in 0 ..< embeddedMediaCount {
|
||||
var mediaLength: Int32 = 0
|
||||
previousEmbeddedMediaData.read(&mediaLength, offset: 0, length: 4)
|
||||
if let media = Decoder(buffer: MemoryBuffer(memory: previousEmbeddedMediaData.memory + previousEmbeddedMediaData.offset, capacity: Int(mediaLength), length: Int(mediaLength), freeWhenDone: false)).decodeRootObject() as? Media {
|
||||
if let mediaId = media.id {
|
||||
previousEmbeddedMediaWithIds.append((mediaId, media))
|
||||
}
|
||||
}
|
||||
previousEmbeddedMediaData.skip(Int(mediaLength))
|
||||
}
|
||||
}
|
||||
|
||||
var previousMediaIds = Set<MediaId>()
|
||||
for (mediaId, _) in previousEmbeddedMediaWithIds {
|
||||
previousMediaIds.insert(mediaId)
|
||||
}
|
||||
for mediaId in previousMessage.referencedMedia {
|
||||
previousMediaIds.insert(mediaId)
|
||||
}
|
||||
|
||||
var updatedMediaIds = Set<MediaId>()
|
||||
for media in message.media {
|
||||
if let mediaId = media.id {
|
||||
updatedMediaIds.insert(mediaId)
|
||||
}
|
||||
}
|
||||
|
||||
if previousMediaIds != updatedMediaIds || index.id != message.id {
|
||||
for (_, media) in previousEmbeddedMediaWithIds {
|
||||
self.messageMediaTable.removeEmbeddedMedia(media)
|
||||
}
|
||||
for mediaId in previousMessage.referencedMedia {
|
||||
self.messageMediaTable.removeReference(mediaId)
|
||||
}
|
||||
}
|
||||
|
||||
self.valueBox.remove(self.tableId, key: self.key(index))
|
||||
if !previousMessage.tags.isEmpty {
|
||||
self.tagsTable.remove(previousMessage.tags, index: index)
|
||||
@@ -715,13 +777,13 @@ final class MessageHistoryTable: Table {
|
||||
|
||||
switch (previousMessage.flags.contains(.Unsent) && !previousMessage.flags.contains(.Failed), message.flags.contains(.Unsent) && !message.flags.contains(.Failed)) {
|
||||
case (true, false):
|
||||
self.unsentTable.remove(index, operations: &unsentMessageOperations)
|
||||
self.unsentTable.remove(index.id, operations: &unsentMessageOperations)
|
||||
case (false, true):
|
||||
self.unsentTable.add(MessageIndex(message), operations: &unsentMessageOperations)
|
||||
self.unsentTable.add(message.id, operations: &unsentMessageOperations)
|
||||
case (true, true):
|
||||
if index != MessageIndex(message) {
|
||||
self.unsentTable.remove(index, operations: &unsentMessageOperations)
|
||||
self.unsentTable.add(MessageIndex(message), operations: &unsentMessageOperations)
|
||||
self.unsentTable.remove(index.id, operations: &unsentMessageOperations)
|
||||
self.unsentTable.add(message.id, operations: &unsentMessageOperations)
|
||||
}
|
||||
case (false, false):
|
||||
break
|
||||
@@ -731,34 +793,6 @@ final class MessageHistoryTable: Table {
|
||||
assertionFailure()
|
||||
}
|
||||
|
||||
var previousMedia: [Media] = []
|
||||
if previousMessage.embeddedMediaData.length > 4 {
|
||||
var embeddedMediaCount: Int32 = 0
|
||||
let previousEmbeddedMediaData = previousMessage.embeddedMediaData
|
||||
previousEmbeddedMediaData.read(&embeddedMediaCount, offset: 0, length: 4)
|
||||
for _ in 0 ..< embeddedMediaCount {
|
||||
var mediaLength: Int32 = 0
|
||||
previousEmbeddedMediaData.read(&mediaLength, offset: 0, length: 4)
|
||||
if let media = Decoder(buffer: MemoryBuffer(memory: previousEmbeddedMediaData.memory + previousEmbeddedMediaData.offset, capacity: Int(mediaLength), length: Int(mediaLength), freeWhenDone: false)).decodeRootObject() as? Media {
|
||||
previousMedia.append(media)
|
||||
}
|
||||
previousEmbeddedMediaData.skip(Int(mediaLength))
|
||||
}
|
||||
}
|
||||
|
||||
var previousReferencedMedia: [Media] = []
|
||||
for mediaId in previousMessage.referencedMedia {
|
||||
if let media = self.messageMediaTable.get(mediaId, embedded: { _ in
|
||||
return nil
|
||||
}) {
|
||||
previousMedia.append(media)
|
||||
}
|
||||
}
|
||||
|
||||
var removedMediaIds: [MediaId] = []
|
||||
|
||||
//self.updateMedia(from: previousMedia, to: message.media)
|
||||
|
||||
sharedBuffer.reset()
|
||||
|
||||
var type: Int8 = 0
|
||||
@@ -844,10 +878,10 @@ final class MessageHistoryTable: Table {
|
||||
if let mediaId = media.id {
|
||||
let mediaInsertResult = self.messageMediaTable.set(media, index: MessageIndex(message), messageHistoryTable: self)
|
||||
switch mediaInsertResult {
|
||||
case let .Embed(media):
|
||||
embeddedMedia.append(media)
|
||||
case .Reference:
|
||||
referencedMedia.append(mediaId)
|
||||
case let .Embed(media):
|
||||
embeddedMedia.append(media)
|
||||
case .Reference:
|
||||
referencedMedia.append(mediaId)
|
||||
}
|
||||
} else {
|
||||
embeddedMedia.append(media)
|
||||
@@ -885,6 +919,30 @@ final class MessageHistoryTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
private func justUpdateTimestamp(_ index: MessageIndex, timestamp: Int32) {
|
||||
if let previousMessage = self.getMessage(index) {
|
||||
self.valueBox.remove(self.tableId, key: self.key(index))
|
||||
var updatedMessage = IntermediateMessage(stableId: previousMessage.stableId, id: previousMessage.id, timestamp: timestamp, flags: previousMessage.flags, tags: previousMessage.tags, forwardInfo: previousMessage.forwardInfo, authorId: previousMessage.authorId, text: previousMessage.text, attributesData: previousMessage.attributesData, embeddedMediaData: previousMessage.embeddedMediaData, referencedMedia: previousMessage.referencedMedia)
|
||||
self.storeIntermediateMessage(updatedMessage, sharedKey: self.key(index))
|
||||
|
||||
let tags = previousMessage.tags.rawValue
|
||||
if tags != 0 {
|
||||
for i in 0 ..< 32 {
|
||||
let currentTags = tags >> UInt32(i)
|
||||
if currentTags == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if (currentTags & 1) != 0 {
|
||||
let tag = MessageTags(rawValue: 1 << UInt32(i))
|
||||
self.tagsTable.remove(tag, index: index)
|
||||
self.tagsTable.add(tag, index: MessageIndex(id: index.id, timestamp: timestamp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func unembedMedia(_ index: MessageIndex, id: MediaId) -> Media? {
|
||||
if let message = self.getMessage(index), message.embeddedMediaData.length > 4 {
|
||||
var embeddedMediaCount: Int32 = 0
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import Foundation
|
||||
|
||||
enum IntermediateMessageHistoryUnsentOperation {
|
||||
case Insert(MessageIndex)
|
||||
case Remove(MessageIndex)
|
||||
case Insert(MessageId)
|
||||
case Remove(MessageId)
|
||||
}
|
||||
|
||||
final class MessageHistoryUnsentTable: Table {
|
||||
private let sharedKey = ValueBoxKey(length: 4 + 4 + 4 + 8)
|
||||
private let sharedKey = ValueBoxKey(length: 4 + 4 + 8)
|
||||
|
||||
private func key(_ index: MessageIndex) -> ValueBoxKey {
|
||||
self.sharedKey.setInt32(0, value: index.timestamp)
|
||||
self.sharedKey.setInt32(4, value: index.id.namespace)
|
||||
self.sharedKey.setInt32(4 + 4, value: index.id.id)
|
||||
self.sharedKey.setInt64(4 + 4 + 4, value: index.id.peerId.toInt64())
|
||||
private func key(_ id: MessageId) -> ValueBoxKey {
|
||||
self.sharedKey.setInt32(0, value: id.namespace)
|
||||
self.sharedKey.setInt32(4, value: id.id)
|
||||
self.sharedKey.setInt64(4 + 4, value: id.peerId.toInt64())
|
||||
|
||||
return self.sharedKey
|
||||
}
|
||||
@@ -24,7 +23,7 @@ final class MessageHistoryUnsentTable: Table {
|
||||
}
|
||||
|
||||
private func upperBound() -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 4 + 4 + 4 + 8)
|
||||
let key = ValueBoxKey(length: 4 + 4 + 8)
|
||||
memset(key.memory, 0xff, key.length)
|
||||
return key
|
||||
}
|
||||
@@ -33,23 +32,23 @@ final class MessageHistoryUnsentTable: Table {
|
||||
super.init(valueBox: valueBox, tableId: tableId)
|
||||
}
|
||||
|
||||
func add(_ index: MessageIndex, operations: inout [IntermediateMessageHistoryUnsentOperation]) {
|
||||
self.valueBox.set(self.tableId, key: self.key(index), value: MemoryBuffer())
|
||||
operations.append(.Insert(index))
|
||||
func add(_ id: MessageId, operations: inout [IntermediateMessageHistoryUnsentOperation]) {
|
||||
self.valueBox.set(self.tableId, key: self.key(id), value: MemoryBuffer())
|
||||
operations.append(.Insert(id))
|
||||
}
|
||||
|
||||
func remove(_ index: MessageIndex, operations: inout [IntermediateMessageHistoryUnsentOperation]) {
|
||||
self.valueBox.remove(self.tableId, key: self.key(index))
|
||||
operations.append(.Remove(index))
|
||||
func remove(_ id: MessageId, operations: inout [IntermediateMessageHistoryUnsentOperation]) {
|
||||
self.valueBox.remove(self.tableId, key: self.key(id))
|
||||
operations.append(.Remove(id))
|
||||
}
|
||||
|
||||
func get() -> [MessageIndex] {
|
||||
var indices: [MessageIndex] = []
|
||||
func get() -> [MessageId] {
|
||||
var ids: [MessageId] = []
|
||||
self.valueBox.range(self.tableId, start: self.lowerBound(), end: self.upperBound(), keys: { key in
|
||||
indices.append(MessageIndex(id: MessageId(peerId: PeerId(key.getInt64(4 + 4 + 4)), namespace: key.getInt32(4), id: key.getInt32(4 + 4)), timestamp: key.getInt32(0)))
|
||||
ids.append(MessageId(peerId: PeerId(key.getInt64(4 + 4)), namespace: key.getInt32(0), id: key.getInt32(4)))
|
||||
return true
|
||||
}, limit: 0)
|
||||
return indices
|
||||
return ids
|
||||
}
|
||||
|
||||
override func beforeCommit() {
|
||||
|
||||
@@ -46,6 +46,20 @@ enum MutableMessageHistoryEntry {
|
||||
return .HoleEntry(hole, location)
|
||||
}
|
||||
}
|
||||
|
||||
func updatedTimestamp(_ timestamp: Int32) -> MutableMessageHistoryEntry {
|
||||
switch self {
|
||||
case let .IntermediateMessageEntry(message, location):
|
||||
var updatedMessage = IntermediateMessage(stableId: message.stableId, id: message.id, timestamp: timestamp, flags: message.flags, tags: message.tags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: message.embeddedMediaData, referencedMedia: message.referencedMedia)
|
||||
return .IntermediateMessageEntry(updatedMessage, location)
|
||||
case let .MessageEntry(message, location):
|
||||
var updatedMessage = Message(stableId: message.stableId, id: message.id, timestamp: timestamp, flags: message.flags, tags: message.tags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages)
|
||||
return .MessageEntry(updatedMessage, location)
|
||||
case let .HoleEntry(hole, location):
|
||||
var updatedHole = MessageHistoryHole(stableId: hole.stableId, maxIndex: MessageIndex(id: hole.maxIndex.id, timestamp: timestamp), min: hole.min, tags: hole.tags)
|
||||
return .HoleEntry(updatedHole, location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct MessageHistoryEntryLocation: Equatable {
|
||||
@@ -278,6 +292,16 @@ final class MutableMessageHistoryView {
|
||||
break
|
||||
}
|
||||
}
|
||||
case let .UpdateTimestamp(index, timestamp):
|
||||
for i in 0 ..< self.entries.count {
|
||||
let entry = self.entries[i]
|
||||
if entry.index == index {
|
||||
self.remove(Set([index]), context: context)
|
||||
self.add(entry.updatedTimestamp(timestamp), holeFillDirections: [:])
|
||||
hasChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,8 +122,12 @@ public final class Modifier {
|
||||
self.postbox?.replaceRecentPeerIds(peerIds)
|
||||
}
|
||||
|
||||
public func updateMessage(_ index: MessageIndex, update: (Message) -> StoreMessage) {
|
||||
self.postbox?.updateMessage(index, update: update)
|
||||
public func updateMessage(_ id: MessageId, update: (Message) -> StoreMessage) {
|
||||
self.postbox?.updateMessage(id, update: update)
|
||||
}
|
||||
|
||||
public func offsetPendingMessagesTimestamps(lowerBound: MessageId, timestamp: Int32) {
|
||||
self.postbox?.offsetPendingMessagesTimestamps(lowerBound: lowerBound, timestamp: timestamp)
|
||||
}
|
||||
|
||||
public func updateMedia(_ id: MediaId, update: Media?) {
|
||||
@@ -325,7 +329,7 @@ public final class Postbox {
|
||||
self.metadataTable = MetadataTable(valueBox: self.valueBox, tableId: 0)
|
||||
|
||||
let userVersion: Int32? = self.metadataTable.userVersion()
|
||||
let currentUserVersion: Int32 = 11
|
||||
let currentUserVersion: Int32 = 14
|
||||
|
||||
if userVersion != currentUserVersion {
|
||||
self.valueBox.drop()
|
||||
@@ -388,7 +392,7 @@ public final class Postbox {
|
||||
return self.cachedPeerDataTable.get(peerId)
|
||||
}, getPeerPresence: { peerId in
|
||||
return self.peerPresenceTable.get(peerId)
|
||||
},unsentMessageIndices: self.messageHistoryUnsentTable!.get(), synchronizePeerReadStateOperations: self.synchronizeReadStateTable!.get())
|
||||
},unsentMessageIds: self.messageHistoryUnsentTable!.get(), synchronizePeerReadStateOperations: self.synchronizeReadStateTable!.get())
|
||||
|
||||
print("(Postbox initialization took \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
||||
})
|
||||
@@ -735,7 +739,7 @@ public final class Postbox {
|
||||
for table in self.tables {
|
||||
table.clearMemoryCache()
|
||||
}
|
||||
self.viewTracker.refreshViewsDueToExternalTransaction(fetchAroundChatEntries: self.fetchAroundChatEntries, fetchAroundHistoryEntries: self.fetchAroundHistoryEntries, fetchUnsendMessageIndices: {
|
||||
self.viewTracker.refreshViewsDueToExternalTransaction(fetchAroundChatEntries: self.fetchAroundChatEntries, fetchAroundHistoryEntries: self.fetchAroundHistoryEntries, fetchUnsentMessageIds: {
|
||||
return self.messageHistoryUnsentTable!.get()
|
||||
}, fetchSynchronizePeerReadStateOperations: {
|
||||
return self.synchronizeReadStateTable!.get()
|
||||
@@ -851,13 +855,17 @@ public final class Postbox {
|
||||
self.peerRatingTable.replace(items: peerIds)
|
||||
}
|
||||
|
||||
fileprivate func updateMessage(_ index: MessageIndex, update: (Message) -> StoreMessage) {
|
||||
if let intermediateMessage = self.messageHistoryTable.getMessage(index) {
|
||||
fileprivate func updateMessage(_ id: MessageId, update: (Message) -> StoreMessage) {
|
||||
if let indexEntry = self.messageHistoryIndexTable.get(id), let intermediateMessage = self.messageHistoryTable.getMessage(indexEntry.index) {
|
||||
let message = self.renderIntermediateMessage(intermediateMessage)
|
||||
self.messageHistoryTable.updateMessage(index.id, message: update(message), operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: &self.currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||
self.messageHistoryTable.updateMessage(id, message: update(message), operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: &self.currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func offsetPendingMessagesTimestamps(lowerBound: MessageId, timestamp: Int32) {
|
||||
self.messageHistoryTable.offsetPendingMessagesTimestamps(lowerBound: lowerBound, timestamp: timestamp, operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: &self.currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||
}
|
||||
|
||||
fileprivate func updateMedia(_ id: MediaId, update: Media?) {
|
||||
self.messageHistoryTable.updateMedia(id, media: update, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia)
|
||||
}
|
||||
@@ -883,9 +891,9 @@ public final class Postbox {
|
||||
return filteredIds
|
||||
}
|
||||
|
||||
public func modify<T>(_ f: @escaping(Modifier) -> T) -> Signal<T, NoError> {
|
||||
public func modify<T>(userInteractive: Bool = false, _ f: @escaping(Modifier) -> T) -> Signal<T, NoError> {
|
||||
return Signal { subscriber in
|
||||
self.queue.justDispatch {
|
||||
let f: () -> Void = {
|
||||
self.valueBox.begin()
|
||||
self.afterBegin()
|
||||
let result = f(Modifier(postbox: self))
|
||||
@@ -903,18 +911,23 @@ public final class Postbox {
|
||||
self.masterClientId.set(.single(updatedMasterClientId))
|
||||
}
|
||||
}
|
||||
if userInteractive {
|
||||
self.queue.justDispatchWithQoS(qos: DispatchQoS.userInteractive, f)
|
||||
} else {
|
||||
self.queue.justDispatch(f)
|
||||
}
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public func aroundUnreadMessageHistoryViewForPeerId(_ peerId: PeerId, count: Int, tagMask: MessageTags? = nil) -> Signal<(MessageHistoryView, ViewUpdateType), NoError> {
|
||||
return self.modify { modifier -> Signal<(MessageHistoryView, ViewUpdateType), NoError> in
|
||||
return self.modify(userInteractive: true, { modifier -> Signal<(MessageHistoryView, ViewUpdateType), NoError> in
|
||||
var index = MessageHistoryAnchorIndex(index: MessageIndex.upperBound(peerId: peerId), exact: true)
|
||||
if let maxReadIndex = self.messageHistoryTable.maxReadIndex(peerId) {
|
||||
index = maxReadIndex
|
||||
}
|
||||
return self.syncAroundMessageHistoryViewForPeerId(peerId, index: index.index, count: count, anchorIndex: index, unreadIndex: index.index, fixedCombinedReadState: nil, tagMask: tagMask)
|
||||
} |> switchToLatest
|
||||
}) |> switchToLatest
|
||||
}
|
||||
|
||||
public func aroundIdMessageHistoryViewForPeerId(_ peerId: PeerId, count: Int, messageId: MessageId, tagMask: MessageTags? = nil) -> Signal<(MessageHistoryView, ViewUpdateType), NoError> {
|
||||
@@ -1173,11 +1186,11 @@ public final class Postbox {
|
||||
}
|
||||
}
|
||||
|
||||
public func unsentMessageIndicesView() -> Signal<UnsentMessageIndicesView, NoError> {
|
||||
public func unsentMessageIdsView() -> Signal<UnsentMessageIdsView, NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
self.queue.async {
|
||||
disposable.set(self.viewTracker.unsentMessageIndicesViewSignal().start(next: { view in
|
||||
disposable.set(self.viewTracker.unsentMessageIdsViewSignal().start(next: { view in
|
||||
subscriber.putNext(view)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import Foundation
|
||||
|
||||
final class UnsentMessageHistoryView {
|
||||
var indices: Set<MessageIndex>
|
||||
var ids: Set<MessageId>
|
||||
|
||||
init(indices: [MessageIndex]) {
|
||||
self.indices = Set(indices)
|
||||
init(ids: [MessageId]) {
|
||||
self.ids = Set(ids)
|
||||
}
|
||||
|
||||
func refreshDueToExternalTransaction(fetchUnsendMessageIndices: () -> [MessageIndex]) -> Bool {
|
||||
let indices = Set(fetchUnsendMessageIndices())
|
||||
if indices != self.indices {
|
||||
self.indices = indices
|
||||
func refreshDueToExternalTransaction(fetchUnsentMessageIds: () -> [MessageId]) -> Bool {
|
||||
let ids = Set(fetchUnsentMessageIds())
|
||||
if ids != self.ids {
|
||||
self.ids = ids
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@@ -21,14 +21,14 @@ final class UnsentMessageHistoryView {
|
||||
var updated = false
|
||||
for operation in operations {
|
||||
switch operation {
|
||||
case let .Insert(index):
|
||||
if !self.indices.contains(index) {
|
||||
self.indices.insert(index)
|
||||
case let .Insert(id):
|
||||
if !self.ids.contains(id) {
|
||||
self.ids.insert(id)
|
||||
updated = true
|
||||
}
|
||||
case let .Remove(index):
|
||||
if self.indices.contains(index) {
|
||||
self.indices.remove(index)
|
||||
case let .Remove(id):
|
||||
if self.ids.contains(id) {
|
||||
self.ids.remove(id)
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import Foundation
|
||||
|
||||
public final class UnsentMessageIndicesView {
|
||||
public let indices: Set<MessageIndex>
|
||||
public final class UnsentMessageIdsView {
|
||||
public let ids: Set<MessageId>
|
||||
|
||||
init(_ indices: Set<MessageIndex>) {
|
||||
self.indices = indices
|
||||
init(_ ids: Set<MessageId>) {
|
||||
self.ids = ids
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,14 +37,14 @@ final class ViewTracker {
|
||||
private let chatListHolesViewSubscribers = Bag<ValuePipe<ChatListHolesView>>()
|
||||
|
||||
private var unsentMessageView: UnsentMessageHistoryView
|
||||
private let unsendMessageIndicesViewSubscribers = Bag<ValuePipe<UnsentMessageIndicesView>>()
|
||||
private let unsendMessageIdsViewSubscribers = Bag<ValuePipe<UnsentMessageIdsView>>()
|
||||
|
||||
private var synchronizeReadStatesView: MutableSynchronizePeerReadStatesView
|
||||
private let synchronizePeerReadStatesViewSubscribers = Bag<ValuePipe<SynchronizePeerReadStatesView>>()
|
||||
|
||||
private var peerViews = Bag<(MutablePeerView, ValuePipe<PeerView>)>()
|
||||
|
||||
init(queue: Queue, fetchEarlierHistoryEntries: @escaping (PeerId, MessageIndex?, Int, MessageTags?) -> [MutableMessageHistoryEntry], fetchLaterHistoryEntries: @escaping (PeerId, MessageIndex?, Int, MessageTags?) -> [MutableMessageHistoryEntry], fetchEarlierChatEntries: @escaping (MessageIndex?, Int) -> [MutableChatListEntry], fetchLaterChatEntries: @escaping (MessageIndex?, Int) -> [MutableChatListEntry], fetchAnchorIndex: @escaping (MessageId) -> MessageHistoryAnchorIndex?, renderMessage: @escaping (IntermediateMessage) -> Message, getPeer: @escaping (PeerId) -> Peer?, getPeerNotificationSettings: @escaping (PeerId) -> PeerNotificationSettings?, getCachedPeerData: @escaping (PeerId) -> CachedPeerData?, getPeerPresence: @escaping (PeerId) -> PeerPresence?, unsentMessageIndices: [MessageIndex], synchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||
init(queue: Queue, fetchEarlierHistoryEntries: @escaping (PeerId, MessageIndex?, Int, MessageTags?) -> [MutableMessageHistoryEntry], fetchLaterHistoryEntries: @escaping (PeerId, MessageIndex?, Int, MessageTags?) -> [MutableMessageHistoryEntry], fetchEarlierChatEntries: @escaping (MessageIndex?, Int) -> [MutableChatListEntry], fetchLaterChatEntries: @escaping (MessageIndex?, Int) -> [MutableChatListEntry], fetchAnchorIndex: @escaping (MessageId) -> MessageHistoryAnchorIndex?, renderMessage: @escaping (IntermediateMessage) -> Message, getPeer: @escaping (PeerId) -> Peer?, getPeerNotificationSettings: @escaping (PeerId) -> PeerNotificationSettings?, getCachedPeerData: @escaping (PeerId) -> CachedPeerData?, getPeerPresence: @escaping (PeerId) -> PeerPresence?, unsentMessageIds: [MessageId], synchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||
self.queue = queue
|
||||
self.fetchEarlierHistoryEntries = fetchEarlierHistoryEntries
|
||||
self.fetchLaterHistoryEntries = fetchLaterHistoryEntries
|
||||
@@ -57,7 +57,7 @@ final class ViewTracker {
|
||||
self.getCachedPeerData = getCachedPeerData
|
||||
self.getPeerPresence = getPeerPresence
|
||||
|
||||
self.unsentMessageView = UnsentMessageHistoryView(indices: unsentMessageIndices)
|
||||
self.unsentMessageView = UnsentMessageHistoryView(ids: unsentMessageIds)
|
||||
self.synchronizeReadStatesView = MutableSynchronizePeerReadStatesView(operations: synchronizePeerReadStateOperations)
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ final class ViewTracker {
|
||||
self.peerViews.remove(index)
|
||||
}
|
||||
|
||||
func refreshViewsDueToExternalTransaction(fetchAroundChatEntries: (_ index: MessageIndex, _ count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?), fetchAroundHistoryEntries: (_ index: MessageIndex, _ count: Int, _ tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?), fetchUnsendMessageIndices: () -> [MessageIndex], fetchSynchronizePeerReadStateOperations: () -> [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||
func refreshViewsDueToExternalTransaction(fetchAroundChatEntries: (_ index: MessageIndex, _ count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?), fetchAroundHistoryEntries: (_ index: MessageIndex, _ count: Int, _ tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?), fetchUnsentMessageIds: () -> [MessageId], fetchSynchronizePeerReadStateOperations: () -> [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||
var updateTrackedHolesPeerIds: [PeerId] = []
|
||||
|
||||
for (peerId, bag) in self.messageHistoryViews {
|
||||
@@ -192,7 +192,7 @@ final class ViewTracker {
|
||||
self.updateTrackedHoles(peerId)
|
||||
}
|
||||
|
||||
if self.unsentMessageView.refreshDueToExternalTransaction(fetchUnsendMessageIndices: fetchUnsendMessageIndices) {
|
||||
if self.unsentMessageView.refreshDueToExternalTransaction(fetchUnsentMessageIds: fetchUnsentMessageIds) {
|
||||
self.unsentViewUpdated()
|
||||
}
|
||||
|
||||
@@ -371,8 +371,8 @@ final class ViewTracker {
|
||||
}
|
||||
|
||||
private func unsentViewUpdated() {
|
||||
for subscriber in self.unsendMessageIndicesViewSubscribers.copyItems() {
|
||||
subscriber.putNext(UnsentMessageIndicesView(self.unsentMessageView.indices))
|
||||
for subscriber in self.unsendMessageIdsViewSubscribers.copyItems() {
|
||||
subscriber.putNext(UnsentMessageIdsView(self.unsentMessageView.ids))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,14 +426,14 @@ final class ViewTracker {
|
||||
}
|
||||
}
|
||||
|
||||
func unsentMessageIndicesViewSignal() -> Signal<UnsentMessageIndicesView, NoError> {
|
||||
func unsentMessageIdsViewSignal() -> Signal<UnsentMessageIdsView, NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
self.queue.async {
|
||||
subscriber.putNext(UnsentMessageIndicesView(self.unsentMessageView.indices))
|
||||
subscriber.putNext(UnsentMessageIdsView(self.unsentMessageView.ids))
|
||||
|
||||
let pipe = ValuePipe<UnsentMessageIndicesView>()
|
||||
let index = self.unsendMessageIndicesViewSubscribers.add(pipe)
|
||||
let pipe = ValuePipe<UnsentMessageIdsView>()
|
||||
let index = self.unsendMessageIdsViewSubscribers.add(pipe)
|
||||
|
||||
let pipeDisposable = pipe.signal().start(next: { view in
|
||||
subscriber.putNext(view)
|
||||
@@ -441,7 +441,7 @@ final class ViewTracker {
|
||||
|
||||
disposable.set(ActionDisposable {
|
||||
pipeDisposable.dispose()
|
||||
self.unsendMessageIndicesViewSubscribers.remove(index)
|
||||
self.unsendMessageIdsViewSubscribers.remove(index)
|
||||
})
|
||||
}
|
||||
return disposable
|
||||
|
||||
Reference in New Issue
Block a user