mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-06 17:00:13 +00:00
[WIP] Monoforums
This commit is contained in:
parent
22ea05b3aa
commit
28f246749f
@ -6,7 +6,7 @@ import TelegramCore
|
||||
public enum ChatListControllerLocation: Equatable {
|
||||
case chatList(groupId: EngineChatList.Group)
|
||||
case forum(peerId: EnginePeer.Id)
|
||||
case savedMessagesChats
|
||||
case savedMessagesChats(peerId: EnginePeer.Id)
|
||||
}
|
||||
|
||||
public protocol ChatListController: ViewController {
|
||||
|
||||
@ -1030,9 +1030,20 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let _ = (self.context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peer.id)])
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] combinedView in
|
||||
|
||||
var forumSourcePeer: Signal<EnginePeer?, NoError> = .single(nil)
|
||||
if case let .savedMessagesChats(peerId) = self.location, peerId != self.context.account.peerId {
|
||||
forumSourcePeer = self.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
|
||||
)
|
||||
}
|
||||
|
||||
let _ = (combineLatest(queue: .mainQueue(),
|
||||
self.context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peer.id)])
|
||||
|> take(1),
|
||||
forumSourcePeer
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] combinedView, forumSourcePeer in
|
||||
guard let self, let cachedDataView = combinedView.views[.cachedPeerData(peerId: peer.id)] as? CachedPeerDataView else {
|
||||
return
|
||||
}
|
||||
@ -1040,19 +1051,30 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
return
|
||||
}
|
||||
|
||||
var peer = peer
|
||||
var threadId = threadId
|
||||
if let forumSourcePeer {
|
||||
threadId = peer.id.toInt64()
|
||||
peer = forumSourcePeer
|
||||
}
|
||||
|
||||
var scrollToEndIfExists = false
|
||||
if let layout = self.validLayout, case .regular = layout.metrics.widthClass {
|
||||
scrollToEndIfExists = true
|
||||
}
|
||||
|
||||
var openAsInlineForum = true
|
||||
if let cachedData = cachedDataView.cachedPeerData as? CachedChannelData, case let .known(viewForumAsMessages) = cachedData.viewForumAsMessages, viewForumAsMessages {
|
||||
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isMonoforum) {
|
||||
openAsInlineForum = false
|
||||
} else {
|
||||
if let cachedData = cachedDataView.cachedPeerData as? CachedChannelData, case let .known(viewForumAsMessages) = cachedData.viewForumAsMessages, viewForumAsMessages {
|
||||
openAsInlineForum = false
|
||||
}
|
||||
}
|
||||
|
||||
if openAsInlineForum, case let .channel(channel) = peer, channel.flags.contains(.isForum), threadId == nil {
|
||||
self.chatListDisplayNode.clearHighlightAnimated(true)
|
||||
|
||||
if self.chatListDisplayNode.inlineStackContainerNode?.location == .forum(peerId: channel.id) {
|
||||
self.setInlineChatList(location: nil)
|
||||
} else {
|
||||
@ -1062,7 +1084,28 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isForum), let threadId {
|
||||
let _ = self.context.sharedContext.navigateToForumThread(context: self.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: scrollToEndIfExists, keepStack: .never).startStandalone()
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
navigationController: navigationController,
|
||||
context: self.context,
|
||||
chatLocation: .replyThread(ChatReplyThreadMessage(
|
||||
peerId: peer.id,
|
||||
threadId: threadId,
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: true,
|
||||
isMonoforum: channel.flags.contains(.isMonoforum),
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
unreadCount: 0,
|
||||
initialFilledHoles: IndexSet(),
|
||||
initialAnchor: .automatic,
|
||||
isNotAvailable: false
|
||||
)),
|
||||
subject: nil,
|
||||
keepStack: .always
|
||||
))
|
||||
|
||||
self.chatListDisplayNode.clearHighlightAnimated(true)
|
||||
} else {
|
||||
var navigationAnimationOptions: NavigationAnimationOptions = []
|
||||
@ -1476,7 +1519,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
if let threadId = threadId {
|
||||
let source: ContextContentSource
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
)), subject: nil, botStart: nil, mode: .standard(.previewing), params: nil)
|
||||
chatController.canReadHistory.set(false)
|
||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||
@ -1545,7 +1588,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
let source: ContextContentSource
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
)), subject: nil, botStart: nil, mode: .standard(.previewing), params: nil)
|
||||
chatController.canReadHistory.set(false)
|
||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||
|
||||
@ -3137,7 +3137,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
if case let .peer(peerData) = item.content, peerData.customMessageListData?.hidePeerStatus == true {
|
||||
currentCredibilityIconContent = nil
|
||||
} else if case .savedMessagesChats = item.chatListLocation, peer.id == item.context.account.peerId {
|
||||
} else if case let .savedMessagesChats(peerId) = item.chatListLocation, peer.id == peerId {
|
||||
currentCredibilityIconContent = nil
|
||||
} else if peer.isScam {
|
||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
|
||||
@ -3273,6 +3273,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var isFirstForumThreadSelectable = false
|
||||
var forumThreads: [(id: Int64, title: NSAttributedString, iconId: Int64?, iconColor: Int32)] = []
|
||||
if case .savedMessagesChats = item.chatListLocation {
|
||||
} else if case let .peer(peer) = item.content, case let .channel(channel) = peer.peer.peer, channel.flags.contains(.isMonoforum) {
|
||||
} else if forumThread != nil || !topForumTopicItems.isEmpty {
|
||||
if let forumThread = forumThread {
|
||||
isFirstForumThreadSelectable = forumThread.isUnread
|
||||
|
||||
@ -1535,9 +1535,9 @@ public final class ChatListNode: ListView {
|
||||
}
|
||||
}
|
||||
}, setItemPinned: { [weak self] itemId, _ in
|
||||
if case .savedMessagesChats = location {
|
||||
if case let .savedMessagesChats(peerId) = location {
|
||||
if case let .peer(itemPeerId) = itemId {
|
||||
let _ = (context.engine.peers.toggleForumChannelTopicPinned(id: context.account.peerId, threadId: itemPeerId.toInt64())
|
||||
let _ = (context.engine.peers.toggleForumChannelTopicPinned(id: peerId, threadId: itemPeerId.toInt64())
|
||||
|> deliverOnMainQueue).start(error: { error in
|
||||
guard let self else {
|
||||
return
|
||||
|
||||
@ -319,9 +319,9 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
||||
isFirst = false
|
||||
return ChatListNodeViewUpdate(list: list, type: type, scrollPosition: nil)
|
||||
}
|
||||
case .savedMessagesChats:
|
||||
let viewKey: PostboxViewKey = .savedMessagesIndex(peerId: account.peerId)
|
||||
let interfaceStateKey: PostboxViewKey = .chatInterfaceState(peerId: account.peerId)
|
||||
case let .savedMessagesChats(peerId):
|
||||
let viewKey: PostboxViewKey = .savedMessagesIndex(peerId: peerId)
|
||||
let interfaceStateKey: PostboxViewKey = .chatInterfaceState(peerId: peerId)
|
||||
|
||||
var isFirst = true
|
||||
return account.postbox.combinedView(keys: [viewKey, interfaceStateKey])
|
||||
|
||||
@ -6833,16 +6833,17 @@ public extension Api.functions.messages {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSavedDialogs(flags: Int32, offsetDate: Int32, offsetId: Int32, offsetPeer: Api.InputPeer, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SavedDialogs>) {
|
||||
static func getSavedDialogs(flags: Int32, parentPeer: Api.InputPeer?, offsetDate: Int32, offsetId: Int32, offsetPeer: Api.InputPeer, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SavedDialogs>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1401016858)
|
||||
buffer.appendInt32(512883865)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {parentPeer!.serialize(buffer, true)}
|
||||
serializeInt32(offsetDate, buffer: buffer, boxed: false)
|
||||
serializeInt32(offsetId, buffer: buffer, boxed: false)
|
||||
offsetPeer.serialize(buffer, true)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getSavedDialogs", parameters: [("flags", String(describing: flags)), ("offsetDate", String(describing: offsetDate)), ("offsetId", String(describing: offsetId)), ("offsetPeer", String(describing: offsetPeer)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SavedDialogs? in
|
||||
return (FunctionDescription(name: "messages.getSavedDialogs", parameters: [("flags", String(describing: flags)), ("parentPeer", String(describing: parentPeer)), ("offsetDate", String(describing: offsetDate)), ("offsetId", String(describing: offsetId)), ("offsetPeer", String(describing: offsetPeer)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SavedDialogs? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.SavedDialogs?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -6868,9 +6869,11 @@ public extension Api.functions.messages {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSavedHistory(peer: Api.InputPeer, offsetId: Int32, offsetDate: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
|
||||
static func getSavedHistory(flags: Int32, parentPeer: Api.InputPeer?, peer: Api.InputPeer, offsetId: Int32, offsetDate: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1033519437)
|
||||
buffer.appendInt32(-1718964215)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {parentPeer!.serialize(buffer, true)}
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(offsetId, buffer: buffer, boxed: false)
|
||||
serializeInt32(offsetDate, buffer: buffer, boxed: false)
|
||||
@ -6879,7 +6882,7 @@ public extension Api.functions.messages {
|
||||
serializeInt32(maxId, buffer: buffer, boxed: false)
|
||||
serializeInt32(minId, buffer: buffer, boxed: false)
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getSavedHistory", parameters: [("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in
|
||||
return (FunctionDescription(name: "messages.getSavedHistory", parameters: [("flags", String(describing: flags)), ("parentPeer", String(describing: parentPeer)), ("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.Messages?
|
||||
if let signature = reader.readInt32() {
|
||||
|
||||
@ -802,7 +802,7 @@ extension StoreMessage {
|
||||
}
|
||||
}
|
||||
|
||||
if peerId == accountPeerId, let savedPeerId = savedPeerId {
|
||||
if let savedPeerId {
|
||||
threadId = savedPeerId.peerId.toInt64()
|
||||
}
|
||||
|
||||
|
||||
@ -684,218 +684,105 @@ public func _internal_fillSavedMessageHistory(accountPeerId: PeerId, postbox: Po
|
||||
}
|
||||
|
||||
func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, query: String?, offsetIndex: StoredPeerThreadCombinedState.Index?, limit: Int) -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> {
|
||||
if peerId == accountPeerId {
|
||||
var flags: Int32 = 0
|
||||
flags = 0
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
|> castError(LoadMessageHistoryThreadsError.self)
|
||||
|> mapToSignal { peer -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
guard let peer else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
var offsetDate: Int32 = 0
|
||||
var offsetId: Int32 = 0
|
||||
var offsetPeer: Api.InputPeer = .inputPeerEmpty
|
||||
if let offsetIndex = offsetIndex {
|
||||
offsetDate = offsetIndex.timestamp
|
||||
offsetId = offsetIndex.messageId
|
||||
//TODO:api
|
||||
offsetPeer = .inputPeerEmpty
|
||||
var isSavedThreads = false
|
||||
if peer.id == accountPeerId {
|
||||
isSavedThreads = true
|
||||
} else if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
isSavedThreads = true
|
||||
}
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = network.request(Api.functions.messages.getSavedDialogs(
|
||||
flags: flags,
|
||||
offsetDate: offsetDate,
|
||||
offsetId: offsetId,
|
||||
offsetPeer: offsetPeer,
|
||||
limit: Int32(limit),
|
||||
hash: 0
|
||||
))
|
||||
|> `catch` { error -> Signal<Api.messages.SavedDialogs, LoadMessageHistoryThreadsError> in
|
||||
if error.errorDescription == "SAVED_DIALOGS_UNSUPPORTED" {
|
||||
return .never()
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { result -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
switch result {
|
||||
case .savedDialogs(let dialogs, let messages, let chats, let users), .savedDialogsSlice(_, let dialogs, let messages, let chats, let users):
|
||||
var items: [LoadMessageHistoryThreadsResult.Item] = []
|
||||
var pinnedIds: [Int64] = []
|
||||
|
||||
let addedMessages = messages.compactMap { message -> StoreMessage? in
|
||||
return StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: false)
|
||||
}
|
||||
|
||||
var minIndex: StoredPeerThreadCombinedState.Index?
|
||||
|
||||
for dialog in dialogs {
|
||||
switch dialog {
|
||||
case let .savedDialog(flags, peer, topMessage):
|
||||
if (flags & (1 << 2)) != 0 {
|
||||
pinnedIds.append(peer.peerId.toInt64())
|
||||
}
|
||||
|
||||
let data = MessageHistoryThreadData(
|
||||
creationDate: 0,
|
||||
isOwnedByMe: true,
|
||||
author: peer.peerId,
|
||||
info: EngineMessageHistoryThread.Info(
|
||||
title: "",
|
||||
icon: nil,
|
||||
iconColor: 0
|
||||
),
|
||||
incomingUnreadCount: 0,
|
||||
maxIncomingReadId: 0,
|
||||
maxKnownMessageId: topMessage,
|
||||
maxOutgoingReadId: 0,
|
||||
isClosed: false,
|
||||
isHidden: false,
|
||||
notificationSettings: TelegramPeerNotificationSettings.defaultSettings
|
||||
)
|
||||
|
||||
var topTimestamp: Int32 = 1
|
||||
for message in addedMessages {
|
||||
if message.id.peerId == peerId && message.threadId == peer.peerId.toInt64() {
|
||||
topTimestamp = max(topTimestamp, message.timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: peer.peerId.toInt64(), messageId: topMessage)
|
||||
if let minIndexValue = minIndex {
|
||||
if topicIndex < minIndexValue {
|
||||
minIndex = topicIndex
|
||||
}
|
||||
} else {
|
||||
minIndex = topicIndex
|
||||
}
|
||||
|
||||
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||
threadId: peer.peerId.toInt64(),
|
||||
data: data,
|
||||
topMessage: topMessage,
|
||||
unreadMentionsCount: 0,
|
||||
unreadReactionsCount: 0,
|
||||
index: topicIndex
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
var pinnedThreadIds: [Int64]?
|
||||
if offsetIndex == nil {
|
||||
pinnedThreadIds = pinnedIds
|
||||
}
|
||||
|
||||
var nextIndex: StoredPeerThreadCombinedState.Index
|
||||
if dialogs.count != 0 {
|
||||
nextIndex = minIndex ?? StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
} else {
|
||||
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
}
|
||||
if let offsetIndex = offsetIndex, nextIndex == offsetIndex {
|
||||
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
}
|
||||
|
||||
let combinedState = PeerThreadCombinedState(validIndexBoundary: nextIndex)
|
||||
|
||||
return .single(LoadMessageHistoryThreadsResult(
|
||||
peerId: peerId,
|
||||
items: items,
|
||||
messages: addedMessages,
|
||||
pinnedThreadIds: pinnedThreadIds,
|
||||
combinedState: combinedState,
|
||||
users: users,
|
||||
chats: chats
|
||||
))
|
||||
case .savedDialogsNotModified:
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
return signal
|
||||
} else {
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = postbox.transaction { transaction -> Api.InputChannel? in
|
||||
guard let channel = transaction.getPeer(peerId) as? TelegramChannel else {
|
||||
return nil
|
||||
}
|
||||
if !channel.flags.contains(.isForum) {
|
||||
return nil
|
||||
}
|
||||
return apiInputChannel(channel)
|
||||
}
|
||||
|> castError(LoadMessageHistoryThreadsError.self)
|
||||
|> mapToSignal { inputChannel -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
guard let inputChannel = inputChannel else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
if isSavedThreads {
|
||||
var flags: Int32 = 0
|
||||
|
||||
if query != nil {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
flags = 0
|
||||
|
||||
var offsetDate: Int32 = 0
|
||||
var offsetId: Int32 = 0
|
||||
var offsetTopic: Int32 = 0
|
||||
var offsetPeer: Api.InputPeer = .inputPeerEmpty
|
||||
if let offsetIndex = offsetIndex {
|
||||
offsetDate = offsetIndex.timestamp
|
||||
offsetId = offsetIndex.messageId
|
||||
offsetTopic = Int32(clamping: offsetIndex.threadId)
|
||||
offsetPeer = .inputPeerEmpty
|
||||
}
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = network.request(Api.functions.channels.getForumTopics(
|
||||
|
||||
var parentPeer: Api.InputPeer?
|
||||
if peerId != accountPeerId {
|
||||
guard let inputChannel = apiInputPeer(peer) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
flags |= 1 << 1
|
||||
parentPeer = inputChannel
|
||||
}
|
||||
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = network.request(Api.functions.messages.getSavedDialogs(
|
||||
flags: flags,
|
||||
channel: inputChannel,
|
||||
q: query,
|
||||
parentPeer: parentPeer,
|
||||
offsetDate: offsetDate,
|
||||
offsetId: offsetId,
|
||||
offsetTopic: offsetTopic,
|
||||
limit: Int32(limit)
|
||||
offsetPeer: offsetPeer,
|
||||
limit: Int32(limit),
|
||||
hash: 0
|
||||
))
|
||||
|> mapError { _ -> LoadMessageHistoryThreadsError in
|
||||
return .generic
|
||||
|> `catch` { error -> Signal<Api.messages.SavedDialogs, LoadMessageHistoryThreadsError> in
|
||||
if error.errorDescription == "SAVED_DIALOGS_UNSUPPORTED" {
|
||||
return .never()
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { result -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
switch result {
|
||||
case let .forumTopics(_, _, topics, messages, chats, users, pts):
|
||||
case .savedDialogs(let dialogs, let messages, let chats, let users), .savedDialogsSlice(_, let dialogs, let messages, let chats, let users):
|
||||
var items: [LoadMessageHistoryThreadsResult.Item] = []
|
||||
var pinnedIds: [Int64] = []
|
||||
|
||||
let addedMessages = messages.compactMap { message -> StoreMessage? in
|
||||
return StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: true)
|
||||
return StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: false)
|
||||
}
|
||||
|
||||
let _ = pts
|
||||
var minIndex: StoredPeerThreadCombinedState.Index?
|
||||
|
||||
for topic in topics {
|
||||
switch topic {
|
||||
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
||||
let _ = draft
|
||||
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
pinnedIds.append(Int64(id))
|
||||
for dialog in dialogs {
|
||||
switch dialog {
|
||||
case let .savedDialog(flags, peer, topMessage):
|
||||
if (flags & (1 << 2)) != 0 {
|
||||
pinnedIds.append(peer.peerId.toInt64())
|
||||
}
|
||||
|
||||
let data = MessageHistoryThreadData(
|
||||
creationDate: date,
|
||||
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||
author: fromId.peerId,
|
||||
creationDate: 0,
|
||||
isOwnedByMe: true,
|
||||
author: peer.peerId,
|
||||
info: EngineMessageHistoryThread.Info(
|
||||
title: title,
|
||||
icon: iconEmojiId == 0 ? nil : iconEmojiId,
|
||||
iconColor: iconColor
|
||||
title: "",
|
||||
icon: nil,
|
||||
iconColor: 0
|
||||
),
|
||||
incomingUnreadCount: unreadCount,
|
||||
maxIncomingReadId: readInboxMaxId,
|
||||
incomingUnreadCount: 0,
|
||||
maxIncomingReadId: 0,
|
||||
maxKnownMessageId: topMessage,
|
||||
maxOutgoingReadId: readOutboxMaxId,
|
||||
isClosed: (flags & (1 << 2)) != 0,
|
||||
isHidden: (flags & (1 << 6)) != 0,
|
||||
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||
maxOutgoingReadId: 0,
|
||||
isClosed: false,
|
||||
isHidden: false,
|
||||
notificationSettings: TelegramPeerNotificationSettings.defaultSettings
|
||||
)
|
||||
|
||||
var topTimestamp = date
|
||||
var topTimestamp: Int32 = 1
|
||||
for message in addedMessages {
|
||||
if message.id.peerId == peerId && message.threadId == Int64(id) {
|
||||
if message.id.peerId == peerId && message.threadId == peer.peerId.toInt64() {
|
||||
topTimestamp = max(topTimestamp, message.timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: Int64(id), messageId: topMessage)
|
||||
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: peer.peerId.toInt64(), messageId: topMessage)
|
||||
if let minIndexValue = minIndex {
|
||||
if topicIndex < minIndexValue {
|
||||
minIndex = topicIndex
|
||||
@ -905,15 +792,13 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
||||
}
|
||||
|
||||
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||
threadId: Int64(id),
|
||||
threadId: peer.peerId.toInt64(),
|
||||
data: data,
|
||||
topMessage: topMessage,
|
||||
unreadMentionsCount: unreadMentionsCount,
|
||||
unreadReactionsCount: unreadReactionsCount,
|
||||
unreadMentionsCount: 0,
|
||||
unreadReactionsCount: 0,
|
||||
index: topicIndex
|
||||
))
|
||||
case .forumTopicDeleted:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -923,7 +808,7 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
||||
}
|
||||
|
||||
var nextIndex: StoredPeerThreadCombinedState.Index
|
||||
if topics.count != 0 {
|
||||
if dialogs.count != 0 {
|
||||
nextIndex = minIndex ?? StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
} else {
|
||||
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
@ -943,12 +828,154 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
||||
users: users,
|
||||
chats: chats
|
||||
))
|
||||
case .savedDialogsNotModified:
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
return signal
|
||||
} else {
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = postbox.transaction { transaction -> Api.InputChannel? in
|
||||
guard let channel = transaction.getPeer(peerId) as? TelegramChannel else {
|
||||
return nil
|
||||
}
|
||||
if !channel.flags.contains(.isForum) {
|
||||
return nil
|
||||
}
|
||||
return apiInputChannel(channel)
|
||||
}
|
||||
|> castError(LoadMessageHistoryThreadsError.self)
|
||||
|> mapToSignal { inputChannel -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
guard let inputChannel = inputChannel else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
|
||||
if query != nil {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
|
||||
var offsetDate: Int32 = 0
|
||||
var offsetId: Int32 = 0
|
||||
var offsetTopic: Int32 = 0
|
||||
if let offsetIndex = offsetIndex {
|
||||
offsetDate = offsetIndex.timestamp
|
||||
offsetId = offsetIndex.messageId
|
||||
offsetTopic = Int32(clamping: offsetIndex.threadId)
|
||||
}
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = network.request(Api.functions.channels.getForumTopics(
|
||||
flags: flags,
|
||||
channel: inputChannel,
|
||||
q: query,
|
||||
offsetDate: offsetDate,
|
||||
offsetId: offsetId,
|
||||
offsetTopic: offsetTopic,
|
||||
limit: Int32(limit)
|
||||
))
|
||||
|> mapError { _ -> LoadMessageHistoryThreadsError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
switch result {
|
||||
case let .forumTopics(_, _, topics, messages, chats, users, pts):
|
||||
var items: [LoadMessageHistoryThreadsResult.Item] = []
|
||||
var pinnedIds: [Int64] = []
|
||||
|
||||
let addedMessages = messages.compactMap { message -> StoreMessage? in
|
||||
return StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: true)
|
||||
}
|
||||
|
||||
let _ = pts
|
||||
var minIndex: StoredPeerThreadCombinedState.Index?
|
||||
|
||||
for topic in topics {
|
||||
switch topic {
|
||||
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
||||
let _ = draft
|
||||
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
pinnedIds.append(Int64(id))
|
||||
}
|
||||
|
||||
let data = MessageHistoryThreadData(
|
||||
creationDate: date,
|
||||
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||
author: fromId.peerId,
|
||||
info: EngineMessageHistoryThread.Info(
|
||||
title: title,
|
||||
icon: iconEmojiId == 0 ? nil : iconEmojiId,
|
||||
iconColor: iconColor
|
||||
),
|
||||
incomingUnreadCount: unreadCount,
|
||||
maxIncomingReadId: readInboxMaxId,
|
||||
maxKnownMessageId: topMessage,
|
||||
maxOutgoingReadId: readOutboxMaxId,
|
||||
isClosed: (flags & (1 << 2)) != 0,
|
||||
isHidden: (flags & (1 << 6)) != 0,
|
||||
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||
)
|
||||
|
||||
var topTimestamp = date
|
||||
for message in addedMessages {
|
||||
if message.id.peerId == peerId && message.threadId == Int64(id) {
|
||||
topTimestamp = max(topTimestamp, message.timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: Int64(id), messageId: topMessage)
|
||||
if let minIndexValue = minIndex {
|
||||
if topicIndex < minIndexValue {
|
||||
minIndex = topicIndex
|
||||
}
|
||||
} else {
|
||||
minIndex = topicIndex
|
||||
}
|
||||
|
||||
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||
threadId: Int64(id),
|
||||
data: data,
|
||||
topMessage: topMessage,
|
||||
unreadMentionsCount: unreadMentionsCount,
|
||||
unreadReactionsCount: unreadReactionsCount,
|
||||
index: topicIndex
|
||||
))
|
||||
case .forumTopicDeleted:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var pinnedThreadIds: [Int64]?
|
||||
if offsetIndex == nil {
|
||||
pinnedThreadIds = pinnedIds
|
||||
}
|
||||
|
||||
var nextIndex: StoredPeerThreadCombinedState.Index
|
||||
if topics.count != 0 {
|
||||
nextIndex = minIndex ?? StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
} else {
|
||||
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
}
|
||||
if let offsetIndex = offsetIndex, nextIndex == offsetIndex {
|
||||
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
}
|
||||
|
||||
let combinedState = PeerThreadCombinedState(validIndexBoundary: nextIndex)
|
||||
|
||||
return .single(LoadMessageHistoryThreadsResult(
|
||||
peerId: peerId,
|
||||
items: items,
|
||||
messages: addedMessages,
|
||||
pinnedThreadIds: pinnedThreadIds,
|
||||
combinedState: combinedState,
|
||||
users: users,
|
||||
chats: chats
|
||||
))
|
||||
}
|
||||
}
|
||||
return signal
|
||||
}
|
||||
|
||||
return signal
|
||||
}
|
||||
|
||||
return signal
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2161,16 +2161,24 @@ public final class AccountViewTracker {
|
||||
if let account = self.account {
|
||||
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>
|
||||
if let peerId = chatLocation.peerId, let threadId = chatLocation.threadId, tag == nil {
|
||||
signal = account.postbox.transaction { transaction -> (MessageHistoryThreadData?, MessageIndex?) in
|
||||
signal = account.postbox.transaction { transaction -> (Peer?, MessageHistoryThreadData?, MessageIndex?) in
|
||||
let interfaceState = transaction.getPeerChatThreadInterfaceState(peerId, threadId: threadId)
|
||||
|
||||
return (
|
||||
transaction.getPeer(peerId),
|
||||
transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self),
|
||||
interfaceState?.historyScrollMessageIndex
|
||||
)
|
||||
}
|
||||
|> mapToSignal { threadInfo, scrollRestorationIndex -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in
|
||||
|> mapToSignal { peer, threadInfo, scrollRestorationIndex -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in
|
||||
var isSimpleThread = false
|
||||
if peerId == account.peerId {
|
||||
isSimpleThread = true
|
||||
} else if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
isSimpleThread = true
|
||||
}
|
||||
|
||||
if isSimpleThread {
|
||||
let anchor: HistoryViewInputAnchor
|
||||
if let scrollRestorationIndex {
|
||||
anchor = .index(scrollRestorationIndex)
|
||||
|
||||
@ -339,9 +339,12 @@ enum FetchMessageHistoryHoleThreadInput: CustomStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
func requestThreadId(accountPeerId: PeerId) -> Int64? {
|
||||
func requestThreadId(accountPeerId: PeerId, peer: Peer) -> Int64? {
|
||||
switch self {
|
||||
case let .direct(peerId, threadId):
|
||||
if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
return nil
|
||||
}
|
||||
if let threadId = threadId, peerId != accountPeerId {
|
||||
return threadId
|
||||
} else {
|
||||
@ -352,10 +355,12 @@ enum FetchMessageHistoryHoleThreadInput: CustomStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
func requestSubPeerId(accountPeerId: PeerId) -> PeerId? {
|
||||
func requestSubPeerId(accountPeerId: PeerId, peer: Peer) -> PeerId? {
|
||||
switch self {
|
||||
case let .direct(peerId, threadId):
|
||||
if let threadId = threadId, peerId == accountPeerId {
|
||||
if let threadId, peerId == accountPeerId {
|
||||
return PeerId(threadId)
|
||||
} else if let threadId, let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
return PeerId(threadId)
|
||||
} else {
|
||||
return nil
|
||||
@ -390,7 +395,12 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
return postbox.transaction { transaction -> (Peer?, Int64, Peer?) in
|
||||
switch peerInput {
|
||||
case let .direct(peerId, _):
|
||||
return (transaction.getPeer(peerId), 0, peerInput.requestSubPeerId(accountPeerId: accountPeerId).flatMap(transaction.getPeer))
|
||||
let peer = transaction.getPeer(peerId)
|
||||
var subPeerId: PeerId?
|
||||
if let peer {
|
||||
subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId, peer: peer)
|
||||
}
|
||||
return (peer, 0, subPeerId.flatMap(transaction.getPeer))
|
||||
case let .threadFromChannel(channelMessageId):
|
||||
return (transaction.getPeer(channelMessageId.peerId), 0, nil)
|
||||
}
|
||||
@ -411,7 +421,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
|
||||
switch space {
|
||||
case .everywhere:
|
||||
if let requestThreadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
if let requestThreadId = peerInput.requestThreadId(accountPeerId: accountPeerId, peer: peer) {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
@ -459,7 +469,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getReplies(peer: inputPeer, msgId: Int32(clamping: requestThreadId), offsetId: offsetId, offsetDate: 0, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: hash))
|
||||
} else if let subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId) {
|
||||
} else if let subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId, peer: peer) {
|
||||
guard let subPeer, subPeer.id == subPeerId, let inputSubPeer = apiInputPeer(subPeer) else {
|
||||
Logger.shared.log("fetchMessageHistoryHole", "subPeer not available")
|
||||
return .never()
|
||||
@ -511,7 +521,14 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
minMaxRange = 1 ... (Int32.max - 1)
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getSavedHistory(peer: inputSubPeer, offsetId: offsetId, offsetDate: 0, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: hash))
|
||||
var getSavedHistoryFlags: Int32 = 0
|
||||
var parentPeer: Api.InputPeer?
|
||||
if peer.id != accountPeerId {
|
||||
getSavedHistoryFlags |= 1 << 0
|
||||
parentPeer = inputPeer
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getSavedHistory(flags: getSavedHistoryFlags, parentPeer: parentPeer, peer: inputSubPeer, offsetId: offsetId, offsetDate: 0, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: hash))
|
||||
} else {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
@ -611,7 +628,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId, peer: peer) {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
@ -666,7 +683,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId, peer: peer) {
|
||||
flags |= (1 << 0)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
@ -730,13 +747,13 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId, peer: peer) {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
|
||||
var savedPeerId: Api.InputPeer?
|
||||
if let subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId), let subPeer = subPeer, subPeer.id == subPeerId {
|
||||
if let subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId, peer: peer), let subPeer = subPeer, subPeer.id == subPeerId {
|
||||
if let inputPeer = apiInputPeer(subPeer) {
|
||||
flags |= 1 << 2
|
||||
savedPeerId = inputPeer
|
||||
@ -799,13 +816,13 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId, peer: peer) {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
|
||||
var savedPeerId: Api.InputPeer?
|
||||
if let subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId), let subPeer = subPeer, subPeer.id == subPeerId {
|
||||
if let subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId, peer: peer), let subPeer = subPeer, subPeer.id == subPeerId {
|
||||
if let inputPeer = apiInputPeer(subPeer) {
|
||||
flags |= 1 << 2
|
||||
savedPeerId = inputPeer
|
||||
@ -960,9 +977,6 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
}
|
||||
|
||||
print("fetchMessageHistoryHole for \(peerInput) space \(space) done")
|
||||
if peerInput.requestThreadId(accountPeerId: accountPeerId) != nil, case .everywhere = space, case .aroundId = direction {
|
||||
assert(true)
|
||||
}
|
||||
|
||||
if ids.count == 0 || implicitelyFillHole {
|
||||
filledRange = minMaxRange
|
||||
@ -974,7 +988,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
filledRange = min(aroundId.id, messageRange.lowerBound) ... max(aroundId.id, messageRange.upperBound)
|
||||
strictFilledIndices = IndexSet(integersIn: Int(min(aroundId.id, messageRange.lowerBound)) ... Int(max(aroundId.id, messageRange.upperBound)))
|
||||
var shouldFillAround = false
|
||||
if peerInput.requestThreadId(accountPeerId: accountPeerId) != nil {
|
||||
if peerInput.requestThreadId(accountPeerId: accountPeerId, peer: peer) != nil || peerInput.requestSubPeerId(accountPeerId: accountPeerId, peer: peer) != nil {
|
||||
shouldFillAround = true
|
||||
}
|
||||
if case .customTag = space {
|
||||
|
||||
@ -565,6 +565,7 @@ public struct ChatReplyThreadMessage: Equatable {
|
||||
public var channelMessageId: MessageId?
|
||||
public var isChannelPost: Bool
|
||||
public var isForumPost: Bool
|
||||
public var isMonoforum: Bool
|
||||
public var maxMessage: MessageId?
|
||||
public var maxReadIncomingMessageId: MessageId?
|
||||
public var maxReadOutgoingMessageId: MessageId?
|
||||
@ -581,12 +582,13 @@ public struct ChatReplyThreadMessage: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public init(peerId: PeerId, threadId: Int64, channelMessageId: MessageId?, isChannelPost: Bool, isForumPost: Bool, maxMessage: MessageId?, maxReadIncomingMessageId: MessageId?, maxReadOutgoingMessageId: MessageId?, unreadCount: Int, initialFilledHoles: IndexSet, initialAnchor: Anchor, isNotAvailable: Bool) {
|
||||
public init(peerId: PeerId, threadId: Int64, channelMessageId: MessageId?, isChannelPost: Bool, isForumPost: Bool, isMonoforum: Bool, maxMessage: MessageId?, maxReadIncomingMessageId: MessageId?, maxReadOutgoingMessageId: MessageId?, unreadCount: Int, initialFilledHoles: IndexSet, initialAnchor: Anchor, isNotAvailable: Bool) {
|
||||
self.peerId = peerId
|
||||
self.threadId = threadId
|
||||
self.channelMessageId = channelMessageId
|
||||
self.isChannelPost = isChannelPost
|
||||
self.isForumPost = isForumPost
|
||||
self.isMonoforum = isMonoforum
|
||||
self.maxMessage = maxMessage
|
||||
self.maxReadIncomingMessageId = maxReadIncomingMessageId
|
||||
self.maxReadOutgoingMessageId = maxReadOutgoingMessageId
|
||||
@ -598,7 +600,7 @@ public struct ChatReplyThreadMessage: Equatable {
|
||||
|
||||
public var normalized: ChatReplyThreadMessage {
|
||||
if self.isForumPost {
|
||||
return ChatReplyThreadMessage(peerId: self.peerId, threadId: self.threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)
|
||||
return ChatReplyThreadMessage(peerId: self.peerId, threadId: self.threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)
|
||||
} else {
|
||||
return self
|
||||
}
|
||||
@ -931,6 +933,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
||||
channelMessageId: discussionMessage.channelMessageId,
|
||||
isChannelPost: discussionMessage.isChannelPost,
|
||||
isForumPost: discussionMessage.isForumPost,
|
||||
isMonoforum: false,
|
||||
maxMessage: discussionMessage.maxMessage,
|
||||
maxReadIncomingMessageId: discussionMessage.maxReadIncomingMessageId,
|
||||
maxReadOutgoingMessageId: discussionMessage.maxReadOutgoingMessageId,
|
||||
|
||||
@ -827,7 +827,13 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
|
||||
guard let subPeer = transaction.getPeer(PeerId(threadId)), let inputSubPeer = apiInputPeer(subPeer) else {
|
||||
return .single(nil)
|
||||
}
|
||||
let primaryIndex = account.network.request(Api.functions.messages.getSavedHistory(peer: inputSubPeer, offsetId: 0, offsetDate: timestamp, addOffset: -1, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||
var getSavedHistoryFlags: Int32 = 0
|
||||
var parentPeer: Api.InputPeer?
|
||||
if peer.id != account.peerId {
|
||||
getSavedHistoryFlags |= 1 << 0
|
||||
parentPeer = inputPeer
|
||||
}
|
||||
let primaryIndex = account.network.request(Api.functions.messages.getSavedHistory(flags: getSavedHistoryFlags, parentPeer: parentPeer, peer: inputSubPeer, offsetId: 0, offsetDate: timestamp, addOffset: -1, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||
|> map { result -> MessageIndex? in
|
||||
let messages: [Api.Message]
|
||||
switch result {
|
||||
|
||||
@ -29,6 +29,9 @@ func _internal_channelMembers(postbox: Postbox, network: Network, accountPeerId:
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
if peer.flags.contains(.isMonoforum) {
|
||||
return .single(nil)
|
||||
}
|
||||
|
||||
let apiFilter: Api.ChannelParticipantsFilter
|
||||
switch category {
|
||||
|
||||
@ -30,6 +30,10 @@ func fetchAndUpdateSupplementalCachedPeerData(peerId rawPeerId: PeerId, accountP
|
||||
} else {
|
||||
peer = rawPeer
|
||||
}
|
||||
|
||||
if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
return .single(false)
|
||||
}
|
||||
|
||||
let cachedData = transaction.getPeerCachedData(peerId: peer.id)
|
||||
|
||||
@ -579,6 +583,9 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
}
|
||||
}
|
||||
} else if let inputChannel = maybePeer.flatMap(apiInputChannel) {
|
||||
if let channel = maybePeer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
return .single(false)
|
||||
}
|
||||
let fullChannelSignal = network.request(Api.functions.channels.getFullChannel(channel: inputChannel))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { error -> Signal<Api.messages.ChatFull?, NoError> in
|
||||
|
||||
@ -804,7 +804,7 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
||||
return ChatListItem(
|
||||
presentationData: chatListPresentationData,
|
||||
context: component.context,
|
||||
chatListLocation: component.peerId == component.context.account.peerId ? .savedMessagesChats : .chatList(groupId: .root),
|
||||
chatListLocation: component.peerId == component.context.account.peerId ? .savedMessagesChats(peerId: component.context.account.peerId) : .chatList(groupId: .root),
|
||||
filterData: nil,
|
||||
index: .forum(
|
||||
pinnedIndex: .none,
|
||||
|
||||
@ -149,7 +149,7 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, AS
|
||||
|
||||
self.chatListNode = ChatListNode(
|
||||
context: self.context,
|
||||
location: .savedMessagesChats,
|
||||
location: .savedMessagesChats(peerId: context.account.peerId),
|
||||
chatListFilter: nil,
|
||||
previewing: false,
|
||||
fillPreloadItems: false,
|
||||
@ -210,6 +210,7 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, AS
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: false,
|
||||
isMonoforum: false,
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
@ -378,7 +379,7 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, AS
|
||||
if case let .peer(peerData) = item.content {
|
||||
let threadId = peerData.peer.peerId.toInt64()
|
||||
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||
peerId: self.context.account.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: self.context.account.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: false, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
)), subject: nil, botStart: nil, mode: .standard(.previewing), params: nil)
|
||||
chatController.canReadHistory.set(false)
|
||||
let source: ContextContentSource = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: parentController.navigationController as? NavigationController))
|
||||
|
||||
@ -149,7 +149,7 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScro
|
||||
|
||||
self.coveringView = UIView()
|
||||
|
||||
self.chatController = context.sharedContext.makeChatController(context: context, chatLocation: .replyThread(message: ChatReplyThreadMessage(peerId: context.account.peerId, threadId: peerId.toInt64(), channelMessageId: nil, isChannelPost: false, isForumPost: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)), subject: nil, botStart: nil, mode: .standard(.embedded(invertDirection: true)), params: nil)
|
||||
self.chatController = context.sharedContext.makeChatController(context: context, chatLocation: .replyThread(message: ChatReplyThreadMessage(peerId: context.account.peerId, threadId: peerId.toInt64(), channelMessageId: nil, isChannelPost: false, isForumPost: false, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)), subject: nil, botStart: nil, mode: .standard(.embedded(invertDirection: true)), params: nil)
|
||||
self.chatController.navigation_setNavigationController(navigationController())
|
||||
|
||||
super.init()
|
||||
|
||||
@ -11016,7 +11016,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
self?.deactivateSearch()
|
||||
})
|
||||
} else if let currentPaneKey = self.paneContainerNode.currentPaneKey, case .savedMessagesChats = currentPaneKey {
|
||||
let contentNode = ChatListSearchContainerNode(context: self.context, animationCache: self.context.animationCache, animationRenderer: self.context.animationRenderer, filter: [.removeSearchHeader], requestPeerType: nil, location: .savedMessagesChats, displaySearchFilters: false, hasDownloads: false, initialFilter: .chats, openPeer: { [weak self] peer, _, _, _ in
|
||||
let contentNode = ChatListSearchContainerNode(context: self.context, animationCache: self.context.animationCache, animationRenderer: self.context.animationRenderer, filter: [.removeSearchHeader], requestPeerType: nil, location: .savedMessagesChats(peerId: self.context.account.peerId), displaySearchFilters: false, hasDownloads: false, initialFilter: .chats, openPeer: { [weak self] peer, _, _, _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -11032,6 +11032,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: false,
|
||||
isMonoforum: false,
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
@ -11061,6 +11062,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: false,
|
||||
isMonoforum: false,
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
@ -13374,7 +13376,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
||||
let navigateChatLocation: NavigateToChatControllerParams.Location
|
||||
if let threadId = item.threadId {
|
||||
navigateChatLocation = .replyThread(ChatReplyThreadMessage(
|
||||
peerId: item.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: item.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false,maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
))
|
||||
} else {
|
||||
navigateChatLocation = .peer(itemPeer)
|
||||
|
||||
@ -2586,7 +2586,7 @@ final class StorageUsageScreenComponent: Component {
|
||||
|
||||
var chatLocation: NavigateToChatControllerParams.Location = .peer(peer)
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isForum), let threadId = message.threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
}
|
||||
|
||||
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
@ -2689,7 +2689,7 @@ final class StorageUsageScreenComponent: Component {
|
||||
|
||||
var chatLocation: NavigateToChatControllerParams.Location = .peer(peer)
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isForum), let threadId = message.threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
}
|
||||
|
||||
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
|
||||
@ -325,7 +325,7 @@ final class AuthorizedApplicationContext {
|
||||
let chatLocation: NavigateToChatControllerParams.Location
|
||||
if let _ = threadData, let threadId = firstMessage.threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(
|
||||
peerId: firstMessage.id.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: firstMessage.id.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
).normalized)
|
||||
} else {
|
||||
guard let peer = firstMessage.peers[firstMessage.id.peerId] else {
|
||||
@ -941,7 +941,7 @@ final class AuthorizedApplicationContext {
|
||||
let chatLocation: NavigateToChatControllerParams.Location
|
||||
if let threadId = threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(
|
||||
peerId: peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
))
|
||||
} else {
|
||||
chatLocation = .peer(peer)
|
||||
|
||||
@ -6231,14 +6231,23 @@ extension ChatControllerImpl {
|
||||
guard let peerId = self.chatLocation.peerId else {
|
||||
return
|
||||
}
|
||||
guard let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer else {
|
||||
return
|
||||
}
|
||||
let updatedChatLocation: ChatLocation
|
||||
if let threadId {
|
||||
var isMonoforum = false
|
||||
if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
isMonoforum = true
|
||||
}
|
||||
|
||||
updatedChatLocation = .replyThread(message: ChatReplyThreadMessage(
|
||||
peerId: peerId,
|
||||
threadId: threadId,
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: true,
|
||||
isMonoforum: isMonoforum,
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
@ -6709,6 +6718,7 @@ extension ChatControllerImpl {
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: true,
|
||||
isMonoforum: false,
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
|
||||
@ -144,7 +144,7 @@ extension ChatControllerImpl {
|
||||
|
||||
let navigateToLocation: NavigateToChatControllerParams.Location
|
||||
if let message = messages.first, let threadId = message.threadId, let channel = message.peers[message.id.peerId] as? TelegramChannel, channel.flags.contains(.isForum) {
|
||||
navigateToLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
navigateToLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false,maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
} else {
|
||||
navigateToLocation = .peer(peer)
|
||||
}
|
||||
@ -179,7 +179,7 @@ extension ChatControllerImpl {
|
||||
var displayMessageNotFoundToast = false
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isForum) {
|
||||
if let message = message, let threadId = message.threadId {
|
||||
let replyThreadMessage = ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)
|
||||
let replyThreadMessage = ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)
|
||||
chatLocation = .replyThread(replyThreadMessage)
|
||||
preloadChatLocation = .replyThread(message: replyThreadMessage)
|
||||
} else {
|
||||
|
||||
@ -6131,7 +6131,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
let chatLocation: ChatLocation
|
||||
if let threadId {
|
||||
chatLocation = .replyThread(message: ChatReplyThreadMessage(peerId: peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
chatLocation = .replyThread(message: ChatReplyThreadMessage(peerId: peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
} else {
|
||||
chatLocation = .peer(id: peerId)
|
||||
}
|
||||
|
||||
@ -2964,6 +2964,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: false,
|
||||
isMonoforum: false,
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
|
||||
@ -1647,8 +1647,18 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
|
||||
let topicAuthorId: Signal<EnginePeer.Id?, NoError>
|
||||
if let peerId = chatLocation.peerId, let threadId = chatLocation.threadId {
|
||||
topicAuthorId = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.ThreadData(id: peerId, threadId: threadId))
|
||||
|> map { data -> EnginePeer.Id? in
|
||||
topicAuthorId = context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.ThreadData(id: peerId, threadId: threadId)
|
||||
)
|
||||
|> map { peer, data -> EnginePeer.Id? in
|
||||
guard let peer else {
|
||||
return nil
|
||||
}
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isMonoforum) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return data?.author
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
@ -102,7 +102,7 @@ func chatHistoryViewForLocation(
|
||||
if tag != nil {
|
||||
requestAroundId = true
|
||||
}
|
||||
if case let .replyThread(message) = chatLocation, message.peerId == context.account.peerId {
|
||||
if case let .replyThread(message) = chatLocation, (message.peerId == context.account.peerId || message.isMonoforum) {
|
||||
preFixedReadState = .peer([:])
|
||||
}
|
||||
|
||||
|
||||
@ -185,7 +185,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, ASScrollViewDe
|
||||
self.searchState = searchState
|
||||
|
||||
if case let .peer(peerId, _, _, _, _, _, _) = location, peerId == context.account.peerId {
|
||||
self.mappedLocation = .savedMessagesChats
|
||||
self.mappedLocation = .savedMessagesChats(peerId: peerId)
|
||||
} else {
|
||||
self.mappedLocation = .chatList(groupId: .root)
|
||||
}
|
||||
|
||||
@ -27,7 +27,9 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
}
|
||||
|
||||
var viewForumAsMessages: Signal<Bool, NoError> = .single(false)
|
||||
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum) {
|
||||
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isMonoforum) {
|
||||
viewForumAsMessages = .single(false)
|
||||
} else if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum) {
|
||||
viewForumAsMessages = params.context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peer.id)])
|
||||
|> take(1)
|
||||
|> map { combinedView in
|
||||
@ -52,6 +54,11 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
let _ = (viewForumAsMessages
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { viewForumAsMessages in
|
||||
var viewForumAsMessages = viewForumAsMessages
|
||||
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isMonoforum), channel.adminRights == nil {
|
||||
viewForumAsMessages = true
|
||||
}
|
||||
|
||||
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum), !viewForumAsMessages {
|
||||
for controller in params.navigationController.viewControllers.reversed() {
|
||||
var chatListController: ChatListControllerImpl?
|
||||
@ -65,6 +72,8 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
var matches = false
|
||||
if case let .forum(peerId) = chatListController.location, peer.id == peerId {
|
||||
matches = true
|
||||
} else if case let .savedMessagesChats(peerId) = chatListController.location, peer.id == peerId {
|
||||
matches = true
|
||||
} else if case let .forum(peerId) = chatListController.effectiveLocation, peer.id == peerId {
|
||||
matches = true
|
||||
}
|
||||
@ -79,7 +88,14 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
}
|
||||
}
|
||||
|
||||
let controller = ChatListControllerImpl(context: params.context, location: .forum(peerId: peer.id), controlsHistoryPreload: false, enableDebugActions: false)
|
||||
let chatListLocation: ChatListControllerLocation
|
||||
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isMonoforum) {
|
||||
chatListLocation = .savedMessagesChats(peerId: peer.id)
|
||||
} else {
|
||||
chatListLocation = .forum(peerId: peer.id)
|
||||
}
|
||||
|
||||
let controller = ChatListControllerImpl(context: params.context, location: chatListLocation, controlsHistoryPreload: false, enableDebugActions: false)
|
||||
|
||||
let activateMessageSearch = params.activateMessageSearch
|
||||
let chatListCompletion = params.chatListCompletion
|
||||
|
||||
@ -76,10 +76,14 @@ public struct ChatTranslationState: Codable {
|
||||
}
|
||||
|
||||
private func cachedChatTranslationState(engine: TelegramEngine, peerId: EnginePeer.Id, threadId: Int64?) -> Signal<ChatTranslationState?, NoError> {
|
||||
let key = EngineDataBuffer(length: 8)
|
||||
key.setInt64(0, value: peerId.id._internalGetInt64Value())
|
||||
let key: EngineDataBuffer
|
||||
if let threadId {
|
||||
key = EngineDataBuffer(length: 8 + 8)
|
||||
key.setInt64(0, value: peerId.id._internalGetInt64Value())
|
||||
key.setInt64(8, value: threadId)
|
||||
} else {
|
||||
key = EngineDataBuffer(length: 8)
|
||||
key.setInt64(0, value: peerId.id._internalGetInt64Value())
|
||||
}
|
||||
|
||||
return engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.translationState, id: key))
|
||||
@ -89,10 +93,14 @@ private func cachedChatTranslationState(engine: TelegramEngine, peerId: EnginePe
|
||||
}
|
||||
|
||||
private func updateChatTranslationState(engine: TelegramEngine, peerId: EnginePeer.Id, threadId: Int64?, state: ChatTranslationState?) -> Signal<Never, NoError> {
|
||||
let key = EngineDataBuffer(length: 8)
|
||||
key.setInt64(0, value: peerId.id._internalGetInt64Value())
|
||||
let key: EngineDataBuffer
|
||||
if let threadId {
|
||||
key = EngineDataBuffer(length: 8 + 8)
|
||||
key.setInt64(0, value: peerId.id._internalGetInt64Value())
|
||||
key.setInt64(8, value: threadId)
|
||||
} else {
|
||||
key = EngineDataBuffer(length: 8)
|
||||
key.setInt64(0, value: peerId.id._internalGetInt64Value())
|
||||
}
|
||||
|
||||
if let state {
|
||||
|
||||
@ -841,7 +841,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
return .progress
|
||||
case let .result(info):
|
||||
if let _ = info {
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
} else {
|
||||
return .result(.peer(peer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))
|
||||
}
|
||||
@ -866,7 +866,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
return .progress
|
||||
case let .result(info):
|
||||
if let _ = info {
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: Int64(replyThreadMessageId.id), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: replyId)))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: Int64(replyThreadMessageId.id), channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: replyId)))
|
||||
} else {
|
||||
return .result(.peer(peer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))
|
||||
}
|
||||
@ -956,7 +956,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
return .progress
|
||||
case let .result(info):
|
||||
if let _ = info {
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: Int64(threadId), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: Int64(threadId), channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
} else {
|
||||
return .result(.peer(peer?._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))
|
||||
}
|
||||
@ -980,7 +980,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
return .progress
|
||||
case let .result(info):
|
||||
if let _ = info {
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforum: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
} else {
|
||||
return .result(.peer(peer?._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user