diff --git a/Postbox/AccountManager.swift b/Postbox/AccountManager.swift index 716a9a083b..24d3ba0e45 100644 --- a/Postbox/AccountManager.swift +++ b/Postbox/AccountManager.swift @@ -8,7 +8,7 @@ import Foundation public struct AccountManagerModifier { public let getRecords: () -> [AccountRecord] public let updateRecord: (AccountRecordId, (AccountRecord?) -> (AccountRecord?)) -> Void - public let getCurrentId: () -> AccountRecordId? + public let getCurrent: () -> (AccountRecordId, [AccountRecordAttribute])? public let setCurrentId: (AccountRecordId) -> Void public let createRecord: ([AccountRecordAttribute]) -> AccountRecordId public let getSharedData: (ValueBoxKey) -> AccountSharedData? @@ -68,8 +68,13 @@ final class AccountManagerImpl { if updated != current { self.recordTable.setRecord(id: id, record: updated, operations: &self.currentRecordOperations) } - }, getCurrentId: { - return self.metadataTable.getCurrentAccountId() + }, getCurrent: { + if let id = self.metadataTable.getCurrentAccountId() { + let record = self.recordTable.getRecord(id: id) + return (id, record?.attributes ?? []) + } else { + return nil + } }, setCurrentId: { id in self.metadataTable.setCurrentAccountId(id, operations: &self.currentMetadataOperations) }, createRecord: { attributes in @@ -179,32 +184,54 @@ final class AccountManagerImpl { } } - fileprivate func currentAccountId(allocateIfNotExists: Bool) -> Signal { - return self.transaction { transaction -> Signal in - let current = transaction.getCurrentId() - let id: AccountRecordId + fileprivate func currentAccountRecord(allocateIfNotExists: Bool) -> Signal<(AccountRecordId, [AccountRecordAttribute])?, NoError> { + return self.transaction { transaction -> Signal<(AccountRecordId, [AccountRecordAttribute])?, NoError> in + let current = transaction.getCurrent() + let record: (AccountRecordId, [AccountRecordAttribute])? if let current = current { - id = current + record = current } else if allocateIfNotExists { - id = generateAccountRecordId() + let id = generateAccountRecordId() transaction.setCurrentId(id) transaction.updateRecord(id, { _ in return AccountRecord(id: id, attributes: [], temporarySessionId: nil) }) + record = (id, []) } else { return .single(nil) } let signal = self.accountRecordsInternal(transaction: transaction) - |> map { view -> AccountRecordId? in - return view.currentRecord?.id + |> map { view -> (AccountRecordId, [AccountRecordAttribute])? in + if let currentRecord = view.currentRecord { + return (currentRecord.id, currentRecord.attributes) + } else { + return nil + } } return signal } |> switchToLatest |> distinctUntilChanged(isEqual: { lhs, rhs in - return lhs == rhs + if let lhs = lhs, let rhs = rhs { + if lhs.0 != rhs.0 { + return false + } + if lhs.1.count != rhs.1.count { + return false + } + for i in 0 ..< lhs.1.count { + if !lhs.1[i].isEqual(to: rhs.1[i]) { + return false + } + } + return true + } else if (lhs != nil) != (rhs != nil) { + return false + } else { + return true + } }) } @@ -283,11 +310,11 @@ public final class AccountManager { } } - public func currentAccountId(allocateIfNotExists: Bool) -> Signal { + public func currentAccountRecord(allocateIfNotExists: Bool) -> Signal<(AccountRecordId, [AccountRecordAttribute])?, NoError> { return Signal { subscriber in let disposable = MetaDisposable() self.impl.with { impl in - disposable.set(impl.currentAccountId(allocateIfNotExists: allocateIfNotExists).start(next: { next in + disposable.set(impl.currentAccountRecord(allocateIfNotExists: allocateIfNotExists).start(next: { next in subscriber.putNext(next) }, completed: { subscriber.putCompletion() diff --git a/Postbox/ChatListView.swift b/Postbox/ChatListView.swift index 6fe9fd8de8..90697b2ca7 100644 --- a/Postbox/ChatListView.swift +++ b/Postbox/ChatListView.swift @@ -146,6 +146,23 @@ public enum ChatListEntry: Comparable { } } +private func processedChatListEntry(_ entry: MutableChatListEntry, cachedDataTable: CachedPeerDataTable, readStateTable: MessageHistoryReadStateTable, messageHistoryTable: MessageHistoryTable) -> MutableChatListEntry { + switch entry { + case let .IntermediateMessageEntry(index, message, readState, embeddedState): + var updatedMessage = message + if let message = message, let cachedData = cachedDataTable.get(message.id.peerId), let associatedHistoryMessageId = cachedData.associatedHistoryMessageId, message.id.id == 1 { + if let indexEntry = messageHistoryTable.messageHistoryIndexTable.earlierEntries(id: associatedHistoryMessageId, count: 1).first, case let .Message(messageIndex) = indexEntry { + if let associatedMessage = messageHistoryTable.getMessage(messageIndex) { + updatedMessage = associatedMessage + } + } + } + return .IntermediateMessageEntry(index, updatedMessage, readState, embeddedState) + default: + return entry + } +} + enum MutableChatListEntry: Equatable { case IntermediateMessageEntry(ChatListIndex, IntermediateMessage?, CombinedPeerReadState?, PeerChatListEmbeddedInterfaceState?) case MessageEntry(ChatListIndex, Message?, CombinedPeerReadState?, PeerNotificationSettings?, PeerChatListEmbeddedInterfaceState?, RenderedPeer, ChatListMessageTagSummaryInfo) @@ -153,10 +170,10 @@ enum MutableChatListEntry: Equatable { case IntermediateGroupReferenceEntry(PeerGroupId, ChatListIndex, ChatListGroupReferenceUnreadCounters?) case GroupReferenceEntry(PeerGroupId, ChatListIndex, Message?, ChatListGroupReferenceTopPeers, ChatListGroupReferenceUnreadCounters) - init(_ intermediateEntry: ChatListIntermediateEntry, readStateTable: MessageHistoryReadStateTable) { + init(_ intermediateEntry: ChatListIntermediateEntry, cachedDataTable: CachedPeerDataTable, readStateTable: MessageHistoryReadStateTable, messageHistoryTable: MessageHistoryTable) { switch intermediateEntry { case let .message(index, message, embeddedState): - self = .IntermediateMessageEntry(index, message, readStateTable.getCombinedState(index.messageIndex.id.peerId), embeddedState) + self = processedChatListEntry(.IntermediateMessageEntry(index, message, readStateTable.getCombinedState(index.messageIndex.id.peerId), embeddedState), cachedDataTable: cachedDataTable, readStateTable: readStateTable, messageHistoryTable: messageHistoryTable) case let .hole(hole): self = .HoleEntry(hole) case let .groupReference(groupId, index): @@ -307,7 +324,7 @@ final class MutableChatListView { self.additionalItemIds = Set(itemIds) for peerId in itemIds { if let entry = postbox.chatListTable.getStandalone(peerId: peerId, messageHistoryTable: postbox.messageHistoryTable) { - self.additionalItemEntries.append(MutableChatListEntry(entry, readStateTable: postbox.readStateTable)) + self.additionalItemEntries.append(MutableChatListEntry(entry, cachedDataTable: postbox.cachedPeerDataTable, readStateTable: postbox.readStateTable, messageHistoryTable: postbox.messageHistoryTable)) } } } else { @@ -356,15 +373,15 @@ final class MutableChatListView { for operation in groupOperations { switch operation { case let .InsertEntry(index, message, combinedReadState, embeddedState): - if self.add(.IntermediateMessageEntry(index, message, combinedReadState, embeddedState)) { + if self.add(.IntermediateMessageEntry(index, message, combinedReadState, embeddedState), postbox: postbox) { hasChanges = true } case let .InsertHole(index): - if self.add(.HoleEntry(index)) { + if self.add(.HoleEntry(index), postbox: postbox) { hasChanges = true } case let .InsertGroupReference(groupId, index): - if self.add(.IntermediateGroupReferenceEntry(groupId, index, cachedGroupCounters[groupId] ?? ChatListGroupReferenceUnreadCounters(postbox: postbox, groupId: groupId))) { + if self.add(.IntermediateGroupReferenceEntry(groupId, index, cachedGroupCounters[groupId] ?? ChatListGroupReferenceUnreadCounters(postbox: postbox, groupId: groupId)), postbox: postbox) { hasChanges = true } case let .RemoveEntry(indices): @@ -494,7 +511,7 @@ final class MutableChatListView { self.additionalItemEntries.removeAll() for peerId in postbox.additionalChatListItemsTable.get() { if let entry = postbox.chatListTable.getStandalone(peerId: peerId, messageHistoryTable: postbox.messageHistoryTable) { - self.additionalItemEntries.append(MutableChatListEntry(entry, readStateTable: postbox.readStateTable)) + self.additionalItemEntries.append(MutableChatListEntry(entry, cachedDataTable: postbox.cachedPeerDataTable, readStateTable: postbox.readStateTable, messageHistoryTable: postbox.messageHistoryTable)) } } hasChanges = true @@ -502,7 +519,8 @@ final class MutableChatListView { return hasChanges } - func add(_ entry: MutableChatListEntry) -> Bool { + func add(_ initialEntry: MutableChatListEntry, postbox: Postbox) -> Bool { + let entry = processedChatListEntry(initialEntry, cachedDataTable: postbox.cachedPeerDataTable, readStateTable: postbox.readStateTable, messageHistoryTable: postbox.messageHistoryTable) if self.entries.count == 0 { self.entries.append(entry) return true diff --git a/Postbox/Postbox.swift b/Postbox/Postbox.swift index 563d0c37ed..a65733f227 100644 --- a/Postbox/Postbox.swift +++ b/Postbox/Postbox.swift @@ -1861,13 +1861,13 @@ public final class Postbox { func fetchAroundChatEntries(groupId: PeerGroupId?, index: ChatListIndex, count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?) { let (intermediateEntries, intermediateLower, intermediateUpper) = self.chatListTable.entriesAround(groupId: groupId, index: index, messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in - return MutableChatListEntry(entry, readStateTable: self.readStateTable) + return MutableChatListEntry(entry, cachedDataTable: self.cachedPeerDataTable, readStateTable: self.readStateTable, messageHistoryTable: self.messageHistoryTable) } let lower: MutableChatListEntry? = intermediateLower.flatMap { entry in - return MutableChatListEntry(entry, readStateTable: self.readStateTable) + return MutableChatListEntry(entry, cachedDataTable: self.cachedPeerDataTable, readStateTable: self.readStateTable, messageHistoryTable: self.messageHistoryTable) } let upper: MutableChatListEntry? = intermediateUpper.flatMap { entry in - return MutableChatListEntry(entry, readStateTable: self.readStateTable) + return MutableChatListEntry(entry, cachedDataTable: self.cachedPeerDataTable, readStateTable: self.readStateTable, messageHistoryTable: self.messageHistoryTable) } return (entries, lower, upper) @@ -1876,7 +1876,7 @@ public final class Postbox { func fetchEarlierChatEntries(groupId: PeerGroupId?, index: ChatListIndex?, count: Int) -> [MutableChatListEntry] { let intermediateEntries = self.chatListTable.earlierEntries(groupId: groupId, index: index, messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in - return MutableChatListEntry(entry, readStateTable: self.readStateTable) + return MutableChatListEntry(entry, cachedDataTable: self.cachedPeerDataTable, readStateTable: self.readStateTable, messageHistoryTable: self.messageHistoryTable) } return entries } @@ -1884,7 +1884,7 @@ public final class Postbox { func fetchLaterChatEntries(groupId: PeerGroupId?, index: ChatListIndex?, count: Int) -> [MutableChatListEntry] { let intermediateEntries = self.chatListTable.laterEntries(groupId: groupId, index: index, messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in - return MutableChatListEntry(entry, readStateTable: self.readStateTable) + return MutableChatListEntry(entry, cachedDataTable: self.cachedPeerDataTable, readStateTable: self.readStateTable, messageHistoryTable: self.messageHistoryTable) } return entries }