Workaround for General topic

This commit is contained in:
Ali
2022-11-28 13:00:32 +04:00
parent 326555ab77
commit e525215e50
24 changed files with 335 additions and 824 deletions

View File

@@ -1,538 +1 @@
import Foundation
import Postbox
import SwiftSignalKit
import TelegramApi
private class FeedHistoryContextImpl {
private let queue: Queue
private let account: Account
private let feedId: Int32
private let userId: Int64
private var currentHole: (MessageHistoryHolesViewEntry, Disposable)?
struct State: Equatable {
var messageIndices: [MessageIndex]
var holeIndices: [MessageId.Namespace: IndexSet]
}
let state = Promise<State>()
private var stateValue: State? {
didSet {
if let stateValue = self.stateValue {
if stateValue != oldValue {
self.state.set(.single(stateValue))
}
}
}
}
let maxReadOutgoingMessageId = Promise<MessageId?>()
private var maxReadOutgoingMessageIdValue: MessageId? {
didSet {
if self.maxReadOutgoingMessageIdValue != oldValue {
self.maxReadOutgoingMessageId.set(.single(self.maxReadOutgoingMessageIdValue))
}
}
}
private var maxReadIncomingMessageIdValue: MessageId?
let unreadCount = Promise<Int>()
private var unreadCountValue: Int = 0 {
didSet {
if self.unreadCountValue != oldValue {
self.unreadCount.set(.single(self.unreadCountValue))
}
}
}
private var initialStateDisposable: Disposable?
private var holesDisposable: Disposable?
private var readStateDisposable: Disposable?
private var updateInitialStateDisposable: Disposable?
private let readDisposable = MetaDisposable()
init(queue: Queue, account: Account, feedId: Int32, userId: Int64) {
self.queue = queue
self.account = account
self.feedId = feedId
self.userId = userId
self.maxReadOutgoingMessageIdValue = nil
self.maxReadOutgoingMessageId.set(.single(self.maxReadOutgoingMessageIdValue))
self.maxReadIncomingMessageIdValue = nil
self.unreadCountValue = 0
self.unreadCount.set(.single(self.unreadCountValue))
self.initialStateDisposable = (account.postbox.transaction { transaction -> State in
return State(messageIndices: [], holeIndices: [Namespaces.Message.Cloud: IndexSet(integersIn: 2 ... 2)])
}
|> deliverOn(self.queue)).start(next: { [weak self] state in
guard let strongSelf = self else {
return
}
strongSelf.stateValue = state
strongSelf.state.set(.single(state))
})
/*self.updateInitialStateDisposable = (account.network.request(Api.functions.feed.getFeed(flags: 0, filterId: self.feedId, offsetPosition: nil, addOffset: 0, limit: 100, maxPosition: nil, minPosition: nil, hash: 0))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.feed.FeedMessages?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<[MessageIndex], NoError> in
return account.postbox.transaction { transaction -> [MessageIndex] in
guard let result = result else {
return []
}
let messages: [Api.Message]
let chats: [Api.Chat]
let users: [Api.User]
switch result {
case let .feedMessages(_, _, _, _, apiMessages, apiChats, apiUsers):
messages = apiMessages
chats = apiChats
users = apiUsers
case .feedMessagesNotModified:
messages = []
users = []
chats = []
}
var peers: [Peer] = []
var peerPresences: [PeerId: PeerPresence] = [:]
for chat in chats {
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
peers.append(groupOrChannel)
}
}
for user in users {
let telegramUser = TelegramUser(user: user)
peers.append(telegramUser)
if let presence = TelegramUserPresence(apiUser: user) {
peerPresences[telegramUser.id] = presence
}
}
var storeMessages: [StoreMessage] = []
for message in messages {
if let storeMessage = StoreMessage(apiMessage: message, namespace: Namespaces.Message.Cloud) {
storeMessages.append(storeMessage)
}
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated
})
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
let _ = transaction.addMessages(storeMessages, location: .Random)
return storeMessages.compactMap({ message in
return message.index
}).sorted()
}
}
|> deliverOn(self.queue)).start(next: { [weak self] indices in
guard let strongSelf = self else {
return
}
assert(indices.sorted() == indices)
strongSelf.stateValue = State(messageIndices: indices, holeIndices: [:])
})*/
let userId = self.userId
self.holesDisposable = (account.postbox.messageHistoryHolesView()
|> map { view -> MessageHistoryHolesViewEntry? in
for entry in view.entries {
if entry.userId == userId {
return entry
}
}
return nil
}
|> distinctUntilChanged
|> deliverOn(self.queue)).start(next: { [weak self] entry in
guard let strongSelf = self else {
return
}
strongSelf.setCurrentHole(entry: entry)
})
/*self.readStateDisposable = (account.stateManager.threadReadStateUpdates
|> deliverOn(self.queue)).start(next: { [weak self] (_, outgoing) in
guard let strongSelf = self else {
return
}
if let value = outgoing[data.messageId] {
strongSelf.maxReadOutgoingMessageIdValue = MessageId(peerId: data.messageId.peerId, namespace: Namespaces.Message.Cloud, id: value)
}
})
let updateInitialState: Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> = account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(data.messageId.peerId).flatMap(apiInputPeer)
}
|> castError(FetchChannelReplyThreadMessageError.self)
|> mapToSignal { inputPeer -> Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> in
guard let inputPeer = inputPeer else {
return .fail(.generic)
}
return account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: data.messageId.id))
|> mapError { _ -> FetchChannelReplyThreadMessageError in
return .generic
}
|> mapToSignal { discussionMessage -> Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> in
return account.postbox.transaction { transaction -> Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> in
switch discussionMessage {
case let .discussionMessage(_, messages, maxId, readInboxMaxId, readOutboxMaxId, unreadCount, chats, users):
let parsedMessages = messages.compactMap { message -> StoreMessage? in
StoreMessage(apiMessage: message)
}
guard let topMessage = parsedMessages.last, let parsedIndex = topMessage.index else {
return .fail(.generic)
}
var channelMessageId: MessageId?
var replyThreadAttribute: ReplyThreadMessageAttribute?
for attribute in topMessage.attributes {
if let attribute = attribute as? SourceReferenceMessageAttribute {
channelMessageId = attribute.messageId
} else if let attribute = attribute as? ReplyThreadMessageAttribute {
replyThreadAttribute = attribute
}
}
var peers: [Peer] = []
var peerPresences: [PeerId: PeerPresence] = [:]
for chat in chats {
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
peers.append(groupOrChannel)
}
}
for user in users {
let telegramUser = TelegramUser(user: user)
peers.append(telegramUser)
if let presence = TelegramUserPresence(apiUser: user) {
peerPresences[telegramUser.id] = presence
}
}
let _ = transaction.addMessages(parsedMessages, location: .Random)
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated
})
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
let resolvedMaxMessage: MessageId?
if let maxId = maxId {
resolvedMaxMessage = MessageId(
peerId: parsedIndex.id.peerId,
namespace: Namespaces.Message.Cloud,
id: maxId
)
} else {
resolvedMaxMessage = nil
}
var isChannelPost = false
for attribute in topMessage.attributes {
if let _ = attribute as? SourceReferenceMessageAttribute {
isChannelPost = true
break
}
}
let maxReadIncomingMessageId = readInboxMaxId.flatMap { readMaxId in
MessageId(peerId: parsedIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: readMaxId)
}
if let channelMessageId = channelMessageId, let replyThreadAttribute = replyThreadAttribute {
account.viewTracker.updateReplyInfoForMessageId(channelMessageId, info: AccountViewTracker.UpdatedMessageReplyInfo(
timestamp: Int32(CFAbsoluteTimeGetCurrent()),
commentsPeerId: parsedIndex.id.peerId,
maxReadIncomingMessageId: maxReadIncomingMessageId,
maxMessageId: resolvedMaxMessage
))
transaction.updateMessage(channelMessageId, update: { currentMessage in
var attributes = currentMessage.attributes
loop: for j in 0 ..< attributes.count {
if let attribute = attributes[j] as? ReplyThreadMessageAttribute {
attributes[j] = ReplyThreadMessageAttribute(
count: replyThreadAttribute.count,
latestUsers: attribute.latestUsers,
commentsPeerId: attribute.commentsPeerId,
maxMessageId: replyThreadAttribute.maxMessageId,
maxReadMessageId: replyThreadAttribute.maxReadMessageId
)
}
}
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init), authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
})
}
return .single(DiscussionMessage(
messageId: parsedIndex.id,
channelMessageId: channelMessageId,
isChannelPost: isChannelPost,
maxMessage: resolvedMaxMessage,
maxReadIncomingMessageId: maxReadIncomingMessageId,
maxReadOutgoingMessageId: readOutboxMaxId.flatMap { readMaxId in
MessageId(peerId: parsedIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: readMaxId)
},
unreadCount: Int(unreadCount)
))
}
}
|> castError(FetchChannelReplyThreadMessageError.self)
|> switchToLatest
}
}
self.updateInitialStateDisposable = (updateInitialState
|> deliverOnMainQueue).start(next: { [weak self] updatedData in
guard let strongSelf = self else {
return
}
if let maxReadOutgoingMessageId = updatedData.maxReadOutgoingMessageId {
if let current = strongSelf.maxReadOutgoingMessageIdValue {
if maxReadOutgoingMessageId > current {
strongSelf.maxReadOutgoingMessageIdValue = maxReadOutgoingMessageId
}
} else {
strongSelf.maxReadOutgoingMessageIdValue = maxReadOutgoingMessageId
}
}
})*/
}
deinit {
self.initialStateDisposable?.dispose()
self.holesDisposable?.dispose()
self.readDisposable.dispose()
self.updateInitialStateDisposable?.dispose()
}
func setCurrentHole(entry: MessageHistoryHolesViewEntry?) {
if self.currentHole?.0 != entry {
self.currentHole?.1.dispose()
if let entry = entry {
self.currentHole = (entry, self.fetchHole(entry: entry).start(next: { [weak self] updatedState in
guard let strongSelf = self else {
return
}
strongSelf.currentHole = nil
strongSelf.stateValue = updatedState
}))
} else {
self.currentHole = nil
}
}
}
private func fetchHole(entry: MessageHistoryHolesViewEntry) -> Signal<State, NoError> {
//feed.getFeed flags:# filter_id:int offset_to_max_read:flags.3?true offset_position:flags.0?FeedPosition add_offset:int limit:int max_position:flags.1?FeedPosition min_position:flags.2?FeedPosition hash:long = messages.FeedMessages;
return .complete()
// let offsetPosition: Api.FeedPosition?
// let addOffset: Int32 = 0
//
// switch entry.direction {
// case let .range(start, end):
// if min(start.id, end.id) == 1 && max(start.id, end.id) == Int32.max - 1 {
// offsetPosition = nil
// } else {
// return .never()
// }
// case let .aroundId(id):
// let _ = id
// return .never()
// }
//
// var flags: Int32 = 0
// if let _ = offsetPosition {
// flags |= 1 << 0
// }
//
// let account = self.account
// let state = self.stateValue
// return self.account.network.request(Api.functions.feed.getFeed(
// flags: flags,
// filterId: self.feedId,
// offsetPosition: offsetPosition,
// addOffset: addOffset,
// limit: 100,
// maxPosition: nil,
// minPosition: nil,
// hash: 0
// ))
// |> map(Optional.init)
// |> `catch` { _ -> Signal<Api.feed.FeedMessages?, NoError> in
// return .single(nil)
// }
// |> mapToSignal { result -> Signal<State, NoError> in
// return account.postbox.transaction { transaction -> State in
// guard let result = result else {
// var updatedState = state ?? State(messageIndices: [], holeIndices: [:])
// updatedState.holeIndices = [:]
// return updatedState
// }
//
// let messages: [Api.Message]
// let chats: [Api.Chat]
// let users: [Api.User]
//
// switch result {
// case let .feedMessages(_, _, _, _, apiMessages, apiChats, apiUsers):
// messages = apiMessages
// chats = apiChats
// users = apiUsers
// case .feedMessagesNotModified:
// messages = []
// users = []
// chats = []
// }
//
// var peers: [Peer] = []
// var peerPresences: [PeerId: PeerPresence] = [:]
// for chat in chats {
// if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
// peers.append(groupOrChannel)
// }
// }
// for user in users {
// let telegramUser = TelegramUser(user: user)
// peers.append(telegramUser)
// if let presence = TelegramUserPresence(apiUser: user) {
// peerPresences[telegramUser.id] = presence
// }
// }
//
// var storeMessages: [StoreMessage] = []
//
// for message in messages {
// if let storeMessage = StoreMessage(apiMessage: message, namespace: Namespaces.Message.Cloud) {
// storeMessages.append(storeMessage)
// }
// }
//
// updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
// return updated
// })
// updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
//
// let _ = transaction.addMessages(storeMessages, location: .Random)
//
// var updatedState = state ?? State(messageIndices: [], holeIndices: [:])
// var currentSet = Set<MessageIndex>(updatedState.messageIndices)
//
// for index in storeMessages.compactMap(\.index) {
// if !currentSet.contains(index) {
// currentSet.insert(index)
// }
// updatedState.messageIndices.append(index)
// }
//
// updatedState.messageIndices.sort()
//
// updatedState.holeIndices = [:]
// return updatedState
// }
// }
}
func applyMaxReadIndex(messageIndex: MessageIndex) {
}
}
public class FeedHistoryContext {
fileprivate final class GuardReference {
private let deallocated: () -> Void
init(deallocated: @escaping () -> Void) {
self.deallocated = deallocated
}
deinit {
self.deallocated()
}
}
private let queue = Queue()
private let impl: QueueLocalObject<FeedHistoryContextImpl>
private let userId: Int64 = Int64.random(in: 0 ..< Int64.max)
public var state: Signal<MessageHistoryViewExternalInput, NoError> {
let userId = self.userId
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
let stateDisposable = impl.state.get().start(next: { state in
subscriber.putNext(MessageHistoryViewExternalInput(
content: .messages(indices: state.messageIndices, holes: state.holeIndices, userId: userId),
maxReadIncomingMessageId: nil,
maxReadOutgoingMessageId: nil
))
})
disposable.set(stateDisposable)
}
return disposable
}
}
public var maxReadOutgoingMessageId: Signal<MessageId?, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.maxReadOutgoingMessageId.get().start(next: { value in
subscriber.putNext(value)
}))
}
return disposable
}
}
public var unreadCount: Signal<Int, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.unreadCount.get().start(next: { value in
subscriber.putNext(value)
}))
}
return disposable
}
}
public init(account: Account, feedId: Int32) {
let queue = self.queue
let userId = self.userId
self.impl = QueueLocalObject(queue: queue, generate: {
return FeedHistoryContextImpl(queue: queue, account: account, feedId: feedId, userId: userId)
})
}
public func applyMaxReadIndex(messageIndex: MessageIndex) {
self.impl.with { impl in
impl.applyMaxReadIndex(messageIndex: messageIndex)
}
}
}

