diff --git a/Postbox.xcodeproj/xcshareddata/xcschemes/Postbox.xcscheme b/Postbox.xcodeproj/xcshareddata/xcschemes/Postbox.xcscheme
new file mode 100644
index 0000000000..924a871637
--- /dev/null
+++ b/Postbox.xcodeproj/xcshareddata/xcschemes/Postbox.xcscheme
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Postbox.xcodeproj/xcshareddata/xcschemes/PostboxTests.xcscheme b/Postbox.xcodeproj/xcshareddata/xcschemes/PostboxTests.xcscheme
new file mode 100644
index 0000000000..df73f379be
--- /dev/null
+++ b/Postbox.xcodeproj/xcshareddata/xcschemes/PostboxTests.xcscheme
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Postbox/Database.swift b/Postbox/Database.swift
index 33e083b6a9..a832a1f52f 100644
--- a/Postbox/Database.swift
+++ b/Postbox/Database.swift
@@ -28,9 +28,11 @@ public final class Database {
internal var handle: OpaquePointer? = nil
public init?(_ location: String) {
- let _ = open(location + "-guard", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
+ if location != ":memory:" {
+ let _ = open(location + "-guard", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
+ }
let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX
- let res = sqlite3_open_v2(location.description, &self.handle, flags, nil)
+ let res = sqlite3_open_v2(location, &self.handle, flags, nil)
if res != SQLITE_OK {
postboxLog("sqlite3_open_v2: \(res)")
return nil
diff --git a/Postbox/MessageHistoryView.swift b/Postbox/MessageHistoryView.swift
index fd8467c448..7fdea77e61 100644
--- a/Postbox/MessageHistoryView.swift
+++ b/Postbox/MessageHistoryView.swift
@@ -253,12 +253,12 @@ final class MutableMessageHistoryView {
self.topTaggedMessages = topTaggedMessages
self.additionalDatas = additionalDatas
- self.state = HistoryViewState(postbox: postbox, inputAnchor: inputAnchor, tag: tag, statistics: self.orderStatistics, limit: count + 2, locations: peerIds)
+ self.state = HistoryViewState(postbox: postbox, inputAnchor: inputAnchor, tag: tag, statistics: self.orderStatistics, halfLimit: count + 1, 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, statistics: self.orderStatistics, limit: count + 2, locations: peerIds, postbox: postbox, holes: holes))
+ self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, statistics: self.orderStatistics, halfLimit: count + 1, locations: peerIds, postbox: postbox, holes: holes))
self.sampledState = self.state.sample(postbox: postbox)
case .loadHole:
break
@@ -270,12 +270,12 @@ final class MutableMessageHistoryView {
}
private func reset(postbox: Postbox) {
- self.state = HistoryViewState(postbox: postbox, inputAnchor: self.anchor, tag: self.tag, statistics: self.orderStatistics, limit: self.fillCount + 2, locations: self.peerIds)
+ self.state = HistoryViewState(postbox: postbox, inputAnchor: self.anchor, tag: self.tag, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, 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, statistics: self.orderStatistics, limit: self.fillCount + 2, locations: self.peerIds, postbox: postbox, holes: holes))
+ self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
case .loadHole:
break
}
@@ -284,7 +284,7 @@ final class MutableMessageHistoryView {
let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState {
case let .ready(anchor, holes):
- self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, statistics: self.orderStatistics, limit: self.fillCount + 2, locations: self.peerIds, postbox: postbox, holes: holes))
+ self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
case .loadHole:
break
}
@@ -381,18 +381,18 @@ final class MutableMessageHistoryView {
switch operation {
case let .InsertMessage(message):
if unwrappedTag.isEmpty || message.tags.contains(unwrappedTag) {
- if loadedState.add(postbox: postbox, entry: .IntermediateMessageEntry(message, nil, nil)) {
+ if loadedState.add(entry: .IntermediateMessageEntry(message, nil, nil)) {
hasChanges = true
}
}
case let .Remove(indicesAndTags):
for (index, _) in indicesAndTags {
- if loadedState.remove(postbox: postbox, index: index) {
+ if loadedState.remove(index: index) {
hasChanges = true
}
}
case let .UpdateEmbeddedMedia(index, buffer):
- if loadedState.updateEmbeddedMedia(postbox: postbox, index: index, buffer: buffer) {
+ if loadedState.updateEmbeddedMedia(index: index, buffer: buffer) {
hasChanges = true
}
case let .UpdateGroupInfos(groupInfos):
@@ -455,7 +455,7 @@ final class MutableMessageHistoryView {
let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState {
case let .ready(anchor, holes):
- self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, statistics: self.orderStatistics, limit: self.fillCount + 2, locations: self.peerIds, postbox: postbox, holes: holes))
+ self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
case .loadHole:
break
}
@@ -745,15 +745,17 @@ public final class MessageHistoryView {
assert(Set(entries.map({ $0.message.stableId })).count == entries.count)
if !entries.isEmpty {
let anchorIndex = binaryIndexOrLower(entries, state.anchor)
- let lowerCount = mutableView.fillCount / 2 + 1
- let upperCount = mutableView.fillCount / 2
- if anchorIndex >= 0 && entries.count - anchorIndex >= upperCount {
+ let lowerOrEqualThanAnchorCount = anchorIndex + 1
+ let higherThanAnchorCount = entries.count - anchorIndex - 1
+
+ if higherThanAnchorCount > mutableView.fillCount {
self.laterId = entries[entries.count - 1].index
entries.removeLast()
} else {
self.laterId = nil
}
- if anchorIndex >= lowerCount {
+
+ if lowerOrEqualThanAnchorCount > mutableView.fillCount {
self.earlierId = entries[0].index
entries.removeFirst()
} else {
diff --git a/Postbox/MessageHistoryViewState.swift b/Postbox/MessageHistoryViewState.swift
index 5b154297b9..5d735e4e4b 100644
--- a/Postbox/MessageHistoryViewState.swift
+++ b/Postbox/MessageHistoryViewState.swift
@@ -165,13 +165,12 @@ private func binaryIndexOrLower(_ inputArr: [MutableMessageHistoryEntry], _ sear
return hi
}
-private func sampleEntries(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries], anchor: HistoryViewAnchor, limit: Int) -> [(PeerIdAndNamespace, Int)] {
+private func sampleEntries(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries], anchor: HistoryViewAnchor, halfLimit: Int) -> (lowerOrAtAnchor:[(PeerIdAndNamespace, Int)], higherThanAnchor: [(PeerIdAndNamespace, Int)]) {
var previousAnchorIndices: [PeerIdAndNamespace: Int] = [:]
var nextAnchorIndices: [PeerIdAndNamespace: Int] = [:]
for (space, items) in orderedEntriesBySpace {
- let index = binaryIndexOrLower(items.entries, anchor)
- previousAnchorIndices[space] = index
- nextAnchorIndices[space] = index + 1
+ previousAnchorIndices[space] = items.lowerOrAtAnchor.count - 1
+ nextAnchorIndices[space] = 0
}
var backwardsResult: [(PeerIdAndNamespace, Int)] = []
@@ -182,7 +181,7 @@ private func sampleEntries(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHi
for (space, value) in previousAnchorIndices {
if value != -1 {
if let minSpaceValue = minSpace {
- if orderedEntriesBySpace[space]!.entries[value].index > orderedEntriesBySpace[minSpaceValue]!.entries[previousAnchorIndices[minSpaceValue]!].index {
+ if orderedEntriesBySpace[space]!.lowerOrAtAnchor[value].index > orderedEntriesBySpace[minSpaceValue]!.lowerOrAtAnchor[previousAnchorIndices[minSpaceValue]!].index {
minSpace = space
}
} else {
@@ -193,16 +192,22 @@ private func sampleEntries(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHi
if let minSpace = minSpace {
backwardsResult.append((minSpace, previousAnchorIndices[minSpace]!))
previousAnchorIndices[minSpace]! -= 1
- if (result.count + backwardsResult.count) == limit {
+ if backwardsResult.count == halfLimit {
break
}
}
+ if minSpace == nil {
+ break
+ }
+ }
+
+ while true {
var maxSpace: PeerIdAndNamespace?
for (space, value) in nextAnchorIndices {
- if value != orderedEntriesBySpace[space]!.entries.count {
+ if value != orderedEntriesBySpace[space]!.higherThanAnchor.count {
if let maxSpaceValue = maxSpace {
- if orderedEntriesBySpace[space]!.entries[value].index < orderedEntriesBySpace[maxSpaceValue]!.entries[nextAnchorIndices[maxSpaceValue]!].index {
+ if orderedEntriesBySpace[space]!.higherThanAnchor[value].index < orderedEntriesBySpace[maxSpaceValue]!.higherThanAnchor[nextAnchorIndices[maxSpaceValue]!].index {
maxSpace = space
}
} else {
@@ -213,16 +218,16 @@ private func sampleEntries(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHi
if let maxSpace = maxSpace {
result.append((maxSpace, nextAnchorIndices[maxSpace]!))
nextAnchorIndices[maxSpace]! += 1
- if (result.count + backwardsResult.count) == limit {
+ if result.count == halfLimit {
break
}
}
- if minSpace == nil && maxSpace == nil {
+ if maxSpace == nil {
break
}
}
- return backwardsResult.reversed() + result
+ return (backwardsResult.reversed(), result)
}
struct SampledHistoryViewHole: Equatable {
@@ -274,9 +279,9 @@ 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?) {
+private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries], holes: HistoryViewHoles, anchor: HistoryViewAnchor, tag: MessageTags?, halfLimit: Int) -> (clipRanges: [ClosedRange], sampledHole: SampledHistoryViewHole?) {
var clipRanges: [ClosedRange] = []
- var sampledHole: (itemIndex: Int?, hole: SampledHistoryViewHole)?
+ var sampledHole: (distanceFromAnchor: Int?, hole: SampledHistoryViewHole)?
for (space, indices) in holes.holesBySpace {
if indices.isEmpty {
@@ -292,7 +297,7 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere
}
}
}
- guard let items = orderedEntriesBySpace[space], !items.entries.isEmpty else {
+ guard let items = orderedEntriesBySpace[space], (!items.lowerOrAtAnchor.isEmpty || !items.higherThanAnchor.isEmpty) else {
let holeBounds: (startId: MessageId.Id, endId: MessageId.Id)
switch anchor {
case .lowerBound:
@@ -307,11 +312,176 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere
continue
}
}
- guard let bounds = items.bounds else {
- assertionFailure("A non-empty entry list should have non-nil bounds")
- continue
+
+ for item in items.lowerOrAtAnchor {
+ if item.index.id.id == 76891 {
+ assert(true)
+ }
}
- let anchorIndex = binaryIndexOrLower(items.entries, anchor)
+ for item in items.higherThanAnchor {
+ if item.index.id.id == 76891 {
+ assert(true)
+ }
+ }
+
+ var lowerOrAtAnchorHole: (distanceFromAnchor: Int, hole: SampledHistoryViewHole)?
+
+ for i in (-1 ..< items.lowerOrAtAnchor.count).reversed() {
+ let startingMessageId: MessageId.Id
+ if items.higherThanAnchor.isEmpty {
+ startingMessageId = Int32.max - 1
+ } else {
+ startingMessageId = items.higherThanAnchor[0].index.id.id
+ }
+ let currentMessageId: MessageId.Id
+ if i == -1 {
+ if items.lowerOrAtAnchor.count >= halfLimit {
+ break
+ }
+ currentMessageId = 1
+ } else {
+ currentMessageId = items.lowerOrAtAnchor[i].index.id.id
+ }
+ let range: ClosedRange = Int(currentMessageId) ... Int(startingMessageId)
+ if indices.intersects(integersIn: range) {
+ let holeStartIndex: Int
+ if let value = indices.integerLessThanOrEqualTo(Int(startingMessageId)) {
+ holeStartIndex = value
+ } else {
+ holeStartIndex = indices[indices.endIndex]
+ }
+ lowerOrAtAnchorHole = (items.lowerOrAtAnchor.count - i, SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: Int32(holeStartIndex), endId: 1))
+
+ if i == -1 {
+ if items.lowerOrAtAnchor.count == 0 {
+ if items.higherThanAnchor.count == 0 {
+ clipRanges.append(MessageIndex.absoluteLowerBound() ... MessageIndex.absoluteUpperBound())
+ } else {
+ let clipIndex = items.higherThanAnchor[0].index.predecessor()
+ clipRanges.append(MessageIndex.absoluteLowerBound() ... clipIndex)
+ }
+ } else {
+ let clipIndex = items.lowerOrAtAnchor[0].index.predecessor()
+ clipRanges.append(MessageIndex.absoluteLowerBound() ... clipIndex)
+ }
+ } else {
+ if i == items.lowerOrAtAnchor.count - 1 {
+ if items.higherThanAnchor.count == 0 {
+ clipRanges.append(MessageIndex.absoluteLowerBound() ... MessageIndex.absoluteUpperBound())
+ } else {
+ let clipIndex = items.higherThanAnchor[0].index.predecessor()
+ clipRanges.append(MessageIndex.absoluteLowerBound() ... clipIndex)
+ }
+ } else {
+ let clipIndex: MessageIndex
+ if indices.contains(Int(items.lowerOrAtAnchor[i + 1].index.id.id)) {
+ clipIndex = items.lowerOrAtAnchor[i + 1].index
+ } else {
+ clipIndex = items.lowerOrAtAnchor[i + 1].index.predecessor()
+ }
+ clipRanges.append(MessageIndex.absoluteLowerBound() ... clipIndex)
+ }
+ }
+ break
+ }
+ }
+
+ var higherThanAnchorHole: (distanceFromAnchor: Int, hole: SampledHistoryViewHole)?
+
+ for i in (0 ..< items.higherThanAnchor.count + 1) {
+ let startingMessageId: MessageId.Id
+ if items.lowerOrAtAnchor.isEmpty {
+ startingMessageId = 1
+ } else {
+ startingMessageId = items.lowerOrAtAnchor[items.lowerOrAtAnchor.count - 1].index.id.id
+ }
+ let currentMessageId: MessageId.Id
+ if i == items.higherThanAnchor.count {
+ if items.higherThanAnchor.count >= halfLimit {
+ break
+ }
+ currentMessageId = Int32.max - 1
+ } else {
+ currentMessageId = items.higherThanAnchor[i].index.id.id
+ }
+ let range: ClosedRange = Int(startingMessageId) ... Int(currentMessageId)
+ if indices.intersects(integersIn: range) {
+ let holeStartIndex: Int
+ if let value = indices.integerGreaterThanOrEqualTo(Int(startingMessageId)) {
+ holeStartIndex = value
+ } else {
+ holeStartIndex = indices[indices.startIndex]
+ }
+ higherThanAnchorHole = (i, SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: Int32(holeStartIndex), endId: Int32.max - 1))
+
+ if i == items.higherThanAnchor.count {
+ if items.higherThanAnchor.count == 0 {
+ if items.lowerOrAtAnchor.count == 0 {
+ clipRanges.append(MessageIndex.absoluteLowerBound() ... MessageIndex.absoluteUpperBound())
+ } else {
+ let clipIndex = items.lowerOrAtAnchor[items.lowerOrAtAnchor.count - 1].index.successor()
+ clipRanges.append(clipIndex ... MessageIndex.absoluteUpperBound())
+ }
+ } else {
+ let clipIndex = items.higherThanAnchor[items.higherThanAnchor.count - 1].index.successor()
+ clipRanges.append(clipIndex ... MessageIndex.absoluteUpperBound())
+ }
+ } else {
+ if i == 0 {
+ if items.lowerOrAtAnchor.count == 0 {
+ clipRanges.append(MessageIndex.absoluteLowerBound() ... MessageIndex.absoluteUpperBound())
+ } else {
+ let clipIndex = items.lowerOrAtAnchor[items.lowerOrAtAnchor.count - 1].index.successor()
+ clipRanges.append(clipIndex ... MessageIndex.absoluteUpperBound())
+ }
+ } else {
+ let clipIndex: MessageIndex
+ if indices.contains(Int(items.higherThanAnchor[i - 1].index.id.id)) {
+ clipIndex = items.higherThanAnchor[i - 1].index
+ } else {
+ clipIndex = items.higherThanAnchor[i - 1].index.successor()
+ }
+ clipRanges.append(clipIndex ... MessageIndex.absoluteUpperBound())
+ }
+ }
+ break
+ }
+ }
+
+ var chosenHole: (distanceFromAnchor: Int, hole: SampledHistoryViewHole)?
+ if let lowerOrAtAnchorHole = lowerOrAtAnchorHole, let higherThanAnchorHole = higherThanAnchorHole {
+ if items.lowerOrAtAnchor.isEmpty != items.higherThanAnchor.isEmpty {
+ if !items.lowerOrAtAnchor.isEmpty {
+ chosenHole = lowerOrAtAnchorHole
+ } else {
+ chosenHole = higherThanAnchorHole
+ }
+ } else {
+ if lowerOrAtAnchorHole.distanceFromAnchor < higherThanAnchorHole.distanceFromAnchor {
+ chosenHole = lowerOrAtAnchorHole
+ } else {
+ chosenHole = higherThanAnchorHole
+ }
+ }
+ } else if let lowerOrAtAnchorHole = lowerOrAtAnchorHole {
+ chosenHole = lowerOrAtAnchorHole
+ } else if let higherThanAnchorHole = higherThanAnchorHole {
+ chosenHole = higherThanAnchorHole
+ }
+
+ if let chosenHole = chosenHole {
+ if let current = sampledHole {
+ if let distance = current.distanceFromAnchor {
+ if chosenHole.distanceFromAnchor < distance {
+ sampledHole = (chosenHole.distanceFromAnchor, chosenHole.hole)
+ }
+ }
+ } else {
+ sampledHole = (chosenHole.distanceFromAnchor, chosenHole.hole)
+ }
+ }
+
+ /*let anchorIndex = binaryIndexOrLower(items.entries, anchor)
let anchorStartingMessageId: MessageId.Id
if anchorIndex == -1 {
anchorStartingMessageId = 1
@@ -406,7 +576,7 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere
}
}
higherDirectionIndex += 1
- }
+ }*/
}
return (clipRanges, sampledHole?.hole)
}
@@ -443,8 +613,61 @@ struct HistoryViewHoles {
}
struct OrderedHistoryViewEntries {
- var entries: [MutableMessageHistoryEntry]
- var bounds: (lower: MessageIndex, upper: MessageIndex)?
+ var lowerOrAtAnchor: [MutableMessageHistoryEntry]
+ var higherThanAnchor: [MutableMessageHistoryEntry]
+
+ func find(index: MessageIndex) -> MutableMessageHistoryEntry? {
+ if let entryIndex = binarySearch(self.lowerOrAtAnchor, extract: { $0.index }, searchItem: index) {
+ return self.lowerOrAtAnchor[entryIndex]
+ } else if let entryIndex = binarySearch(self.higherThanAnchor, extract: { $0.index }, searchItem: index) {
+ return self.higherThanAnchor[entryIndex]
+ } else {
+ return nil
+ }
+ }
+
+ mutating func mutableScan(_ f: (MutableMessageHistoryEntry) -> MutableMessageHistoryEntry?) -> Bool {
+ for i in 0 ..< self.lowerOrAtAnchor.count {
+ if let updated = f(self.lowerOrAtAnchor[i]) {
+ self.lowerOrAtAnchor[i] = updated
+ return true
+ }
+ }
+ for i in 0 ..< self.higherThanAnchor.count {
+ if let updated = f(self.higherThanAnchor[i]) {
+ self.higherThanAnchor[i] = updated
+ return true
+ }
+ }
+ return false
+ }
+
+ mutating func update(index: MessageIndex, _ f: (MutableMessageHistoryEntry) -> MutableMessageHistoryEntry?) -> Bool {
+ if let entryIndex = binarySearch(self.lowerOrAtAnchor, extract: { $0.index }, searchItem: index) {
+ if let updated = f(self.lowerOrAtAnchor[entryIndex]) {
+ self.lowerOrAtAnchor[entryIndex] = updated
+ return true
+ }
+ } else if let entryIndex = binarySearch(self.higherThanAnchor, extract: { $0.index }, searchItem: index) {
+ if let updated = f(self.higherThanAnchor[entryIndex]) {
+ self.higherThanAnchor[entryIndex] = updated
+ return true
+ }
+ }
+ return false
+ }
+
+ mutating func remove(index: MessageIndex) -> Bool {
+ if let entryIndex = binarySearch(self.lowerOrAtAnchor, extract: { $0.index }, searchItem: index) {
+ self.lowerOrAtAnchor.remove(at: entryIndex)
+ return true
+ } else if let entryIndex = binarySearch(self.higherThanAnchor, extract: { $0.index }, searchItem: index) {
+ self.higherThanAnchor.remove(at: entryIndex)
+ return true
+ } else {
+ return false
+ }
+ }
}
struct HistoryViewLoadedSample {
@@ -459,17 +682,17 @@ final class HistoryViewLoadedState {
let anchor: HistoryViewAnchor
let tag: MessageTags?
let statistics: MessageHistoryViewOrderStatistics
- let limit: Int
+ let halfLimit: Int
var orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries]
var holes: HistoryViewHoles
var spacesWithRemovals = Set()
- init(anchor: HistoryViewAnchor, tag: MessageTags?, statistics: MessageHistoryViewOrderStatistics, limit: Int, locations: MessageHistoryViewPeerIds, postbox: Postbox, holes: HistoryViewHoles) {
- precondition(limit >= 3)
+ init(anchor: HistoryViewAnchor, tag: MessageTags?, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewPeerIds, postbox: Postbox, holes: HistoryViewHoles) {
+ precondition(halfLimit >= 3)
self.anchor = anchor
self.tag = tag
self.statistics = statistics
- self.limit = limit
+ self.halfLimit = halfLimit
self.orderedEntriesBySpace = [:]
self.holes = holes
@@ -509,56 +732,43 @@ final class HistoryViewLoadedState {
anchorIndex = upperBound
}
- var lowerMessages: [MutableMessageHistoryEntry] = []
- var higherMessages: [MutableMessageHistoryEntry] = []
+ var lowerOrAtAnchorMessages: [MutableMessageHistoryEntry] = []
+ var higherThanAnchorMessages: [MutableMessageHistoryEntry] = []
- if let currentEntries = self.orderedEntriesBySpace[space], !currentEntries.entries.isEmpty {
- let index = binaryIndexOrLower(currentEntries.entries, self.anchor)
- if index >= 0 {
- lowerMessages = Array(currentEntries.entries[0 ... index].reversed())
- }
- if index < currentEntries.entries.count {
- higherMessages = Array(currentEntries.entries[index + 1 ..< currentEntries.entries.count])
- }
+ if let currentEntries = self.orderedEntriesBySpace[space] {
+ lowerOrAtAnchorMessages = currentEntries.lowerOrAtAnchor.reversed()
+ higherThanAnchorMessages = currentEntries.higherThanAnchor
}
func mapEntry(_ message: IntermediateMessage) -> MutableMessageHistoryEntry {
return .IntermediateMessageEntry(message, nil, nil)
}
- if lowerMessages.count < self.limit / 2 + 1 {
+ if lowerOrAtAnchorMessages.count < self.halfLimit {
let nextLowerIndex: (index: MessageIndex, includeFrom: Bool)
- if let lastMessage = lowerMessages.last {
+ if let lastMessage = lowerOrAtAnchorMessages.last {
nextLowerIndex = (lastMessage.index, false)
} else {
nextLowerIndex = (anchorIndex, true)
}
- lowerMessages.append(contentsOf: postbox.messageHistoryTable.fetch(peerId: space.peerId, namespace: space.namespace, tag: self.tag, from: nextLowerIndex.index, includeFrom: nextLowerIndex.includeFrom, to: lowerBound, limit: self.limit / 2 + 1 - lowerMessages.count).map(mapEntry))
+ lowerOrAtAnchorMessages.append(contentsOf: postbox.messageHistoryTable.fetch(peerId: space.peerId, namespace: space.namespace, tag: self.tag, from: nextLowerIndex.index, includeFrom: nextLowerIndex.includeFrom, to: lowerBound, limit: self.halfLimit - lowerOrAtAnchorMessages.count).map(mapEntry))
}
- if higherMessages.count < self.limit - lowerMessages.count {
+ if higherThanAnchorMessages.count < self.halfLimit {
let nextHigherIndex: MessageIndex
- if let lastMessage = higherMessages.last {
+ if let lastMessage = higherThanAnchorMessages.last {
nextHigherIndex = lastMessage.index
} else {
nextHigherIndex = anchorIndex
}
- higherMessages.append(contentsOf: postbox.messageHistoryTable.fetch(peerId: space.peerId, namespace: space.namespace, tag: self.tag, from: nextHigherIndex, includeFrom: false, to: upperBound, limit: self.limit - lowerMessages.count - higherMessages.count).map(mapEntry))
+ higherThanAnchorMessages.append(contentsOf: postbox.messageHistoryTable.fetch(peerId: space.peerId, namespace: space.namespace, tag: self.tag, from: nextHigherIndex, includeFrom: false, to: upperBound, limit: self.halfLimit - higherThanAnchorMessages.count).map(mapEntry))
}
- if !lowerMessages.isEmpty && lowerMessages.count + higherMessages.count < self.limit {
- let additionalLowerMessages = postbox.messageHistoryTable.fetch(peerId: space.peerId, namespace: space.namespace, tag: self.tag, from: lowerMessages[lowerMessages.count - 1].index, includeFrom: false, to: lowerBound, limit: self.limit - lowerMessages.count - higherMessages.count).map(mapEntry)
- lowerMessages.append(contentsOf: additionalLowerMessages)
- }
+ lowerOrAtAnchorMessages.reverse()
- var messages: [MutableMessageHistoryEntry] = []
- messages.append(contentsOf: lowerMessages.reversed())
- messages.append(contentsOf: higherMessages)
+ assert(lowerOrAtAnchorMessages.count <= self.halfLimit)
+ assert(higherThanAnchorMessages.count <= self.halfLimit)
- assert(messages.count <= self.limit)
-
- let bounds = postbox.messageHistoryTable.fetchBoundaries(peerId: space.peerId, namespace: space.namespace, tag: self.tag)
-
- if let tag = self.tag, self.statistics.contains(.combinedLocation) {
+ /*if let tag = self.tag, self.statistics.contains(.combinedLocation) {
if let first = messages.first {
let messageIndex = first.index
let previousCount = postbox.messageHistoryTagsTable.getMessageCountInRange(tag: tag, peerId: space.peerId, namespace: space.namespace, lowerBound: MessageIndex.lowerBound(peerId: space.peerId, namespace: space.namespace), upperBound: messageIndex)
@@ -600,9 +810,9 @@ final class HistoryViewLoadedState {
nextLocation.1 = max(0, nextLocation.1 - 1)
}
}
- }
+ }*/
- self.orderedEntriesBySpace[space] = OrderedHistoryViewEntries(entries: messages, bounds: bounds)
+ self.orderedEntriesBySpace[space] = OrderedHistoryViewEntries(lowerOrAtAnchor: lowerOrAtAnchorMessages, higherThanAnchor: higherThanAnchorMessages)
}
func insertHole(space: PeerIdAndNamespace, range: ClosedRange) -> Bool {
@@ -618,15 +828,14 @@ final class HistoryViewLoadedState {
if self.orderedEntriesBySpace[space] == nil {
return false
}
- guard let entryIndex = binarySearch(self.orderedEntriesBySpace[space]!.entries, extract: { $0.index }, searchItem: index) else {
+ guard let entry = self.orderedEntriesBySpace[space]!.find(index: index) else {
return false
}
- let entry = self.orderedEntriesBySpace[space]!.entries[entryIndex]
var updated = false
- if self.remove(postbox: postbox, index: index) {
+ if self.remove(index: index) {
updated = true
}
- if self.add(postbox: postbox, entry: entry.updatedTimestamp(timestamp)) {
+ if self.add(entry: entry.updatedTimestamp(timestamp)) {
updated = true
}
return updated
@@ -646,43 +855,46 @@ final class HistoryViewLoadedState {
if self.orderedEntriesBySpace[space] == nil {
continue
}
- for i in 0 ..< self.orderedEntriesBySpace[space]!.entries.count {
- if let groupInfo = spaceMapping[self.orderedEntriesBySpace[space]!.entries[i].index.id.id] {
+ let spaceUpdated = self.orderedEntriesBySpace[space]!.mutableScan({ entry in
+ if let groupInfo = spaceMapping[entry.index.id.id] {
updated = true
- switch self.orderedEntriesBySpace[space]!.entries[i] {
+ switch entry {
case let .IntermediateMessageEntry(message, location, monthLocation):
- self.orderedEntriesBySpace[space]!.entries[i] = .IntermediateMessageEntry(message.withUpdatedGroupInfo(groupInfo), location, monthLocation)
+ return .IntermediateMessageEntry(message.withUpdatedGroupInfo(groupInfo), location, monthLocation)
case let .MessageEntry(messageEntry):
- self.orderedEntriesBySpace[space]!.entries[i] = .MessageEntry(MessageHistoryMessageEntry(message: messageEntry.message.withUpdatedGroupInfo(groupInfo), location: messageEntry.location, monthLocation: messageEntry.monthLocation, attributes: messageEntry.attributes))
+ return .MessageEntry(MessageHistoryMessageEntry(message: messageEntry.message.withUpdatedGroupInfo(groupInfo), location: messageEntry.location, monthLocation: messageEntry.monthLocation, attributes: messageEntry.attributes))
}
}
+ return nil
+ })
+ if spaceUpdated {
+ updated = true
}
}
return updated
}
- func updateEmbeddedMedia(postbox: Postbox, index: MessageIndex, buffer: ReadBuffer) -> Bool {
+ func updateEmbeddedMedia(index: MessageIndex, buffer: ReadBuffer) -> Bool {
let space = PeerIdAndNamespace(peerId: index.id.peerId, namespace: index.id.namespace)
if self.orderedEntriesBySpace[space] == nil {
return false
}
- guard let itemIndex = binarySearch(self.orderedEntriesBySpace[space]!.entries, extract: { $0.index }, searchItem: index) else {
- return false
- }
- switch self.orderedEntriesBySpace[space]!.entries[itemIndex] {
- case let .IntermediateMessageEntry(message, location, monthLocation):
- self.orderedEntriesBySpace[space]!.entries[itemIndex] = .IntermediateMessageEntry(message.withUpdatedEmbeddedMedia(buffer), location, monthLocation)
- case let .MessageEntry(messageEntry):
- self.orderedEntriesBySpace[space]!.entries[itemIndex] = .MessageEntry(MessageHistoryMessageEntry(message: messageEntry.message, location: messageEntry.location, monthLocation: messageEntry.monthLocation, attributes: messageEntry.attributes))
- }
- return true
+
+ return self.orderedEntriesBySpace[space]!.update(index: index, { entry in
+ switch entry {
+ case let .IntermediateMessageEntry(message, location, monthLocation):
+ return .IntermediateMessageEntry(message.withUpdatedEmbeddedMedia(buffer), location, monthLocation)
+ case let .MessageEntry(messageEntry):
+ return .MessageEntry(MessageHistoryMessageEntry(message: messageEntry.message, location: messageEntry.location, monthLocation: messageEntry.monthLocation, attributes: messageEntry.attributes))
+ }
+ })
}
func updateMedia(updatedMedia: [MediaId: Media?]) -> Bool {
- var hasChanges = false
+ var updated = false
for space in self.orderedEntriesBySpace.keys {
- for i in 0 ..< self.orderedEntriesBySpace[space]!.entries.count {
- switch self.orderedEntriesBySpace[space]!.entries[i] {
+ let spaceUpdated = self.orderedEntriesBySpace[space]!.mutableScan({ entry in
+ switch entry {
case let .MessageEntry(value):
let message = value.message
@@ -706,41 +918,25 @@ final class HistoryViewLoadedState {
}
}
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds)
- self.orderedEntriesBySpace[space]!.entries[i] = .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes))
- hasChanges = true
- }
- case let .IntermediateMessageEntry(message, _, _):
- var rebuild = false
- for mediaId in message.referencedMedia {
- if let media = updatedMedia[mediaId] , media?.id != mediaId {
- rebuild = true
- break
- }
- }
- if rebuild {
- var referencedMedia: [MediaId] = []
- for mediaId in message.referencedMedia {
- if let media = updatedMedia[mediaId] , media?.id != mediaId {
- if let id = media?.id {
- referencedMedia.append(id)
- }
- } else {
- referencedMedia.append(mediaId)
- }
- }
- hasChanges = true
+ return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes))
}
+ case .IntermediateMessageEntry:
+ break
}
+ return nil
+ })
+ if spaceUpdated {
+ updated = true
}
}
- return hasChanges
+ return updated
}
- func add(postbox: Postbox, entry: MutableMessageHistoryEntry) -> Bool {
+ func add(entry: MutableMessageHistoryEntry) -> Bool {
let space = PeerIdAndNamespace(peerId: entry.index.id.peerId, namespace: entry.index.id.namespace)
if self.orderedEntriesBySpace[space] == nil {
- self.orderedEntriesBySpace[space] = OrderedHistoryViewEntries(entries: [], bounds: nil)
+ self.orderedEntriesBySpace[space] = OrderedHistoryViewEntries(lowerOrAtAnchor: [], higherThanAnchor: [])
}
var updated = false
@@ -763,66 +959,48 @@ final class HistoryViewLoadedState {
}
}*/
- let insertionIndex = binaryInsertionIndex(self.orderedEntriesBySpace[space]!.entries, extract: { $0.index }, searchItem: entry.index)
-
- if insertionIndex < self.orderedEntriesBySpace[space]!.entries.count {
- if self.orderedEntriesBySpace[space]!.entries[insertionIndex].index == entry.index {
- assertionFailure("Inserting an existing index is not allowed")
- self.orderedEntriesBySpace[space]!.entries[insertionIndex] = entry
- return true
- }
- }
-
- var shouldBeAdded = false
- if insertionIndex == 0 {
- if let bounds = self.orderedEntriesBySpace[space]!.bounds {
- if entry.index <= bounds.lower {
- shouldBeAdded = true
+ if self.anchor.isEqualOrGreater(than: entry.index) {
+ let insertionIndex = binaryInsertionIndex(self.orderedEntriesBySpace[space]!.lowerOrAtAnchor, extract: { $0.index }, searchItem: entry.index)
+
+ if insertionIndex < self.orderedEntriesBySpace[space]!.lowerOrAtAnchor.count {
+ if self.orderedEntriesBySpace[space]!.lowerOrAtAnchor[insertionIndex].index == entry.index {
+ assertionFailure("Inserting an existing index is not allowed")
+ self.orderedEntriesBySpace[space]!.lowerOrAtAnchor[insertionIndex] = entry
+ return true
}
- } else {
- //assert(self.orderedEntriesBySpace[space]!.entries.isEmpty, "A non-empty entry list should have non-nil bounds")
- shouldBeAdded = true
- }
- } else if insertionIndex == self.orderedEntriesBySpace[space]!.entries.count {
- if let bounds = self.orderedEntriesBySpace[space]!.bounds {
- if entry.index >= bounds.upper {
- shouldBeAdded = true
- }
- } else {
- //assert(self.orderedEntriesBySpace[space]!.entries.isEmpty, "A non-empty entry list should have non-nil bounds")
- shouldBeAdded = true
- }
- } else {
- shouldBeAdded = true
- }
-
- if shouldBeAdded {
- self.orderedEntriesBySpace[space]!.entries.insert(entry, at: insertionIndex)
- if let currentBounds = self.orderedEntriesBySpace[space]!.bounds {
- if entry.index < currentBounds.lower {
- self.orderedEntriesBySpace[space]!.bounds = (lower: entry.index, upper: currentBounds.upper)
- } else if entry.index > currentBounds.upper {
- self.orderedEntriesBySpace[space]!.bounds = (lower: currentBounds.lower, upper: entry.index)
- }
- } else {
- self.orderedEntriesBySpace[space]!.bounds = (lower: entry.index, upper: entry.index)
}
- if self.orderedEntriesBySpace[space]!.entries.count > self.limit {
- let anchorIndex = binaryIndexOrLower(self.orderedEntriesBySpace[space]!.entries, self.anchor)
- if anchorIndex > self.limit / 2 {
- self.orderedEntriesBySpace[space]!.entries.removeFirst()
- } else {
- self.orderedEntriesBySpace[space]!.entries.removeLast()
+ if insertionIndex == 0 && self.orderedEntriesBySpace[space]!.lowerOrAtAnchor.count >= self.halfLimit {
+ return updated
+ }
+ self.orderedEntriesBySpace[space]!.lowerOrAtAnchor.insert(entry, at: insertionIndex)
+ if self.orderedEntriesBySpace[space]!.lowerOrAtAnchor.count > self.halfLimit {
+ self.orderedEntriesBySpace[space]!.lowerOrAtAnchor.removeFirst()
+ }
+ return true
+ } else {
+ let insertionIndex = binaryInsertionIndex(self.orderedEntriesBySpace[space]!.higherThanAnchor, extract: { $0.index }, searchItem: entry.index)
+
+ if insertionIndex < self.orderedEntriesBySpace[space]!.higherThanAnchor.count {
+ if self.orderedEntriesBySpace[space]!.higherThanAnchor[insertionIndex].index == entry.index {
+ assertionFailure("Inserting an existing index is not allowed")
+ self.orderedEntriesBySpace[space]!.higherThanAnchor[insertionIndex] = entry
+ return true
}
}
- updated = true
+
+ if insertionIndex == self.orderedEntriesBySpace[space]!.higherThanAnchor.count && self.orderedEntriesBySpace[space]!.higherThanAnchor.count >= self.halfLimit {
+ return updated
+ }
+ self.orderedEntriesBySpace[space]!.higherThanAnchor.insert(entry, at: insertionIndex)
+ if self.orderedEntriesBySpace[space]!.higherThanAnchor.count > self.halfLimit {
+ self.orderedEntriesBySpace[space]!.higherThanAnchor.removeLast()
+ }
+ return true
}
-
- return updated
}
- func remove(postbox: Postbox, index: MessageIndex) -> Bool {
+ func remove(index: MessageIndex) -> Bool {
let space = PeerIdAndNamespace(peerId: index.id.peerId, namespace: index.id.namespace)
if self.orderedEntriesBySpace[space] == nil {
return false
@@ -842,16 +1020,7 @@ final class HistoryViewLoadedState {
}
}*/
- if let itemIndex = binarySearch(self.orderedEntriesBySpace[space]!.entries, extract: { $0.index }, searchItem: index) {
- if let currentBounds = self.orderedEntriesBySpace[space]!.bounds {
- if currentBounds.lower == index || currentBounds.upper
- == index {
- self.orderedEntriesBySpace[space]!.bounds = postbox.messageHistoryTable.fetchBoundaries(peerId: space.peerId, namespace: space.namespace, tag: self.tag)
- }
- } else {
- //assertionFailure("A non-empty entry list should have non-nil bounds")
- }
- self.orderedEntriesBySpace[space]!.entries.remove(at: itemIndex)
+ if self.orderedEntriesBySpace[space]!.remove(index: index) {
self.spacesWithRemovals.insert(space)
updated = true
}
@@ -866,48 +1035,62 @@ final class HistoryViewLoadedState {
}
self.spacesWithRemovals.removeAll()
}
- let combinedSpacesAndIndices = sampleEntries(orderedEntriesBySpace: self.orderedEntriesBySpace, anchor: self.anchor, limit: self.limit)
- let (clipRanges, sampledHole) = sampleHoleRanges(orderedEntriesBySpace: self.orderedEntriesBySpace, holes: self.holes, anchor: self.anchor, tag: self.tag)
+ let combinedSpacesAndIndicesByDirection = sampleEntries(orderedEntriesBySpace: self.orderedEntriesBySpace, anchor: self.anchor, halfLimit: self.halfLimit)
+ let (clipRanges, sampledHole) = sampleHoleRanges(orderedEntriesBySpace: self.orderedEntriesBySpace, holes: self.holes, anchor: self.anchor, tag: self.tag, halfLimit: self.halfLimit)
var holesToLower = false
var holesToHigher = false
var result: [MessageHistoryMessageEntry] = []
- if combinedSpacesAndIndices.isEmpty {
+ if combinedSpacesAndIndicesByDirection.lowerOrAtAnchor.isEmpty && combinedSpacesAndIndicesByDirection.higherThanAnchor.isEmpty {
if !clipRanges.isEmpty {
holesToLower = true
holesToHigher = true
}
} else {
- outer: for i in 0 ..< combinedSpacesAndIndices.count {
- let (space, index) = combinedSpacesAndIndices[i]
-
- if !clipRanges.isEmpty {
- let entryIndex = self.orderedEntriesBySpace[space]!.entries[index].index
- for range in clipRanges {
- if range.contains(entryIndex) {
- if i == 0 {
- holesToLower = true
+ let directions = [combinedSpacesAndIndicesByDirection.lowerOrAtAnchor, combinedSpacesAndIndicesByDirection.higherThanAnchor]
+ for directionIndex in 0 ..< directions.count {
+ outer: for i in 0 ..< directions[directionIndex].count {
+ let (space, index) = directions[directionIndex][i]
+
+ let entry: MutableMessageHistoryEntry
+ if directionIndex == 0 {
+ entry = self.orderedEntriesBySpace[space]!.lowerOrAtAnchor[index]
+ } else {
+ entry = self.orderedEntriesBySpace[space]!.higherThanAnchor[index]
+ }
+
+ if !clipRanges.isEmpty {
+ let entryIndex = entry.index
+ for range in clipRanges {
+ if range.contains(entryIndex) {
+ if directionIndex == 0 && i == 0 {
+ holesToLower = true
+ }
+ if directionIndex == 1 && i == directions[directionIndex].count - 1 {
+ holesToHigher = true
+ }
+ continue outer
}
- if i == combinedSpacesAndIndices.count - 1 {
- holesToHigher = true
- }
- continue outer
}
}
- }
-
- switch self.orderedEntriesBySpace[space]!.entries[index] {
- case let .MessageEntry(value):
- result.append(value)
- case let .IntermediateMessageEntry(message, location, monthLocation):
- let renderedMessage = postbox.messageHistoryTable.renderMessage(message, peerTable: postbox.peerTable)
- var authorIsContact = false
- if let author = renderedMessage.author {
- authorIsContact = postbox.contactsTable.isContact(peerId: author.id)
- }
- let entry = MessageHistoryMessageEntry(message: renderedMessage, location: location, monthLocation: monthLocation, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: authorIsContact))
- self.orderedEntriesBySpace[space]!.entries[index] = .MessageEntry(entry)
- result.append(entry)
+
+ switch entry {
+ case let .MessageEntry(value):
+ result.append(value)
+ case let .IntermediateMessageEntry(message, location, monthLocation):
+ let renderedMessage = postbox.messageHistoryTable.renderMessage(message, peerTable: postbox.peerTable)
+ var authorIsContact = false
+ if let author = renderedMessage.author {
+ authorIsContact = postbox.contactsTable.isContact(peerId: author.id)
+ }
+ let entry = MessageHistoryMessageEntry(message: renderedMessage, location: location, monthLocation: monthLocation, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: authorIsContact))
+ if directionIndex == 0 {
+ self.orderedEntriesBySpace[space]!.lowerOrAtAnchor[index] = .MessageEntry(entry)
+ } else {
+ self.orderedEntriesBySpace[space]!.higherThanAnchor[index] = .MessageEntry(entry)
+ }
+ result.append(entry)
+ }
}
}
}
@@ -948,13 +1131,13 @@ enum HistoryViewLoadingSample {
final class HistoryViewLoadingState {
var messageId: MessageId
let tag: MessageTags?
- let limit: Int
+ let halfLimit: Int
var holes: HistoryViewHoles
- init(postbox: Postbox, locations: MessageHistoryViewPeerIds, tag: MessageTags?, messageId: MessageId, limit: Int) {
+ init(postbox: Postbox, locations: MessageHistoryViewPeerIds, tag: MessageTags?, messageId: MessageId, halfLimit: Int) {
self.messageId = messageId
self.tag = tag
- self.limit = limit
+ self.halfLimit = halfLimit
self.holes = HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))
}
@@ -995,14 +1178,14 @@ enum HistoryViewState {
case loaded(HistoryViewLoadedState)
case loading(HistoryViewLoadingState)
- init(postbox: Postbox, inputAnchor: HistoryViewInputAnchor, tag: MessageTags?, statistics: MessageHistoryViewOrderStatistics, limit: Int, locations: MessageHistoryViewPeerIds) {
+ init(postbox: Postbox, inputAnchor: HistoryViewInputAnchor, tag: MessageTags?, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewPeerIds) {
switch inputAnchor {
case let .index(index):
- self = .loaded(HistoryViewLoadedState(anchor: .index(index), tag: tag, statistics: statistics, limit: limit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))))
+ self = .loaded(HistoryViewLoadedState(anchor: .index(index), tag: tag, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))))
case .lowerBound:
- self = .loaded(HistoryViewLoadedState(anchor: .lowerBound, tag: tag, statistics: statistics, limit: limit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))))
+ self = .loaded(HistoryViewLoadedState(anchor: .lowerBound, tag: tag, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))))
case .upperBound:
- self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, statistics: statistics, limit: limit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))))
+ self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))))
case .unread:
let anchorPeerId: PeerId
switch locations {
@@ -1035,26 +1218,26 @@ enum HistoryViewState {
}
}
if let messageId = messageId {
- let loadingState = HistoryViewLoadingState(postbox: postbox, locations: locations, tag: tag, messageId: messageId, limit: limit)
+ let loadingState = HistoryViewLoadingState(postbox: postbox, locations: locations, tag: tag, messageId: messageId, halfLimit: halfLimit)
let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState {
case let .ready(anchor, holes):
- self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, statistics: statistics, limit: limit, locations: locations, postbox: postbox, holes: holes))
+ self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes))
case .loadHole:
self = .loading(loadingState)
}
} else {
- self = .loaded(HistoryViewLoadedState(anchor: anchor ?? .upperBound, tag: tag, statistics: statistics, limit: limit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))))
+ self = .loaded(HistoryViewLoadedState(anchor: anchor ?? .upperBound, tag: tag, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag))))
}
} else {
preconditionFailure()
}
case let .message(messageId):
- let loadingState = HistoryViewLoadingState(postbox: postbox, locations: locations, tag: tag, messageId: messageId, limit: limit)
+ let loadingState = HistoryViewLoadingState(postbox: postbox, locations: locations, tag: tag, messageId: messageId, halfLimit: halfLimit)
let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState {
case let .ready(anchor, holes):
- self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, statistics: statistics, limit: limit, locations: locations, postbox: postbox, holes: holes))
+ self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes))
case .loadHole:
self = .loading(loadingState)
}
diff --git a/Postbox/Postbox.swift b/Postbox/Postbox.swift
index a3b44406be..fa5ebc22e7 100644
--- a/Postbox/Postbox.swift
+++ b/Postbox/Postbox.swift
@@ -935,7 +935,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()
diff --git a/Postbox/SqliteValueBox.swift b/Postbox/SqliteValueBox.swift
index 4a4209aaf3..01e08b0120 100644
--- a/Postbox/SqliteValueBox.swift
+++ b/Postbox/SqliteValueBox.swift
@@ -159,6 +159,7 @@ public final class SqliteValueBox: ValueBox {
private let lock = NSRecursiveLock()
fileprivate let basePath: String
+ private let inMemory: Bool
private let encryptionParameters: ValueBoxEncryptionParameters?
private let databasePath: String
private var database: Database!
@@ -196,8 +197,9 @@ public final class SqliteValueBox: ValueBox {
private let queue: Queue
- public init(basePath: String, queue: Queue, encryptionParameters: ValueBoxEncryptionParameters?, upgradeProgress: (Float) -> Void) {
+ public init(basePath: String, queue: Queue, encryptionParameters: ValueBoxEncryptionParameters?, upgradeProgress: (Float) -> Void, inMemory: Bool = false) {
self.basePath = basePath
+ self.inMemory = inMemory
self.encryptionParameters = encryptionParameters
self.databasePath = basePath + "/db_sqlite"
self.queue = queue
@@ -247,7 +249,7 @@ public final class SqliteValueBox: ValueBox {
#endif
var database: Database
- if let result = Database(path) {
+ if let result = Database(self.inMemory ? ":memory:" : path) {
database = result
} else {
postboxLog("Couldn't open DB")
diff --git a/PostboxTests/MessageHistoryIndexTableTests.swift b/PostboxTests/MessageHistoryIndexTableTests.swift
index 036ccb69a9..8fa8c0d294 100644
--- a/PostboxTests/MessageHistoryIndexTableTests.swift
+++ b/PostboxTests/MessageHistoryIndexTableTests.swift
@@ -22,7 +22,7 @@ private extension MessageTags {
}
class MessageHistoryIndexTableTests: XCTestCase {
- var valueBox: ValueBox?
+ var valueBox: SqliteValueBox?
var path: String?
var postbox: Postbox?
@@ -45,7 +45,7 @@ class MessageHistoryIndexTableTests: XCTestCase {
arc4random_buf(bytes, 16)
})
- self.valueBox = SqliteValueBox(basePath: path!, queue: Queue.mainQueue(), encryptionParameters: ValueBoxEncryptionParameters(key: ValueBoxEncryptionParameters.Key(data: randomKey)!, salt: ValueBoxEncryptionParameters.Salt(data: randomSalt)!))
+ self.valueBox = SqliteValueBox(basePath: path!, queue: Queue.mainQueue(), encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: true, key: ValueBoxEncryptionParameters.Key(data: randomKey)!, salt: ValueBoxEncryptionParameters.Salt(data: randomSalt)!), upgradeProgress: { _ in })
let messageHoles: [PeerId.Namespace: [MessageId.Namespace: Set]] = [
peerId.namespace: [
@@ -53,7 +53,7 @@ class MessageHistoryIndexTableTests: XCTestCase {
]
]
- let seedConfiguration = SeedConfiguration(globalMessageIdsPeerIdNamespaces: Set(), initializeChatListWithHole: (topLevel: nil, groups: nil), messageHoles: messageHoles, existingMessageTags: [.media], messageTagsWithSummary: [], existingGlobalMessageTags: [], peerNamespacesRequiringMessageTextIndex: [], peerSummaryCounterTags: { _ in PeerSummaryCounterTags(rawValue: 0) }, additionalChatListIndexNamespace: nil)
+ let seedConfiguration = SeedConfiguration(globalMessageIdsPeerIdNamespaces: Set(), initializeChatListWithHole: (topLevel: nil, groups: nil), messageHoles: messageHoles, existingMessageTags: [.media], messageTagsWithSummary: [], existingGlobalMessageTags: [], peerNamespacesRequiringMessageTextIndex: [], peerSummaryCounterTags: { _ in PeerSummaryCounterTags(rawValue: 0) }, additionalChatListIndexNamespace: nil, messageNamespacesRequiringGroupStatsValidation: Set())
self.postbox = Postbox(queue: Queue.mainQueue(), basePath: path!, seedConfiguration: seedConfiguration, valueBox: self.valueBox!)
}
diff --git a/PostboxTests/MessageHistoryViewTests.swift b/PostboxTests/MessageHistoryViewTests.swift
index 143aa0d2ff..4e9c9db05b 100644
--- a/PostboxTests/MessageHistoryViewTests.swift
+++ b/PostboxTests/MessageHistoryViewTests.swift
@@ -10,42 +10,33 @@ import SwiftSignalKit
private let peerId = PeerId(namespace: 1, id: 1)
private let namespace: Int32 = 1
-private func extract(from array: [Int32], aroundIndex: Int, limit: Int) -> [Int32] {
+private func extract(from array: [Int32], aroundIndex: Int, halfLimit: Int) -> [Int32] {
var lower: [Int32] = []
var higher: [Int32] = []
var i = aroundIndex
- while i >= 0 && lower.count < limit / 2 + 1 {
+ while i >= 0 && lower.count < halfLimit {
lower.append(array[i])
i -= 1
}
var j = aroundIndex + 1
- while j < array.count && higher.count < limit - lower.count {
+ while j < array.count && higher.count < halfLimit {
higher.append(array[j])
j += 1
}
- if !lower.isEmpty && lower.count + higher.count < limit {
- var additionalLower: [Int32] = []
- while i >= 0 && additionalLower.count < limit - lower.count - higher.count {
- additionalLower.append(array[i])
- i -= 1
- }
- lower.append(contentsOf: additionalLower)
- }
-
var result: [Int32] = []
result.append(contentsOf: lower.reversed())
result.append(contentsOf: higher)
- assert(result.count <= limit)
+ assert(result.count <= halfLimit * 2)
return result
}
class MessageHistoryViewTests: XCTestCase {
- var valueBox: ValueBox?
+ var valueBox: SqliteValueBox?
var path: String?
var postbox: Postbox?
@@ -68,7 +59,7 @@ class MessageHistoryViewTests: XCTestCase {
arc4random_buf(bytes, 16)
})
- self.valueBox = SqliteValueBox(basePath: path!, queue: Queue.mainQueue(), encryptionParameters: ValueBoxEncryptionParameters(key: ValueBoxEncryptionParameters.Key(data: randomKey)!, salt: ValueBoxEncryptionParameters.Salt(data: randomSalt)!))
+ self.valueBox = SqliteValueBox(basePath: path!, queue: Queue.mainQueue(), encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: randomKey)!, salt: ValueBoxEncryptionParameters.Salt(data: randomSalt)!), upgradeProgress: { _ in }, inMemory: true)
let messageHoles: [PeerId.Namespace: [MessageId.Namespace: Set]] = [
peerId.namespace: [:
@@ -76,7 +67,7 @@ class MessageHistoryViewTests: XCTestCase {
]
]
- let seedConfiguration = SeedConfiguration(globalMessageIdsPeerIdNamespaces: Set(), initializeChatListWithHole: (topLevel: nil, groups: nil), messageHoles: messageHoles, existingMessageTags: [], messageTagsWithSummary: [], existingGlobalMessageTags: [], peerNamespacesRequiringMessageTextIndex: [], peerSummaryCounterTags: { _ in PeerSummaryCounterTags(rawValue: 0) }, additionalChatListIndexNamespace: nil)
+ let seedConfiguration = SeedConfiguration(globalMessageIdsPeerIdNamespaces: Set(), initializeChatListWithHole: (topLevel: nil, groups: nil), messageHoles: messageHoles, existingMessageTags: [], messageTagsWithSummary: [], existingGlobalMessageTags: [], peerNamespacesRequiringMessageTextIndex: [], peerSummaryCounterTags: { _ in PeerSummaryCounterTags(rawValue: 0) }, additionalChatListIndexNamespace: nil, messageNamespacesRequiringGroupStatsValidation: Set())
self.postbox = Postbox(queue: Queue.mainQueue(), basePath: path!, seedConfiguration: seedConfiguration, valueBox: self.valueBox!)
}
@@ -101,10 +92,14 @@ class MessageHistoryViewTests: XCTestCase {
}).start()
}
- private func addMessage(_ id: Int32, _ timestamp: Int32, _ groupingKey: Int64? = nil) {
+ private func addMessage(_ id: Int32, _ timestamp: Int32, _ groupingKey: Int64? = nil) -> UInt32 {
+ var stableId: UInt32?
let _ = self.postbox!.transaction({ transaction -> Void in
- let _ = transaction.addMessages([StoreMessage(id: MessageId(peerId: peerId, namespace: namespace, id: id), globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "", attributes: [], media: [])], location: .Random)
+ let messageId = MessageId(peerId: peerId, namespace: namespace, id: id)
+ let _ = transaction.addMessages([StoreMessage(id: messageId, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "", attributes: [], media: [])], location: .Random)
+ stableId = transaction.getMessage(messageId)!.stableId
}).start()
+ return stableId!
}
private func removeMessage(_ id: Int32) {
@@ -120,7 +115,7 @@ class MessageHistoryViewTests: XCTestCase {
}
func testEmpty() {
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, limit: 10, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, statistics: [], halfLimit: 10, locations: .single(peerId))
switch state {
case let .loaded(loadedState):
let entries = loadedState.completeAndSample(postbox: self.postbox!).entries
@@ -134,10 +129,10 @@ class MessageHistoryViewTests: XCTestCase {
var testIds: [MessageId.Id] = []
for i in 1 ..< 11 {
testIds.append(Int32(i * 10))
- addMessage(Int32(i * 10), Int32(i * 10))
+ let _ = addMessage(Int32(i * 10), Int32(i * 10))
}
for i in 3 ... testIds.count + 10 {
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, limit: i, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, statistics: [], halfLimit: i, locations: .single(peerId))
switch state {
case let .loaded(loadedState):
let entries = loadedState.completeAndSample(postbox: self.postbox!).entries
@@ -154,7 +149,7 @@ class MessageHistoryViewTests: XCTestCase {
}
}
for i in 3 ... testIds.count + 10 {
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .lowerBound, tag: nil, limit: i, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .lowerBound, tag: nil, statistics: [], halfLimit: i, locations: .single(peerId))
switch state {
case let .loaded(loadedState):
let entries = loadedState.completeAndSample(postbox: self.postbox!).entries
@@ -172,11 +167,11 @@ class MessageHistoryViewTests: XCTestCase {
}
for i in 3 ... testIds.count + 10 {
for j in testIds[0] - 10 ... testIds.last! + 10 {
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: Int32(j)), timestamp: Int32(j))), tag: nil, limit: i, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: Int32(j)), timestamp: Int32(j))), tag: nil, statistics: [], halfLimit: i, locations: .single(peerId))
let clippedTestIds: [Int32]
if let index = testIds.firstIndex(where: { $0 > Int32(j) }), index >= 0 {
- clippedTestIds = extract(from: testIds, aroundIndex: index - 1, limit: i)
+ clippedTestIds = extract(from: testIds, aroundIndex: index - 1, halfLimit: i)
} else {
if i >= testIds.count {
clippedTestIds = testIds
@@ -233,12 +228,12 @@ class MessageHistoryViewTests: XCTestCase {
for operationSetIndex in 0 ..< operationSets.count {
let operations = operationSets[operationSetIndex]
- for limit in [3, 4, 5, 6, 7, 200] {
+ for halfLimit in [3, 4, 5, 6, 7, 200] {
for position in 10 ... 110 {
removeAllMessages()
var testIds: [MessageId.Id] = []
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: Int32(position)), timestamp: Int32(position))), tag: nil, limit: limit, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: Int32(position)), timestamp: Int32(position))), tag: nil, statistics: [], halfLimit: halfLimit, locations: .single(peerId))
switch state {
case let .loaded(loadedState):
for operationIndex in 0 ..< operations.count {
@@ -252,20 +247,20 @@ class MessageHistoryViewTests: XCTestCase {
let attributesData = ReadBuffer(data: Data())
- addMessage(Int32(insertId), Int32(insertId))
- let _ = loadedState.add(entry: .IntermediateMessageEntry(IntermediateMessage(stableId: UInt32(insertId), stableVersion: 0, id: MessageId(peerId: peerId, namespace: namespace, id: insertId), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: insertId, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "", attributesData: attributesData, embeddedMediaData: attributesData, referencedMedia: []), nil, nil))
+ let stableId = addMessage(Int32(insertId), Int32(insertId))
+ let _ = loadedState.add(entry: .IntermediateMessageEntry(IntermediateMessage(stableId: stableId, stableVersion: 0, id: MessageId(peerId: peerId, namespace: namespace, id: insertId), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: insertId, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "", attributesData: attributesData, embeddedMediaData: attributesData, referencedMedia: []), nil, nil))
let entries = loadedState.completeAndSample(postbox: self.postbox!).entries
let ids = entries.map({ $0.message.id.id })
let clippedTestIds: [Int32]
if let index = testIds.firstIndex(where: { $0 > Int32(position) }), index >= 0 {
- clippedTestIds = extract(from: testIds, aroundIndex: index - 1, limit: limit)
+ clippedTestIds = extract(from: testIds, aroundIndex: index - 1, halfLimit: halfLimit)
} else {
- if limit >= testIds.count {
+ if halfLimit >= testIds.count {
clippedTestIds = testIds
} else {
- clippedTestIds = Array(testIds.dropFirst(testIds.count - limit))
+ clippedTestIds = Array(testIds.dropFirst(testIds.count - halfLimit))
}
}
@@ -310,12 +305,12 @@ class MessageHistoryViewTests: XCTestCase {
for operationSetIndex in 0 ..< operationSets.count {
let operations = operationSets[operationSetIndex]
- for limit in [3, 4, 5, 6, 7, 200] {
+ for halfLimit in [3, 4, 5, 6, 7, 200] {
for position in 10 ... 110 {
removeAllMessages()
var testIds: [MessageId.Id] = []
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: Int32(position)), timestamp: Int32(position))), tag: nil, limit: limit, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: namespace, id: Int32(position)), timestamp: Int32(position))), tag: nil, statistics: [], halfLimit: halfLimit, locations: .single(peerId))
switch state {
case let .loaded(loadedState):
for operationIndex in 0 ..< operations.count {
@@ -337,12 +332,12 @@ class MessageHistoryViewTests: XCTestCase {
let messageId = MessageId(peerId: peerId, namespace: namespace, id: itemId)
if isAdd {
- addMessage(Int32(itemId), Int32(itemId))
+ let stableId = addMessage(Int32(itemId), Int32(itemId))
let attributesData = ReadBuffer(data: Data())
- let _ = loadedState.add(entry: .IntermediateMessageEntry(IntermediateMessage(stableId: UInt32(messageId.id), stableVersion: 0, id: messageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: itemId, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "", attributesData: attributesData, embeddedMediaData: attributesData, referencedMedia: []), nil, nil))
+ let _ = loadedState.add(entry: .IntermediateMessageEntry(IntermediateMessage(stableId: stableId, stableVersion: 0, id: messageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: itemId, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "", attributesData: attributesData, embeddedMediaData: attributesData, referencedMedia: []), nil, nil))
} else {
removeMessage(itemId)
- let _ = loadedState.remove(postbox: self.postbox!, index: MessageIndex(id: messageId, timestamp: itemId))
+ let _ = loadedState.remove(index: MessageIndex(id: messageId, timestamp: itemId))
}
let entries = loadedState.completeAndSample(postbox: self.postbox!).entries
@@ -350,12 +345,12 @@ class MessageHistoryViewTests: XCTestCase {
let clippedTestIds: [Int32]
if let index = testIds.firstIndex(where: { $0 > Int32(position) }), index >= 0 {
- clippedTestIds = extract(from: testIds, aroundIndex: index - 1, limit: limit)
+ clippedTestIds = extract(from: testIds, aroundIndex: index - 1, halfLimit: halfLimit)
} else {
- if limit >= testIds.count {
+ if halfLimit >= testIds.count {
clippedTestIds = testIds
} else {
- clippedTestIds = Array(testIds.dropFirst(testIds.count - limit))
+ clippedTestIds = Array(testIds.dropFirst(testIds.count - halfLimit))
}
}
@@ -371,7 +366,7 @@ class MessageHistoryViewTests: XCTestCase {
func testLoadInitialHole() {
addHole(1 ... 1000, space: .everywhere)
- var state = HistoryViewState(postbox: self.postbox!, inputAnchor: .message(MessageId(peerId: peerId, namespace: namespace, id: Int32(100))), tag: nil, limit: 10, locations: .single(peerId))
+ var state = HistoryViewState(postbox: self.postbox!, inputAnchor: .message(MessageId(peerId: peerId, namespace: namespace, id: Int32(100))), tag: nil, statistics: [], halfLimit: 10, locations: .single(peerId))
switch state {
case .loaded:
XCTAssert(false)
@@ -405,7 +400,7 @@ class MessageHistoryViewTests: XCTestCase {
default:
XCTAssert(false)
}
- state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: nil, limit: 10, locations: .single(peerId), postbox: self.postbox!, holes: holes))
+ state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: nil, statistics: [], halfLimit: 10, locations: .single(peerId), postbox: self.postbox!, holes: holes))
case .loadHole:
XCTAssert(false)
}
@@ -421,13 +416,13 @@ class MessageHistoryViewTests: XCTestCase {
}
func testEdgeHoles1() {
- addMessage(100, 100)
- addMessage(200, 200)
- addMessage(300, 300)
+ let _ = addMessage(100, 100)
+ let _ = addMessage(200, 200)
+ let _ = addMessage(300, 300)
addHole(1 ... 100, space: .everywhere)
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, limit: 10, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, statistics: [], halfLimit: 10, locations: .single(peerId))
guard case let .loaded(loadedState) = state else {
XCTAssert(false)
return
@@ -441,13 +436,13 @@ class MessageHistoryViewTests: XCTestCase {
}
func testEdgeHoles2() {
- addMessage(100, 100)
- addMessage(200, 200)
- addMessage(300, 300)
+ let _ = addMessage(100, 100)
+ let _ = addMessage(200, 200)
+ let _ = addMessage(300, 300)
addHole(1 ... 99, space: .everywhere)
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, limit: 10, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, statistics: [], halfLimit: 10, locations: .single(peerId))
guard case let .loaded(loadedState) = state else {
XCTAssert(false)
return
@@ -461,13 +456,13 @@ class MessageHistoryViewTests: XCTestCase {
}
func testEdgeHoles3() {
- addMessage(100, 100)
- addMessage(200, 200)
- addMessage(300, 300)
+ let _ = addMessage(100, 100)
+ let _ = addMessage(200, 200)
+ let _ = addMessage(300, 300)
addHole(300 ... 400, space: .everywhere)
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, limit: 10, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .upperBound, tag: nil, statistics: [], halfLimit: 10, locations: .single(peerId))
guard case let .loaded(loadedState) = state else {
XCTAssert(false)
return
@@ -475,19 +470,19 @@ class MessageHistoryViewTests: XCTestCase {
let sampledState = loadedState.completeAndSample(postbox: self.postbox!)
let ids = sampledState.entries.map({ $0.message.id.id })
XCTAssert(ids == [])
- XCTAssert(sampledState.hole == SampledHistoryViewHole(peerId: peerId, namespace: namespace, tag: nil, indices: IndexSet(integersIn: 300 ... 400), startId: 300, endId: 1))
- XCTAssert(sampledState.holesToHigher == true)
+ XCTAssert(sampledState.hole == SampledHistoryViewHole(peerId: peerId, namespace: namespace, tag: nil, indices: IndexSet(integersIn: 300 ... 400), startId: 400, endId: 1))
+ XCTAssert(sampledState.holesToHigher == false)
XCTAssert(sampledState.holesToLower == true)
}
func testEdgeHoles4() {
- addMessage(100, 100)
- addMessage(200, 200)
- addMessage(300, 300)
+ let _ = addMessage(100, 100)
+ let _ = addMessage(200, 200)
+ let _ = addMessage(300, 300)
addHole(300 ... 400, space: .everywhere)
- let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .message(MessageId(peerId: peerId, namespace: namespace, id: 200)), tag: nil, limit: 10, locations: .single(peerId))
+ let state = HistoryViewState(postbox: self.postbox!, inputAnchor: .message(MessageId(peerId: peerId, namespace: namespace, id: 200)), tag: nil, statistics: [], halfLimit: 10, locations: .single(peerId))
guard case let .loaded(loadedState) = state else {
XCTAssert(false)
return