Merge improved history view handling

This commit is contained in:
Ali
2019-12-06 10:43:49 +04:00
parent 88fe8966e8
commit c0f70aa421
9 changed files with 74 additions and 174 deletions

View File

@@ -645,14 +645,14 @@ final class MutableMessageHistoryView {
} }
} }
func firstHole() -> (MessageHistoryViewHole, MessageHistoryViewRelativeHoleDirection)? { func firstHole() -> (MessageHistoryViewHole, MessageHistoryViewRelativeHoleDirection, Int)? {
switch self.sampledState { switch self.sampledState {
case let .loading(loadingSample): case let .loading(loadingSample):
switch loadingSample { switch loadingSample {
case .ready: case .ready:
return nil return nil
case let .loadHole(peerId, namespace, _, id): case let .loadHole(peerId, namespace, _, id):
return (.peer(MessageHistoryViewPeerHole(peerId: peerId, namespace: namespace)), .aroundId(MessageId(peerId: peerId, namespace: namespace, id: id))) return (.peer(MessageHistoryViewPeerHole(peerId: peerId, namespace: namespace)), .aroundId(MessageId(peerId: peerId, namespace: namespace, id: id)), self.fillCount * 2)
} }
case let .loaded(loadedSample): case let .loaded(loadedSample):
if let hole = loadedSample.hole { if let hole = loadedSample.hole {
@@ -662,7 +662,7 @@ final class MutableMessageHistoryView {
} else { } else {
direction = .aroundId(MessageId(peerId: hole.peerId, namespace: hole.namespace, id: hole.startId)) direction = .aroundId(MessageId(peerId: hole.peerId, namespace: hole.namespace, id: hole.startId))
} }
return (.peer(MessageHistoryViewPeerHole(peerId: hole.peerId, namespace: hole.namespace)), direction) return (.peer(MessageHistoryViewPeerHole(peerId: hole.peerId, namespace: hole.namespace)), direction, self.fillCount * 2)
} else { } else {
return nil return nil
} }

View File

@@ -321,17 +321,6 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere
} }
} }
for item in items.lowerOrAtAnchor {
if item.index.id.id == 76891 {
assert(true)
}
}
for item in items.higherThanAnchor {
if item.index.id.id == 76891 {
assert(true)
}
}
var lowerOrAtAnchorHole: (distanceFromAnchor: Int, hole: SampledHistoryViewHole)? var lowerOrAtAnchorHole: (distanceFromAnchor: Int, hole: SampledHistoryViewHole)?
for i in (-1 ..< items.lowerOrAtAnchor.count).reversed() { for i in (-1 ..< items.lowerOrAtAnchor.count).reversed() {
@@ -500,103 +489,6 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere
sampledHole = (chosenHole.distanceFromAnchor, chosenHole.hole) sampledHole = (chosenHole.distanceFromAnchor, chosenHole.hole)
} }
} }
/*let anchorIndex = binaryIndexOrLower(items.entries, anchor)
let anchorStartingMessageId: MessageId.Id
if anchorIndex == -1 {
anchorStartingMessageId = 1
} else {
anchorStartingMessageId = items.entries[anchorIndex].index.id.id
}
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
var itemBoundaryMessageId: MessageId.Id = itemIndex.id.id
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
}
let toLowerRange: ClosedRange<Int> = min(Int(anchorStartingMessageId), Int(itemBoundaryMessageId)) ... max(Int(anchorStartingMessageId), Int(itemBoundaryMessageId))
if indices.intersects(integersIn: toLowerRange) {
var itemClipIndex: MessageIndex
if indices.contains(Int(previousBoundaryIndex.id.id)) {
itemClipIndex = previousBoundaryIndex
} else {
itemClipIndex = previousBoundaryIndex.predecessor()
}
clipRanges.append(MessageIndex.absoluteLowerBound() ... itemClipIndex)
var replaceHole = false
if let (currentItemIndex, _) = sampledHole {
if let currentItemIndex = currentItemIndex, abs(lowerDirectionIndex - anchorIndex) < abs(currentItemIndex - anchorIndex) {
replaceHole = true
}
} else {
replaceHole = true
}
if replaceHole {
if let idInHole = indices.integerLessThanOrEqualTo(toLowerRange.upperBound) {
sampledHole = (lowerDirectionIndex, SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: MessageId.Id(idInHole), endId: 1))
} else {
assertionFailure()
}
}
lowerDirectionIndex = -1
}
}
lowerDirectionIndex -= 1
if higherDirectionIndex < items.entries.count {
let itemIndex = items.entries[higherDirectionIndex].index
var itemBoundaryMessageId: MessageId.Id = itemIndex.id.id
if higherDirectionIndex == items.entries.count - 1 && itemBoundaryMessageId == bounds.upper.id.id {
itemBoundaryMessageId = Int32.max - 1
}
let previousBoundaryIndex: MessageIndex
if higherDirectionIndex == startingHigherDirectionIndex {
previousBoundaryIndex = itemIndex
} else {
previousBoundaryIndex = items.entries[higherDirectionIndex - 1].index
}
let toHigherRange: ClosedRange<Int> = min(Int(anchorStartingMessageId), Int(itemBoundaryMessageId)) ... max(Int(anchorStartingMessageId), Int(itemBoundaryMessageId))
if indices.intersects(integersIn: toHigherRange) {
var itemClipIndex: MessageIndex
if indices.contains(Int(previousBoundaryIndex.id.id)) {
itemClipIndex = previousBoundaryIndex
} else {
itemClipIndex = previousBoundaryIndex.successor()
}
clipRanges.append(itemClipIndex ... MessageIndex.absoluteUpperBound())
var replaceHole = false
if let (currentItemIndex, _) = sampledHole {
if let currentItemIndex = currentItemIndex, abs(higherDirectionIndex - anchorIndex) < abs(currentItemIndex - anchorIndex) {
replaceHole = true
}
} else {
replaceHole = true
}
if replaceHole {
if let idInHole = indices.integerGreaterThanOrEqualTo(toHigherRange.lowerBound) {
sampledHole = (higherDirectionIndex, SampledHistoryViewHole(peerId: space.peerId, namespace: space.namespace, tag: tag, indices: indices, startId: MessageId.Id(idInHole), endId: Int32.max - 1))
}
}
higherDirectionIndex = items.entries.count
}
}
higherDirectionIndex += 1
}*/
} }
return (clipRanges, sampledHole?.hole) return (clipRanges, sampledHole?.hole)
} }

