Swiftgram/submodules/TelegramCore/Sources/TelegramEngine/Messages/EarliestUnseenPersonalMentionMessage.swift
2024-01-10 00:45:01 +04:00

145 lines
7.0 KiB
Swift

import Foundation
import Postbox
import SwiftSignalKit
import MtProtoKit
public enum EarliestUnseenPersonalMentionMessageResult: Equatable {
case loading
case result(MessageId?)
}
func _internal_earliestUnseenPersonalMentionMessage(account: Account, peerId: PeerId, threadId: Int64?) -> Signal<EarliestUnseenPersonalMentionMessageResult, NoError> {
return account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId: peerId, threadId: threadId), index: .lowerBound, anchorIndex: .lowerBound, count: 4, fixedCombinedReadStates: nil, tag: .tag(.unseenPersonalMessage), additionalData: [.peerChatState(peerId)])
|> mapToSignal { view -> Signal<EarliestUnseenPersonalMentionMessageResult, NoError> in
if view.0.isLoading {
return .single(.loading)
}
if case .FillHole = view.1 {
return _internal_earliestUnseenPersonalMentionMessage(account: account, peerId: peerId, threadId: threadId)
}
if let message = view.0.entries.first?.message {
if peerId.namespace == Namespaces.Peer.CloudChannel {
var invalidatedPts: Int32?
for data in view.0.additionalData {
switch data {
case let .peerChatState(_, state):
if let state = state as? ChannelState {
invalidatedPts = state.invalidatedPts
}
default:
break
}
}
if let invalidatedPts = invalidatedPts {
var messagePts: Int32?
for attribute in message.attributes {
if let attribute = attribute as? ChannelMessageStateVersionAttribute {
messagePts = attribute.pts
break
}
}
if let messagePts = messagePts {
if messagePts < invalidatedPts {
return .single(.loading)
}
}
}
return .single(.result(message.id))
} else {
return .single(.result(message.id))
}
} else {
return account.postbox.transaction { transaction -> EarliestUnseenPersonalMentionMessageResult in
if let topId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud) {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: 0, maxId: topId.id)
transaction.removeHole(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, space: .tag(.unseenPersonalMessage), range: 1 ... (Int32.max - 1))
let ids = transaction.getMessageIndicesWithTag(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, tag: .unseenPersonalMessage).map({ $0.id })
for id in ids {
markUnseenPersonalMessage(transaction: transaction, id: id, addSynchronizeAction: false)
}
}
return .result(nil)
}
}
}
|> distinctUntilChanged
|> take(until: { value in
if case .result = value {
return SignalTakeAction(passthrough: true, complete: true)
} else {
return SignalTakeAction(passthrough: true, complete: false)
}
})
}
func _internal_earliestUnseenPersonalReactionMessage(account: Account, peerId: PeerId, threadId: Int64?) -> Signal<EarliestUnseenPersonalMentionMessageResult, NoError> {
return account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId: peerId, threadId: threadId), index: .lowerBound, anchorIndex: .lowerBound, count: 4, fixedCombinedReadStates: nil, tag: .tag(.unseenReaction), additionalData: [.peerChatState(peerId)])
|> mapToSignal { view -> Signal<EarliestUnseenPersonalMentionMessageResult, NoError> in
if view.0.isLoading {
return .single(.loading)
}
if case .FillHole = view.1 {
return _internal_earliestUnseenPersonalReactionMessage(account: account, peerId: peerId, threadId: threadId)
}
if let message = view.0.entries.first?.message {
if peerId.namespace == Namespaces.Peer.CloudChannel {
var invalidatedPts: Int32?
for data in view.0.additionalData {
switch data {
case let .peerChatState(_, state):
if let state = state as? ChannelState {
invalidatedPts = state.invalidatedPts
}
default:
break
}
}
if let invalidatedPts = invalidatedPts {
var messagePts: Int32?
for attribute in message.attributes {
if let attribute = attribute as? ChannelMessageStateVersionAttribute {
messagePts = attribute.pts
break
}
}
if let messagePts = messagePts {
if messagePts < invalidatedPts {
return .single(.loading)
}
}
}
return .single(.result(message.id))
} else {
return .single(.result(message.id))
}
} else {
return account.postbox.transaction { transaction -> EarliestUnseenPersonalMentionMessageResult in
if let topId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud) {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: 0, maxId: topId.id)
transaction.removeHole(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, space: .tag(.unseenReaction), range: 1 ... (Int32.max - 1))
let ids = transaction.getMessageIndicesWithTag(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, tag: .unseenReaction).map({ $0.id })
for id in ids {
markUnseenReactionMessage(transaction: transaction, id: id, addSynchronizeAction: false)
}
}
return .result(nil)
}
}
}
|> distinctUntilChanged
|> take(until: { value in
if case .result = value {
return SignalTakeAction(passthrough: true, complete: true)
} else {
return SignalTakeAction(passthrough: true, complete: false)
}
})
}