diff --git a/Postbox/ItemCollectionsView.swift b/Postbox/ItemCollectionsView.swift index 7b8157be81..437e810507 100644 --- a/Postbox/ItemCollectionsView.swift +++ b/Postbox/ItemCollectionsView.swift @@ -156,13 +156,85 @@ private func aroundEntries(namespaces: [ItemCollectionId.Namespace], final class MutableItemCollectionsView { let orderedItemListsViews: [MutableOrderedItemListView] let namespaces: [ItemCollectionId.Namespace] + let requestedAroundIndex: ItemCollectionViewEntryIndex? + let requestedCount: Int var collectionInfos: [(ItemCollectionId, ItemCollectionInfo, ItemCollectionItem?)] var entries: [ItemCollectionViewEntry] var lower: ItemCollectionViewEntry? var higher: ItemCollectionViewEntry? - init(orderedItemListsViews: [MutableOrderedItemListView], namespaces: [ItemCollectionId.Namespace], aroundIndex: ItemCollectionViewEntryIndex?, count: Int, getInfos: (_ namespace: ItemCollectionId.Namespace) -> [(Int, ItemCollectionId, ItemCollectionInfo)], lowerCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, lowerItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem], higherCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, higherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) { + init(postbox: Postbox, orderedItemListsViews: [MutableOrderedItemListView], namespaces: [ItemCollectionId.Namespace], aroundIndex: ItemCollectionViewEntryIndex?, count: Int) { + self.orderedItemListsViews = orderedItemListsViews + self.namespaces = namespaces + self.requestedAroundIndex = aroundIndex + self.requestedCount = count + + self.collectionInfos = [] + self.entries = [] + self.lower = nil + self.higher = nil + + self.reload(postbox: postbox, aroundIndex: aroundIndex, count: count) + } + + private func lowerItems(postbox: Postbox, collectionId: ItemCollectionId, itemIndex: ItemCollectionItemIndex, count: Int) -> [ItemCollectionItem] { + return postbox.itemCollectionItemTable.lowerItems(collectionId: collectionId, itemIndex: itemIndex, count: count) + } + + private func higherItems(postbox: Postbox, collectionId: ItemCollectionId, itemIndex: ItemCollectionItemIndex, count: Int) -> [ItemCollectionItem] { + return postbox.itemCollectionItemTable.higherItems(collectionId: collectionId, itemIndex: itemIndex, count: count) + } + + private func lowerCollectionId(postbox: Postbox, namespaceList: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32) -> (ItemCollectionId, Int32)? { + return postbox.itemCollectionInfoTable.lowerCollectionId(namespaceList: namespaceList, collectionId: collectionId, index: collectionIndex) + } + + private func higherCollectionId(postbox: Postbox, namespaceList: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32) -> (ItemCollectionId, Int32)? { + return postbox.itemCollectionInfoTable.higherCollectionId(namespaceList: namespaceList, collectionId: collectionId, index: collectionIndex) + } + + private func reload(postbox: Postbox, aroundIndex: ItemCollectionViewEntryIndex?, count: Int) { + self.collectionInfos = [] + for namespace in namespaces { + for (_, id, info) in postbox.itemCollectionInfoTable.getInfos(namespace: namespace) { + let item = self.higherItems(postbox: postbox, collectionId: id, itemIndex: ItemCollectionItemIndex.lowerBound, count: 1).first + self.collectionInfos.append((id, info, item)) + } + } + + let selectedAroundIndex: ItemCollectionViewEntryIndex + if let aroundIndex = aroundIndex { + selectedAroundIndex = aroundIndex + } else { + selectedAroundIndex = ItemCollectionViewEntryIndex(collectionIndex: 0, collectionId: ItemCollectionId(namespace: namespaces[0], id: 0), itemIndex: ItemCollectionItemIndex.lowerBound) + } + + let (entries, lower, higher) = aroundEntries(namespaces: namespaces, + collectionId: selectedAroundIndex.collectionId, + collectionIndex: selectedAroundIndex.collectionIndex, + itemIndex: selectedAroundIndex.itemIndex, + count: count, + lowerCollectionId: { namespaceList, collectionId, collectionIndex in + return self.lowerCollectionId(postbox: postbox, namespaceList: namespaceList, collectionId: collectionId, collectionIndex: collectionIndex) + }, + fetchLowerItems: { collectionId, itemIndex, count in + return self.lowerItems(postbox: postbox, collectionId: collectionId, itemIndex: itemIndex, count: count) + }, + higherCollectionId: { namespaceList, collectionId, collectionIndex in + return self.higherCollectionId(postbox: postbox, namespaceList: namespaceList, collectionId: collectionId, collectionIndex: collectionIndex) + }, + fetchHigherItems: { + collectionId, itemIndex, count in + return self.higherItems(postbox: postbox, collectionId: collectionId, itemIndex: itemIndex, count: count) + }) + + self.entries = entries + self.lower = lower + self.higher = higher + } + + /*init(orderedItemListsViews: [MutableOrderedItemListView], namespaces: [ItemCollectionId.Namespace], aroundIndex: ItemCollectionViewEntryIndex?, count: Int, getInfos: (_ namespace: ItemCollectionId.Namespace) -> [(Int, ItemCollectionId, ItemCollectionInfo)], lowerCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, lowerItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem], higherCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, higherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) { self.orderedItemListsViews = orderedItemListsViews self.namespaces = namespaces @@ -194,15 +266,52 @@ final class MutableItemCollectionsView { self.entries = entries self.lower = lower self.higher = higher - } + }*/ - func replay(orderedItemListOperations: [Int32: [OrderedItemListOperation]]) -> Bool { + func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool { var updated = false - for view in self.orderedItemListsViews { - if view.replay(operations: orderedItemListOperations) { - updated = true + + if !transaction.currentOrderedItemListOperations.isEmpty { + for view in self.orderedItemListsViews { + if view.replay(operations: transaction.currentOrderedItemListOperations) { + updated = true + } } } + + + var reloadNamespaces = Set() + for operation in transaction.currentItemCollectionInfosOperations { + switch operation { + case let .replaceInfos(namespace): + reloadNamespaces.insert(namespace) + } + } + + for (id, operations) in transaction.currentItemCollectionItemsOperations { + for operation in operations { + switch operation { + case .replaceItems: + reloadNamespaces.insert(id.namespace) + } + } + } + + var shouldReloadEntries = false + if !reloadNamespaces.isEmpty { + for namespace in self.namespaces { + if reloadNamespaces.contains(namespace) { + shouldReloadEntries = true + break + } + } + } + + if shouldReloadEntries { + self.reload(postbox: postbox, aroundIndex: self.requestedAroundIndex, count: self.requestedCount) + updated = true + } + return updated } } diff --git a/Postbox/Postbox.swift b/Postbox/Postbox.swift index afa42b0dfc..8ee7381b24 100644 --- a/Postbox/Postbox.swift +++ b/Postbox/Postbox.swift @@ -15,6 +15,11 @@ public protocol PeerChatState: Coding { func equals(_ other: PeerChatState) -> Bool } +public enum PostboxUpdateMessage { + case update(StoreMessage) + case skip +} + public final class Modifier { private weak var postbox: Postbox? @@ -199,7 +204,7 @@ public final class Modifier { self.postbox?.replaceRecentPeerIds(peerIds) } - public func updateMessage(_ id: MessageId, update: (Message) -> StoreMessage) { + public func updateMessage(_ id: MessageId, update: (Message) -> PostboxUpdateMessage) { self.postbox?.updateMessage(id, update: update) } @@ -1258,10 +1263,12 @@ public final class Postbox { self.peerRatingTable.replace(items: peerIds) } - fileprivate func updateMessage(_ id: MessageId, update: (Message) -> StoreMessage) { + fileprivate func updateMessage(_ id: MessageId, update: (Message) -> PostboxUpdateMessage) { if let indexEntry = self.messageHistoryIndexTable.get(id), let intermediateMessage = self.messageHistoryTable.getMessage(indexEntry.index) { let message = self.renderIntermediateMessage(intermediateMessage) - self.messageHistoryTable.updateMessage(id, message: update(message), operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: &self.currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations) + if case let .update(updatedMessage) = update(message) { + self.messageHistoryTable.updateMessage(id, message: updatedMessage, operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: &self.currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations) + } } } @@ -1799,17 +1806,7 @@ public final class Postbox { }) } - let mutableView = MutableItemCollectionsView(orderedItemListsViews: itemListViews, namespaces: namespaces, aroundIndex: aroundIndex, count: count, getInfos: { namespace in - return self.itemCollectionInfoTable.getInfos(namespace: namespace) - }, lowerCollectionId: { namespaceList, collectionId, collectionIndex in - return self.itemCollectionInfoTable.lowerCollectionId(namespaceList: namespaceList, collectionId: collectionId, index: collectionIndex) - }, lowerItems: { collectionId, itemIndex, count in - return self.itemCollectionItemTable.lowerItems(collectionId: collectionId, itemIndex: itemIndex, count: count) - }, higherCollectionId: { namespaceList, collectionId, collectionIndex in - return self.itemCollectionInfoTable.higherCollectionId(namespaceList: namespaceList, collectionId: collectionId, index: collectionIndex) - }, higherItems: { collectionId, itemIndex, count in - return self.itemCollectionItemTable.higherItems(collectionId: collectionId, itemIndex: itemIndex, count: count) - }) + let mutableView = MutableItemCollectionsView(postbox: self, orderedItemListsViews: itemListViews, namespaces: namespaces, aroundIndex: aroundIndex, count: count) let (index, signal) = self.viewTracker.addItemCollectionView(mutableView) diff --git a/Postbox/ViewTracker.swift b/Postbox/ViewTracker.swift index 7c7205db74..5a71adc859 100644 --- a/Postbox/ViewTracker.swift +++ b/Postbox/ViewTracker.swift @@ -531,7 +531,7 @@ final class ViewTracker { } for (mutableView, pipe) in self.itemCollectionsViews.copyItems() { - if mutableView.replay(orderedItemListOperations: transaction.currentOrderedItemListOperations) { + if mutableView.replay(postbox: postbox, transaction: transaction) { pipe.putNext(ItemCollectionsView(mutableView)) } }