View File

@@ -37,28 +37,30 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
self.location = location self.location = location
self.count = count self.count = count
var peerId: PeerId let mainPeerId: PeerId
let peerIds: MessageHistoryViewPeerIds
switch self.location { switch self.location {
case let .peer(id): case let .peer(id):
peerId = id mainPeerId = id
peerIds = postbox.peerIdsForLocation(.peer(id), tagMask: nil)
} }
var anchor: HistoryViewInputAnchor = .upperBound var anchor: HistoryViewInputAnchor = .upperBound
if let combinedState = postbox.readStateTable.getCombinedState(peerId), let state = combinedState.states.first, state.1.count != 0 { if let combinedState = postbox.readStateTable.getCombinedState(mainPeerId), let state = combinedState.states.first, state.1.count != 0 {
switch state.1 { switch state.1 {
case let .idBased(maxIncomingReadId, _, _, _, _): case let .idBased(maxIncomingReadId, _, _, _, _):
anchor = .message(MessageId(peerId: peerId, namespace: state.0, id: maxIncomingReadId)) anchor = .message(MessageId(peerId: mainPeerId, namespace: state.0, id: maxIncomingReadId))
case let .indexBased(maxIncomingReadIndex, _, _, _): case let .indexBased(maxIncomingReadIndex, _, _, _):
anchor = .index(maxIncomingReadIndex) anchor = .index(maxIncomingReadIndex)
} }
} }
self.anchor = anchor self.anchor = anchor
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], peerIds: .single(peerId), anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0})
let _ = self.updateFromView() let _ = self.updateFromView()
} }
private func updateFromView() -> Bool { private func updateFromView() -> Bool {
let closestHole: MessageOfInterestHole? let closestHole: MessageOfInterestHole?
if let (hole, direction) = self.wrappedView.firstHole() { if let (hole, direction, _) = self.wrappedView.firstHole() {
closestHole = MessageOfInterestHole(hole: hole, direction: direction) closestHole = MessageOfInterestHole(hole: hole, direction: direction)
} else { } else {
closestHole = nil closestHole = nil
@@ -105,6 +107,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
} }
var anchor: HistoryViewInputAnchor = self.anchor var anchor: HistoryViewInputAnchor = self.anchor
if transaction.alteredInitialPeerCombinedReadStates[peerId] != nil { if transaction.alteredInitialPeerCombinedReadStates[peerId] != nil {
var anchor: HistoryViewInputAnchor = .upperBound
if let combinedState = postbox.readStateTable.getCombinedState(peerId), let state = combinedState.states.first, state.1.count != 0 { if let combinedState = postbox.readStateTable.getCombinedState(peerId), let state = combinedState.states.first, state.1.count != 0 {
switch state.1 { switch state.1 {
case let .idBased(maxIncomingReadId, _, _, _, _): case let .idBased(maxIncomingReadId, _, _, _, _):
@@ -117,7 +120,12 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
if self.anchor != anchor { if self.anchor != anchor {
self.anchor = anchor self.anchor = anchor
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], peerIds: .single(peerId), anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) let peerIds: MessageHistoryViewPeerIds
switch self.location {
case let .peer(id):
peerIds = postbox.peerIdsForLocation(.peer(id), tagMask: nil)
}
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0})
return self.updateFromView() return self.updateFromView()
} else if self.wrappedView.replay(postbox: postbox, transaction: transaction) { } else if self.wrappedView.replay(postbox: postbox, transaction: transaction) {
return self.updateFromView() return self.updateFromView()

View File

@@ -2231,7 +2231,7 @@ public final class Postbox {
} }
} }
private func peerIdsForLocation(_ chatLocation: ChatLocation, tagMask: MessageTags?) -> MessageHistoryViewPeerIds { func peerIdsForLocation(_ chatLocation: ChatLocation, tagMask: MessageTags?) -> MessageHistoryViewPeerIds {
var peerIds: MessageHistoryViewPeerIds var peerIds: MessageHistoryViewPeerIds
switch chatLocation { switch chatLocation {
case let .peer(peerId): case let .peer(peerId):

View File

@@ -458,14 +458,14 @@ final class ViewTracker {
private func updateTrackedHoles() { private func updateTrackedHoles() {
var firstHolesAndTags = Set<MessageHistoryHolesViewEntry>() var firstHolesAndTags = Set<MessageHistoryHolesViewEntry>()
for (view, _) in self.messageHistoryViews.copyItems() { for (view, _) in self.messageHistoryViews.copyItems() {
if let (hole, direction) = view.firstHole() { if let (hole, direction, count) = view.firstHole() {
let space: MessageHistoryHoleSpace let space: MessageHistoryHoleSpace
if let tag = view.tag { if let tag = view.tag {
space = .tag(tag) space = .tag(tag)
} else { } else {
space = .everywhere space = .everywhere
} }
firstHolesAndTags.insert(MessageHistoryHolesViewEntry(hole: hole, direction: direction, space: space)) firstHolesAndTags.insert(MessageHistoryHolesViewEntry(hole: hole, direction: direction, space: space, count: count))
} }
} }

View File

@@ -121,7 +121,7 @@ func withResolvedAssociatedMessages(postbox: Postbox, source: FetchMessageHistor
|> switchToLatest |> switchToLatest
} }
func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryHoleSource, postbox: Postbox, peerId: PeerId, namespace: MessageId.Namespace, direction: MessageHistoryViewRelativeHoleDirection, space: MessageHistoryHoleSpace, limit: Int = 100) -> Signal<Never, NoError> { func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryHoleSource, postbox: Postbox, peerId: PeerId, namespace: MessageId.Namespace, direction: MessageHistoryViewRelativeHoleDirection, space: MessageHistoryHoleSpace, count: Int) -> Signal<Never, NoError> {
return postbox.stateView() return postbox.stateView()
|> mapToSignal { view -> Signal<AuthorizedAccountState, NoError> in |> mapToSignal { view -> Signal<AuthorizedAccountState, NoError> in
if let state = view.state as? AuthorizedAccountState { if let state = view.state as? AuthorizedAccountState {
@@ -136,8 +136,8 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|> take(1) |> take(1)
|> mapToSignal { peer in |> mapToSignal { peer in
if let inputPeer = forceApiInputPeer(peer) { if let inputPeer = forceApiInputPeer(peer) {
print("fetchMessageHistoryHole for \(peer.debugDisplayTitle) \(direction) space \(space)") print("fetchMessageHistoryHole for \(peer.id) \(peer.debugDisplayTitle) \(direction) space \(space)")
Logger.shared.log("fetchMessageHistoryHole", "fetch for \(peer.debugDisplayTitle) \(direction) space \(space)") Logger.shared.log("fetchMessageHistoryHole", "fetch for \(peer.id) \(peer.debugDisplayTitle) \(direction) space \(space)")
let request: Signal<Api.messages.Messages, MTRpcError> let request: Signal<Api.messages.Messages, MTRpcError>
var implicitelyFillHole = false var implicitelyFillHole = false
let minMaxRange: ClosedRange<MessageId.Id> let minMaxRange: ClosedRange<MessageId.Id>
@@ -146,7 +146,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
case .everywhere: case .everywhere:
let offsetId: Int32 let offsetId: Int32
let addOffset: Int32 let addOffset: Int32
let selectedLimit = limit let selectedLimit = count
let maxId: Int32 let maxId: Int32
let minId: Int32 let minId: Int32
@@ -195,7 +195,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
if tag == .unseenPersonalMessage { if tag == .unseenPersonalMessage {
let offsetId: Int32 let offsetId: Int32
let addOffset: Int32 let addOffset: Int32
let selectedLimit = limit let selectedLimit = count
let maxId: Int32 let maxId: Int32
let minId: Int32 let minId: Int32
@@ -241,7 +241,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
request = source.request(Api.functions.messages.getUnreadMentions(peer: inputPeer, offsetId: offsetId, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId)) request = source.request(Api.functions.messages.getUnreadMentions(peer: inputPeer, offsetId: offsetId, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId))
} else if tag == .liveLocation { } else if tag == .liveLocation {
let selectedLimit = limit let selectedLimit = count
switch direction { switch direction {
case .aroundId, .range: case .aroundId, .range:
@@ -252,7 +252,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
} else if let filter = messageFilterForTagMask(tag) { } else if let filter = messageFilterForTagMask(tag) {
let offsetId: Int32 let offsetId: Int32
let addOffset: Int32 let addOffset: Int32
let selectedLimit = limit let selectedLimit = count
let maxId: Int32 let maxId: Int32
let minId: Int32 let minId: Int32
@@ -391,7 +391,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
}) })
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences) updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
print("fetchMessageHistoryHole for \(peer.debugDisplayTitle) space \(space) done") print("fetchMessageHistoryHole for \(peer.id) \(peer.debugDisplayTitle) space \(space) done")
return return
}) })

View File

@@ -50,7 +50,7 @@ func managedMessageHistoryHoles(accountPeerId: PeerId, network: Network, postbox
for (entry, disposable) in added { for (entry, disposable) in added {
switch entry.hole { switch entry.hole {
case let .peer(hole): case let .peer(hole):
disposable.set(fetchMessageHistoryHole(accountPeerId: accountPeerId, source: .network(network), postbox: postbox, peerId: hole.peerId, namespace: hole.namespace, direction: entry.direction, space: entry.space).start()) disposable.set(fetchMessageHistoryHole(accountPeerId: accountPeerId, source: .network(network), postbox: postbox, peerId: hole.peerId, namespace: hole.namespace, direction: entry.direction, space: entry.space, count: entry.count).start())
} }
} }
}) })

View File

@@ -14,7 +14,7 @@ import TemporaryCachedPeerDataManager
import ChatListSearchItemNode import ChatListSearchItemNode
import Emoji import Emoji
private let historyMessageCount: Int = 100 private let historyMessageCount: Int = 90
public enum ChatHistoryListMode: Equatable { public enum ChatHistoryListMode: Equatable {
case bubbles case bubbles

View File

@@ -206,7 +206,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: A
let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up
let chatScrollPosition = ChatHistoryViewScrollPosition.index(index: index, position: scrollPosition, directionHint: directionHint, animated: animated) let chatScrollPosition = ChatHistoryViewScrollPosition.index(index: index, position: scrollPosition, directionHint: directionHint, animated: animated)
var first = true var first = true
return account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: index, anchorIndex: anchorIndex, count: 100, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) return account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: index, anchorIndex: anchorIndex, count: 128, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData)
|> map { view, updateType, initialData -> ChatHistoryViewUpdate in |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation)