mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-31 23:47:01 +00:00
Monoforums
This commit is contained in:
parent
23e52bc1f7
commit
77e21b4047
@ -463,6 +463,7 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
||||
|
||||
public static let toggleUnread = Actions(rawValue: 1 << 0)
|
||||
public static let delete = Actions(rawValue: 1 << 1)
|
||||
public static let togglePinned = Actions(rawValue: 1 << 2)
|
||||
}
|
||||
|
||||
case custom(Actions)
|
||||
|
@ -247,7 +247,7 @@ func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title:
|
||||
}
|
||||
|> castError(CreateForumChannelTopicError.self)
|
||||
|> mapToSignal { _ -> Signal<Int64, CreateForumChannelTopicError> in
|
||||
return resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: topicId)])
|
||||
return resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), additionalPeers: AccumulatedPeers(), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: topicId)])
|
||||
|> castError(CreateForumChannelTopicError.self)
|
||||
|> map { _ -> Int64 in
|
||||
return topicId
|
||||
@ -277,7 +277,7 @@ func _internal_fetchForumChannelTopic(account: Account, peerId: PeerId, threadId
|
||||
if let info = info {
|
||||
return .single(.result(info))
|
||||
} else {
|
||||
return .single(.progress) |> then(resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: threadId)])
|
||||
return .single(.progress) |> then(resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), additionalPeers: AccumulatedPeers(), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: threadId)])
|
||||
|> mapToSignal { _ -> Signal<FetchForumChannelTopicResult, NoError> in
|
||||
return account.postbox.transaction { transaction -> FetchForumChannelTopicResult in
|
||||
if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||
|
@ -2019,7 +2019,16 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
||||
}
|
||||
|
||||
if peer.flags.contains(.isMonoforum) {
|
||||
let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { transaction.getPeer(PeerId($0)).flatMap(apiInputPeer(_:)) }))
|
||||
let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { threadId in
|
||||
let threadPeerId = PeerId(threadId)
|
||||
if let threadPeer = state.peers[threadPeerId] {
|
||||
return apiInputPeer(threadPeer)
|
||||
} else if let threadPeer = transaction.getPeer(threadPeerId) {
|
||||
return apiInputPeer(threadPeer)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}))
|
||||
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||
let result = FetchedForumThreads(savedDialogs: result)
|
||||
return (peer, result)
|
||||
@ -2146,7 +2155,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
||||
}
|
||||
}
|
||||
|
||||
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, ids: [PeerAndBoundThreadId]) -> Signal<Void, NoError> {
|
||||
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, additionalPeers: AccumulatedPeers, ids: [PeerAndBoundThreadId]) -> Signal<Void, NoError> {
|
||||
let forumThreadIds = Set(ids)
|
||||
|
||||
if forumThreadIds.isEmpty {
|
||||
@ -2172,7 +2181,16 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
||||
}
|
||||
|
||||
if peer.flags.contains(.isMonoforum) {
|
||||
let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { transaction.getPeer(PeerId($0)).flatMap(apiInputPeer(_:)) }))
|
||||
let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { threadId in
|
||||
let threadPeerId = PeerId(threadId)
|
||||
if let threadPeer = additionalPeers.get(threadPeerId) {
|
||||
return apiInputPeer(threadPeer)
|
||||
} else if let threadPeer = transaction.getPeer(threadPeerId) {
|
||||
return apiInputPeer(threadPeer)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}))
|
||||
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||
let result = FetchedForumThreads(savedDialogs: result)
|
||||
return (peer, result)
|
||||
@ -2329,7 +2347,16 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
||||
}
|
||||
|
||||
if peer.flags.contains(.isMonoforum) {
|
||||
let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { transaction.getPeer(PeerId($0)).flatMap(apiInputPeer(_:)) }))
|
||||
let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { threadId in
|
||||
let threadPeerId = PeerId(threadId)
|
||||
if let threadPeer = fetchedChatList.peers.get(threadPeerId) {
|
||||
return apiInputPeer(threadPeer)
|
||||
} else if let threadPeer = transaction.getPeer(threadPeerId) {
|
||||
return apiInputPeer(threadPeer)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}))
|
||||
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||
let result = FetchedForumThreads(savedDialogs: result)
|
||||
return (peer, result)
|
||||
|
@ -225,7 +225,7 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages, additionalPeers: parsedPeers, result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
if resolveThreads && !threadIds.isEmpty {
|
||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, ids: Array(threadIds))
|
||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, additionalPeers: parsedPeers, ids: Array(threadIds))
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
return postbox.transaction { transaction -> T in
|
||||
return f(transaction, parsedPeers, [])
|
||||
@ -325,7 +325,8 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
||||
let combinedMessages = storeMessages + additionalMessages
|
||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: combinedMessages, reactions: [], result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: parsedPeers.union(with: additionalPeers), result: Void())
|
||||
let additionalPeers = parsedPeers.union(with: additionalPeers)
|
||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: additionalPeers, result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
var threadIds = Set<PeerAndBoundThreadId>()
|
||||
for message in combinedMessages {
|
||||
@ -335,7 +336,7 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
||||
}
|
||||
|
||||
if resolveThreads && !threadIds.isEmpty {
|
||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, ids: Array(threadIds))
|
||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, additionalPeers: additionalPeers, ids: Array(threadIds))
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
return postbox.transaction { transaction -> T in
|
||||
return f(transaction, parsedPeers, [])
|
||||
|
@ -1426,7 +1426,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
strongSelf.textNode.textNode.frame = imageFrame
|
||||
}
|
||||
|
||||
strongSelf.imageNode.frame = updatedContentFrame
|
||||
animation.animator.updateFrame(layer: strongSelf.imageNode.layer, frame: updatedContentFrame, completion: nil)
|
||||
|
||||
strongSelf.contextSourceNode.contentRect = contextContentFrame
|
||||
strongSelf.containerNode.targetNodeForActivationProgressContentRect = strongSelf.contextSourceNode.contentRect
|
||||
@ -1458,11 +1458,13 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
let foregroundColor: UIColor = .clear// = bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.stickerPlaceholderColor, wallpaper: item.presentationData.theme.wallpaper)
|
||||
let shimmeringColor = bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.stickerPlaceholderShimmerColor, wallpaper: item.presentationData.theme.wallpaper)
|
||||
strongSelf.placeholderNode.update(backgroundColor: nil, foregroundColor: foregroundColor, shimmeringColor: shimmeringColor, data: immediateThumbnailData, size: animationNodeFrame.size, enableEffect: item.context.sharedContext.energyUsageSettings.fullTranslucency, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0))
|
||||
strongSelf.placeholderNode.frame = animationNodeFrame
|
||||
animation.animator.updateFrame(layer: strongSelf.placeholderNode.layer, frame: animationNodeFrame, completion: nil)
|
||||
}
|
||||
|
||||
if strongSelf.animationNode?.supernode === strongSelf.contextSourceNode.contentNode {
|
||||
strongSelf.animationNode?.frame = animationNodeFrame
|
||||
if let animationNode = strongSelf.animationNode {
|
||||
animation.animator.updateFrame(layer: animationNode.layer, frame: animationNodeFrame, completion: nil)
|
||||
}
|
||||
if let animationNode = strongSelf.animationNode as? AnimatedStickerNode {
|
||||
animationNode.updateLayout(size: updatedContentFrame.insetBy(dx: imageInset, dy: imageInset).size)
|
||||
|
||||
@ -1494,7 +1496,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||
updatedShareButtonNode.frame = CGRect(origin: CGPoint(x: !incoming ? updatedImageFrame.minX - buttonSize.width - 6.0 : updatedImageFrame.maxX + 8.0, y: updatedImageFrame.maxY - buttonSize.height - 4.0 + imageBottomPadding), size: buttonSize)
|
||||
animation.animator.updateFrame(layer: updatedShareButtonNode.layer, frame: CGRect(origin: CGPoint(x: !incoming ? updatedImageFrame.minX - buttonSize.width - 6.0 : updatedImageFrame.maxX + 8.0, y: updatedImageFrame.maxY - buttonSize.height - 4.0 + imageBottomPadding), size: buttonSize), completion: nil)
|
||||
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
||||
shareButtonNode.removeFromSupernode()
|
||||
strongSelf.shareButtonNode = nil
|
||||
|
@ -178,6 +178,9 @@ final class ChatMessageNotificationItemNode: NotificationItemNode {
|
||||
if firstMessage.id.peerId.isRepliesOrVerificationCodes, let author = firstMessage.forwardInfo?.author {
|
||||
avatarPeer = EnginePeer(author)
|
||||
}
|
||||
if case let .channel(channel) = avatarPeer, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = firstMessage.peers[linkedMonoforumId] as? TelegramChannel {
|
||||
avatarPeer = .channel(mainChannel)
|
||||
}
|
||||
self.avatarNode.setPeer(context: item.context, theme: presentationData.theme, peer: avatarPeer, overrideImage: peer.id == item.context.account.peerId ? .savedMessagesIcon : nil, emptyColor: presentationData.theme.list.mediaPlaceholderColor)
|
||||
}
|
||||
|
||||
|
@ -995,7 +995,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
|
||||
let placeholderFrame = updatedImageFrame.insetBy(dx: innerImageInset, dy: innerImageInset)
|
||||
strongSelf.placeholderNode.update(backgroundColor: nil, foregroundColor: foregroundColor, shimmeringColor: shimmeringColor, data: immediateThumbnailData, size: placeholderFrame.size, enableEffect: item.context.sharedContext.energyUsageSettings.fullTranslucency)
|
||||
strongSelf.placeholderNode.frame = placeholderFrame
|
||||
animation.animator.updateFrame(layer: strongSelf.placeholderNode.layer, frame: placeholderFrame, completion: nil)
|
||||
}
|
||||
|
||||
strongSelf.messageAccessibilityArea.frame = CGRect(origin: CGPoint(), size: layoutSize)
|
||||
@ -1067,7 +1067,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
strongSelf.contextSourceNode.contentNode.addSubnode(threadInfoNode)
|
||||
}
|
||||
let threadInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 6.0) : (params.width - params.rightInset - threadInfoSize.width - layoutConstants.bubble.edgeInset - 8.0)), y: 8.0), size: threadInfoSize)
|
||||
threadInfoNode.frame = threadInfoFrame
|
||||
animation.animator.updateFrame(layer: threadInfoNode.layer, frame: threadInfoFrame, completion: nil)
|
||||
|
||||
headersOffset += threadInfoSize.height + 10.0
|
||||
} else if let replyInfoNode = strongSelf.replyInfoNode {
|
||||
@ -1120,7 +1120,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0 + 5.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 8.0 - 5.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: forwardInfoSize)
|
||||
forwardInfoNode.frame = forwardInfoFrame
|
||||
animation.animator.updateFrame(layer: forwardInfoNode.layer, frame: forwardInfoFrame, completion: nil)
|
||||
|
||||
messageInfoSize = CGSize(width: messageInfoSize.width, height: messageInfoSize.height + forwardInfoSize.height + 8.0)
|
||||
|
||||
|
@ -1409,11 +1409,11 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
/*#if DEBUG
|
||||
#if DEBUG
|
||||
if "".isEmpty {
|
||||
hasTranslationPanel = true
|
||||
}
|
||||
#endif*/
|
||||
#endif
|
||||
|
||||
if hasTranslationPanel {
|
||||
let translationPanelNode: ChatTranslationPanelNode
|
||||
@ -3283,71 +3283,16 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
guard let self else {
|
||||
return nil
|
||||
}
|
||||
guard let peerId = self.chatPresentationInterfaceState.chatLocation.peerId else {
|
||||
guard let peer = self.chatPresentationInterfaceState.renderedPeer?.peer else {
|
||||
return nil
|
||||
}
|
||||
if !peer.isForumOrMonoForum {
|
||||
return nil
|
||||
}
|
||||
|
||||
let viewKey: PostboxViewKey = .savedMessagesIndex(peerId: peerId)
|
||||
let threadListSignal: Signal<EngineChatList, NoError> = context.sharedContext.subscribeChatListData(context: self.context, location: peer.isMonoForum ? .savedMessagesChats(peerId: peer.id) : .forum(peerId: peer.id))
|
||||
|
||||
let threadListSignal: Signal<EngineChatList?, NoError> = self.context.account.postbox.combinedView(keys: [viewKey])
|
||||
|> map { views -> EngineChatList? in
|
||||
guard let view = views.views[viewKey] as? MessageHistorySavedMessagesIndexView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
||||
var items: [EngineChatList.Item] = []
|
||||
for item in view.items {
|
||||
guard let sourcePeer = item.peer else {
|
||||
continue
|
||||
}
|
||||
|
||||
let sourceId = PeerId(item.id)
|
||||
|
||||
var messages: [EngineMessage] = []
|
||||
if let topMessage = item.topMessage {
|
||||
messages.append(EngineMessage(topMessage))
|
||||
}
|
||||
|
||||
let mappedMessageIndex = MessageIndex(id: MessageId(peerId: sourceId, namespace: item.index.id.namespace, id: item.index.id.id), timestamp: item.index.timestamp)
|
||||
|
||||
items.append(EngineChatList.Item(
|
||||
id: .chatList(sourceId),
|
||||
index: .chatList(ChatListIndex(pinningIndex: item.pinnedIndex.flatMap(UInt16.init), messageIndex: mappedMessageIndex)),
|
||||
messages: messages,
|
||||
readCounters: EnginePeerReadCounters(
|
||||
incomingReadId: 0, outgoingReadId: 0, count: Int32(item.unreadCount), markedUnread: item.markedUnread),
|
||||
isMuted: false,
|
||||
draft: nil,
|
||||
threadData: nil,
|
||||
renderedPeer: EngineRenderedPeer(peer: EnginePeer(sourcePeer)),
|
||||
presence: nil,
|
||||
hasUnseenMentions: false,
|
||||
hasUnseenReactions: false,
|
||||
forumTopicData: nil,
|
||||
topForumTopicItems: [],
|
||||
hasFailed: false,
|
||||
isContact: false,
|
||||
autoremoveTimeout: nil,
|
||||
storyStats: nil,
|
||||
displayAsTopicList: false,
|
||||
isPremiumRequiredToMessage: false,
|
||||
mediaDraftContentType: nil
|
||||
))
|
||||
}
|
||||
|
||||
let list = EngineChatList(
|
||||
items: items.reversed(),
|
||||
groupItems: [],
|
||||
additionalItems: [],
|
||||
hasEarlier: false,
|
||||
hasLater: false,
|
||||
isLoading: view.isLoading
|
||||
)
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
return threadListSignal
|
||||
return threadListSignal |> map(Optional.init)
|
||||
},
|
||||
loadMoreSearchResults: { [weak self] in
|
||||
guard let self, let controller = self.controller else {
|
||||
|
@ -167,9 +167,13 @@ final class ChatTranslationPanelNode: ASDisplayNode {
|
||||
let buttonTextSize = self.buttonTextNode.updateLayout(CGSize(width: width - contentRightInset - moreButtonSize.width, height: panelHeight))
|
||||
if let icon = self.buttonIconNode.image {
|
||||
let buttonSize = CGSize(width: buttonTextSize.width + icon.size.width + buttonSpacing + buttonPadding * 2.0, height: panelHeight)
|
||||
self.button.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - buttonSize.width) / 2.0), y: 0.0), size: buttonSize)
|
||||
self.buttonIconNode.frame = CGRect(origin: CGPoint(x: buttonPadding, y: floorToScreenPixels((buttonSize.height - icon.size.height) / 2.0)), size: icon.size)
|
||||
self.buttonTextNode.frame = CGRect(origin: CGPoint(x: buttonPadding + icon.size.width + buttonSpacing, y: floorToScreenPixels((buttonSize.height - buttonTextSize.height) / 2.0)), size: buttonTextSize)
|
||||
transition.updateFrame(node: self.button, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((width - buttonSize.width) / 2.0), y: 0.0), size: buttonSize))
|
||||
|
||||
transition.updateFrame(node: self.buttonIconNode, frame: CGRect(origin: CGPoint(x: buttonPadding, y: floorToScreenPixels((buttonSize.height - icon.size.height) / 2.0)), size: icon.size))
|
||||
|
||||
let buttonTextFrame = CGRect(origin: CGPoint(x: buttonPadding + icon.size.width + buttonSpacing, y: floorToScreenPixels((buttonSize.height - buttonTextSize.height) / 2.0)), size: buttonTextSize)
|
||||
transition.updatePosition(node: self.buttonTextNode, position: buttonTextFrame.center)
|
||||
self.buttonTextNode.bounds = CGRect(origin: CGPoint(), size: buttonTextFrame.size)
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user