View File

@@ -47,8 +47,7 @@ func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Po
if case .cloud = strategy {
return postboxSignal
|> mapToSignal { (existMessages, missingMessageIds, supportPeers) in
var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = []
var signals: [Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), NoError>] = []
for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingMessageIds) {
if let peer = supportPeers[peerId] {
var signal: Signal<Api.messages.Messages, MTRpcError>?
@@ -63,17 +62,17 @@ func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Po
signals.append(signal |> map { result in
switch result {
case let .messages(messages, chats, users):
return (messages, chats, users)
return (peer, messages, chats, users)
case let .messagesSlice(_, _, _, _, messages, chats, users):
return (messages, chats, users)
return (peer, messages, chats, users)
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
let _ = apiTopics
return (messages, chats, users)
return (peer, messages, chats, users)
case .messagesNotModified:
return ([], [], [])
return (peer, [], [], [])
}
} |> `catch` { _ in
return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], []))
return Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), NoError>.single((peer, [], [], []))
})
}
}
@@ -81,13 +80,12 @@ func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Po
return combineLatest(signals) |> mapToSignal { results -> Signal<[Message], NoError> in
return postbox.transaction { transaction -> [Message] in
for (messages, chats, users) in results {
for (peer, messages, chats, users) in results {
if !messages.isEmpty {
var storeMessages: [StoreMessage] = []
for message in messages {
if let message = StoreMessage(apiMessage: message) {
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
storeMessages.append(message)
}
}

View File

@@ -138,12 +138,15 @@ private class ReplyThreadHistoryContextImpl {
}
})
let updateInitialState: Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> = account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(data.messageId.peerId).flatMap(apiInputPeer)
let updateInitialState: Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> = account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(data.messageId.peerId)
}
|> castError(FetchChannelReplyThreadMessageError.self)
|> mapToSignal { inputPeer -> Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> in
guard let inputPeer = inputPeer else {
|> mapToSignal { peer -> Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> in
guard let peer else {
return .fail(.generic)
}
guard let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
@@ -156,7 +159,7 @@ private class ReplyThreadHistoryContextImpl {
switch discussionMessage {
case let .discussionMessage(_, messages, maxId, readInboxMaxId, readOutboxMaxId, unreadCount, chats, users):
let parsedMessages = messages.compactMap { message -> StoreMessage? in
StoreMessage(apiMessage: message)
StoreMessage(apiMessage: message, peerIsForum: peer.isForum)
}
guard let topMessage = parsedMessages.last, let parsedIndex = topMessage.index else {
@@ -605,12 +608,15 @@ public enum FetchChannelReplyThreadMessageError {
}
func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: MessageId, atMessageId: MessageId?) -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> {
return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer)
return account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(messageId.peerId)
}
|> castError(FetchChannelReplyThreadMessageError.self)
|> mapToSignal { inputPeer -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> in
guard let inputPeer = inputPeer else {
|> mapToSignal { peer -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> in
guard let peer else {
return .fail(.generic)
}
guard let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
@@ -632,7 +638,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
switch discussionMessage {
case let .discussionMessage(_, messages, maxId, readInboxMaxId, readOutboxMaxId, unreadCount, chats, users):
let parsedMessages = messages.compactMap { message -> StoreMessage? in
StoreMessage(apiMessage: message)
StoreMessage(apiMessage: message, peerIsForum: peer.isForum)
}
guard let topMessage = parsedMessages.last, let parsedIndex = topMessage.index else {

View File

@@ -121,7 +121,11 @@ private func mergedState(transaction: Transaction, seedConfiguration: SeedConfig
var renderedMessages: [Message] = []
for message in messages {
if let message = StoreMessage(apiMessage: message) {
var peerIsForum = false
if let peerId = message.peerId, let peer = peers[peerId], peer.isForum {
peerIsForum = true
}
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
var associatedThreadInfo: Message.AssociatedThreadInfo?
if let threadId = message.threadId, let threadInfo = transaction.getMessageHistoryThreadInfo(peerId: message.id.peerId, threadId: threadId) {
associatedThreadInfo = seedConfiguration.decodeMessageThreadInfo(threadInfo.data)
@@ -521,7 +525,7 @@ func _internal_downloadMessage(postbox: Postbox, network: Network, messageId: Me
var renderedMessages: [Message] = []
for message in messages {
if let message = StoreMessage(apiMessage: message), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) {
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) {
renderedMessages.append(renderedMessage)
}
}
@@ -610,7 +614,11 @@ func fetchRemoteMessage(postbox: Postbox, source: FetchMessageHistoryHoleSource,
var renderedMessages: [Message] = []
for message in messages {
if let message = StoreMessage(apiMessage: message, namespace: id.namespace), case let .Id(updatedId) = message.id {
var peerIsForum = false
if let peerId = message.peerId, let peer = transaction.getPeer(peerId), peer.isForum {
peerIsForum = true
}
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum, namespace: id.namespace), case let .Id(updatedId) = message.id {
var addedExisting = false
if transaction.getMessage(updatedId) != nil {
transaction.updateMessage(updatedId, update: { _ in
@@ -655,7 +663,7 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
messages = []
}
for message in messages {
if let message = StoreMessage(apiMessage: message) {
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
return message.index
}
}
@@ -685,7 +693,7 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
messages = []
}
for message in messages {
if let message = StoreMessage(apiMessage: message) {
if let message = StoreMessage(apiMessage: message, peerIsForum: secondaryPeer.isForum) {
return message.index
}
}
@@ -709,7 +717,7 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
messages = []
}
for message in messages {
if let message = StoreMessage(apiMessage: message) {
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
return message.index
}
}

View File

@@ -712,111 +712,6 @@ public final class SparseMessageList {
}
}
/*public final class SparseMessageScrollingContext {
public struct State: Equatable {
public var totalCount: Int
public var minTimestamp: Int32
}
private final class Impl {
private let queue: Queue
private let account: Account
private let peerId: PeerId
let statePromise = Promise<State>()
private let disposable = MetaDisposable()
init(queue: Queue, account: Account, peerId: PeerId) {
self.queue = queue
self.account = account
self.peerId = peerId
self.reload()
}
deinit {
self.disposable.dispose()
}
private func reload() {
let account = self.account
let peerId = self.peerId
let signal: Signal<State?, NoError> = self.account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(peerId).flatMap(apiInputPeer)
}
|> mapToSignal { inputPeer -> Signal<State?, NoError> in
guard let inputPeer = inputPeer else {
return .single(nil)
}
return account.network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: 1, offsetDate: 0, addOffset: -1, limit: 1, maxId: 0, minId: 0, hash: 0))
|> map { result -> State? in
let messages: [Api.Message]
let totalCount: Int
switch result {
case let .messages(apiMessages, _, _):
messages = apiMessages
totalCount = messages.count
case let .messagesSlice(_, count, _, _, apiMessages, _, _):
messages = apiMessages
totalCount = Int(count)
case let .channelMessages(_, _, count, _, apiMessages, _, _, _):
messages = apiMessages
totalCount = Int(count)
case .messagesNotModified:
messages = []
totalCount = 0
}
if let apiMessage = messages.first, let message = StoreMessage(apiMessage: apiMessage) {
return State(totalCount: totalCount, minTimestamp: message.timestamp)
} else {
return State(totalCount: 0, minTimestamp: 0)
}
}
|> `catch` { _ -> Signal<State?, NoError> in
return .single(nil)
}
}
self.disposable.set((signal |> deliverOn(self.queue)).start(next: { [weak self] state in
guard let strongSelf = self else {
return
}
if let state = state {
strongSelf.statePromise.set(.single(state))
}
}))
}
}
private let queue: Queue
private let impl: QueueLocalObject<Impl>
public var state: Signal<State, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.statePromise.get().start(next: subscriber.putNext))
}
return disposable
}
}
init(account: Account, peerId: PeerId) {
let queue = Queue()
self.queue = queue
self.impl = QueueLocalObject(queue: queue, generate: {
return Impl(queue: queue, account: account, peerId: peerId)
})
}
}*/
public final class SparseMessageCalendar {
private final class Impl {
struct InternalState {
@@ -908,11 +803,14 @@ public final class SparseMessageCalendar {
let account = self.account
let peerId = self.peerId
let messageTag = self.messageTag
self.disposable.set((self.account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(peerId).flatMap(apiInputPeer)
self.disposable.set((self.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
|> mapToSignal { inputPeer -> Signal<LoadResult, NoError> in
guard let inputPeer = inputPeer else {
|> mapToSignal { peer -> Signal<LoadResult, NoError> in
guard let peer else {
return .single(LoadResult(messagesByDay: [:], nextOffset: nil, minMessageId: nil, minTimestamp: nil))
}
guard let inputPeer = apiInputPeer(peer) else {
return .single(LoadResult(messagesByDay: [:], nextOffset: nil, minMessageId: nil, minTimestamp: nil))
}
guard let messageFilter = messageFilterForTagMask(messageTag) else {
@@ -947,7 +845,7 @@ public final class SparseMessageCalendar {
}
for message in messages {
if let parsedMessage = StoreMessage(apiMessage: message) {
if let parsedMessage = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
parsedMessages.append(parsedMessage)
}
}

View File

@@ -491,7 +491,7 @@ func _internal_sendBotPaymentForm(account: Account, formId: Int64, source: BotPa
account.stateManager.addUpdates(updates)
var receiptMessageId: MessageId?
for apiMessage in updates.messages {
if let message = StoreMessage(apiMessage: apiMessage) {
if let message = StoreMessage(apiMessage: apiMessage, peerIsForum: false) {
for media in message.media {
if let action = media as? TelegramMediaAction {
if case .paymentSent = action.action {

View File

@@ -195,16 +195,16 @@ func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, m
case .messageEmpty:
action = .updatePinned(nil)
default:
if let message = StoreMessage(apiMessage: new), let rendered = locallyRenderedMessage(message: message, peers: peers) {
if let message = StoreMessage(apiMessage: new, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
action = .updatePinned(rendered)
}
}
case let .channelAdminLogEventActionEditMessage(prev, new):
if let prev = StoreMessage(apiMessage: prev), let prevRendered = locallyRenderedMessage(message: prev, peers: peers), let new = StoreMessage(apiMessage: new), let newRendered = locallyRenderedMessage(message: new, peers: peers) {
if let prev = StoreMessage(apiMessage: prev, peerIsForum: peer.isForum), let prevRendered = locallyRenderedMessage(message: prev, peers: peers), let new = StoreMessage(apiMessage: new, peerIsForum: peer.isForum), let newRendered = locallyRenderedMessage(message: new, peers: peers) {
action = .editMessage(prev: prevRendered, new: newRendered)
}
case let .channelAdminLogEventActionDeleteMessage(message):
if let message = StoreMessage(apiMessage: message), let rendered = locallyRenderedMessage(message: message, peers: peers) {
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
action = .deleteMessage(rendered)
}
case .channelAdminLogEventActionParticipantJoin:
@@ -238,7 +238,7 @@ func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, m
case let .channelAdminLogEventActionDefaultBannedRights(prevBannedRights, newBannedRights):
action = .updateDefaultBannedRights(prev: TelegramChatBannedRights(apiBannedRights: prevBannedRights), new: TelegramChatBannedRights(apiBannedRights: newBannedRights))
case let .channelAdminLogEventActionStopPoll(message):
if let message = StoreMessage(apiMessage: message), let rendered = locallyRenderedMessage(message: message, peers: peers) {
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
action = .pollStopped(rendered)
}
case let .channelAdminLogEventActionChangeLinkedChat(prevValue, newValue):
@@ -277,7 +277,7 @@ func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, m
case let .channelAdminLogEventActionToggleNoForwards(new):
action = .toggleCopyProtection(boolFromApiValue(new))
case let .channelAdminLogEventActionSendMessage(message):
if let message = StoreMessage(apiMessage: message), let rendered = locallyRenderedMessage(message: message, peers: peers) {
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
action = .sendMessage(rendered)
}
case let .channelAdminLogEventActionChangeAvailableReactions(prevValue, newValue):

View File

@@ -728,9 +728,18 @@ private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox,
}
}
var peerMap: [PeerId: Peer] = [:]
for peer in peers {
peerMap[peer.id] = peer
}
var storeMessages: [StoreMessage] = []
for message in messages {
if let storeMessage = StoreMessage(apiMessage: message) {
var peerIsForum = false
if let peerId = message.peerId, let peer = peerMap[peerId], peer.isForum {
peerIsForum = true
}
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
var updatedStoreMessage = storeMessage
if case let .Id(id) = storeMessage.id {
if let channelPts = channelStates[id.peerId] {

View File

@@ -114,7 +114,7 @@ func _internal_requestPeerPhotos(postbox: Postbox, network: Network, peerId: Pee
var renderedMessages: [Message] = []
for message in messages {
if let message = StoreMessage(apiMessage: message), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) {
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) {
renderedMessages.append(renderedMessage)
}
}