mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-23 19:50:47 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
df2e72300f
@ -183,6 +183,7 @@ struct AccountMutableState {
|
||||
|
||||
var state: AuthorizedAccountState.State
|
||||
var peers: [PeerId: Peer]
|
||||
var apiChats: [PeerId: Api.Chat]
|
||||
var channelStates: [PeerId: AccountStateChannelState]
|
||||
var peerChatInfos: [PeerId: PeerChatInfo]
|
||||
var referencedReplyMessageIds: ReferencedReplyMessageIds
|
||||
@ -213,6 +214,7 @@ struct AccountMutableState {
|
||||
self.initialState = initialState
|
||||
self.state = initialState.state
|
||||
self.peers = initialPeers
|
||||
self.apiChats = [:]
|
||||
self.referencedReplyMessageIds = initialReferencedReplyMessageIds
|
||||
self.referencedGeneralMessageIds = initialReferencedGeneralMessageIds
|
||||
self.storedMessages = initialStoredMessages
|
||||
@ -225,11 +227,12 @@ struct AccountMutableState {
|
||||
self.updatedOutgoingUniqueMessageIds = [:]
|
||||
}
|
||||
|
||||
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) {
|
||||
init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], apiChats: [PeerId: Api.Chat], 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.operations = operations
|
||||
self.state = state
|
||||
self.peers = peers
|
||||
self.apiChats = apiChats
|
||||
self.channelStates = channelStates
|
||||
self.referencedReplyMessageIds = referencedReplyMessageIds
|
||||
self.referencedGeneralMessageIds = referencedGeneralMessageIds
|
||||
@ -245,7 +248,7 @@ struct AccountMutableState {
|
||||
}
|
||||
|
||||
func branch() -> AccountMutableState {
|
||||
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)
|
||||
return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, apiChats: self.apiChats, 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) {
|
||||
@ -258,6 +261,9 @@ struct AccountMutableState {
|
||||
for (_, peer) in other.insertedPeers {
|
||||
self.peers[peer.id] = peer
|
||||
}
|
||||
for (_, chat) in other.apiChats {
|
||||
self.apiChats[chat.peerId] = chat
|
||||
}
|
||||
self.preCachedResources.append(contentsOf: other.preCachedResources)
|
||||
self.externallyUpdatedPeerId.formUnion(other.externallyUpdatedPeerId)
|
||||
for (peerId, namespaces) in other.namespacesWithHolesFromPreviousState {
|
||||
@ -410,8 +416,26 @@ struct AccountMutableState {
|
||||
}
|
||||
}
|
||||
|
||||
func isPeerForum(peerId: PeerId) -> Bool {
|
||||
if let peer = self.peers[peerId] {
|
||||
return peer.isForum
|
||||
} else if let chat = self.apiChats[peerId] {
|
||||
if let channel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
return channel.isForum
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
Logger.shared.log("AccountIntermediateState", "isPeerForum undefinded for \(peerId)")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
mutating func mergeChats(_ chats: [Api.Chat]) {
|
||||
self.addOperation(.MergeApiChats(chats))
|
||||
for chat in chats {
|
||||
self.apiChats[chat.peerId] = chat
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
switch chat {
|
||||
|
@ -418,7 +418,7 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes
|
||||
}
|
||||
|
||||
extension StoreMessage {
|
||||
convenience init?(apiMessage: Api.Message, namespace: MessageId.Namespace = Namespaces.Message.Cloud) {
|
||||
convenience init?(apiMessage: Api.Message, peerIsForum: Bool, namespace: MessageId.Namespace = Namespaces.Message.Cloud) {
|
||||
switch apiMessage {
|
||||
case let .message(flags, id, fromId, chatPeerId, fwdFrom, viaBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod):
|
||||
let resolvedFromId = fromId?.peerId ?? chatPeerId.peerId
|
||||
@ -443,7 +443,9 @@ extension StoreMessage {
|
||||
if let replyTo = replyTo {
|
||||
var threadMessageId: MessageId?
|
||||
switch replyTo {
|
||||
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyToTopId):
|
||||
case let .messageReplyHeader(flags, replyToMsgId, replyToPeerId, replyToTopId):
|
||||
let isForumTopic = (flags & (1 << 3)) != 0
|
||||
|
||||
let replyPeerId = replyToPeerId?.peerId ?? peerId
|
||||
if let replyToTopId = replyToTopId {
|
||||
let threadIdValue = MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToTopId)
|
||||
@ -453,8 +455,16 @@ extension StoreMessage {
|
||||
}
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
let threadIdValue = MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
|
||||
if peerIsForum {
|
||||
if isForumTopic {
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
}
|
||||
} else {
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
}
|
||||
}
|
||||
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId))
|
||||
}
|
||||
|
@ -188,12 +188,15 @@ public enum CreateForumChannelTopicError {
|
||||
}
|
||||
|
||||
func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title: String, iconColor: Int32, iconFileId: Int64?) -> Signal<Int64, CreateForumChannelTopicError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputChannel? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputChannel)
|
||||
return account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
|> castError(CreateForumChannelTopicError.self)
|
||||
|> mapToSignal { inputChannel -> Signal<Int64, CreateForumChannelTopicError> in
|
||||
guard let inputChannel = inputChannel else {
|
||||
|> mapToSignal { peer -> Signal<Int64, CreateForumChannelTopicError> in
|
||||
guard let peer else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
guard let inputChannel = apiInputChannel(peer) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
@ -221,7 +224,7 @@ func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title:
|
||||
for update in result.allUpdates {
|
||||
switch update {
|
||||
case let .updateNewChannelMessage(message, _, _):
|
||||
if let message = StoreMessage(apiMessage: message) {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
|
||||
if case let .Id(id) = message.id {
|
||||
topicId = Int64(id.id)
|
||||
}
|
||||
@ -605,7 +608,7 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
||||
var pinnedIds: [Int64] = []
|
||||
|
||||
let addedMessages = messages.compactMap { message -> StoreMessage? in
|
||||
return StoreMessage(apiMessage: message)
|
||||
return StoreMessage(apiMessage: message, peerIsForum: true)
|
||||
}
|
||||
|
||||
let _ = pts
|
||||
|
@ -25,7 +25,7 @@ public func requestUpdatesXml(account: Account, source: String) -> Signal<Data,
|
||||
|> mapToSignal { result in
|
||||
switch result {
|
||||
case let .channelMessages(_, _, _, _, apiMessages, _, apiChats, apiUsers):
|
||||
if let apiMessage = apiMessages.first, let storeMessage = StoreMessage(apiMessage: apiMessage) {
|
||||
if let apiMessage = apiMessages.first, let storeMessage = StoreMessage(apiMessage: apiMessage, peerIsForum: peer.isForum) {
|
||||
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for chat in apiChats {
|
||||
@ -103,7 +103,7 @@ public func downloadAppUpdate(account: Account, source: String, messageId: Int32
|
||||
}
|
||||
|
||||
let messageAndFile:(Message, TelegramMediaFile)? = apiMessages.compactMap { value in
|
||||
return StoreMessage(apiMessage: value)
|
||||
return StoreMessage(apiMessage: value, peerIsForum: peer.isForum)
|
||||
}.compactMap { value in
|
||||
return locallyRenderedMessage(message: value, peers: peers)
|
||||
}.sorted(by: {
|
||||
|
@ -191,7 +191,7 @@ private func requestEditMessageInternal(postbox: Postbox, network: Network, stat
|
||||
if let result = result {
|
||||
return postbox.transaction { transaction -> RequestEditMessageResult in
|
||||
var toMedia: Media?
|
||||
if let message = result.messages.first.flatMap({ StoreMessage(apiMessage: $0) }) {
|
||||
if let message = result.messages.first.flatMap({ StoreMessage(apiMessage: $0, peerIsForum: peer.isForum) }) {
|
||||
toMedia = message.media.first
|
||||
}
|
||||
|
||||
@ -217,7 +217,7 @@ private func requestEditMessageInternal(postbox: Postbox, network: Network, stat
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in updated })
|
||||
|
||||
if let message = StoreMessage(apiMessage: message), case let .Id(id) = message.id {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), case let .Id(id) = message.id {
|
||||
transaction.updateMessage(id, update: { previousMessage in
|
||||
var updatedFlags = message.flags
|
||||
var updatedLocalTags = message.localTags
|
||||
|
@ -713,7 +713,11 @@ func finalStateWithDifference(accountPeerId: PeerId, postbox: Postbox, network:
|
||||
updatedState.addPreCachedResource(resource, data: data)
|
||||
}
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: message) {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
updatedState.addMessages([message], location: .UpperHistoryBlock)
|
||||
}
|
||||
}
|
||||
@ -917,7 +921,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
||||
}
|
||||
}
|
||||
case let .updateEditChannelMessage(apiMessage, pts, ptsCount):
|
||||
if let message = StoreMessage(apiMessage: apiMessage), case let .Id(messageId) = message.id {
|
||||
var peerIsForum = false
|
||||
if let peerId = apiMessage.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum), case let .Id(messageId) = message.id {
|
||||
let peerId = messageId.peerId
|
||||
if let previousState = updatedState.channelStates[peerId] {
|
||||
if previousState.pts >= pts {
|
||||
@ -984,7 +992,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
||||
MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)
|
||||
}, pinned: (flags & (1 << 0)) != 0)
|
||||
case let .updateEditMessage(apiMessage, _, _):
|
||||
if let message = StoreMessage(apiMessage: apiMessage), case let .Id(messageId) = message.id {
|
||||
var peerIsForum = false
|
||||
if let peerId = apiMessage.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum), case let .Id(messageId) = message.id {
|
||||
if let preCachedResources = apiMessage.preCachedResources {
|
||||
for (resource, data) in preCachedResources {
|
||||
updatedState.addPreCachedResource(resource, data: data)
|
||||
@ -1000,7 +1012,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
||||
}
|
||||
}
|
||||
case let .updateNewChannelMessage(apiMessage, pts, ptsCount):
|
||||
if let message = StoreMessage(apiMessage: apiMessage) {
|
||||
var peerIsForum = false
|
||||
if let peerId = apiMessage.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum) {
|
||||
if let previousState = updatedState.channelStates[message.id.peerId] {
|
||||
if previousState.pts >= pts {
|
||||
let messageText: String
|
||||
@ -1038,7 +1054,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
||||
}
|
||||
}
|
||||
case let .updateNewMessage(apiMessage, _, _):
|
||||
if let message = StoreMessage(apiMessage: apiMessage) {
|
||||
var peerIsForum = false
|
||||
if let peerId = apiMessage.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum) {
|
||||
if let preCachedResources = apiMessage.preCachedResources {
|
||||
for (resource, data) in preCachedResources {
|
||||
updatedState.addPreCachedResource(resource, data: data)
|
||||
@ -1510,7 +1530,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
||||
}
|
||||
updatedState.updatePeersNearby(peersNearby)
|
||||
case let .updateNewScheduledMessage(apiMessage):
|
||||
if let message = StoreMessage(apiMessage: apiMessage, namespace: Namespaces.Message.ScheduledCloud) {
|
||||
var peerIsForum = false
|
||||
if let peerId = apiMessage.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum, namespace: Namespaces.Message.ScheduledCloud) {
|
||||
updatedState.addScheduledMessages([message])
|
||||
}
|
||||
case let .updateDeleteScheduledMessages(peer, messages):
|
||||
@ -1703,17 +1727,17 @@ func resolveForumThreads(postbox: Postbox, network: Network, state: AccountMutab
|
||||
if missingForumThreadIds.isEmpty {
|
||||
return .single(state)
|
||||
} else {
|
||||
var signals: [Signal<(PeerId, Api.messages.ForumTopics)?, NoError>] = []
|
||||
var signals: [Signal<(Peer, Api.messages.ForumTopics)?, NoError>] = []
|
||||
for (peerId, threadIds) in missingForumThreadIds {
|
||||
guard let inputChannel = transaction.getPeer(peerId).flatMap(apiInputChannel) else {
|
||||
guard let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) else {
|
||||
Logger.shared.log("State", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
||||
continue
|
||||
}
|
||||
let signal = network.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds))
|
||||
|> map { result -> (PeerId, Api.messages.ForumTopics)? in
|
||||
return (peerId, result)
|
||||
|> map { result -> (Peer, Api.messages.ForumTopics)? in
|
||||
return (peer, result)
|
||||
}
|
||||
|> `catch` { _ -> Signal<(PeerId, Api.messages.ForumTopics)?, NoError> in
|
||||
|> `catch` { _ -> Signal<(Peer, Api.messages.ForumTopics)?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
signals.append(signal)
|
||||
@ -1726,14 +1750,17 @@ func resolveForumThreads(postbox: Postbox, network: Network, state: AccountMutab
|
||||
var storeMessages: [StoreMessage] = []
|
||||
|
||||
for maybeResult in results {
|
||||
if let (peerId, result) = maybeResult {
|
||||
if let (peer, result) = maybeResult {
|
||||
let peerIsForum = peer.isForum
|
||||
let peerId = peer.id
|
||||
|
||||
switch result {
|
||||
case let .forumTopics(_, _, topics, messages, chats, users, pts):
|
||||
state.mergeChats(chats)
|
||||
state.mergeUsers(users)
|
||||
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message) {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
storeMessages.append(message)
|
||||
}
|
||||
}
|
||||
@ -1805,17 +1832,17 @@ func resolveForumThreads(postbox: Postbox, network: Network, ids: [MessageId]) -
|
||||
if missingForumThreadIds.isEmpty {
|
||||
return .single(Void())
|
||||
} else {
|
||||
var signals: [Signal<(PeerId, Api.messages.ForumTopics)?, NoError>] = []
|
||||
var signals: [Signal<(Peer, Api.messages.ForumTopics)?, NoError>] = []
|
||||
for (peerId, threadIds) in missingForumThreadIds {
|
||||
guard let inputChannel = transaction.getPeer(peerId).flatMap(apiInputChannel) else {
|
||||
guard let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) else {
|
||||
Logger.shared.log("State", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
||||
continue
|
||||
}
|
||||
let signal = network.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds))
|
||||
|> map { result -> (PeerId, Api.messages.ForumTopics)? in
|
||||
return (peerId, result)
|
||||
|> map { result -> (Peer, Api.messages.ForumTopics)? in
|
||||
return (peer, result)
|
||||
}
|
||||
|> `catch` { _ -> Signal<(PeerId, Api.messages.ForumTopics)?, NoError> in
|
||||
|> `catch` { _ -> Signal<(Peer, Api.messages.ForumTopics)?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
signals.append(signal)
|
||||
@ -1829,14 +1856,17 @@ func resolveForumThreads(postbox: Postbox, network: Network, ids: [MessageId]) -
|
||||
var storeMessages: [StoreMessage] = []
|
||||
|
||||
for maybeResult in results {
|
||||
if let (peerId, result) = maybeResult {
|
||||
if let (peer, result) = maybeResult {
|
||||
let peerIsForum = peer.isForum
|
||||
let peerId = peer.id
|
||||
|
||||
switch result {
|
||||
case let .forumTopics(_, _, topics, messages, apiChats, apiUsers, _):
|
||||
chats.append(contentsOf: apiChats)
|
||||
users.append(contentsOf: apiUsers)
|
||||
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message) {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
storeMessages.append(message)
|
||||
}
|
||||
}
|
||||
@ -1927,17 +1957,17 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
||||
if missingForumThreadIds.isEmpty {
|
||||
return .single(fetchedChatList)
|
||||
} else {
|
||||
var signals: [Signal<(PeerId, Api.messages.ForumTopics)?, NoError>] = []
|
||||
var signals: [Signal<(Peer, Api.messages.ForumTopics)?, NoError>] = []
|
||||
for (peerId, threadIds) in missingForumThreadIds {
|
||||
guard let inputChannel = fetchedChatList.peers.first(where: { $0.id == peerId }).flatMap(apiInputChannel) else {
|
||||
guard let peer = fetchedChatList.peers.first(where: { $0.id == peerId }), let inputChannel = apiInputChannel(peer) else {
|
||||
Logger.shared.log("resolveForumThreads", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
||||
continue
|
||||
}
|
||||
let signal = network.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds))
|
||||
|> map { result -> (PeerId, Api.messages.ForumTopics)? in
|
||||
return (peerId, result)
|
||||
|> map { result -> (Peer, Api.messages.ForumTopics)? in
|
||||
return (peer, result)
|
||||
}
|
||||
|> `catch` { _ -> Signal<(PeerId, Api.messages.ForumTopics)?, NoError> in
|
||||
|> `catch` { _ -> Signal<(Peer, Api.messages.ForumTopics)?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
signals.append(signal)
|
||||
@ -1948,7 +1978,10 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
||||
var fetchedChatList = fetchedChatList
|
||||
|
||||
for maybeResult in results {
|
||||
if let (peerId, result) = maybeResult {
|
||||
if let (peer, result) = maybeResult {
|
||||
let peerIsForum = peer.isForum
|
||||
let peerId = peer.id
|
||||
|
||||
switch result {
|
||||
case let .forumTopics(_, _, topics, messages, chats, users, _):
|
||||
fetchedChatList.peers.append(contentsOf: chats.compactMap { chat in
|
||||
@ -1959,7 +1992,7 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
||||
})
|
||||
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message) {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
fetchedChatList.storeMessages.append(message)
|
||||
}
|
||||
}
|
||||
@ -2141,21 +2174,26 @@ private func resolveAssociatedMessages(postbox: Postbox, network: Network, state
|
||||
|> map { results in
|
||||
var updatedState = state
|
||||
for (messages, chats, users) in results {
|
||||
if !messages.isEmpty {
|
||||
var storeMessages: [StoreMessage] = []
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message) {
|
||||
storeMessages.append(message)
|
||||
}
|
||||
}
|
||||
updatedState.addMessages(storeMessages, location: .Random)
|
||||
}
|
||||
if !chats.isEmpty {
|
||||
updatedState.mergeChats(chats)
|
||||
}
|
||||
if !users.isEmpty {
|
||||
updatedState.mergeUsers(users)
|
||||
}
|
||||
|
||||
if !messages.isEmpty {
|
||||
var storeMessages: [StoreMessage] = []
|
||||
for message in messages {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
storeMessages.append(message)
|
||||
}
|
||||
}
|
||||
updatedState.addMessages(storeMessages, location: .Random)
|
||||
}
|
||||
}
|
||||
return updatedState
|
||||
}
|
||||
@ -2272,7 +2310,11 @@ private func resolveMissingPeerChatInfos(network: Network, state: AccountMutable
|
||||
|
||||
var storeMessages: [StoreMessage] = []
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message) {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
var updatedStoreMessage = storeMessage
|
||||
if case let .Id(id) = storeMessage.id {
|
||||
if let channelState = channelStates[id.peerId] {
|
||||
@ -2501,7 +2543,11 @@ private func resetChannels(accountPeerId: PeerId, postbox: Postbox, network: Net
|
||||
}
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message) {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId {
|
||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||
}
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
var updatedStoreMessage = storeMessage
|
||||
if case let .Id(id) = storeMessage.id {
|
||||
if let channelState = channelStates[id.peerId] {
|
||||
@ -2645,7 +2691,11 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
||||
var forumThreadIds = Set<MessageId>()
|
||||
|
||||
for apiMessage in newMessages {
|
||||
if var message = StoreMessage(apiMessage: apiMessage) {
|
||||
var peerIsForum = peer.isForum
|
||||
if let peerId = apiMessage.peerId, updatedState.isPeerForum(peerId: peerId) {
|
||||
peerIsForum = true
|
||||
}
|
||||
if var message = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum) {
|
||||
var attributes = message.attributes
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
||||
message = message.withUpdatedAttributes(attributes)
|
||||
@ -2674,7 +2724,11 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
||||
let peerId = peer.id
|
||||
updatedState.deleteMessages(messages.map({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) }))
|
||||
case let .updateEditChannelMessage(apiMessage, _, _):
|
||||
if let message = StoreMessage(apiMessage: apiMessage), case let .Id(messageId) = message.id, messageId.peerId == peer.id {
|
||||
var peerIsForum = peer.isForum
|
||||
if let peerId = apiMessage.peerId, updatedState.isPeerForum(peerId: peerId) {
|
||||
peerIsForum = true
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum), case let .Id(messageId) = message.id, messageId.peerId == peer.id {
|
||||
if let preCachedResources = apiMessage.preCachedResources {
|
||||
for (resource, data) in preCachedResources {
|
||||
updatedState.addPreCachedResource(resource, data: data)
|
||||
@ -2766,6 +2820,11 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
||||
|
||||
var resetForumTopics = Set<PeerId>()
|
||||
|
||||
var peerIsForum = peer.isForum
|
||||
if updatedState.isPeerForum(peerId: peer.id) {
|
||||
peerIsForum = true
|
||||
}
|
||||
|
||||
if let (peer, pts, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, ttlPeriod) = parameters {
|
||||
updatedState.updateChannelState(peer.peerId, pts: pts)
|
||||
updatedState.updateChannelInvalidationPts(peer.peerId, invalidationPts: pts)
|
||||
@ -2779,7 +2838,7 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
||||
resetForumTopics.insert(peer.peerId)
|
||||
|
||||
for apiMessage in messages {
|
||||
if var message = StoreMessage(apiMessage: apiMessage) {
|
||||
if var message = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum) {
|
||||
var attributes = message.attributes
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
||||
message = message.withUpdatedAttributes(attributes)
|
||||
|
@ -120,7 +120,7 @@ private func fetchWebpage(account: Account, messageId: MessageId) -> Signal<Void
|
||||
}
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, namespace: isScheduledMessage ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud) {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peer.isForum, namespace: isScheduledMessage ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud) {
|
||||
var webpage: TelegramMediaWebpage?
|
||||
for media in storeMessage.media {
|
||||
if let media = media as? TelegramMediaWebpage {
|
||||
@ -1065,22 +1065,22 @@ public final class AccountViewTracker {
|
||||
}
|
||||
|
||||
return signal
|
||||
|> map { result -> ([Api.Message], [Api.Chat], [Api.User]) in
|
||||
|> map { result -> (Peer, [Api.Message], [Api.Chat], [Api.User]) 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, _, chats, users):
|
||||
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, [], [], []))
|
||||
}
|
||||
|> mapToSignal { messages, chats, users -> Signal<Void, NoError> in
|
||||
|> mapToSignal { topPeer, messages, chats, users -> Signal<Void, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
@ -1104,7 +1104,7 @@ public final class AccountViewTracker {
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
|
||||
for message in messages {
|
||||
guard let storeMessage = StoreMessage(apiMessage: message) else {
|
||||
guard let storeMessage = StoreMessage(apiMessage: message, peerIsForum: topPeer.isForum) else {
|
||||
continue
|
||||
}
|
||||
guard case let .Id(id) = storeMessage.id else {
|
||||
|
@ -142,7 +142,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
|
||||
var attributes: [MessageAttribute]
|
||||
let text: String
|
||||
let forwardInfo: StoreMessageForwardInfo?
|
||||
if let apiMessage = apiMessage, let updatedMessage = StoreMessage(apiMessage: apiMessage) {
|
||||
if let apiMessage = apiMessage, let apiMessagePeerId = apiMessage.peerId, let updatedMessage = StoreMessage(apiMessage: apiMessage, peerIsForum: transaction.getPeer(apiMessagePeerId)?.isForum ?? false) {
|
||||
media = updatedMessage.media
|
||||
attributes = updatedMessage.attributes
|
||||
text = updatedMessage.text
|
||||
@ -317,7 +317,14 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage
|
||||
|
||||
var resultMessages: [MessageId: StoreMessage] = [:]
|
||||
for apiMessage in result.messages {
|
||||
if let resultMessage = StoreMessage(apiMessage: apiMessage, namespace: namespace), case let .Id(id) = resultMessage.id {
|
||||
var peerIsForum = false
|
||||
if let apiMessagePeerId = apiMessage.peerId, let peer = transaction.getPeer(apiMessagePeerId) {
|
||||
if peer.isForum {
|
||||
peerIsForum = true
|
||||
}
|
||||
}
|
||||
|
||||
if let resultMessage = StoreMessage(apiMessage: apiMessage, peerIsForum: peerIsForum, namespace: namespace), case let .Id(id) = resultMessage.id {
|
||||
resultMessages[id] = resultMessage
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,11 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
var lowerNonPinnedIndex: MessageIndex?
|
||||
|
||||
for message in apiMessages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message) {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId, let peer = peers[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] {
|
||||
|
@ -485,7 +485,7 @@ private func hashForMessages(_ messages: [StoreMessage], withChannelIds: Bool) -
|
||||
|
||||
private enum ValidatedMessages {
|
||||
case notModified
|
||||
case messages([Api.Message], [Api.Chat], [Api.User], Int32?)
|
||||
case messages(Peer, [Api.Message], [Api.Chat], [Api.User], Int32?)
|
||||
}
|
||||
|
||||
private func validateChannelMessagesBatch(postbox: Postbox, network: Network, accountPeerId: PeerId, tag: MessageTags?, messageIds: [MessageId], historyState: HistoryState) -> Signal<Void, NoError> {
|
||||
@ -546,7 +546,7 @@ private func validateChannelMessagesBatch(postbox: Postbox, network: Network, ac
|
||||
case .messagesNotModified:
|
||||
return .notModified
|
||||
}
|
||||
return .messages(messages, chats, users, channelPts)
|
||||
return .messages(peer, messages, chats, users, channelPts)
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
@ -615,7 +615,7 @@ private func validateReplyThreadMessagesBatch(postbox: Postbox, network: Network
|
||||
case .messagesNotModified:
|
||||
return .notModified
|
||||
}
|
||||
return .messages(messages, chats, users, channelPts)
|
||||
return .messages(peer, messages, chats, users, channelPts)
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
@ -656,7 +656,7 @@ private func validateScheduledMessagesBatch(postbox: Postbox, network: Network,
|
||||
case .messagesNotModified:
|
||||
return .notModified
|
||||
}
|
||||
return .messages(messages, chats, users, nil)
|
||||
return .messages(peer, messages, chats, users, nil)
|
||||
}
|
||||
} else {
|
||||
signal = .complete()
|
||||
@ -683,11 +683,11 @@ private func validateBatch(postbox: Postbox, network: Network, transaction: Tran
|
||||
return .complete()
|
||||
}
|
||||
switch result {
|
||||
case let .messages(messages, _, _, channelPts):
|
||||
case let .messages(topPeer, messages, _, _, channelPts):
|
||||
var storeMessages: [StoreMessage] = []
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, namespace: messageNamespace) {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: topPeer.isForum, namespace: messageNamespace) {
|
||||
var attributes = storeMessage.attributes
|
||||
if let channelPts = channelPts {
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
|
||||
@ -734,7 +734,7 @@ private func validateBatch(postbox: Postbox, network: Network, transaction: Tran
|
||||
}
|
||||
var ids = Set<MessageId>()
|
||||
for message in apiMessages {
|
||||
if let parsedMessage = StoreMessage(apiMessage: message, namespace: messageNamespace), case let .Id(id) = parsedMessage.id {
|
||||
if let parsedMessage = StoreMessage(apiMessage: message, peerIsForum: topPeer.isForum, namespace: messageNamespace), case let .Id(id) = parsedMessage.id {
|
||||
if let tag = tag {
|
||||
if parsedMessage.tags.contains(tag) {
|
||||
ids.insert(id)
|
||||
@ -934,11 +934,11 @@ private func validateReplyThreadBatch(postbox: Postbox, network: Network, transa
|
||||
return .complete()
|
||||
}
|
||||
switch result {
|
||||
case let .messages(messages, _, _, channelPts):
|
||||
case let .messages(topPeer, messages, _, _, channelPts):
|
||||
var storeMessages: [StoreMessage] = []
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, namespace: messageNamespace) {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: topPeer.isForum, namespace: messageNamespace) {
|
||||
var attributes = storeMessage.attributes
|
||||
if let channelPts = channelPts {
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
|
||||
@ -983,7 +983,7 @@ private func validateReplyThreadBatch(postbox: Postbox, network: Network, transa
|
||||
}
|
||||
var ids = Set<MessageId>()
|
||||
for message in apiMessages {
|
||||
if let parsedMessage = StoreMessage(apiMessage: message, namespace: messageNamespace), case let .Id(id) = parsedMessage.id {
|
||||
if let parsedMessage = StoreMessage(apiMessage: message, peerIsForum: topPeer.isForum, namespace: messageNamespace), case let .Id(id) = parsedMessage.id {
|
||||
ids.insert(id)
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMe
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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(referencedReplyIds) {
|
||||
if let peer = transaction.getPeer(peerId) ?? peers[peerId] {
|
||||
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
||||
@ -150,18 +150,18 @@ private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMe
|
||||
|> 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, [], [], []))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -181,18 +181,18 @@ private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMe
|
||||
|> 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, [], [], []))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -204,10 +204,10 @@ private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMe
|
||||
|> mapToSignal { results -> Signal<T, NoError> in
|
||||
var additionalPeers: [Peer] = []
|
||||
var additionalMessages: [StoreMessage] = []
|
||||
for (messages, chats, users) in results {
|
||||
for (peer, messages, chats, users) in results {
|
||||
if !messages.isEmpty {
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message) {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
|
||||
additionalMessages.append(message)
|
||||
}
|
||||
}
|
||||
@ -286,16 +286,19 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
}
|
||||
|> take(1)
|
||||
|> mapToSignal { _ -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||
return postbox.transaction { transaction -> (Api.InputPeer?, Int64) in
|
||||
return postbox.transaction { transaction -> (Peer?, Int64) in
|
||||
switch peerInput {
|
||||
case let .direct(peerId, _):
|
||||
return (transaction.getPeer(peerId).flatMap(forceApiInputPeer), 0)
|
||||
return (transaction.getPeer(peerId), 0)
|
||||
case let .threadFromChannel(channelMessageId):
|
||||
return (transaction.getPeer(channelMessageId.peerId).flatMap(forceApiInputPeer), 0)
|
||||
return (transaction.getPeer(channelMessageId.peerId), 0)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { (inputPeer, hash) -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
|> mapToSignal { (peer, hash) -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||
guard let peer else {
|
||||
return .single(FetchMessageHistoryHoleResult(removedIndices: IndexSet(), strictRemovedIndices: IndexSet(), actualPeerId: nil, actualThreadId: nil, ids: []))
|
||||
}
|
||||
guard let inputPeer = forceApiInputPeer(peer) else {
|
||||
return .single(FetchMessageHistoryHoleResult(removedIndices: IndexSet(), strictRemovedIndices: IndexSet(), actualPeerId: nil, actualThreadId: nil, ids: []))
|
||||
}
|
||||
|
||||
@ -649,7 +652,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
var storeMessages: [StoreMessage] = []
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, namespace: namespace) {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peer.isForum, namespace: namespace) {
|
||||
if let channelPts = channelPts {
|
||||
var attributes = storeMessage.attributes
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
|
||||
@ -908,8 +911,30 @@ func fetchCallListHole(network: Network, postbox: Postbox, accountPeerId: PeerId
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var topIndex: MessageIndex?
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
}
|
||||
var peerMap: [PeerId: Peer] = [:]
|
||||
for peer in peers {
|
||||
peerMap[peer.id] = peer
|
||||
}
|
||||
|
||||
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) {
|
||||
storeMessages.append(storeMessage)
|
||||
if let index = storeMessage.index, topIndex == nil || index < topIndex! {
|
||||
topIndex = index
|
||||
@ -924,20 +949,6 @@ func fetchCallListHole(network: Network, postbox: Postbox, accountPeerId: PeerId
|
||||
|
||||
transaction.replaceGlobalMessageTagsHole(globalTags: [.Calls, .MissedCalls], index: holeIndex, with: updatedIndex, messages: storeMessages)
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
@ -151,6 +151,11 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox,
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
var peerMap: [PeerId: Peer] = [:]
|
||||
for peer in peers {
|
||||
peerMap[peer.id] = peer
|
||||
}
|
||||
|
||||
loop: for dialog in dialogs {
|
||||
let apiPeer: Api.Peer
|
||||
@ -197,7 +202,11 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox,
|
||||
}
|
||||
|
||||
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) {
|
||||
storeMessages.append(storeMessage)
|
||||
}
|
||||
}
|
||||
|
@ -115,6 +115,19 @@ extension Api.Message {
|
||||
return MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)
|
||||
}
|
||||
}
|
||||
|
||||
var peerId: PeerId? {
|
||||
switch self {
|
||||
case let .message(_, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
let peerId: PeerId = messagePeerId.peerId
|
||||
return peerId
|
||||
case let .messageEmpty(_, _, peerId):
|
||||
return peerId?.peerId
|
||||
case let .messageService(_, _, _, chatPeerId, _, _, _, _):
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
return peerId
|
||||
}
|
||||
}
|
||||
|
||||
var timestamp: Int32? {
|
||||
switch self {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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):
|
||||
|
@ -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] {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -199,6 +199,14 @@ public extension Peer {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var isForum: Bool {
|
||||
if let channel = self as? TelegramChannel {
|
||||
return channel.flags.contains(.isForum)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension TelegramPeerUsername {
|
||||
|
@ -366,9 +366,8 @@ public final class AccountContextImpl: AccountContext {
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, data: data)
|
||||
return .thread(peerId: data.messageId.peerId, threadId: makeMessageThreadId(data.messageId), data: context.state)
|
||||
}
|
||||
case let .feed(id):
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, feedId: id)
|
||||
return .feed(id: id, data: context.state)
|
||||
case .feed:
|
||||
preconditionFailure()
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,9 +390,8 @@ public final class AccountContextImpl: AccountContext {
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, data: data)
|
||||
return context.maxReadOutgoingMessageId
|
||||
}
|
||||
case let .feed(id):
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, feedId: id)
|
||||
return context.maxReadOutgoingMessageId
|
||||
case .feed:
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,9 +426,8 @@ public final class AccountContextImpl: AccountContext {
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, data: data)
|
||||
return context.unreadCount
|
||||
}
|
||||
case let .feed(id):
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, feedId: id)
|
||||
return context.unreadCount
|
||||
case .feed:
|
||||
return .single(0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,9 +438,8 @@ public final class AccountContextImpl: AccountContext {
|
||||
case let .replyThread(data):
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, data: data)
|
||||
context.applyMaxReadIndex(messageIndex: messageIndex)
|
||||
case let .feed(id):
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, feedId: id)
|
||||
context.applyMaxReadIndex(messageIndex: messageIndex)
|
||||
case .feed:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,17 +601,6 @@ private func chatLocationContext(holder: Atomic<ChatLocationContextHolder?>, acc
|
||||
return holder.context
|
||||
}
|
||||
|
||||
private func chatLocationContext(holder: Atomic<ChatLocationContextHolder?>, account: Account, feedId: Int32) -> FeedHistoryContext {
|
||||
let holder = holder.modify { current in
|
||||
if let current = current as? ChatLocationFeedContextHolderImpl {
|
||||
return current
|
||||
} else {
|
||||
return ChatLocationFeedContextHolderImpl(account: account, feedId: feedId)
|
||||
}
|
||||
} as! ChatLocationFeedContextHolderImpl
|
||||
return holder.context
|
||||
}
|
||||
|
||||
private final class ChatLocationReplyContextHolderImpl: ChatLocationContextHolder {
|
||||
let context: ReplyThreadHistoryContext
|
||||
|
||||
@ -624,14 +609,6 @@ private final class ChatLocationReplyContextHolderImpl: ChatLocationContextHolde
|
||||
}
|
||||
}
|
||||
|
||||
private final class ChatLocationFeedContextHolderImpl: ChatLocationContextHolder {
|
||||
let context: FeedHistoryContext
|
||||
|
||||
init(account: Account, feedId: Int32) {
|
||||
self.context = FeedHistoryContext(account: account, feedId: feedId)
|
||||
}
|
||||
}
|
||||
|
||||
func getAppConfiguration(transaction: Transaction) -> AppConfiguration {
|
||||
let appConfiguration: AppConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
|
||||
return appConfiguration
|
||||
|
Loading…
x
Reference in New Issue
Block a user