no message

This commit is contained in:
Peter
2016-11-02 03:14:12 +03:00
parent 6bde6d964c
commit 4d308bcb69
14 changed files with 225 additions and 114 deletions

View File

@@ -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 */,

View File

@@ -1,4 +0,0 @@
public protocol CachedMediaResource {
var id: String { get }
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,4 +6,5 @@ enum MessageHistoryOperation {
case Remove([MessageIndex])
case UpdateReadState(CombinedPeerReadState)
case UpdateEmbeddedMedia(MessageIndex, ReadBuffer)
case UpdateTimestamp(MessageIndex, Int32)
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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