Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2022-11-28 13:22:55 +04:00
commit df2e72300f
24 changed files with 333 additions and 826 deletions

View File

@ -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 {

View File

@ -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))
}

View File

@ -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

View File

@ -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: {

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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] {

View File

@ -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)
}
}

View File

@ -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
})

View File

@ -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)
}
}

View File

@ -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 {

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)
}
}

View File

@ -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 {

View File

@ -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