Bug fixes in message history view

This commit is contained in:
Peter 2019-04-12 10:06:46 +01:00
parent 1739bf14ff
commit 36aaf31045
5 changed files with 268 additions and 77 deletions

View File

@ -143,6 +143,10 @@ public struct MessageIndex: Comparable, Hashable {
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 {
return lhs.timestamp < rhs.timestamp

View File

@ -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
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: 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
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)
}
return result
if let index = index {
if let closestIndexValue = closestIndex {
if abs(index.timestamp - timestamp) < abs(closestIndexValue.timestamp - timestamp) {
closestIndex = index
}
} else {
closestIndex = index
}
}
}
return closestIndex
}
func findRandomMessage(peerId: PeerId, namespace: MessageId.Namespace, tag: MessageTags, ignoreIds: ([MessageId], Set<MessageId>)) -> 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)
}

View File

@ -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,40 +374,63 @@ 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<PeerId>()
switch self.peerIds {
case let .single(peerId):
peerIdsSet.insert(peerId)
if let value = transaction.currentOperationsByPeerId[peerId] {
operations.append(value)
}
case .associated:
var ids = Set<PeerId>()
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) {
if peerIdsSet.contains(peerId) {
operations.append(value)
}
}
}
}
var hasChanges = false
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,7 +886,50 @@ 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 {
@ -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<PeerId>()
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
}
}

View File

@ -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<MessageIndex>], sampledHole: SampledHistoryViewHole?) {
var clipRanges: [ClosedRange<MessageIndex>] = []
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 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<MessageId.Id>) {
mutating func insertHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) -> 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<MessageId.Id>) {
self.holesBySpace[space]?.remove(integersIn: Int(range.lowerBound) ... Int(range.upperBound))
mutating func removeHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) -> 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<MessageId.Id>) {
self.holes.insertHole(space: space, range: range)
func insertHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) -> Bool {
return self.holes.insertHole(space: space, range: range)
}
func removeHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) {
self.holes.removeHole(space: space, range: range)
func removeHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) -> 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<MessageId.Id>) {
self.holes.insertHole(space: space, range: range)
func insertHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) -> Bool {
return self.holes.insertHole(space: space, range: range)
}
func removeHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) {
self.holes.removeHole(space: space, range: range)
func removeHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) -> Bool {
return self.holes.removeHole(space: space, range: range)
}
func checkAndSample(postbox: Postbox) -> HistoryViewLoadingSample {

View File

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