mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
c5d5d97d8c
@ -596,7 +596,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
return (state, filterId)
|
return (state, filterId)
|
||||||
})
|
})
|
||||||
|
|
||||||
if self.controlsHistoryPreload {
|
if self.controlsHistoryPreload, case .chatList(groupId: .root) = self.location {
|
||||||
self.context.account.viewTracker.chatListPreloadItems.set(combineLatest(queue: .mainQueue(),
|
self.context.account.viewTracker.chatListPreloadItems.set(combineLatest(queue: .mainQueue(),
|
||||||
context.sharedContext.hasOngoingCall.get(),
|
context.sharedContext.hasOngoingCall.get(),
|
||||||
itemNode.listNode.preloadItems.get()
|
itemNode.listNode.preloadItems.get()
|
||||||
|
@ -2955,7 +2955,7 @@ final class PostboxImpl {
|
|||||||
return ActionDisposable { [weak self] in
|
return ActionDisposable { [weak self] in
|
||||||
disposable.dispose()
|
disposable.dispose()
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.queue.async {
|
strongSelf.queue.justDispatch {
|
||||||
strongSelf.viewTracker.removeMessageHistoryView(index: index)
|
strongSelf.viewTracker.removeMessageHistoryView(index: index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,38 @@ enum StateResetForumTopics {
|
|||||||
case error(PeerId)
|
case error(PeerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ReferencedReplyMessageIds {
|
||||||
|
var targetIdsBySourceId: [MessageId: MessageId] = [:]
|
||||||
|
|
||||||
|
var isEmpty: Bool {
|
||||||
|
return self.targetIdsBySourceId.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func add(sourceId: MessageId, targetId: MessageId) {
|
||||||
|
if self.targetIdsBySourceId[targetId] == nil {
|
||||||
|
self.targetIdsBySourceId[targetId] = sourceId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func formUnion(_ other: ReferencedReplyMessageIds) {
|
||||||
|
for (targetId, sourceId) in other.targetIdsBySourceId {
|
||||||
|
if self.targetIdsBySourceId[targetId] == nil {
|
||||||
|
self.targetIdsBySourceId[targetId] = sourceId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func subtractingStoredIds(_ ids: Set<MessageId>) -> ReferencedReplyMessageIds {
|
||||||
|
var result = ReferencedReplyMessageIds()
|
||||||
|
for (targetId, sourceId) in self.targetIdsBySourceId {
|
||||||
|
if !ids.contains(targetId) {
|
||||||
|
result.add(sourceId: sourceId, targetId: targetId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AccountMutableState {
|
struct AccountMutableState {
|
||||||
let initialState: AccountInitialState
|
let initialState: AccountInitialState
|
||||||
let branchOperationIndex: Int
|
let branchOperationIndex: Int
|
||||||
@ -153,7 +185,8 @@ struct AccountMutableState {
|
|||||||
var peers: [PeerId: Peer]
|
var peers: [PeerId: Peer]
|
||||||
var channelStates: [PeerId: AccountStateChannelState]
|
var channelStates: [PeerId: AccountStateChannelState]
|
||||||
var peerChatInfos: [PeerId: PeerChatInfo]
|
var peerChatInfos: [PeerId: PeerChatInfo]
|
||||||
var referencedMessageIds: Set<MessageId>
|
var referencedReplyMessageIds: ReferencedReplyMessageIds
|
||||||
|
var referencedGeneralMessageIds: Set<MessageId>
|
||||||
var storedMessages: Set<MessageId>
|
var storedMessages: Set<MessageId>
|
||||||
var readInboxMaxIds: [PeerId: MessageId]
|
var readInboxMaxIds: [PeerId: MessageId]
|
||||||
var namespacesWithHolesFromPreviousState: [PeerId: [MessageId.Namespace: HoleFromPreviousState]]
|
var namespacesWithHolesFromPreviousState: [PeerId: [MessageId.Namespace: HoleFromPreviousState]]
|
||||||
@ -176,11 +209,12 @@ struct AccountMutableState {
|
|||||||
|
|
||||||
var authorizationListUpdated: Bool = false
|
var authorizationListUpdated: Bool = false
|
||||||
|
|
||||||
init(initialState: AccountInitialState, initialPeers: [PeerId: Peer], initialReferencedMessageIds: Set<MessageId>, initialStoredMessages: Set<MessageId>, initialReadInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>]) {
|
init(initialState: AccountInitialState, initialPeers: [PeerId: Peer], initialReferencedReplyMessageIds: ReferencedReplyMessageIds, initialReferencedGeneralMessageIds: Set<MessageId>, initialStoredMessages: Set<MessageId>, initialReadInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>]) {
|
||||||
self.initialState = initialState
|
self.initialState = initialState
|
||||||
self.state = initialState.state
|
self.state = initialState.state
|
||||||
self.peers = initialPeers
|
self.peers = initialPeers
|
||||||
self.referencedMessageIds = initialReferencedMessageIds
|
self.referencedReplyMessageIds = initialReferencedReplyMessageIds
|
||||||
|
self.referencedGeneralMessageIds = initialReferencedGeneralMessageIds
|
||||||
self.storedMessages = initialStoredMessages
|
self.storedMessages = initialStoredMessages
|
||||||
self.readInboxMaxIds = initialReadInboxMaxIds
|
self.readInboxMaxIds = initialReadInboxMaxIds
|
||||||
self.channelStates = initialState.channelStates
|
self.channelStates = initialState.channelStates
|
||||||
@ -191,13 +225,14 @@ struct AccountMutableState {
|
|||||||
self.updatedOutgoingUniqueMessageIds = [:]
|
self.updatedOutgoingUniqueMessageIds = [:]
|
||||||
}
|
}
|
||||||
|
|
||||||
init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: AccountStateChannelState], peerChatInfos: [PeerId: PeerChatInfo], referencedMessageIds: Set<MessageId>, storedMessages: Set<MessageId>, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>], namespacesWithHolesFromPreviousState: [PeerId: [MessageId.Namespace: HoleFromPreviousState]], updatedOutgoingUniqueMessageIds: [Int64: Int32], displayAlerts: [(text: String, isDropAuth: Bool)], dismissBotWebViews: [Int64], branchOperationIndex: Int) {
|
init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: AccountStateChannelState], peerChatInfos: [PeerId: PeerChatInfo], referencedReplyMessageIds: ReferencedReplyMessageIds, referencedGeneralMessageIds: Set<MessageId>, storedMessages: Set<MessageId>, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>], namespacesWithHolesFromPreviousState: [PeerId: [MessageId.Namespace: HoleFromPreviousState]], updatedOutgoingUniqueMessageIds: [Int64: Int32], displayAlerts: [(text: String, isDropAuth: Bool)], dismissBotWebViews: [Int64], branchOperationIndex: Int) {
|
||||||
self.initialState = initialState
|
self.initialState = initialState
|
||||||
self.operations = operations
|
self.operations = operations
|
||||||
self.state = state
|
self.state = state
|
||||||
self.peers = peers
|
self.peers = peers
|
||||||
self.channelStates = channelStates
|
self.channelStates = channelStates
|
||||||
self.referencedMessageIds = referencedMessageIds
|
self.referencedReplyMessageIds = referencedReplyMessageIds
|
||||||
|
self.referencedGeneralMessageIds = referencedGeneralMessageIds
|
||||||
self.storedMessages = storedMessages
|
self.storedMessages = storedMessages
|
||||||
self.peerChatInfos = peerChatInfos
|
self.peerChatInfos = peerChatInfos
|
||||||
self.readInboxMaxIds = readInboxMaxIds
|
self.readInboxMaxIds = readInboxMaxIds
|
||||||
@ -210,11 +245,13 @@ struct AccountMutableState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func branch() -> AccountMutableState {
|
func branch() -> AccountMutableState {
|
||||||
return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerChatInfos: self.peerChatInfos, referencedMessageIds: self.referencedMessageIds, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, namespacesWithHolesFromPreviousState: self.namespacesWithHolesFromPreviousState, updatedOutgoingUniqueMessageIds: self.updatedOutgoingUniqueMessageIds, displayAlerts: self.displayAlerts, dismissBotWebViews: self.dismissBotWebViews, branchOperationIndex: self.operations.count)
|
return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerChatInfos: self.peerChatInfos, referencedReplyMessageIds: self.referencedReplyMessageIds, referencedGeneralMessageIds: self.referencedGeneralMessageIds, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, namespacesWithHolesFromPreviousState: self.namespacesWithHolesFromPreviousState, updatedOutgoingUniqueMessageIds: self.updatedOutgoingUniqueMessageIds, displayAlerts: self.displayAlerts, dismissBotWebViews: self.dismissBotWebViews, branchOperationIndex: self.operations.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func merge(_ other: AccountMutableState) {
|
mutating func merge(_ other: AccountMutableState) {
|
||||||
self.referencedMessageIds.formUnion(other.referencedMessageIds)
|
self.referencedReplyMessageIds.formUnion(other.referencedReplyMessageIds)
|
||||||
|
self.referencedGeneralMessageIds.formUnion(other.referencedGeneralMessageIds)
|
||||||
|
|
||||||
for i in other.branchOperationIndex ..< other.operations.count {
|
for i in other.branchOperationIndex ..< other.operations.count {
|
||||||
self.addOperation(other.operations[i])
|
self.addOperation(other.operations[i])
|
||||||
}
|
}
|
||||||
@ -567,26 +604,26 @@ struct AccountMutableState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
inner: for attribute in message.attributes {
|
inner: for attribute in message.attributes {
|
||||||
if let attribute = attribute as? ReplyMessageAttribute {
|
if let attribute = attribute as? ReplyMessageAttribute {
|
||||||
self.referencedMessageIds.insert(attribute.messageId)
|
self.referencedReplyMessageIds.add(sourceId: id, targetId: attribute.messageId)
|
||||||
break inner
|
break inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case let .AddScheduledMessages(messages):
|
case let .AddScheduledMessages(messages):
|
||||||
for message in messages {
|
for message in messages {
|
||||||
if case let .Id(id) = message.id {
|
if case let .Id(id) = message.id {
|
||||||
self.storedMessages.insert(id)
|
self.storedMessages.insert(id)
|
||||||
}
|
|
||||||
inner: for attribute in message.attributes {
|
inner: for attribute in message.attributes {
|
||||||
if let attribute = attribute as? ReplyMessageAttribute {
|
if let attribute = attribute as? ReplyMessageAttribute {
|
||||||
self.referencedMessageIds.insert(attribute.messageId)
|
self.referencedReplyMessageIds.add(sourceId: id, targetId: attribute.messageId)
|
||||||
break inner
|
break inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case let .UpdateState(state):
|
case let .UpdateState(state):
|
||||||
self.state = state
|
self.state = state
|
||||||
case let .UpdateChannelState(peerId, pts):
|
case let .UpdateChannelState(peerId, pts):
|
||||||
|
@ -236,24 +236,30 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> [MessageId]? {
|
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: ReferencedReplyMessageIds, generalIds: [MessageId])? {
|
||||||
switch message {
|
switch message {
|
||||||
case let .message(_, _, _, chatPeerId, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
case let .message(_, id, _, chatPeerId, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||||
if let replyTo = replyTo {
|
if let replyTo = replyTo {
|
||||||
let peerId: PeerId = chatPeerId.peerId
|
let peerId: PeerId = chatPeerId.peerId
|
||||||
|
|
||||||
switch replyTo {
|
switch replyTo {
|
||||||
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, _):
|
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, _):
|
||||||
return [MessageId(peerId: replyToPeerId?.peerId ?? peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)]
|
let targetId = MessageId(peerId: replyToPeerId?.peerId ?? peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
|
||||||
|
var replyIds = ReferencedReplyMessageIds()
|
||||||
|
replyIds.add(sourceId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), targetId: targetId)
|
||||||
|
return (replyIds, [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .messageEmpty:
|
case .messageEmpty:
|
||||||
break
|
break
|
||||||
case let .messageService(_, _, _, chatPeerId, replyHeader, _, _, _):
|
case let .messageService(_, id, _, chatPeerId, replyHeader, _, _, _):
|
||||||
if let replyHeader = replyHeader {
|
if let replyHeader = replyHeader {
|
||||||
switch replyHeader {
|
switch replyHeader {
|
||||||
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, _):
|
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, _):
|
||||||
return [MessageId(peerId: replyToPeerId?.peerId ?? chatPeerId.peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)]
|
let targetId = MessageId(peerId: replyToPeerId?.peerId ?? chatPeerId.peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
|
||||||
|
var replyIds = ReferencedReplyMessageIds()
|
||||||
|
replyIds.add(sourceId: MessageId(peerId: chatPeerId.peerId, namespace: Namespaces.Message.Cloud, id: id), targetId: targetId)
|
||||||
|
return (replyIds, [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,20 +88,20 @@ private func activeChannelsFromUpdateGroups(_ groups: [UpdateGroup]) -> Set<Peer
|
|||||||
return peerIds.intersection(peerIdsRequiringLocalChatStateFromUpdateGroups(groups))
|
return peerIds.intersection(peerIdsRequiringLocalChatStateFromUpdateGroups(groups))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func associatedMessageIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> Set<MessageId> {
|
private func associatedMessageIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> (replyIds: ReferencedReplyMessageIds, generalIds: Set<MessageId>) {
|
||||||
var messageIds = Set<MessageId>()
|
var replyIds = ReferencedReplyMessageIds()
|
||||||
|
var generalIds = Set<MessageId>()
|
||||||
|
|
||||||
for group in groups {
|
for group in groups {
|
||||||
for update in group.updates {
|
for update in group.updates {
|
||||||
if let associatedMessageIds = update.associatedMessageIds {
|
if let associatedMessageIds = update.associatedMessageIds {
|
||||||
for messageId in associatedMessageIds {
|
replyIds.formUnion(associatedMessageIds.replyIds)
|
||||||
messageIds.insert(messageId)
|
generalIds.formUnion(associatedMessageIds.generalIds)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return messageIds
|
return (replyIds, generalIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func peerIdsRequiringLocalChatStateFromUpdates(_ updates: [Api.Update]) -> Set<PeerId> {
|
private func peerIdsRequiringLocalChatStateFromUpdates(_ updates: [Api.Update]) -> Set<PeerId> {
|
||||||
@ -282,23 +282,22 @@ private func activeChannelsFromDifference(_ difference: Api.updates.Difference)
|
|||||||
return peerIds
|
return peerIds
|
||||||
}
|
}
|
||||||
|
|
||||||
private func associatedMessageIdsFromDifference(_ difference: Api.updates.Difference) -> Set<MessageId> {
|
private func associatedMessageIdsFromDifference(_ difference: Api.updates.Difference) -> (replyIds: ReferencedReplyMessageIds, generalIds: Set<MessageId>) {
|
||||||
var messageIds = Set<MessageId>()
|
var replyIds = ReferencedReplyMessageIds()
|
||||||
|
var generalIds = Set<MessageId>()
|
||||||
|
|
||||||
switch difference {
|
switch difference {
|
||||||
case let .difference(newMessages, _, otherUpdates, _, _, _):
|
case let .difference(newMessages, _, otherUpdates, _, _, _):
|
||||||
for message in newMessages {
|
for message in newMessages {
|
||||||
if let associatedMessageIds = apiMessageAssociatedMessageIds(message) {
|
if let associatedMessageIds = apiMessageAssociatedMessageIds(message) {
|
||||||
for messageId in associatedMessageIds {
|
replyIds.formUnion(associatedMessageIds.replyIds)
|
||||||
messageIds.insert(messageId)
|
generalIds.formUnion(associatedMessageIds.generalIds)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for update in otherUpdates {
|
for update in otherUpdates {
|
||||||
if let associatedMessageIds = update.associatedMessageIds {
|
if let associatedMessageIds = update.associatedMessageIds {
|
||||||
for messageId in associatedMessageIds {
|
replyIds.formUnion(associatedMessageIds.replyIds)
|
||||||
messageIds.insert(messageId)
|
generalIds.formUnion(associatedMessageIds.generalIds)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .differenceEmpty:
|
case .differenceEmpty:
|
||||||
@ -306,24 +305,22 @@ private func associatedMessageIdsFromDifference(_ difference: Api.updates.Differ
|
|||||||
case let .differenceSlice(newMessages, _, otherUpdates, _, _, _):
|
case let .differenceSlice(newMessages, _, otherUpdates, _, _, _):
|
||||||
for message in newMessages {
|
for message in newMessages {
|
||||||
if let associatedMessageIds = apiMessageAssociatedMessageIds(message) {
|
if let associatedMessageIds = apiMessageAssociatedMessageIds(message) {
|
||||||
for messageId in associatedMessageIds {
|
replyIds.formUnion(associatedMessageIds.replyIds)
|
||||||
messageIds.insert(messageId)
|
generalIds.formUnion(associatedMessageIds.generalIds)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for update in otherUpdates {
|
for update in otherUpdates {
|
||||||
if let associatedMessageIds = update.associatedMessageIds {
|
if let associatedMessageIds = update.associatedMessageIds {
|
||||||
for messageId in associatedMessageIds {
|
replyIds.formUnion(associatedMessageIds.replyIds)
|
||||||
messageIds.insert(messageId)
|
generalIds.formUnion(associatedMessageIds.generalIds)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .differenceTooLong:
|
case .differenceTooLong:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return messageIds
|
return (replyIds, generalIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func peerIdsRequiringLocalChatStateFromDifference(_ difference: Api.updates.Difference) -> Set<PeerId> {
|
private func peerIdsRequiringLocalChatStateFromDifference(_ difference: Api.updates.Difference) -> Set<PeerId> {
|
||||||
@ -424,7 +421,7 @@ private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.u
|
|||||||
return messageTimestamps
|
return messageTimestamps
|
||||||
}
|
}
|
||||||
|
|
||||||
private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<PeerId>, activeChannelIds: Set<PeerId>, associatedMessageIds: Set<MessageId>, peerIdsRequiringLocalChatState: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState {
|
private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<PeerId>, activeChannelIds: Set<PeerId>, referencedReplyMessageIds: ReferencedReplyMessageIds, referencedGeneralMessageIds: Set<MessageId>, peerIdsRequiringLocalChatState: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState {
|
||||||
var peers: [PeerId: Peer] = [:]
|
var peers: [PeerId: Peer] = [:]
|
||||||
var channelStates: [PeerId: AccountStateChannelState] = [:]
|
var channelStates: [PeerId: AccountStateChannelState] = [:]
|
||||||
|
|
||||||
@ -454,7 +451,8 @@ private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<Pe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let storedMessages = transaction.filterStoredMessageIds(associatedMessageIds)
|
let storedMessages = transaction.filterStoredMessageIds(Set(referencedReplyMessageIds.targetIdsBySourceId.keys).union(referencedGeneralMessageIds))
|
||||||
|
|
||||||
var storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>] = [:]
|
var storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>] = [:]
|
||||||
if !locallyGeneratedMessageTimestamps.isEmpty {
|
if !locallyGeneratedMessageTimestamps.isEmpty {
|
||||||
for (peerId, namespacesAndTimestamps) in locallyGeneratedMessageTimestamps {
|
for (peerId, namespacesAndTimestamps) in locallyGeneratedMessageTimestamps {
|
||||||
@ -517,7 +515,7 @@ private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<Pe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let state = AccountMutableState(initialState: AccountInitialState(state: (transaction.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps, cloudReadStates: cloudReadStates, channelsToPollExplicitely: channelsToPollExplicitely), initialPeers: peers, initialReferencedMessageIds: associatedMessageIds, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp)
|
let state = AccountMutableState(initialState: AccountInitialState(state: (transaction.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps, cloudReadStates: cloudReadStates, channelsToPollExplicitely: channelsToPollExplicitely), initialPeers: peers, initialReferencedReplyMessageIds: referencedReplyMessageIds, initialReferencedGeneralMessageIds: referencedGeneralMessageIds, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,7 +526,7 @@ func initialStateWithUpdateGroups(postbox: Postbox, groups: [UpdateGroup]) -> Si
|
|||||||
let associatedMessageIds = associatedMessageIdsFromUpdateGroups(groups)
|
let associatedMessageIds = associatedMessageIdsFromUpdateGroups(groups)
|
||||||
let peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatStateFromUpdateGroups(groups)
|
let peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatStateFromUpdateGroups(groups)
|
||||||
|
|
||||||
return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, associatedMessageIds: associatedMessageIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromUpdateGroups(groups))
|
return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, referencedReplyMessageIds: associatedMessageIds.replyIds, referencedGeneralMessageIds: associatedMessageIds.generalIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromUpdateGroups(groups))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +536,7 @@ func initialStateWithDifference(postbox: Postbox, difference: Api.updates.Differ
|
|||||||
let activeChannelIds = activeChannelsFromDifference(difference)
|
let activeChannelIds = activeChannelsFromDifference(difference)
|
||||||
let associatedMessageIds = associatedMessageIdsFromDifference(difference)
|
let associatedMessageIds = associatedMessageIdsFromDifference(difference)
|
||||||
let peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatStateFromDifference(difference)
|
let peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatStateFromDifference(difference)
|
||||||
return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, associatedMessageIds: associatedMessageIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromDifference(difference))
|
return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, referencedReplyMessageIds: associatedMessageIds.replyIds, referencedGeneralMessageIds: associatedMessageIds.generalIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromDifference(difference))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2058,8 +2056,10 @@ private func reactionsFromState(_ state: AccountMutableState) -> [MessageReactio
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func resolveAssociatedMessages(postbox: Postbox, network: Network, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
private func resolveAssociatedMessages(postbox: Postbox, network: Network, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
||||||
let missingMessageIds = state.referencedMessageIds.subtracting(state.storedMessages)
|
let missingReplyMessageIds = state.referencedReplyMessageIds.subtractingStoredIds(state.storedMessages)
|
||||||
if missingMessageIds.isEmpty {
|
let missingGeneralMessageIds = state.referencedGeneralMessageIds.subtracting(state.storedMessages)
|
||||||
|
|
||||||
|
if missingReplyMessageIds.isEmpty && missingGeneralMessageIds.isEmpty {
|
||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: state), reactions: reactionsFromState(state), result: state)
|
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: state), reactions: reactionsFromState(state), result: state)
|
||||||
|> mapToSignal { state in
|
|> mapToSignal { state in
|
||||||
return resolveForumThreads(postbox: postbox, network: network, state: state)
|
return resolveForumThreads(postbox: postbox, network: network, state: state)
|
||||||
@ -2069,7 +2069,38 @@ private func resolveAssociatedMessages(postbox: Postbox, network: Network, state
|
|||||||
let _ = missingPeers
|
let _ = missingPeers
|
||||||
|
|
||||||
var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = []
|
var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = []
|
||||||
for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingMessageIds) {
|
for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingReplyMessageIds) {
|
||||||
|
if let peer = state.peers[peerId] {
|
||||||
|
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
||||||
|
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||||
|
signal = network.request(Api.functions.messages.getMessages(id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
|
||||||
|
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
if let inputChannel = apiInputChannel(peer) {
|
||||||
|
signal = network.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let signal = signal {
|
||||||
|
signals.append(signal |> map { result in
|
||||||
|
switch result {
|
||||||
|
case let .messages(messages, chats, users):
|
||||||
|
return (messages, chats, users)
|
||||||
|
case let .messagesSlice(_, _, _, _, messages, chats, users):
|
||||||
|
return (messages, chats, users)
|
||||||
|
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
|
||||||
|
let _ = apiTopics
|
||||||
|
return (messages, chats, users)
|
||||||
|
case .messagesNotModified:
|
||||||
|
return ([], [], [])
|
||||||
|
}
|
||||||
|
} |> `catch` { _ in
|
||||||
|
return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], []))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
missingPeers = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingGeneralMessageIds) {
|
||||||
if let peer = state.peers[peerId] {
|
if let peer = state.peers[peerId] {
|
||||||
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
||||||
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||||
@ -2290,7 +2321,7 @@ func pollChannelOnce(accountPeerId: PeerId, postbox: Postbox, network: Network,
|
|||||||
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
|
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
|
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedReplyMessageIds: ReferencedReplyMessageIds(), initialReferencedGeneralMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
|
||||||
return pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: initialState)
|
return pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: initialState)
|
||||||
|> mapToSignal { (finalState, _, timeout) -> Signal<Int32, NoError> in
|
|> mapToSignal { (finalState, _, timeout) -> Signal<Int32, NoError> in
|
||||||
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
||||||
@ -2344,7 +2375,7 @@ public func standalonePollChannelOnce(accountPeerId: PeerId, postbox: Postbox, n
|
|||||||
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
|
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
|
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedReplyMessageIds: ReferencedReplyMessageIds(), initialReferencedGeneralMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
|
||||||
return pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: initialState)
|
return pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: initialState)
|
||||||
|> mapToSignal { (finalState, _, timeout) -> Signal<Never, NoError> in
|
|> mapToSignal { (finalState, _, timeout) -> Signal<Never, NoError> in
|
||||||
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
||||||
|
@ -1562,7 +1562,7 @@ public final class AccountViewTracker {
|
|||||||
let (pollMessageIds, pollMessageDict) = pollMessages(entries: next.0.entries)
|
let (pollMessageIds, pollMessageDict) = pollMessages(entries: next.0.entries)
|
||||||
strongSelf.updatePolls(viewId: viewId, messageIds: pollMessageIds, messages: pollMessageDict)
|
strongSelf.updatePolls(viewId: viewId, messageIds: pollMessageIds, messages: pollMessageDict)
|
||||||
if case let .peer(peerId, _) = chatLocation, peerId.namespace == Namespaces.Peer.CloudChannel {
|
if case let .peer(peerId, _) = chatLocation, peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
strongSelf.historyViewStateValidationContexts.updateView(id: viewId, view: next.0)
|
strongSelf.historyViewStateValidationContexts.updateView(id: viewId, view: next.0, location: chatLocation)
|
||||||
} else if case let .thread(peerId, _, _) = chatLocation, peerId.namespace == Namespaces.Peer.CloudChannel {
|
} else if case let .thread(peerId, _, _) = chatLocation, peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
strongSelf.historyViewStateValidationContexts.updateView(id: viewId, view: next.0, location: chatLocation)
|
strongSelf.historyViewStateValidationContexts.updateView(id: viewId, view: next.0, location: chatLocation)
|
||||||
}
|
}
|
||||||
@ -1576,7 +1576,7 @@ public final class AccountViewTracker {
|
|||||||
switch chatLocation {
|
switch chatLocation {
|
||||||
case let .peer(peerId, _):
|
case let .peer(peerId, _):
|
||||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
strongSelf.historyViewStateValidationContexts.updateView(id: viewId, view: nil)
|
strongSelf.historyViewStateValidationContexts.updateView(id: viewId, view: nil, location: chatLocation)
|
||||||
}
|
}
|
||||||
case let .thread(peerId, _, _):
|
case let .thread(peerId, _, _):
|
||||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
@ -1694,7 +1694,7 @@ public final class AccountViewTracker {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.queue.async {
|
strongSelf.queue.async {
|
||||||
strongSelf.updatePendingWebpages(viewId: viewId, messageIds: [], localWebpages: [:])
|
strongSelf.updatePendingWebpages(viewId: viewId, messageIds: [], localWebpages: [:])
|
||||||
strongSelf.historyViewStateValidationContexts.updateView(id: viewId, view: nil)
|
strongSelf.historyViewStateValidationContexts.updateView(id: viewId, view: nil, location: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -137,7 +137,13 @@ final class HistoryViewStateValidationContexts {
|
|||||||
self.accountPeerId = accountPeerId
|
self.accountPeerId = accountPeerId
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateView(id: Int32, view: MessageHistoryView?, location: ChatLocationInput? = nil) {
|
func updateView(id: Int32, view: MessageHistoryView?, location: ChatLocationInput?) {
|
||||||
|
#if DEBUG
|
||||||
|
if "".isEmpty {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(self.queue.isCurrent())
|
assert(self.queue.isCurrent())
|
||||||
guard let view = view, view.tagMask == nil || view.tagMask == MessageTags.unseenPersonalMessage || view.tagMask == MessageTags.unseenReaction || view.tagMask == MessageTags.music || view.tagMask == MessageTags.pinned else {
|
guard let view = view, view.tagMask == nil || view.tagMask == MessageTags.unseenPersonalMessage || view.tagMask == MessageTags.unseenReaction || view.tagMask == MessageTags.music || view.tagMask == MessageTags.pinned else {
|
||||||
if self.contexts[id] != nil {
|
if self.contexts[id] != nil {
|
||||||
|
@ -103,20 +103,29 @@ func resolveUnknownEmojiFiles<T>(postbox: Postbox, source: FetchMessageHistoryHo
|
|||||||
private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, peers: [PeerId: Peer], storeMessages: [StoreMessage], _ f: @escaping (Transaction, [Peer], [StoreMessage]) -> T) -> Signal<T, NoError> {
|
private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, peers: [PeerId: Peer], storeMessages: [StoreMessage], _ f: @escaping (Transaction, [Peer], [StoreMessage]) -> T) -> Signal<T, NoError> {
|
||||||
return postbox.transaction { transaction -> Signal<T, NoError> in
|
return postbox.transaction { transaction -> Signal<T, NoError> in
|
||||||
var storedIds = Set<MessageId>()
|
var storedIds = Set<MessageId>()
|
||||||
var referencedIds = Set<MessageId>()
|
var referencedReplyIds = ReferencedReplyMessageIds()
|
||||||
|
var referencedGeneralIds = Set<MessageId>()
|
||||||
for message in storeMessages {
|
for message in storeMessages {
|
||||||
guard case let .Id(id) = message.id else {
|
guard case let .Id(id) = message.id else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
storedIds.insert(id)
|
storedIds.insert(id)
|
||||||
for attribute in message.attributes {
|
for attribute in message.attributes {
|
||||||
referencedIds.formUnion(attribute.associatedMessageIds)
|
if let attribute = attribute as? ReplyMessageAttribute {
|
||||||
|
referencedReplyIds.add(sourceId: id, targetId: attribute.messageId)
|
||||||
|
} else {
|
||||||
|
referencedGeneralIds.formUnion(attribute.associatedMessageIds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
referencedIds.subtract(storedIds)
|
|
||||||
referencedIds.subtract(transaction.filterStoredMessageIds(referencedIds))
|
|
||||||
|
|
||||||
if referencedIds.isEmpty {
|
let allPossiblyStoredReferencedIds = storedIds.union(referencedGeneralIds).union(referencedReplyIds.targetIdsBySourceId.keys)
|
||||||
|
let allStoredReferencedIds = transaction.filterStoredMessageIds(allPossiblyStoredReferencedIds)
|
||||||
|
|
||||||
|
referencedReplyIds = referencedReplyIds.subtractingStoredIds(allStoredReferencedIds)
|
||||||
|
referencedGeneralIds.subtract(allStoredReferencedIds)
|
||||||
|
|
||||||
|
if referencedReplyIds.isEmpty && referencedGeneralIds.isEmpty {
|
||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, reactions: [], result: Void())
|
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, reactions: [], result: Void())
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
return postbox.transaction { transaction -> T in
|
return postbox.transaction { transaction -> T in
|
||||||
@ -125,7 +134,38 @@ private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMe
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = []
|
var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = []
|
||||||
for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedIds) {
|
for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedReplyIds) {
|
||||||
|
if let peer = transaction.getPeer(peerId) ?? peers[peerId] {
|
||||||
|
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
||||||
|
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||||
|
signal = source.request(Api.functions.messages.getMessages(id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
|
||||||
|
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
if let inputChannel = apiInputChannel(peer) {
|
||||||
|
signal = source.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let signal = signal {
|
||||||
|
signals.append(signal
|
||||||
|
|> map { result in
|
||||||
|
switch result {
|
||||||
|
case let .messages(messages, chats, users):
|
||||||
|
return (messages, chats, users)
|
||||||
|
case let .messagesSlice(_, _, _, _, messages, chats, users):
|
||||||
|
return (messages, chats, users)
|
||||||
|
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
|
||||||
|
let _ = apiTopics
|
||||||
|
return (messages, chats, users)
|
||||||
|
case .messagesNotModified:
|
||||||
|
return ([], [], [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> `catch` { _ in
|
||||||
|
return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], []))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedGeneralIds) {
|
||||||
if let peer = transaction.getPeer(peerId) ?? peers[peerId] {
|
if let peer = transaction.getPeer(peerId) ?? peers[peerId] {
|
||||||
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
||||||
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||||
@ -231,6 +271,10 @@ struct FetchMessageHistoryHoleResult: Equatable {
|
|||||||
func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryHoleSource, postbox: Postbox, peerInput: FetchMessageHistoryHoleThreadInput, namespace: MessageId.Namespace, direction: MessageHistoryViewRelativeHoleDirection, space: MessageHistoryHoleSpace, count rawCount: Int) -> Signal<FetchMessageHistoryHoleResult?, NoError> {
|
func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryHoleSource, postbox: Postbox, peerInput: FetchMessageHistoryHoleThreadInput, namespace: MessageId.Namespace, direction: MessageHistoryViewRelativeHoleDirection, space: MessageHistoryHoleSpace, count rawCount: Int) -> Signal<FetchMessageHistoryHoleResult?, NoError> {
|
||||||
let count = min(100, rawCount)
|
let count = min(100, rawCount)
|
||||||
|
|
||||||
|
if peerInput.requestThreadId != nil, case .everywhere = space, case .aroundId = direction {
|
||||||
|
assert(true)
|
||||||
|
}
|
||||||
|
|
||||||
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 {
|
||||||
@ -654,6 +698,12 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print("fetchMessageHistoryHole for \(peerInput) space \(space) done")
|
||||||
|
if peerInput.requestThreadId != nil, case .everywhere = space, case .aroundId = direction {
|
||||||
|
assert(true)
|
||||||
|
}
|
||||||
|
|
||||||
if ids.count == 0 || implicitelyFillHole {
|
if ids.count == 0 || implicitelyFillHole {
|
||||||
filledRange = minMaxRange
|
filledRange = minMaxRange
|
||||||
strictFilledIndices = IndexSet()
|
strictFilledIndices = IndexSet()
|
||||||
@ -702,8 +752,6 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||||||
})
|
})
|
||||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||||
|
|
||||||
print("fetchMessageHistoryHole for \(peerInput) space \(space) done")
|
|
||||||
|
|
||||||
let result = FetchMessageHistoryHoleResult(
|
let result = FetchMessageHistoryHoleResult(
|
||||||
removedIndices: IndexSet(integersIn: Int(filledRange.lowerBound) ... Int(filledRange.upperBound)),
|
removedIndices: IndexSet(integersIn: Int(filledRange.lowerBound) ... Int(filledRange.upperBound)),
|
||||||
strictRemovedIndices: strictFilledIndices,
|
strictRemovedIndices: strictFilledIndices,
|
||||||
|
@ -3,46 +3,148 @@ import Postbox
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
|
||||||
private final class ManagedMessageHistoryHolesState {
|
private final class ManagedMessageHistoryHolesState {
|
||||||
private var holeDisposables: [MessageHistoryHolesViewEntry: Disposable] = [:]
|
private struct LocationKey: Equatable {
|
||||||
|
var peerId: PeerId
|
||||||
|
var threadId: Int64?
|
||||||
|
var space: MessageHistoryHoleSpace
|
||||||
|
|
||||||
|
init(peerId: PeerId, threadId: Int64?, space: MessageHistoryHoleSpace) {
|
||||||
|
self.peerId = peerId
|
||||||
|
self.threadId = threadId
|
||||||
|
self.space = space
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct PendingEntry {
|
||||||
|
var key: LocationKey
|
||||||
|
var entry: MessageHistoryHolesViewEntry
|
||||||
|
var disposable: Disposable
|
||||||
|
|
||||||
|
init(key: LocationKey, entry: MessageHistoryHolesViewEntry, disposable: Disposable) {
|
||||||
|
self.key = key
|
||||||
|
self.entry = entry
|
||||||
|
self.disposable = disposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct DiscardedEntry {
|
||||||
|
var entry: PendingEntry
|
||||||
|
var timestamp: Double
|
||||||
|
|
||||||
|
init(entry: PendingEntry, timestamp: Double) {
|
||||||
|
self.entry = entry
|
||||||
|
self.timestamp = timestamp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var pendingEntries: [PendingEntry] = []
|
||||||
|
private var discardedEntries: [DiscardedEntry] = []
|
||||||
|
|
||||||
|
private let performWork: (@escaping (ManagedMessageHistoryHolesState) -> Void) -> Void
|
||||||
|
private var oldEntriesTimer: SwiftSignalKit.Timer?
|
||||||
|
|
||||||
|
init(performWork: @escaping (@escaping (ManagedMessageHistoryHolesState) -> Void) -> Void) {
|
||||||
|
self.performWork = performWork
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.oldEntriesTimer?.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
func clearDisposables() -> [Disposable] {
|
func clearDisposables() -> [Disposable] {
|
||||||
let disposables = Array(self.holeDisposables.values)
|
var disposables = Array(self.pendingEntries.map(\.disposable))
|
||||||
self.holeDisposables.removeAll()
|
disposables.append(contentsOf: self.discardedEntries.map(\.entry.disposable))
|
||||||
|
self.pendingEntries.removeAll()
|
||||||
|
self.discardedEntries.removeAll()
|
||||||
return disposables
|
return disposables
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(entries: Set<MessageHistoryHolesViewEntry>) -> (removed: [Disposable], added: [MessageHistoryHolesViewEntry: MetaDisposable]) {
|
private func updateNeedsTimer() {
|
||||||
var removed: [Disposable] = []
|
let needsTimer = !self.discardedEntries.isEmpty
|
||||||
|
if needsTimer {
|
||||||
|
if self.oldEntriesTimer == nil {
|
||||||
|
let performWork = self.performWork
|
||||||
|
self.oldEntriesTimer = SwiftSignalKit.Timer(timeout: 0.2, repeat: true, completion: {
|
||||||
|
performWork { impl in
|
||||||
|
let disposables = impl.discardOldEntries()
|
||||||
|
for disposable in disposables {
|
||||||
|
disposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, queue: .mainQueue())
|
||||||
|
self.oldEntriesTimer?.start()
|
||||||
|
}
|
||||||
|
} else if let oldEntriesTimer = self.oldEntriesTimer {
|
||||||
|
self.oldEntriesTimer = nil
|
||||||
|
oldEntriesTimer.invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func discardOldEntries() -> [Disposable] {
|
||||||
|
let timestamp = CFAbsoluteTimeGetCurrent()
|
||||||
|
|
||||||
|
var result: [Disposable] = []
|
||||||
|
for i in (0 ..< self.discardedEntries.count).reversed() {
|
||||||
|
if self.discardedEntries[i].timestamp < timestamp - 0.5 {
|
||||||
|
result.append(self.discardedEntries[i].entry.disposable)
|
||||||
|
self.discardedEntries.remove(at: i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(entries: Set<MessageHistoryHolesViewEntry>) -> (removed: [Disposable], added: [MessageHistoryHolesViewEntry: MetaDisposable], hasOldEntries: Bool) {
|
||||||
|
let removed: [Disposable] = []
|
||||||
var added: [MessageHistoryHolesViewEntry: MetaDisposable] = [:]
|
var added: [MessageHistoryHolesViewEntry: MetaDisposable] = [:]
|
||||||
|
|
||||||
for (entry, disposable) in self.holeDisposables {
|
let timestamp = CFAbsoluteTimeGetCurrent()
|
||||||
if !entries.contains(entry) {
|
|
||||||
removed.append(disposable)
|
for i in (0 ..< self.pendingEntries.count).reversed() {
|
||||||
self.holeDisposables.removeValue(forKey: entry)
|
if !entries.contains(self.pendingEntries[i].entry) {
|
||||||
|
self.discardedEntries.append(DiscardedEntry(entry: self.pendingEntries[i], timestamp: timestamp))
|
||||||
|
self.pendingEntries.remove(at: i)
|
||||||
|
//removed.append(self.pendingEntries[i].disposable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
switch entry.hole {
|
switch entry.hole {
|
||||||
case .peer:
|
case let .peer(peerHole):
|
||||||
if self.holeDisposables[entry] == nil {
|
let key = LocationKey(peerId: peerHole.peerId, threadId: peerHole.threadId, space: entry.space)
|
||||||
|
if !self.pendingEntries.contains(where: { $0.key == key }) {
|
||||||
|
if let discardedIndex = self.discardedEntries.firstIndex(where: { $0.entry.entry == entry }) {
|
||||||
|
let discardedEntry = self.discardedEntries.remove(at: discardedIndex)
|
||||||
|
self.pendingEntries.append(discardedEntry.entry)
|
||||||
|
} else {
|
||||||
let disposable = MetaDisposable()
|
let disposable = MetaDisposable()
|
||||||
self.holeDisposables[entry] = disposable
|
self.pendingEntries.append(PendingEntry(key: key, entry: entry, disposable: disposable))
|
||||||
added[entry] = disposable
|
added[entry] = disposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (removed, added)
|
self.updateNeedsTimer()
|
||||||
|
|
||||||
|
return (removed, added, !self.discardedEntries.isEmpty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func managedMessageHistoryHoles(accountPeerId: PeerId, network: Network, postbox: Postbox) -> Signal<Void, NoError> {
|
func managedMessageHistoryHoles(accountPeerId: PeerId, network: Network, postbox: Postbox) -> Signal<Void, NoError> {
|
||||||
return Signal { _ in
|
return Signal { _ in
|
||||||
let state = Atomic(value: ManagedMessageHistoryHolesState())
|
var performWorkImpl: ((@escaping (ManagedMessageHistoryHolesState) -> Void) -> Void)?
|
||||||
|
let state = Atomic(value: ManagedMessageHistoryHolesState(performWork: { f in
|
||||||
|
performWorkImpl?(f)
|
||||||
|
}))
|
||||||
|
performWorkImpl = { [weak state] f in
|
||||||
|
state?.with { state in
|
||||||
|
f(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let disposable = postbox.messageHistoryHolesView().start(next: { view in
|
let disposable = postbox.messageHistoryHolesView().start(next: { view in
|
||||||
let (removed, added) = state.with { state -> (removed: [Disposable], added: [MessageHistoryHolesViewEntry: MetaDisposable]) in
|
let (removed, added, _) = state.with { state in
|
||||||
return state.update(entries: view.entries)
|
return state.update(entries: view.entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ extension Api.Update {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var associatedMessageIds: [MessageId]? {
|
var associatedMessageIds: (replyIds: ReferencedReplyMessageIds, generalIds: [MessageId])? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .updateNewMessage(message, _, _):
|
case let .updateNewMessage(message, _, _):
|
||||||
return apiMessageAssociatedMessageIds(message)
|
return apiMessageAssociatedMessageIds(message)
|
||||||
|
@ -156,6 +156,17 @@ func messagesIdsGroupedByPeerId(_ ids: [MessageId]) -> [PeerId: [MessageId]] {
|
|||||||
return dict
|
return dict
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func messagesIdsGroupedByPeerId(_ ids: ReferencedReplyMessageIds) -> [PeerId: ReferencedReplyMessageIds] {
|
||||||
|
var dict: [PeerId: ReferencedReplyMessageIds] = [:]
|
||||||
|
|
||||||
|
for (targetId, sourceId) in ids.targetIdsBySourceId {
|
||||||
|
let peerId = sourceId.peerId
|
||||||
|
dict[peerId, default: ReferencedReplyMessageIds()].add(sourceId: sourceId, targetId: targetId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
|
||||||
func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Message? {
|
func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Message? {
|
||||||
guard case let .Id(id) = message.id else {
|
guard case let .Id(id) = message.id else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -5792,7 +5792,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
var index: Int
|
var index: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
let topMessage = pinnedHistorySignal(anchorMessageId: nil, count: 3)
|
let topMessage = pinnedHistorySignal(anchorMessageId: nil, count: 10)
|
||||||
|> map { update -> TopMessage? in
|
|> map { update -> TopMessage? in
|
||||||
switch update {
|
switch update {
|
||||||
case .Loading:
|
case .Loading:
|
||||||
@ -5816,7 +5816,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let loadCount = 100
|
let loadCount = 10
|
||||||
|
|
||||||
struct PinnedHistory {
|
struct PinnedHistory {
|
||||||
struct PinnedMessage {
|
struct PinnedMessage {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user