From 36aaf31045a939f5af2946f978bc2f47d100b6ac Mon Sep 17 00:00:00 2001 From: Peter <> Date: Fri, 12 Apr 2019 10:06:46 +0100 Subject: [PATCH] Bug fixes in message history view --- Postbox/Message.swift | 4 + Postbox/MessageHistoryTable.swift | 53 ++++++--- Postbox/MessageHistoryView.swift | 160 ++++++++++++++++++++++---- Postbox/MessageHistoryViewState.swift | 120 +++++++++++++------ Postbox/Postbox.swift | 8 +- 5 files changed, 268 insertions(+), 77 deletions(-) diff --git a/Postbox/Message.swift b/Postbox/Message.swift index eca110fed1..7287f332de 100644 --- a/Postbox/Message.swift +++ b/Postbox/Message.swift @@ -142,6 +142,10 @@ public struct MessageIndex: Comparable, Hashable { func withPeerId(_ peerId: PeerId) -> MessageIndex { return MessageIndex(id: MessageId(peerId: peerId, namespace: self.id.namespace, id: self.id.id), timestamp: self.timestamp) } + + func withNamespace(_ namespace: MessageId.Namespace) -> MessageIndex { + return MessageIndex(id: MessageId(peerId: self.id.peerId, namespace: namespace, id: self.id.id), timestamp: self.timestamp) + } public static func <(lhs: MessageIndex, rhs: MessageIndex) -> Bool { if lhs.timestamp != rhs.timestamp { diff --git a/Postbox/MessageHistoryTable.swift b/Postbox/MessageHistoryTable.swift index bb242c4af4..a37c88f2b7 100644 --- a/Postbox/MessageHistoryTable.swift +++ b/Postbox/MessageHistoryTable.swift @@ -2358,21 +2358,31 @@ final class MessageHistoryTable: Table { return result } - func findClosestMessageId(peerId: PeerId, namespace: MessageId.Namespace, timestamp: Int32) -> MessageId? { - var result: MessageId? - self.valueBox.range(self.table, start: self.key(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: 0), timestamp: timestamp)), end: self.lowerBound(peerId: peerId, namespace: namespace), values: { key, value in - let entry = self.readIntermediateEntry(key, value: value) - result = entry.message.id - return false - }, limit: 1) - if result == nil { - self.valueBox.range(self.table, start: self.key(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: 0), timestamp: timestamp)), end: self.upperBound(peerId: peerId, namespace: namespace), values: { key, value in - let entry = self.readIntermediateEntry(key, value: value) - result = entry.message.id + func findClosestMessageIndex(peerId: PeerId, timestamp: Int32) -> MessageIndex? { + var closestIndex: MessageIndex? + for namespace in self.messageHistoryIndexTable.existingNamespaces(peerId: peerId) { + var index: MessageIndex? + self.valueBox.range(self.table, start: self.key(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: 0), timestamp: timestamp)), end: self.lowerBound(peerId: peerId, namespace: namespace), keys: { key in + index = extractKey(key) return false - }, limit: 0) + }, limit: 1) + if index == nil { + self.valueBox.range(self.table, start: self.key(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: 0), timestamp: timestamp)), end: self.upperBound(peerId: peerId, namespace: namespace), keys: { key in + index = extractKey(key) + return false + }, limit: 0) + } + if let index = index { + if let closestIndexValue = closestIndex { + if abs(index.timestamp - timestamp) < abs(closestIndexValue.timestamp - timestamp) { + closestIndex = index + } + } else { + closestIndex = index + } + } } - return result + return closestIndex } func findRandomMessage(peerId: PeerId, namespace: MessageId.Namespace, tag: MessageTags, ignoreIds: ([MessageId], Set)) -> MessageIndex? { @@ -2554,6 +2564,8 @@ final class MessageHistoryTable: Table { } func fetch(peerId: PeerId, namespace: MessageId.Namespace, tag: MessageTags?, from fromIndex: MessageIndex, includeFrom: Bool, to toIndex: MessageIndex, limit: Int) -> [IntermediateMessage] { + precondition(fromIndex.id.peerId == toIndex.id.peerId) + precondition(fromIndex.id.namespace == toIndex.id.namespace) var result: [IntermediateMessage] = [] if let tag = tag { let indices: [MessageIndex] @@ -2563,6 +2575,15 @@ final class MessageHistoryTable: Table { indices = self.tagsTable.earlierIndices(tag: tag, peerId: peerId, namespace: namespace, index: fromIndex, includeFrom: includeFrom, count: limit) } for index in indices { + if fromIndex < toIndex { + if index < fromIndex || index > toIndex { + continue + } + } else { + if index < toIndex || index > fromIndex { + continue + } + } if let message = self.getMessage(index) { result.append(message) } else { @@ -2571,7 +2592,7 @@ final class MessageHistoryTable: Table { } } else { let startKey: ValueBoxKey - if includeFrom { + if includeFrom && fromIndex != MessageIndex.upperBound(peerId: peerId, namespace: namespace) { if fromIndex < toIndex { startKey = self.key(fromIndex).predecessor } else { @@ -2581,7 +2602,9 @@ final class MessageHistoryTable: Table { startKey = self.key(fromIndex) } self.valueBox.range(self.table, start: startKey, end: self.key(toIndex), values: { key, value in - result.append(self.readIntermediateEntry(key, value: value).message) + let message = self.readIntermediateEntry(key, value: value).message + assert(message.id.peerId == peerId && message.id.namespace == namespace) + result.append(message) return true }, limit: limit) } diff --git a/Postbox/MessageHistoryView.swift b/Postbox/MessageHistoryView.swift index 886d42024a..56c690fdbd 100644 --- a/Postbox/MessageHistoryView.swift +++ b/Postbox/MessageHistoryView.swift @@ -313,12 +313,13 @@ final class MutableMessageHistoryView { self.topTaggedMessages = topTaggedMessages self.additionalDatas = additionalDatas - self.state = HistoryViewState(postbox: postbox, inputAnchor: inputAnchor, tag: tag, limit: count, locations: peerIds) + self.state = HistoryViewState(postbox: postbox, inputAnchor: inputAnchor, tag: tag, limit: count + 2, locations: peerIds) if case let .loading(loadingState) = self.state { let sampledState = loadingState.checkAndSample(postbox: postbox) switch sampledState { case let .ready(anchor, holes): - self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, limit: count, locations: peerIds, postbox: postbox, holes: holes)) + self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, limit: count + 2, locations: peerIds, postbox: postbox, holes: holes)) + self.sampledState = self.state.sample(postbox: postbox) case .loadHole: break } @@ -327,12 +328,21 @@ final class MutableMessageHistoryView { } private func reset(postbox: Postbox) { - self.state = HistoryViewState(postbox: postbox, inputAnchor: self.anchor, tag: self.tag, limit: self.fillCount, locations: self.peerIds) + self.state = HistoryViewState(postbox: postbox, inputAnchor: self.anchor, tag: self.tag, limit: self.fillCount + 2, locations: self.peerIds) if case let .loading(loadingState) = self.state { let sampledState = loadingState.checkAndSample(postbox: postbox) switch sampledState { case let .ready(anchor, holes): - self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, limit: self.fillCount, locations: self.peerIds, postbox: postbox, holes: holes)) + self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, limit: self.fillCount + 2, locations: self.peerIds, postbox: postbox, holes: holes)) + case .loadHole: + break + } + } + if case let .loading(loadingState) = self.state { + let sampledState = loadingState.checkAndSample(postbox: postbox) + switch sampledState { + case let .ready(anchor, holes): + self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, limit: self.fillCount + 2, locations: self.peerIds, postbox: postbox, holes: holes)) case .loadHole: break } @@ -364,29 +374,28 @@ final class MutableMessageHistoryView { func replay(postbox: Postbox, transaction: PostboxTransaction, updatedMedia: [MediaId: Media?], updatedCachedPeerData: [PeerId: CachedPeerData], context: MutableMessageHistoryViewReplayContext, renderIntermediateMessage: (IntermediateMessage) -> Message) -> Bool { var operations: [[MessageHistoryOperation]] = [] + var peerIdsSet = Set() switch self.peerIds { case let .single(peerId): + peerIdsSet.insert(peerId) if let value = transaction.currentOperationsByPeerId[peerId] { operations.append(value) } case .associated: - var ids = Set() switch self.peerIds { case .single: assertionFailure() case let .associated(mainPeerId, associatedPeerId): - ids.insert(mainPeerId) + peerIdsSet.insert(mainPeerId) if let associatedPeerId = associatedPeerId { - ids.insert(associatedPeerId.peerId) + peerIdsSet.insert(associatedPeerId.peerId) } } - if !ids.isEmpty { - for (peerId, value) in transaction.currentOperationsByPeerId { - if ids.contains(peerId) { - operations.append(value) - } + for (peerId, value) in transaction.currentOperationsByPeerId { + if peerIdsSet.contains(peerId) { + operations.append(value) } } } @@ -396,8 +405,32 @@ final class MutableMessageHistoryView { let unwrappedTag: MessageTags = self.tag ?? [] switch self.state { - case .loading: - break + case let .loading(loadingState): + for (key, holeOperations) in transaction.currentPeerHoleOperations { + var matchesSpace = false + switch key.space { + case .everywhere: + matchesSpace = unwrappedTag.isEmpty + case let .tag(tag): + matchesSpace = tag.contains(unwrappedTag) + } + if matchesSpace { + if peerIdsSet.contains(key.peerId) { + for operation in holeOperations { + switch operation { + case let .insert(range): + if loadingState.insertHole(space: PeerIdAndNamespace(peerId: key.peerId, namespace: key.namespace), range: range) { + hasChanges = true + } + case let .remove(range): + if loadingState.removeHole(space: PeerIdAndNamespace(peerId: key.peerId, namespace: key.namespace), range: range) { + hasChanges = true + } + } + } + } + } + } case let .loaded(loadedState): for operationSet in operations { for operation in operationSet { @@ -439,9 +472,43 @@ final class MutableMessageHistoryView { } } } + for (key, holeOperations) in transaction.currentPeerHoleOperations { + var matchesSpace = false + switch key.space { + case .everywhere: + matchesSpace = unwrappedTag.isEmpty + case let .tag(tag): + matchesSpace = tag.contains(unwrappedTag) + } + if matchesSpace { + if peerIdsSet.contains(key.peerId) { + for operation in holeOperations { + switch operation { + case let .insert(range): + if loadedState.insertHole(space: PeerIdAndNamespace(peerId: key.peerId, namespace: key.namespace), range: range) { + hasChanges = true + } + case let .remove(range): + if loadedState.removeHole(space: PeerIdAndNamespace(peerId: key.peerId, namespace: key.namespace), range: range) { + hasChanges = true + } + } + } + } + } + } } if hasChanges { + if case let .loading(loadingState) = self.state { + let sampledState = loadingState.checkAndSample(postbox: postbox) + switch sampledState { + case let .ready(anchor, holes): + self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, limit: self.fillCount + 2, locations: self.peerIds, postbox: postbox, holes: holes)) + case .loadHole: + break + } + } self.sampledState = self.state.sample(postbox: postbox) } @@ -799,10 +866,16 @@ public final class MessageHistoryView { init(_ mutableView: MutableMessageHistoryView) { self.tagMask = mutableView.tag - switch mutableView.state { + var entries: [MessageHistoryEntry] + switch mutableView.sampledState { case .loading: self.isLoading = true self.anchorIndex = .upperBound + entries = [] + self.holeEarlier = true + self.holeLater = true + self.earlierId = nil + self.laterId = nil case let .loaded(state): self.isLoading = false switch state.anchor { @@ -813,8 +886,51 @@ public final class MessageHistoryView { case let .index(index): self.anchorIndex = .message(index) } + self.holeEarlier = state.holesToLower + self.holeLater = state.holesToHigher + entries = [] + if let transientReadStates = mutableView.transientReadStates, case let .peer(states) = transientReadStates { + for entry in state.entries { + let read: Bool + if entry.message.flags.contains(.Incoming) { + read = false + } else if let readState = states[entry.message.id.peerId] { + read = readState.isOutgoingMessageIndexRead(entry.message.index) + } else { + read = false + } + entries.append(MessageHistoryEntry(message: entry.message, isRead: read, location: entry.location, monthLocation: entry.monthLocation, attributes: entry.attributes)) + } + } else { + for entry in state.entries { + entries.append(MessageHistoryEntry(message: entry.message, isRead: false, location: entry.location, monthLocation: entry.monthLocation, attributes: entry.attributes)) + } + } + let stableIds = Set(entries.map({ $0.message.stableId })) + assert(stableIds.count == entries.count) + if !entries.isEmpty { + let anchorIndex = binaryIndexOrLower(entries, state.anchor) + let lowerCount = mutableView.fillCount / 2 + 1 + let upperCount = mutableView.fillCount / 2 + if entries.count - anchorIndex >= upperCount { + self.laterId = entries[entries.count - 1].index + entries.removeLast() + } else { + self.laterId = nil + } + if anchorIndex >= lowerCount { + self.earlierId = entries[0].index + entries.removeFirst() + } else { + self.earlierId = nil + } + } else { + self.earlierId = nil + self.laterId = nil + } } + /*var entries: [MessageHistoryEntry] = [] if let transientReadStates = mutableView.transientReadStates, case let .peer(states) = transientReadStates { for entry in mutableView.entries { @@ -972,14 +1088,6 @@ public final class MessageHistoryView { self.topTaggedMessages = topTaggedMessages self.additionalData = mutableView.additionalDatas - var entries: [MessageHistoryEntry] = [] - - self.entries = entries - self.earlierId = nil - self.laterId = nil - self.holeEarlier = false - self.holeLater = false - self.fixedReadStates = mutableView.combinedReadStates if let combinedReadStates = mutableView.combinedReadStates { @@ -997,14 +1105,14 @@ public final class MessageHistoryView { if hasUnread { var peerIds = Set() - for entry in self.entries { + for entry in entries { peerIds.insert(entry.index.id.peerId) } for peerId in peerIds { if let combinedReadState = states[peerId] { for (namespace, state) in combinedReadState.states { var maxNamespaceIndex: MessageIndex? - var index = self.entries.count - 1 + var index = entries.count - 1 for entry in entries.reversed() { if entry.index.id.peerId == peerId && entry.index.id.namespace == namespace && state.isIncomingMessageIndexRead(entry.index) { maxNamespaceIndex = entry.index @@ -1043,5 +1151,7 @@ public final class MessageHistoryView { } else { self.maxReadIndex = nil } + + self.entries = entries } } diff --git a/Postbox/MessageHistoryViewState.swift b/Postbox/MessageHistoryViewState.swift index 2a41c56f76..93fa7424dd 100644 --- a/Postbox/MessageHistoryViewState.swift +++ b/Postbox/MessageHistoryViewState.swift @@ -72,6 +72,22 @@ private func binaryInsertionIndex(_ inputArr: [MutableMessageHistoryEntry], sear return lo } +func binaryIndexOrLower(_ inputArr: [MessageHistoryEntry], _ searchItem: HistoryViewAnchor) -> Int { + var lo = 0 + var hi = inputArr.count - 1 + while lo <= hi { + let mid = (lo + hi) / 2 + if searchItem.isGreater(than: inputArr[mid].index) { + lo = mid + 1 + } else if searchItem.isLower(than: inputArr[mid].index) { + hi = mid - 1 + } else { + return mid + } + } + return hi +} + private func binaryIndexOrLower(_ inputArr: [MutableMessageHistoryEntry], _ searchItem: HistoryViewAnchor) -> Int { var lo = 0 var hi = inputArr.count - 1 @@ -115,9 +131,8 @@ private func sampleEntries(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHi } if let minSpace = minSpace { backwardsResult.append((minSpace, previousAnchorIndices[minSpace]!)) - //result.insert(sortedEntriesBySpace[minSpace]![previousAnchorIndices[minSpace]!], at: 0) previousAnchorIndices[minSpace]! -= 1 - if result.count == limit { + if (result.count + backwardsResult.count) == limit { break } } @@ -136,9 +151,8 @@ private func sampleEntries(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHi } if let maxSpace = maxSpace { result.append((maxSpace, nextAnchorIndices[maxSpace]!)) - //result.append(sortedEntriesBySpace[maxSpace]![nextAnchorIndices[maxSpace]!]) nextAnchorIndices[maxSpace]! += 1 - if result.count == limit { + if (result.count + backwardsResult.count) == limit { break } } @@ -202,18 +216,24 @@ private func isIndex(index: MessageIndex, closerTo anchor: HistoryViewAnchor, th private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries], holes: HistoryViewHoles, anchor: HistoryViewAnchor, tag: MessageTags?) -> (clipRanges: [ClosedRange], sampledHole: SampledHistoryViewHole?) { var clipRanges: [ClosedRange] = [] var sampledHole: (index: MessageIndex, hole: SampledHistoryViewHole)? - for (space, items) in orderedEntriesBySpace { - guard let indices = holes.holesBySpace[space], !indices.isEmpty else { + + for (space, indices) in holes.holesBySpace { + if indices.isEmpty { continue } switch anchor { case .lowerBound, .upperBound: break case let .index(index): - if indices.contains(Int(index.id.id)) { - return ([MessageIndex.absoluteLowerBound() ... MessageIndex.absoluteUpperBound()], SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: index.id.id, endId: nil)) + if index.id.peerId == space.peerId && index.id.namespace == space.namespace { + if indices.contains(Int(index.id.id)) { + return ([MessageIndex.absoluteLowerBound() ... MessageIndex.absoluteUpperBound()], SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: index.id.id, endId: nil)) + } } } + guard let items = orderedEntriesBySpace[space] else { + return ([MessageIndex.absoluteLowerBound() ... MessageIndex.absoluteUpperBound()], SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: Int32.max - 1, endId: 1)) + } if items.entries.isEmpty { return ([MessageIndex.absoluteLowerBound() ... MessageIndex.absoluteUpperBound()], SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: Int32.max - 1, endId: 1)) } @@ -229,8 +249,11 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere anchorStartingMessageId = items.entries[anchorIndex].index.id.id } - var lowerDirectionIndex = anchorIndex - var higherDirectionIndex = anchorIndex + 1 + let startingLowerDirectionIndex = anchorIndex + let startingHigherDirectionIndex = anchorIndex + 1 + + var lowerDirectionIndex = startingLowerDirectionIndex + var higherDirectionIndex = startingHigherDirectionIndex while lowerDirectionIndex >= 0 || higherDirectionIndex < items.entries.count { if lowerDirectionIndex >= 0 { let itemIndex = items.entries[lowerDirectionIndex].index @@ -238,17 +261,23 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere if lowerDirectionIndex == 0 && itemBoundaryMessageId == bounds.lower.id.id { itemBoundaryMessageId = 1 } + let previousBoundaryIndex: MessageIndex + if lowerDirectionIndex == startingLowerDirectionIndex { + previousBoundaryIndex = itemIndex + } else { + previousBoundaryIndex = items.entries[lowerDirectionIndex + 1].index + } if indices.intersects(integersIn: min(Int(anchorStartingMessageId), Int(itemBoundaryMessageId)) ... max(Int(anchorStartingMessageId), Int(itemBoundaryMessageId))) { var itemClipIndex: MessageIndex - if indices.contains(Int(itemIndex.id.id)) { - itemClipIndex = itemIndex + if indices.contains(Int(previousBoundaryIndex.id.id)) { + itemClipIndex = previousBoundaryIndex } else { - itemClipIndex = itemIndex.predecessor() + itemClipIndex = previousBoundaryIndex.predecessor() } clipRanges.append(MessageIndex.absoluteLowerBound() ... itemClipIndex) var replaceHole = false if let (currentIndex, _) = sampledHole { - if isIndex(index: itemIndex, closerTo: anchor, than: currentIndex) { + if isIndex(index: itemClipIndex, closerTo: anchor, than: currentIndex) { replaceHole = true } } else { @@ -257,12 +286,16 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere if replaceHole { let holeStartId: MessageId.Id - if indices.contains(Int(itemIndex.id.id)) { - holeStartId = itemIndex.id.id + if indices.contains(Int(previousBoundaryIndex.id.id)) { + holeStartId = previousBoundaryIndex.id.id } else { - holeStartId = itemIndex.id.id - 1 + holeStartId = previousBoundaryIndex.id.id - 1 + } + if let idInHole = indices.integerLessThanOrEqualTo(IndexSet.Element(holeStartId)) { + sampledHole = (itemIndex, SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: MessageId.Id(idInHole), endId: 1)) + } else { + assertionFailure() } - sampledHole = (itemIndex, SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: holeStartId, endId: 1)) } lowerDirectionIndex = -1 } @@ -299,7 +332,9 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere } else { holeStartId = itemIndex.id.id + 1 } - sampledHole = (itemIndex, SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: holeStartId, endId: Int32.max - 1)) + if let idInHole = indices.integerGreaterThanOrEqualTo(IndexSet.Element(holeStartId)) { + sampledHole = (itemIndex, SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: MessageId.Id(idInHole), endId: Int32.max - 1)) + } } higherDirectionIndex = items.entries.count } @@ -313,15 +348,31 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere struct HistoryViewHoles { var holesBySpace: [PeerIdAndNamespace: IndexSet] - mutating func insertHole(space: PeerIdAndNamespace, range: ClosedRange) { + mutating func insertHole(space: PeerIdAndNamespace, range: ClosedRange) -> Bool { if self.holesBySpace[space] == nil { self.holesBySpace[space] = IndexSet() } - self.holesBySpace[space]!.insert(integersIn: Int(range.lowerBound) ... Int(range.upperBound)) + let intRange = Int(range.lowerBound) ... Int(range.upperBound) + if self.holesBySpace[space]!.contains(integersIn: intRange) { + self.holesBySpace[space]!.insert(integersIn: intRange) + return true + } else { + return false + } } - mutating func removeHole(space: PeerIdAndNamespace, range: ClosedRange) { - self.holesBySpace[space]?.remove(integersIn: Int(range.lowerBound) ... Int(range.upperBound)) + mutating func removeHole(space: PeerIdAndNamespace, range: ClosedRange) -> Bool { + if self.holesBySpace[space] != nil { + let intRange = Int(range.lowerBound) ... Int(range.upperBound) + if self.holesBySpace[space]!.intersects(integersIn: intRange) { + self.holesBySpace[space]!.remove(integersIn: intRange) + return true + } else { + return false + } + } else { + return false + } } } @@ -331,6 +382,7 @@ struct OrderedHistoryViewEntries { } struct HistoryViewLoadedSample { + let anchor: HistoryViewAnchor let entries: [MessageHistoryMessageEntry] let holesToLower: Bool let holesToHigher: Bool @@ -382,7 +434,7 @@ final class HistoryViewLoadedState { let upperBound = MessageIndex.upperBound(peerId: space.peerId, namespace: space.namespace) switch self.anchor { case let .index(index): - anchorIndex = index + anchorIndex = index.withPeerId(space.peerId).withNamespace(space.namespace) case .lowerBound: anchorIndex = lowerBound case .upperBound: @@ -441,12 +493,12 @@ final class HistoryViewLoadedState { self.orderedEntriesBySpace[space] = OrderedHistoryViewEntries(entries: messages, bounds: bounds) } - func insertHole(space: PeerIdAndNamespace, range: ClosedRange) { - self.holes.insertHole(space: space, range: range) + func insertHole(space: PeerIdAndNamespace, range: ClosedRange) -> Bool { + return self.holes.insertHole(space: space, range: range) } - func removeHole(space: PeerIdAndNamespace, range: ClosedRange) { - self.holes.removeHole(space: space, range: range) + func removeHole(space: PeerIdAndNamespace, range: ClosedRange) -> Bool { + return self.holes.removeHole(space: space, range: range) } func updateTimestamp(postbox: Postbox, index: MessageIndex, timestamp: Int32) -> Bool { @@ -648,7 +700,9 @@ final class HistoryViewLoadedState { result.append(entry) } } - return HistoryViewLoadedSample(entries: result, holesToLower: holesToLower, holesToHigher: holesToHigher, hole: sampledHole) + let stableIds = Set(result.map({ $0.message.stableId })) + assert(stableIds.count == result.count) + return HistoryViewLoadedSample(anchor: self.anchor, entries: result, holesToLower: holesToLower, holesToHigher: holesToHigher, hole: sampledHole) } } @@ -694,12 +748,12 @@ final class HistoryViewLoadingState { self.holes = HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag)) } - func insertHole(space: PeerIdAndNamespace, range: ClosedRange) { - self.holes.insertHole(space: space, range: range) + func insertHole(space: PeerIdAndNamespace, range: ClosedRange) -> Bool { + return self.holes.insertHole(space: space, range: range) } - func removeHole(space: PeerIdAndNamespace, range: ClosedRange) { - self.holes.removeHole(space: space, range: range) + func removeHole(space: PeerIdAndNamespace, range: ClosedRange) -> Bool { + return self.holes.removeHole(space: space, range: range) } func checkAndSample(postbox: Postbox) -> HistoryViewLoadingSample { diff --git a/Postbox/Postbox.swift b/Postbox/Postbox.swift index 4a25563fcf..09b3679cfc 100644 --- a/Postbox/Postbox.swift +++ b/Postbox/Postbox.swift @@ -624,9 +624,9 @@ public final class Transaction { return self.postbox?.messageHistoryTable.findMessageId(peerId: peerId, namespace: namespace, timestamp: timestamp) } - public func findClosestMessageIdByTimestamp(peerId: PeerId, namespace: MessageId.Namespace, timestamp: Int32) -> MessageId? { + public func findClosestMessageIdByTimestamp(peerId: PeerId, timestamp: Int32) -> MessageId? { assert(!self.disposed) - return self.postbox?.messageHistoryTable.findClosestMessageId(peerId: peerId, namespace: namespace, timestamp: timestamp) + return self.postbox?.messageHistoryTable.findClosestMessageIndex(peerId: peerId, timestamp: timestamp)?.id } public func findRandomMessage(peerId: PeerId, namespace: MessageId.Namespace, tag: MessageTags, ignoreIds: ([MessageId], Set)) -> MessageIndex? { @@ -992,7 +992,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, #if DEBUG //debugSaveState(basePath: basePath, name: "previous1") - //debugRestoreState(basePath: basePath, name: "previous1") + debugRestoreState(basePath: basePath, name: "previous1") #endif let startTime = CFAbsoluteTimeGetCurrent() @@ -2229,7 +2229,7 @@ public final class Postbox { subscriber.putCompletion() }) } - if self.queue.isCurrent() { + if self.queue.isCurrent() && Queue.mainQueue().isCurrent() { f() } else if userInteractive { self.queue.justDispatchWithQoS(qos: DispatchQoS.userInteractive, f)