mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-19 01:31:33 +00:00
[WIP] Monoforums
This commit is contained in:
parent
b752a49432
commit
1a56afcb48
@ -142,7 +142,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
|
||||
let primaryPeer: EnginePeer
|
||||
var chatPeer: EnginePeer?
|
||||
let maybeChatPeer = EnginePeer(peer.peer.peers[peer.peer.peerId]!)
|
||||
if let associatedPeerId = maybeChatPeer._asPeer().associatedPeerId, let associatedPeer = peer.peer.peers[associatedPeerId] {
|
||||
if case .secretChat = maybeChatPeer, let associatedPeerId = maybeChatPeer._asPeer().associatedPeerId, let associatedPeer = peer.peer.peers[associatedPeerId] {
|
||||
primaryPeer = EnginePeer(associatedPeer)
|
||||
chatPeer = maybeChatPeer
|
||||
} else {
|
||||
@ -1154,7 +1154,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
|
||||
if message.id.peerId == peerId {
|
||||
if let threadId = message.threadId, let threadInfo = threadInfo {
|
||||
chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo, isOwnedByMe: false, isClosed: false, isHidden: false)
|
||||
chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo, isOwnedByMe: false, isClosed: false, isHidden: false, threadPeer: nil)
|
||||
index = .forum(pinnedIndex: .none, timestamp: message.index.timestamp, threadId: threadId, namespace: message.index.id.namespace, id: message.index.id.id)
|
||||
} else {
|
||||
index = .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index))
|
||||
@ -2748,7 +2748,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
|
||||
for thread in allAndFoundThreads {
|
||||
if let peer = thread.renderedPeer.peer, let threadData = thread.threadData, case let .forum(_, _, id, _, _) = thread.index {
|
||||
entries.append(.topic(peer, ChatListItemContent.ThreadInfo(id: id, info: threadData.info, isOwnedByMe: threadData.isOwnedByMe, isClosed: threadData.isClosed, isHidden: threadData.isHidden), index, presentationData.theme, presentationData.strings, .none))
|
||||
entries.append(.topic(peer, ChatListItemContent.ThreadInfo(id: id, info: threadData.info, isOwnedByMe: threadData.isOwnedByMe, isClosed: threadData.isClosed, isHidden: threadData.isHidden, threadPeer: nil), index, presentationData.theme, presentationData.strings, .none))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
@ -32,19 +32,43 @@ import MultilineTextWithEntitiesComponent
|
||||
import ShimmerEffect
|
||||
|
||||
public enum ChatListItemContent {
|
||||
public struct ThreadInfo: Equatable {
|
||||
public var id: Int64
|
||||
public var info: EngineMessageHistoryThread.Info
|
||||
public var isOwnedByMe: Bool
|
||||
public var isClosed: Bool
|
||||
public var isHidden: Bool
|
||||
public final class ThreadInfo: Equatable {
|
||||
public let id: Int64
|
||||
public let info: EngineMessageHistoryThread.Info
|
||||
public let isOwnedByMe: Bool
|
||||
public let isClosed: Bool
|
||||
public let isHidden: Bool
|
||||
public let threadPeer: EnginePeer?
|
||||
|
||||
public init(id: Int64, info: EngineMessageHistoryThread.Info, isOwnedByMe: Bool, isClosed: Bool, isHidden: Bool) {
|
||||
public init(id: Int64, info: EngineMessageHistoryThread.Info, isOwnedByMe: Bool, isClosed: Bool, isHidden: Bool, threadPeer: EnginePeer?) {
|
||||
self.id = id
|
||||
self.info = info
|
||||
self.isOwnedByMe = isOwnedByMe
|
||||
self.isClosed = isClosed
|
||||
self.isHidden = isHidden
|
||||
self.threadPeer = threadPeer
|
||||
}
|
||||
|
||||
public static func ==(lhs: ThreadInfo, rhs: ThreadInfo) -> Bool {
|
||||
if lhs.id != rhs.id {
|
||||
return false
|
||||
}
|
||||
if lhs.info != rhs.info {
|
||||
return false
|
||||
}
|
||||
if lhs.isOwnedByMe != rhs.isOwnedByMe {
|
||||
return false
|
||||
}
|
||||
if lhs.isClosed != rhs.isClosed {
|
||||
return false
|
||||
}
|
||||
if lhs.isHidden != rhs.isHidden {
|
||||
return false
|
||||
}
|
||||
if lhs.threadPeer != rhs.threadPeer {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -953,23 +977,25 @@ private let loginCodeRegex = try? NSRegularExpression(pattern: "\\b\\d{5,8}\\b",
|
||||
public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
final class TopicItemNode: ASDisplayNode {
|
||||
let topicTitleNode: TextNode
|
||||
let titleTopicIconView: ComponentHostView<Empty>
|
||||
var titleTopicIconComponent: EmojiStatusComponent
|
||||
let titleTopicIconView: ComponentHostView<Empty>?
|
||||
var titleTopicIconComponent: EmojiStatusComponent?
|
||||
|
||||
var visibilityStatus: Bool = false {
|
||||
didSet {
|
||||
if self.visibilityStatus != oldValue {
|
||||
let _ = self.titleTopicIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(self.titleTopicIconComponent.withVisibleForAnimations(self.visibilityStatus)),
|
||||
environment: {},
|
||||
containerSize: self.titleTopicIconView.bounds.size
|
||||
)
|
||||
if let titleTopicIconView = self.titleTopicIconView, let titleTopicIconComponent = self.titleTopicIconComponent {
|
||||
let _ = titleTopicIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(titleTopicIconComponent.withVisibleForAnimations(self.visibilityStatus)),
|
||||
environment: {},
|
||||
containerSize: titleTopicIconView.bounds.size
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private init(topicTitleNode: TextNode, titleTopicIconView: ComponentHostView<Empty>, titleTopicIconComponent: EmojiStatusComponent) {
|
||||
private init(topicTitleNode: TextNode, titleTopicIconView: ComponentHostView<Empty>?, titleTopicIconComponent: EmojiStatusComponent?) {
|
||||
self.topicTitleNode = topicTitleNode
|
||||
self.titleTopicIconView = titleTopicIconView
|
||||
self.titleTopicIconComponent = titleTopicIconComponent
|
||||
@ -977,60 +1003,72 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.topicTitleNode)
|
||||
self.view.addSubview(self.titleTopicIconView)
|
||||
if let titleTopicIconView = self.titleTopicIconView {
|
||||
self.view.addSubview(titleTopicIconView)
|
||||
}
|
||||
}
|
||||
|
||||
static func asyncLayout(_ currentNode: TopicItemNode?) -> (_ constrainedWidth: CGFloat, _ context: AccountContext, _ theme: PresentationTheme, _ threadId: Int64, _ title: NSAttributedString, _ iconId: Int64?, _ iconColor: Int32) -> (CGSize, () -> TopicItemNode) {
|
||||
static func asyncLayout(_ currentNode: TopicItemNode?) -> (_ constrainedWidth: CGFloat, _ context: AccountContext, _ theme: PresentationTheme, _ threadId: Int64, _ title: NSAttributedString, _ iconId: Int64?, _ iconColor: Int32?) -> (CGSize, () -> TopicItemNode) {
|
||||
let makeTopicTitleLayout = TextNode.asyncLayout(currentNode?.topicTitleNode)
|
||||
|
||||
return { constrainedWidth, context, theme, threadId, title, iconId, iconColor in
|
||||
let remainingWidth = max(1.0, constrainedWidth - (18.0 + 2.0))
|
||||
let remainingWidth = max(1.0, constrainedWidth - ((iconId == nil ? 1.0 : 18.0) + 2.0))
|
||||
|
||||
let topicTitleArguments = TextNodeLayoutArguments(attributedString: title, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: remainingWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 1.0, bottom: 2.0, right: 1.0))
|
||||
|
||||
let topicTitleLayout = makeTopicTitleLayout(topicTitleArguments)
|
||||
|
||||
return (CGSize(width: 18.0 + 2.0 + topicTitleLayout.0.size.width, height: topicTitleLayout.0.size.height), {
|
||||
return (CGSize(width: (iconId == nil ? 1.0 : 18.0) + 2.0 + topicTitleLayout.0.size.width, height: topicTitleLayout.0.size.height), {
|
||||
let topicTitleNode = topicTitleLayout.1()
|
||||
|
||||
let titleTopicIconView: ComponentHostView<Empty>
|
||||
if let current = currentNode?.titleTopicIconView {
|
||||
titleTopicIconView = current
|
||||
} else {
|
||||
titleTopicIconView = ComponentHostView<Empty>()
|
||||
}
|
||||
|
||||
let titleTopicIconContent: EmojiStatusComponent.Content
|
||||
let titleTopicIconContent: EmojiStatusComponent.Content?
|
||||
if threadId == 1 {
|
||||
titleTopicIconContent = .image(image: PresentationResourcesChatList.generalTopicSmallIcon(theme))
|
||||
} else if let fileId = iconId, fileId != 0 {
|
||||
titleTopicIconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 36.0, height: 36.0), placeholderColor: theme.list.mediaPlaceholderColor, themeColor: theme.list.itemAccentColor, loopMode: .count(0))
|
||||
} else {
|
||||
} else if let iconColor {
|
||||
titleTopicIconContent = .topic(title: String(title.string.prefix(1)), color: iconColor, size: CGSize(width: 18.0, height: 18.0))
|
||||
} else {
|
||||
titleTopicIconContent = nil
|
||||
}
|
||||
|
||||
let titleTopicIconComponent = EmojiStatusComponent(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
content: titleTopicIconContent,
|
||||
isVisibleForAnimations: (currentNode?.visibilityStatus ?? false) && context.sharedContext.energyUsageSettings.loopEmoji,
|
||||
action: nil
|
||||
)
|
||||
var titleTopicIconComponent: EmojiStatusComponent?
|
||||
var titleTopicIconView: ComponentHostView<Empty>?
|
||||
|
||||
if let titleTopicIconContent {
|
||||
titleTopicIconComponent = EmojiStatusComponent(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
content: titleTopicIconContent,
|
||||
isVisibleForAnimations: (currentNode?.visibilityStatus ?? false) && context.sharedContext.energyUsageSettings.loopEmoji,
|
||||
action: nil
|
||||
)
|
||||
|
||||
if let current = currentNode?.titleTopicIconView {
|
||||
titleTopicIconView = current
|
||||
} else {
|
||||
titleTopicIconView = ComponentHostView<Empty>()
|
||||
}
|
||||
}
|
||||
|
||||
let targetNode = currentNode ?? TopicItemNode(topicTitleNode: topicTitleNode, titleTopicIconView: titleTopicIconView, titleTopicIconComponent: titleTopicIconComponent)
|
||||
|
||||
targetNode.titleTopicIconComponent = titleTopicIconComponent
|
||||
|
||||
let iconSize = titleTopicIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(titleTopicIconComponent),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 18.0, height: 18.0)
|
||||
)
|
||||
titleTopicIconView.frame = CGRect(origin: CGPoint(x: 0.0, y: 2.0), size: iconSize)
|
||||
|
||||
topicTitleNode.frame = CGRect(origin: CGPoint(x: 18.0 + 2.0, y: 0.0), size: topicTitleLayout.0.size)
|
||||
if let titleTopicIconView, let titleTopicIconComponent {
|
||||
let iconSize = titleTopicIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(titleTopicIconComponent),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 18.0, height: 18.0)
|
||||
)
|
||||
titleTopicIconView.frame = CGRect(origin: CGPoint(x: 0.0, y: 2.0), size: iconSize)
|
||||
|
||||
topicTitleNode.frame = CGRect(origin: CGPoint(x: 18.0 + 2.0, y: 0.0), size: topicTitleLayout.0.size)
|
||||
} else {
|
||||
topicTitleNode.frame = CGRect(origin: CGPoint(x: 1.0, y: 0.0), size: topicTitleLayout.0.size)
|
||||
}
|
||||
|
||||
return targetNode
|
||||
})
|
||||
@ -1090,9 +1128,9 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ context: AccountContext, _ constrainedWidth: CGFloat, _ theme: PresentationTheme, _ authorTitle: NSAttributedString?, _ topics: [(id: Int64, title: NSAttributedString, iconId: Int64?, iconColor: Int32)]) -> (CGSize, () -> CGRect?) {
|
||||
func asyncLayout() -> (_ context: AccountContext, _ constrainedWidth: CGFloat, _ theme: PresentationTheme, _ authorTitle: NSAttributedString?, _ topics: [(id: Int64, title: NSAttributedString, iconId: Int64?, iconColor: Int32?)]) -> (CGSize, () -> CGRect?) {
|
||||
let makeAuthorLayout = TextNode.asyncLayout(self.authorNode)
|
||||
var makeExistingTopicLayouts: [Int64: (_ constrainedWidth: CGFloat, _ context: AccountContext, _ theme: PresentationTheme, _ threadId: Int64, _ title: NSAttributedString, _ iconId: Int64?, _ iconColor: Int32) -> (CGSize, () -> TopicItemNode)] = [:]
|
||||
var makeExistingTopicLayouts: [Int64: (_ constrainedWidth: CGFloat, _ context: AccountContext, _ theme: PresentationTheme, _ threadId: Int64, _ title: NSAttributedString, _ iconId: Int64?, _ iconColor: Int32?) -> (CGSize, () -> TopicItemNode)] = [:]
|
||||
for (topicId, topicNode) in self.topicNodes {
|
||||
makeExistingTopicLayouts[topicId] = TopicItemNode.asyncLayout(topicNode)
|
||||
}
|
||||
@ -1119,7 +1157,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
var topicsSizeAndApply: [(Int64, CGSize, () -> TopicItemNode)] = []
|
||||
for topic in topics {
|
||||
if remainingWidth <= 22.0 + 2.0 + 10.0 {
|
||||
if remainingWidth <= (topic.iconId == nil ? 8.0 : 22.0) + 2.0 + 10.0 {
|
||||
break
|
||||
}
|
||||
|
||||
@ -1347,7 +1385,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
return result
|
||||
case let .peer(peerData):
|
||||
guard let chatMainPeer = peerData.peer.chatMainPeer else {
|
||||
guard let chatMainPeer = peerData.peer.chatOrMonoforumMainPeer else {
|
||||
return nil
|
||||
}
|
||||
var result = ""
|
||||
@ -1394,7 +1432,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var result = ""
|
||||
var isFirst = true
|
||||
for peer in peers {
|
||||
if let chatMainPeer = peer.peer.chatMainPeer {
|
||||
if let chatMainPeer = peer.peer.chatOrMonoforumMainPeer {
|
||||
let peerTitle = chatMainPeer.compactDisplayTitle
|
||||
if !peerTitle.isEmpty {
|
||||
if isFirst {
|
||||
@ -1670,6 +1708,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var peer: EnginePeer?
|
||||
var displayAsMessage = false
|
||||
var enablePreview = true
|
||||
var peerIsMonoforum = false
|
||||
switch item.content {
|
||||
case .loading:
|
||||
displayAsMessage = true
|
||||
@ -1679,7 +1718,10 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
if displayAsMessage, case let .user(author) = peerData.messages.last?.author {
|
||||
peer = .user(author)
|
||||
} else {
|
||||
peer = peerData.peer.chatMainPeer
|
||||
peer = peerData.peer.chatOrMonoforumMainPeer
|
||||
if case let .channel(channel) = peerData.peer.peer, channel.isMonoForum {
|
||||
peerIsMonoforum = true
|
||||
}
|
||||
}
|
||||
if peerData.peer.peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
enablePreview = false
|
||||
@ -1726,6 +1768,9 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
overrideImage = .deletedIcon
|
||||
}
|
||||
var isForumAvatar = false
|
||||
if peerIsMonoforum {
|
||||
isForumAvatar = true
|
||||
}
|
||||
if case let .channel(channel) = peer, channel.isForumOrMonoForum {
|
||||
isForumAvatar = true
|
||||
}
|
||||
@ -2055,7 +2100,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
topForumTopicItems = topForumTopicItemsValue
|
||||
|
||||
if item.interaction.searchTextHighightState != nil, threadInfo == nil, topForumTopicItems.isEmpty, let message = messagesValue.first, let threadId = message.threadId, let associatedThreadInfo = message.associatedThreadInfo {
|
||||
topForumTopicItems = [EngineChatList.ForumTopicData(id: threadId, title: associatedThreadInfo.title, iconFileId: associatedThreadInfo.icon, iconColor: associatedThreadInfo.iconColor, maxOutgoingReadMessageId: message.id, isUnread: false)]
|
||||
topForumTopicItems = [EngineChatList.ForumTopicData(id: threadId, title: associatedThreadInfo.title, iconFileId: associatedThreadInfo.icon, iconColor: associatedThreadInfo.iconColor, maxOutgoingReadMessageId: message.id, isUnread: false, threadPeer: nil)]
|
||||
}
|
||||
|
||||
switch peerValue.peer {
|
||||
@ -2325,7 +2370,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
var contentImageSpecs: [ContentImageSpec] = []
|
||||
var avatarContentImageSpec: ContentImageSpec?
|
||||
var forumThread: (id: Int64, title: String, iconId: Int64?, iconColor: Int32, isUnread: Bool)?
|
||||
var forumThread: (id: Int64, title: String, iconId: Int64?, iconColor: Int32, threadPeer: EnginePeer?, isUnread: Bool)?
|
||||
|
||||
var displayForwardedIcon = false
|
||||
var displayStoryReplyIcon = false
|
||||
@ -2393,10 +2438,10 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
if let _ = peerText, case let .channel(channel) = itemPeer.chatMainPeer, channel.isForumOrMonoForum, threadInfo == nil {
|
||||
if let forumTopicData = forumTopicData {
|
||||
forumThread = (forumTopicData.id, forumTopicData.title, forumTopicData.iconFileId, forumTopicData.iconColor, forumTopicData.isUnread)
|
||||
} else if let threadInfo = threadInfo {
|
||||
forumThread = (threadInfo.id, threadInfo.info.title, threadInfo.info.icon, threadInfo.info.iconColor, false)
|
||||
if let forumTopicData {
|
||||
forumThread = (forumTopicData.id, forumTopicData.title, forumTopicData.iconFileId, forumTopicData.iconColor, forumTopicData.threadPeer, forumTopicData.isUnread)
|
||||
} else if let threadInfo {
|
||||
forumThread = (threadInfo.id, threadInfo.info.title, threadInfo.info.icon, threadInfo.info.iconColor, nil, false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2906,14 +2951,19 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Replies, font: titleFont, textColor: theme.titleColor)
|
||||
} else if let id = itemPeer.chatMainPeer?.id, id.isAnonymousSavedMessages {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.ChatList_AuthorHidden, font: titleFont, textColor: theme.titleColor)
|
||||
} else if let displayTitle = itemPeer.chatMainPeer?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) {
|
||||
} else if let displayTitle = itemPeer.chatOrMonoforumMainPeer?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) {
|
||||
let textColor: UIColor
|
||||
if case let .chatList(index) = item.index, index.messageIndex.id.peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
textColor = theme.secretTitleColor
|
||||
} else {
|
||||
textColor = theme.titleColor
|
||||
}
|
||||
titleAttributedString = NSAttributedString(string: displayTitle, font: titleFont, textColor: textColor)
|
||||
//TODO:localize
|
||||
if case let .channel(channel) = itemPeer.peer, channel.flags.contains(.isMonoforum) {
|
||||
titleAttributedString = NSAttributedString(string: "\(displayTitle) Messages", font: titleFont, textColor: textColor)
|
||||
} else {
|
||||
titleAttributedString = NSAttributedString(string: displayTitle, font: titleFont, textColor: textColor)
|
||||
}
|
||||
}
|
||||
case .group:
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.ChatList_ArchivedChatsTitle, font: titleFont, textColor: theme.titleColor)
|
||||
@ -3271,9 +3321,30 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
let isSearching = item.interaction.searchTextHighightState != nil
|
||||
|
||||
var isFirstForumThreadSelectable = false
|
||||
var forumThreads: [(id: Int64, title: NSAttributedString, iconId: Int64?, iconColor: Int32)] = []
|
||||
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) {
|
||||
if forumThread != nil || !topForumTopicItems.isEmpty {
|
||||
if let forumThread {
|
||||
isFirstForumThreadSelectable = forumThread.isUnread
|
||||
forumThreads.append((id: forumThread.id, title: NSAttributedString(string: forumThread.threadPeer?.compactDisplayTitle ?? " ", font: textFont, textColor: forumThread.isUnread || isSearching ? theme.authorNameColor : theme.messageTextColor), iconId: nil, iconColor: nil))
|
||||
}
|
||||
for topicItem in topForumTopicItems {
|
||||
if forumThread?.id != topicItem.id {
|
||||
forumThreads.append((id: topicItem.id, title: NSAttributedString(string: topicItem.threadPeer?.compactDisplayTitle ?? " ", font: textFont, textColor: topicItem.isUnread || isSearching ? theme.authorNameColor : theme.messageTextColor), iconId: nil, iconColor: nil))
|
||||
}
|
||||
}
|
||||
|
||||
if let effectiveAuthorTitle, let textAttributedStringValue = textAttributedString {
|
||||
let mutableTextAttributedString = NSMutableAttributedString()
|
||||
mutableTextAttributedString.append(NSAttributedString(string: effectiveAuthorTitle.string + ": ", font: textFont, textColor: theme.authorNameColor))
|
||||
mutableTextAttributedString.append(textAttributedStringValue)
|
||||
|
||||
textAttributedString = mutableTextAttributedString
|
||||
}
|
||||
|
||||
effectiveAuthorTitle = nil
|
||||
}
|
||||
} else if forumThread != nil || !topForumTopicItems.isEmpty {
|
||||
if let forumThread = forumThread {
|
||||
isFirstForumThreadSelectable = forumThread.isUnread
|
||||
|
@ -704,8 +704,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
||||
}
|
||||
|
||||
var threadInfo: ChatListItemContent.ThreadInfo?
|
||||
if let threadData = entry.threadData, let threadId = threadId {
|
||||
threadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadData.info, isOwnedByMe: threadData.isOwnedByMe, isClosed: threadData.isClosed, isHidden: threadData.isHidden)
|
||||
if let threadData = entry.threadData, let threadId {
|
||||
threadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadData.info, isOwnedByMe: threadData.isOwnedByMe, isClosed: threadData.isClosed, isHidden: threadData.isHidden, threadPeer: nil)
|
||||
}
|
||||
|
||||
let entry: ChatListNodeEntry = .PeerEntry(ChatListNodeEntry.PeerEntryData(
|
||||
@ -863,7 +863,9 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
||||
draftState: draftState,
|
||||
mediaDraftContentType: item.item.mediaDraftContentType,
|
||||
peer: item.item.renderedPeer,
|
||||
threadInfo: item.item.threadData.flatMap { ChatListItemContent.ThreadInfo(id: threadId, info: $0.info, isOwnedByMe: $0.isOwnedByMe, isClosed: $0.isClosed, isHidden: $0.isHidden) },
|
||||
threadInfo: item.item.threadData.flatMap {
|
||||
return ChatListItemContent.ThreadInfo(id: threadId, info: $0.info, isOwnedByMe: $0.isOwnedByMe, isClosed: $0.isClosed, isHidden: $0.isHidden, threadPeer: nil)
|
||||
},
|
||||
presence: item.item.presence,
|
||||
hasUnseenMentions: item.item.hasUnseenMentions,
|
||||
hasUnseenReactions: item.item.hasUnseenReactions,
|
||||
|
@ -198,13 +198,13 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
|
||||
if let previous = previous {
|
||||
var isThreadBasedUnreadCalculation = postbox.seedConfiguration.peerSummaryIsThreadBased(updated.0)
|
||||
var isThreadBasedUnreadCalculation = postbox.seedConfiguration.peerSummaryIsThreadBased(updated.0).value
|
||||
if let cachedData = updatedCachedPeerData[updated.0.id]?.1, postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedData) {
|
||||
isThreadBasedUnreadCalculation = false
|
||||
}
|
||||
|
||||
var wasThreadBasedUnreadCalculation = false
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(previous.0) {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(previous.0).value {
|
||||
if let cachedData = postbox.cachedPeerDataTable.get(previous.0.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedData) {
|
||||
} else {
|
||||
wasThreadBasedUnreadCalculation = true
|
||||
@ -224,13 +224,13 @@ final class ChatListIndexTable: Table {
|
||||
continue
|
||||
}
|
||||
|
||||
var isThreadBasedUnreadCalculation = postbox.seedConfiguration.peerSummaryIsThreadBased(peer)
|
||||
var isThreadBasedUnreadCalculation = postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value
|
||||
if postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedDataUpdate.1) {
|
||||
isThreadBasedUnreadCalculation = false
|
||||
}
|
||||
|
||||
var wasThreadBasedUnreadCalculation = false
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
if let previousCachedData = cachedDataUpdate.0, postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(previousCachedData) {
|
||||
} else {
|
||||
wasThreadBasedUnreadCalculation = true
|
||||
@ -412,7 +412,12 @@ final class ChatListIndexTable: Table {
|
||||
continue
|
||||
}
|
||||
let isContact = postbox.contactsTable.isContact(peerId: peerId)
|
||||
let notificationPeerId: PeerId = peer.associatedPeerId ?? peerId
|
||||
let notificationPeerId: PeerId
|
||||
if let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
notificationPeerId = associatedPeerId
|
||||
} else {
|
||||
notificationPeerId = peerId
|
||||
}
|
||||
|
||||
let initialReadState: CombinedPeerReadState?
|
||||
if let updated = updatedIsThreadBasedUnreadCountCalculation[peerId] {
|
||||
@ -434,7 +439,7 @@ final class ChatListIndexTable: Table {
|
||||
displayAsRegularChat = true
|
||||
}
|
||||
|
||||
if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer), !displayAsRegularChat {
|
||||
if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value, !displayAsRegularChat {
|
||||
let previousCount: Int32
|
||||
if let previousSummary = alteredInitialPeerThreadsSummaries[peerId] {
|
||||
previousCount = previousSummary.effectiveUnreadCount
|
||||
@ -453,7 +458,7 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
|
||||
let currentReadState: CombinedPeerReadState?
|
||||
if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer), !displayAsRegularChat {
|
||||
if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value, !displayAsRegularChat {
|
||||
let count = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0
|
||||
currentReadState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 1, maxKnownId: 0, count: count, markedUnread: false))])
|
||||
} else {
|
||||
@ -686,7 +691,7 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
|
||||
let combinedState: CombinedPeerReadState?
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
let count: Int32 = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0
|
||||
combinedState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 1, maxKnownId: 0, count: count, markedUnread: false))])
|
||||
} else {
|
||||
@ -698,7 +703,12 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
|
||||
let isContact = postbox.contactsTable.isContact(peerId: peerId)
|
||||
let notificationPeerId: PeerId = peer.associatedPeerId ?? peerId
|
||||
let notificationPeerId: PeerId
|
||||
if let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
notificationPeerId = associatedPeerId
|
||||
} else {
|
||||
notificationPeerId = peerId
|
||||
}
|
||||
let inclusion = self.get(peerId: peerId)
|
||||
if let (groupId, _) = inclusion.includedIndex(peerId: peerId) {
|
||||
if totalStates[groupId] == nil {
|
||||
@ -778,7 +788,7 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
|
||||
let combinedState: CombinedPeerReadState?
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
let count: Int32 = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0
|
||||
combinedState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 1, maxKnownId: 0, count: count, markedUnread: false))])
|
||||
} else {
|
||||
|
@ -100,13 +100,28 @@ public struct ChatListGroupReferenceEntry: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ChatListForumTopicData: Equatable {
|
||||
public var id: Int64
|
||||
public var info: StoredMessageHistoryThreadInfo
|
||||
public final class ChatListForumTopicData: Equatable {
|
||||
public let id: Int64
|
||||
public let info: StoredMessageHistoryThreadInfo
|
||||
public let threadPeer: Peer?
|
||||
|
||||
public init(id: Int64, info: StoredMessageHistoryThreadInfo) {
|
||||
public init(id: Int64, info: StoredMessageHistoryThreadInfo, threadPeer: Peer?) {
|
||||
self.id = id
|
||||
self.info = info
|
||||
self.threadPeer = threadPeer
|
||||
}
|
||||
|
||||
public static func ==(lhs: ChatListForumTopicData, rhs: ChatListForumTopicData) -> Bool {
|
||||
if lhs.id != rhs.id {
|
||||
return false
|
||||
}
|
||||
if lhs.info != rhs.info {
|
||||
return false
|
||||
}
|
||||
if !arePeersEqual(lhs.threadPeer, rhs.threadPeer) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,7 +462,12 @@ public struct ChatListFilterPredicate {
|
||||
if self.pinnedPeerIds.contains(peer.id) {
|
||||
return false
|
||||
}
|
||||
let includePeerId = peer.associatedPeerId ?? peer.id
|
||||
let includePeerId: PeerId
|
||||
if let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
includePeerId = associatedPeerId
|
||||
} else {
|
||||
includePeerId = peer.id
|
||||
}
|
||||
if self.excludePeerIds.contains(includePeerId) {
|
||||
return false
|
||||
}
|
||||
@ -694,7 +714,7 @@ final class MutableChatListView {
|
||||
let renderedPeer = RenderedPeer(peerId: peer.id, peers: peers, associatedMedia: renderAssociatedMediaForPeers(postbox: postbox, peers: peers))
|
||||
|
||||
let isUnread: Bool
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
let hasUnmutedUnread = postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.hasUnmutedUnread ?? false
|
||||
isUnread = hasUnmutedUnread
|
||||
} else {
|
||||
@ -826,7 +846,7 @@ final class MutableChatListView {
|
||||
displayAsRegularChat = postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedData)
|
||||
}
|
||||
|
||||
if let peer = groupEntries[i].renderedPeers[j].peer.peer, postbox.seedConfiguration.peerSummaryIsThreadBased(peer), !displayAsRegularChat {
|
||||
if let peer = groupEntries[i].renderedPeers[j].peer.peer, postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value, !displayAsRegularChat {
|
||||
isUnread = postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.hasUnmutedUnread ?? false
|
||||
} else {
|
||||
isUnread = postbox.readStateTable.getCombinedState(groupEntries[i].renderedPeers[j].peer.peerId)?.isUnread ?? false
|
||||
@ -904,6 +924,9 @@ final class MutableChatListView {
|
||||
if let associatedPeer = postbox.peerTable.get(associatedPeerId) {
|
||||
peers[associatedPeer.id] = associatedPeer
|
||||
}
|
||||
}
|
||||
|
||||
if let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
notificationSettings = postbox.peerNotificationSettingsTable.getEffective(associatedPeerId)
|
||||
presence = postbox.peerPresenceTable.get(associatedPeerId)
|
||||
isContact = postbox.contactsTable.isContact(peerId: associatedPeerId)
|
||||
@ -916,17 +939,25 @@ final class MutableChatListView {
|
||||
|
||||
let renderedPeer = RenderedPeer(peerId: index.messageIndex.id.peerId, peers: peers, associatedMedia: renderAssociatedMediaForPeers(postbox: postbox, peers: peers))
|
||||
|
||||
var isThreadBased = false
|
||||
var threadsArePeers = false
|
||||
if let peer = renderedPeer.peer {
|
||||
let value = postbox.seedConfiguration.peerSummaryIsThreadBased(peer)
|
||||
isThreadBased = value.value
|
||||
threadsArePeers = value.threadsArePeers
|
||||
}
|
||||
|
||||
var forumTopicData: ChatListForumTopicData?
|
||||
if let message = renderedMessages.first, let threadId = message.threadId {
|
||||
if let info = postbox.messageHistoryThreadIndexTable.get(peerId: message.id.peerId, threadId: threadId) {
|
||||
forumTopicData = ChatListForumTopicData(id: threadId, info: info)
|
||||
forumTopicData = ChatListForumTopicData(id: threadId, info: info, threadPeer: threadsArePeers ? postbox.peerTable.get(PeerId(threadId)) : nil)
|
||||
}
|
||||
}
|
||||
|
||||
var topForumTopics: [ChatListForumTopicData] = []
|
||||
if let peer = renderedPeer.peer, postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if let peer = renderedPeer.peer, isThreadBased {
|
||||
for item in postbox.messageHistoryThreadIndexTable.fetch(peerId: peer.id, namespace: 0, start: .upperBound, end: .lowerBound, limit: 5) {
|
||||
topForumTopics.append(ChatListForumTopicData(id: item.threadId, info: item.info))
|
||||
topForumTopics.append(ChatListForumTopicData(id: item.threadId, info: item.info, threadPeer: threadsArePeers ? postbox.peerTable.get(PeerId(item.threadId)) : nil))
|
||||
}
|
||||
}
|
||||
|
||||
@ -938,7 +969,7 @@ final class MutableChatListView {
|
||||
displayAsRegularChat = postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedData)
|
||||
}
|
||||
|
||||
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer), !displayAsRegularChat {
|
||||
if isThreadBased, !displayAsRegularChat {
|
||||
let summary = postbox.peerThreadsSummaryTable.get(peerId: index.messageIndex.id.peerId)
|
||||
var count: Int32 = 0
|
||||
var isMuted: Bool = false
|
||||
|
@ -65,7 +65,7 @@ private func mappedChatListFilterPredicate(postbox: PostboxImpl, currentTransact
|
||||
if let cachedPeerData = postbox.cachedPeerDataTable.get(peer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) {
|
||||
displayAsRegularChat = true
|
||||
}
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) && !displayAsRegularChat {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value && !displayAsRegularChat {
|
||||
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.effectiveUnreadCount ?? 0) > 0
|
||||
} else {
|
||||
isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false
|
||||
@ -441,7 +441,7 @@ private final class ChatListViewSpaceState {
|
||||
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peer.id, threadId: nil, calculation: filterPredicate.messageTagSummary)
|
||||
|
||||
var isUnread: Bool
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) && !displayAsRegularChat {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value && !displayAsRegularChat {
|
||||
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.effectiveUnreadCount ?? 0) > 0
|
||||
} else {
|
||||
isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false
|
||||
@ -571,7 +571,7 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
|
||||
var isUnread: Bool
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer) && !displayAsRegularChat {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer).value && !displayAsRegularChat {
|
||||
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: entryPeer.id)?.effectiveUnreadCount ?? 0) > 0
|
||||
} else {
|
||||
isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false
|
||||
@ -620,7 +620,7 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
|
||||
var isUnread: Bool
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer) && !displayAsRegularChat {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer).value && !displayAsRegularChat {
|
||||
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0) > 0
|
||||
} else {
|
||||
isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false
|
||||
@ -750,7 +750,7 @@ private final class ChatListViewSpaceState {
|
||||
switch entry {
|
||||
case let .MessageEntry(entryData):
|
||||
var presencePeerId = entryData.renderedPeer.peerId
|
||||
if let peer = entryData.renderedPeer.peers[entryData.renderedPeer.peerId], let associatedPeerId = peer.associatedPeerId {
|
||||
if let peer = entryData.renderedPeer.peers[entryData.renderedPeer.peerId], let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
presencePeerId = associatedPeerId
|
||||
}
|
||||
if let presence = transaction.currentUpdatedPeerPresences[presencePeerId] {
|
||||
@ -802,7 +802,7 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
|
||||
var isUnread: Bool
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer) && !displayAsRegularChat {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer).value && !displayAsRegularChat {
|
||||
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: entryPeer.id)?.effectiveUnreadCount ?? 0) > 0
|
||||
} else {
|
||||
isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false
|
||||
@ -860,7 +860,7 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
|
||||
var isUnread: Bool
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer) && !displayAsRegularChat {
|
||||
if postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer).value && !displayAsRegularChat {
|
||||
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0) > 0
|
||||
} else {
|
||||
isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false
|
||||
@ -954,7 +954,7 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
|
||||
var updatedReadState = entryData.readState
|
||||
if let peer = postbox.peerTable.get(entryData.index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer), !displayAsRegularChat {
|
||||
if let peer = postbox.peerTable.get(entryData.index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value, !displayAsRegularChat {
|
||||
let summary = postbox.peerThreadsSummaryTable.get(peerId: peer.id)
|
||||
|
||||
var count: Int32 = 0
|
||||
@ -1534,7 +1534,11 @@ struct ChatListViewState {
|
||||
if let associatedPeer = postbox.peerTable.get(associatedPeerId) {
|
||||
peers[associatedPeer.id] = associatedPeer
|
||||
}
|
||||
presence = postbox.peerPresenceTable.get(associatedPeerId)
|
||||
if peer.associatedPeerOverridesIdentity {
|
||||
presence = postbox.peerPresenceTable.get(associatedPeerId)
|
||||
} else {
|
||||
presence = postbox.peerPresenceTable.get(index.messageIndex.id.peerId)
|
||||
}
|
||||
} else {
|
||||
presence = postbox.peerPresenceTable.get(index.messageIndex.id.peerId)
|
||||
}
|
||||
@ -1580,10 +1584,18 @@ struct ChatListViewState {
|
||||
}
|
||||
}
|
||||
|
||||
var isThreadBased = false
|
||||
var threadsArePeers = false
|
||||
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId) {
|
||||
let value = postbox.seedConfiguration.peerSummaryIsThreadBased(peer)
|
||||
isThreadBased = value.value
|
||||
threadsArePeers = value.threadsArePeers
|
||||
}
|
||||
|
||||
var forumTopicData: ChatListForumTopicData?
|
||||
if let message = renderedMessages.first, let threadId = message.threadId {
|
||||
if let info = postbox.messageHistoryThreadIndexTable.get(peerId: message.id.peerId, threadId: threadId) {
|
||||
forumTopicData = ChatListForumTopicData(id: threadId, info: info)
|
||||
forumTopicData = ChatListForumTopicData(id: threadId, info: info, threadPeer: threadsArePeers ? postbox.peerTable.get(PeerId(threadId)) : nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1597,12 +1609,12 @@ struct ChatListViewState {
|
||||
var topForumTopics: [ChatListForumTopicData] = []
|
||||
let readState: ChatListViewReadState?
|
||||
|
||||
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer), !displayAsRegularChat {
|
||||
for item in postbox.messageHistoryThreadIndexTable.fetch(peerId: peer.id, namespace: 0, start: .upperBound, end: .lowerBound, limit: 5) {
|
||||
topForumTopics.append(ChatListForumTopicData(id: item.threadId, info: item.info))
|
||||
if isThreadBased, !displayAsRegularChat {
|
||||
for item in postbox.messageHistoryThreadIndexTable.fetch(peerId: index.messageIndex.id.peerId, namespace: 0, start: .upperBound, end: .lowerBound, limit: 5) {
|
||||
topForumTopics.append(ChatListForumTopicData(id: item.threadId, info: item.info, threadPeer: threadsArePeers ? postbox.peerTable.get(PeerId(item.threadId)) : nil))
|
||||
}
|
||||
|
||||
let summary = postbox.peerThreadsSummaryTable.get(peerId: peer.id)
|
||||
let summary = postbox.peerThreadsSummaryTable.get(peerId: index.messageIndex.id.peerId)
|
||||
|
||||
var count: Int32 = 0
|
||||
var isMuted: Bool = false
|
||||
|
@ -1,5 +1,9 @@
|
||||
import Foundation
|
||||
|
||||
// Incuding at least one Objective-C class in a swift file ensures that it doesn't get stripped by the linker
|
||||
private final class LinkHelperClass: NSObject {
|
||||
}
|
||||
|
||||
public func fileSize(_ path: String, useTotalFileAllocatedSize: Bool = false) -> Int64? {
|
||||
/*if useTotalFileAllocatedSize {
|
||||
let url = URL(fileURLWithPath: path)
|
||||
|
@ -900,7 +900,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
||||
case let .peerIsContact(peerId, value):
|
||||
if let replacedPeerIds = transaction.replaceContactPeerIds {
|
||||
let updatedValue: Bool
|
||||
if let contactPeer = postbox.peerTable.get(peerId), let associatedPeerId = contactPeer.associatedPeerId {
|
||||
if let contactPeer = postbox.peerTable.get(peerId), let associatedPeerId = contactPeer.associatedPeerId, contactPeer.associatedPeerOverridesIdentity {
|
||||
updatedValue = replacedPeerIds.contains(associatedPeerId)
|
||||
} else {
|
||||
updatedValue = replacedPeerIds.contains(peerId)
|
||||
|
@ -298,6 +298,7 @@ public protocol Peer: AnyObject, PostboxCoding {
|
||||
var id: PeerId { get }
|
||||
var indexName: PeerIndexNameRepresentation { get }
|
||||
var associatedPeerId: PeerId? { get }
|
||||
var associatedPeerOverridesIdentity: Bool { get }
|
||||
var notificationSettingsPeerId: PeerId? { get }
|
||||
var associatedMediaIds: [MediaId]? { get }
|
||||
var timeoutAttribute: UInt32? { get }
|
||||
@ -305,6 +306,10 @@ public protocol Peer: AnyObject, PostboxCoding {
|
||||
func isEqual(_ other: Peer) -> Bool
|
||||
}
|
||||
|
||||
public extension Peer {
|
||||
var associatedPeerOverridesIdentity: Bool { return false }
|
||||
}
|
||||
|
||||
public func arePeersEqual(_ lhs: Peer?, _ rhs: Peer?) -> Bool {
|
||||
if let lhs = lhs, let rhs = rhs {
|
||||
return lhs.isEqual(rhs)
|
||||
|
@ -9,7 +9,7 @@ final class MutablePeerNotificationSettingsView: MutablePostboxView {
|
||||
self.notificationSettings = [:]
|
||||
for peerId in peerIds {
|
||||
var notificationPeerId = peerId
|
||||
if let peer = postbox.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId {
|
||||
if let peer = postbox.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
if let settings = postbox.peerNotificationSettingsTable.getEffective(notificationPeerId) {
|
||||
@ -23,7 +23,7 @@ final class MutablePeerNotificationSettingsView: MutablePostboxView {
|
||||
var updated = false
|
||||
for peerId in self.peerIds {
|
||||
var notificationPeerId = peerId
|
||||
if let peer = postbox.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId {
|
||||
if let peer = postbox.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
if let (_, settings) = transaction.currentUpdatedPeerNotificationSettings[notificationPeerId] {
|
||||
@ -41,7 +41,7 @@ final class MutablePeerNotificationSettingsView: MutablePostboxView {
|
||||
/*var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
for peerId in self.peerIds {
|
||||
var notificationPeerId = peerId
|
||||
if let peer = postbox.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId {
|
||||
if let peer = postbox.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
if let settings = postbox.peerNotificationSettingsTable.getEffective(notificationPeerId) {
|
||||
|
@ -48,7 +48,7 @@ final class MutablePeerView: MutablePostboxView {
|
||||
var messageIds = Set<MessageId>()
|
||||
peerIds.insert(peerId)
|
||||
|
||||
if let peer = getPeer(peerId), let associatedPeerId = peer.associatedPeerId {
|
||||
if let peer = getPeer(peerId), let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
peerIds.insert(associatedPeerId)
|
||||
self.contactPeerId = associatedPeerId
|
||||
self.peerIsContact = postbox.contactsTable.isContact(peerId: associatedPeerId)
|
||||
@ -76,7 +76,7 @@ final class MutablePeerView: MutablePostboxView {
|
||||
self.memberStoryStats[id] = value
|
||||
}
|
||||
}
|
||||
if let peer = self.peers[peerId], let associatedPeerId = peer.associatedPeerId {
|
||||
if let peer = self.peers[peerId], let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
if let peer = getPeer(associatedPeerId) {
|
||||
self.peers[associatedPeerId] = peer
|
||||
}
|
||||
@ -236,7 +236,7 @@ final class MutablePeerView: MutablePostboxView {
|
||||
}
|
||||
|
||||
if let peer = self.peers[self.peerId] {
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
if let (_, notificationSettings) = updatedNotificationSettings[associatedPeerId] {
|
||||
self.notificationSettings = notificationSettings
|
||||
updated = true
|
||||
|
@ -3309,7 +3309,7 @@ final class PostboxImpl {
|
||||
additionalDataEntries.append(.totalUnreadState(self.messageHistoryMetadataTable.getTotalUnreadState(groupId: .root)))
|
||||
case let .peerNotificationSettings(peerId):
|
||||
var notificationPeerId = peerId
|
||||
if let peer = self.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId {
|
||||
if let peer = self.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
additionalDataEntries.append(.peerNotificationSettings(self.peerNotificationSettingsTable.getEffective(notificationPeerId)))
|
||||
@ -3319,7 +3319,7 @@ final class PostboxImpl {
|
||||
additionalDataEntries.append(.preferencesEntry(key, self.preferencesTable.get(key: key)))
|
||||
case let .peerIsContact(peerId):
|
||||
let value: Bool
|
||||
if let contactPeer = self.peerTable.get(peerId), let associatedPeerId = contactPeer.associatedPeerId {
|
||||
if let contactPeer = self.peerTable.get(peerId), contactPeer.associatedPeerOverridesIdentity, let associatedPeerId = contactPeer.associatedPeerId {
|
||||
value = self.contactsTable.isContact(peerId: associatedPeerId)
|
||||
} else {
|
||||
value = self.contactsTable.isContact(peerId: peerId)
|
||||
|
@ -66,7 +66,7 @@ public final class SeedConfiguration {
|
||||
public let existingGlobalMessageTags: GlobalMessageTags
|
||||
public let peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace]
|
||||
public let peerSummaryCounterTags: (Peer, Bool) -> PeerSummaryCounterTags
|
||||
public let peerSummaryIsThreadBased: (Peer) -> Bool
|
||||
public let peerSummaryIsThreadBased: (Peer) -> (value: Bool, threadsArePeers: Bool)
|
||||
public let additionalChatListIndexNamespace: MessageId.Namespace?
|
||||
public let messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>
|
||||
public let defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState]
|
||||
@ -97,7 +97,7 @@ public final class SeedConfiguration {
|
||||
existingGlobalMessageTags: GlobalMessageTags,
|
||||
peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace],
|
||||
peerSummaryCounterTags: @escaping (Peer, Bool) -> PeerSummaryCounterTags,
|
||||
peerSummaryIsThreadBased: @escaping (Peer) -> Bool,
|
||||
peerSummaryIsThreadBased: @escaping (Peer) -> (value: Bool, threadsArePeers: Bool),
|
||||
additionalChatListIndexNamespace: MessageId.Namespace?,
|
||||
messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>,
|
||||
defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState],
|
||||
|
@ -64,7 +64,7 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
|
||||
case let .totalInGroup(groupId):
|
||||
return .totalInGroup(groupId, postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId))
|
||||
case let .peer(peerId, handleThreads):
|
||||
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
var count: Int32 = 0
|
||||
if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) {
|
||||
count = summary.totalUnreadCount
|
||||
@ -113,7 +113,7 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
|
||||
}
|
||||
}
|
||||
case let .peer(peerId, handleThreads, _):
|
||||
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
if transaction.updatedPeerThreadsSummaries.contains(peerId) {
|
||||
var count: Int32 = 0
|
||||
if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) {
|
||||
@ -143,7 +143,7 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
|
||||
case let .totalInGroup(groupId):
|
||||
return .totalInGroup(groupId, postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId))
|
||||
case let .peer(peerId, handleThreads):
|
||||
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
var count: Int32 = 0
|
||||
if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) {
|
||||
count = summary.totalUnreadCount
|
||||
@ -240,7 +240,7 @@ final class MutableCombinedReadStateView: MutablePostboxView {
|
||||
var updated = false
|
||||
|
||||
if transaction.alteredInitialPeerCombinedReadStates[self.peerId] != nil || transaction.updatedPeerThreadCombinedStates.contains(self.peerId) {
|
||||
if self.handleThreads, let peer = postbox.peerTable.get(self.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if self.handleThreads, let peer = postbox.peerTable.get(self.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
var count: Int32 = 0
|
||||
if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) {
|
||||
count = summary.totalUnreadCount
|
||||
@ -260,7 +260,7 @@ final class MutableCombinedReadStateView: MutablePostboxView {
|
||||
|
||||
func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool {
|
||||
let state: CombinedPeerReadState?
|
||||
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value {
|
||||
var count: Int32 = 0
|
||||
if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) {
|
||||
count = summary.totalUnreadCount
|
||||
|
@ -539,6 +539,7 @@ struct LoadMessageHistoryThreadsResult {
|
||||
var unreadMentionsCount: Int32
|
||||
var unreadReactionsCount: Int32
|
||||
var index: StoredPeerThreadCombinedState.Index?
|
||||
var threadPeer: Peer?
|
||||
|
||||
init(
|
||||
threadId: Int64,
|
||||
@ -546,7 +547,8 @@ struct LoadMessageHistoryThreadsResult {
|
||||
topMessage: Int32,
|
||||
unreadMentionsCount: Int32,
|
||||
unreadReactionsCount: Int32,
|
||||
index: StoredPeerThreadCombinedState.Index
|
||||
index: StoredPeerThreadCombinedState.Index,
|
||||
threadPeer: Peer?
|
||||
) {
|
||||
self.threadId = threadId
|
||||
self.data = data
|
||||
@ -554,6 +556,7 @@ struct LoadMessageHistoryThreadsResult {
|
||||
self.unreadMentionsCount = unreadMentionsCount
|
||||
self.unreadReactionsCount = unreadReactionsCount
|
||||
self.index = index
|
||||
self.threadPeer = threadPeer
|
||||
}
|
||||
}
|
||||
|
||||
@ -661,7 +664,8 @@ public func _internal_fillSavedMessageHistory(accountPeerId: PeerId, postbox: Po
|
||||
topMessage: message.id.id,
|
||||
unreadMentionsCount: 0,
|
||||
unreadReactionsCount: 0,
|
||||
index: StoredPeerThreadCombinedState.Index(timestamp: message.timestamp, threadId: threadId, messageId: message.id.id)
|
||||
index: StoredPeerThreadCombinedState.Index(timestamp: message.timestamp, threadId: threadId, messageId: message.id.id),
|
||||
threadPeer: nil
|
||||
))
|
||||
}
|
||||
|
||||
@ -791,13 +795,22 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
||||
minIndex = topicIndex
|
||||
}
|
||||
|
||||
var threadPeer: Peer?
|
||||
for user in users {
|
||||
if user.peerId == peer.peerId {
|
||||
threadPeer = TelegramUser(user: user)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||
threadId: peer.peerId.toInt64(),
|
||||
data: data,
|
||||
topMessage: topMessage,
|
||||
unreadMentionsCount: 0,
|
||||
unreadReactionsCount: 0,
|
||||
index: topicIndex
|
||||
index: topicIndex,
|
||||
threadPeer: threadPeer
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -936,7 +949,8 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
||||
topMessage: topMessage,
|
||||
unreadMentionsCount: unreadMentionsCount,
|
||||
unreadReactionsCount: unreadReactionsCount,
|
||||
index: topicIndex
|
||||
index: topicIndex,
|
||||
threadPeer: nil
|
||||
))
|
||||
case .forumTopicDeleted:
|
||||
break
|
||||
@ -1157,7 +1171,8 @@ public func _internal_searchForumTopics(account: Account, peerId: EnginePeer.Id,
|
||||
iconFileId: itemData.info.icon,
|
||||
iconColor: itemData.info.iconColor,
|
||||
maxOutgoingReadMessageId: EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Cloud, id: itemData.maxOutgoingReadId),
|
||||
isUnread: false
|
||||
isUnread: false,
|
||||
threadPeer: item.threadPeer.flatMap(EnginePeer.init)
|
||||
),
|
||||
topForumTopicItems: [],
|
||||
hasFailed: false,
|
||||
|
@ -2336,7 +2336,7 @@ public func messagesForNotification(transaction: Transaction, id: MessageId, alw
|
||||
|
||||
var notificationPeerId = id.peerId
|
||||
let peer = transaction.getPeer(id.peerId)
|
||||
if let peer = peer, let associatedPeerId = peer.associatedPeerId {
|
||||
if let peer, peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
if message.personal, let author = message.author {
|
||||
|
@ -93,7 +93,7 @@ func pushPeerNotificationSettings(postbox: Postbox, network: Network, peerId: Pe
|
||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
|
@ -946,9 +946,14 @@ public final class PendingMessageManager {
|
||||
}
|
||||
|
||||
var topMsgId: Int32?
|
||||
var monoforumPeerId: Api.InputPeer?
|
||||
if let threadId = messages[0].0.threadId {
|
||||
flags |= Int32(1 << 9)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
monoforumPeerId = transaction.getPeer(PeerId(threadId)).flatMap(apiInputPeer)
|
||||
} else {
|
||||
flags |= Int32(1 << 9)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
}
|
||||
|
||||
var quickReplyShortcut: Api.InputQuickReplyShortcut?
|
||||
@ -965,6 +970,12 @@ public final class PendingMessageManager {
|
||||
flags |= 1 << 21
|
||||
}
|
||||
|
||||
var replyTo: Api.InputReplyTo?
|
||||
if let monoforumPeerId {
|
||||
replyTo = .inputReplyToMonoForum(monoforumPeerId: monoforumPeerId)
|
||||
flags |= 1 << 22
|
||||
}
|
||||
|
||||
let forwardPeerIds = Set(forwardIds.map { $0.0.peerId })
|
||||
if forwardPeerIds.count != 1 {
|
||||
assertionFailure()
|
||||
@ -972,7 +983,7 @@ public final class PendingMessageManager {
|
||||
} else if let inputSourcePeerId = forwardPeerIds.first, let inputSourcePeer = transaction.getPeer(inputSourcePeerId).flatMap(apiInputPeer) {
|
||||
let dependencyTag = PendingMessageRequestDependencyTag(messageId: messages[0].0.id)
|
||||
|
||||
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, topMsgId: topMsgId, replyTo: nil, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars), tag: dependencyTag)
|
||||
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars), tag: dependencyTag)
|
||||
} else {
|
||||
assertionFailure()
|
||||
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "Invalid forward source"))
|
||||
@ -1601,9 +1612,14 @@ public final class PendingMessageManager {
|
||||
|> map(NetworkRequestResult.result)
|
||||
case let .forward(sourceInfo):
|
||||
var topMsgId: Int32?
|
||||
var monoforumPeerId: Api.InputPeer?
|
||||
if let threadId = message.threadId {
|
||||
flags |= Int32(1 << 9)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||
monoforumPeerId = transaction.getPeer(PeerId(threadId)).flatMap(apiInputPeer)
|
||||
} else {
|
||||
flags |= Int32(1 << 9)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
}
|
||||
|
||||
var quickReplyShortcut: Api.InputQuickReplyShortcut?
|
||||
@ -1624,8 +1640,14 @@ public final class PendingMessageManager {
|
||||
flags |= 1 << 21
|
||||
}
|
||||
|
||||
var replyTo: Api.InputReplyTo?
|
||||
if let monoforumPeerId {
|
||||
replyTo = .inputReplyToMonoForum(monoforumPeerId: monoforumPeerId)
|
||||
flags |= 1 << 22
|
||||
}
|
||||
|
||||
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
|
||||
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: nil, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars), tag: dependencyTag)
|
||||
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars), tag: dependencyTag)
|
||||
|> map(NetworkRequestResult.result)
|
||||
} else {
|
||||
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))
|
||||
|
@ -76,12 +76,14 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
||||
peerSummaryIsThreadBased: { peer in
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if channel.flags.contains(.isForum) {
|
||||
return true
|
||||
return (true, false)
|
||||
} else if channel.flags.contains(.isMonoforum) {
|
||||
return (true, true)
|
||||
} else {
|
||||
return false
|
||||
return (false, false)
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
return (false, false)
|
||||
}
|
||||
},
|
||||
additionalChatListIndexNamespace: Namespaces.Message.Cloud,
|
||||
|
@ -214,6 +214,14 @@ public final class TelegramChannel: Peer, Equatable {
|
||||
public let sendPaidMessageStars: StarsAmount?
|
||||
public let linkedMonoforumId: PeerId?
|
||||
|
||||
public var associatedPeerId: PeerId? {
|
||||
if self.flags.contains(.isMonoforum) {
|
||||
return self.linkedMonoforumId
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var indexName: PeerIndexNameRepresentation {
|
||||
var addressNames = self.usernames.map { $0.username }
|
||||
if addressNames.isEmpty, let username = self.username, !username.isEmpty {
|
||||
@ -245,7 +253,6 @@ public final class TelegramChannel: Peer, Equatable {
|
||||
return mediaIds
|
||||
}
|
||||
|
||||
public let associatedPeerId: PeerId? = nil
|
||||
public let notificationSettingsPeerId: PeerId? = nil
|
||||
|
||||
public var timeoutAttribute: UInt32? {
|
||||
|
@ -17,6 +17,10 @@ public final class TelegramSecretChat: Peer, Equatable {
|
||||
public var associatedMediaIds: [MediaId]? { return nil }
|
||||
|
||||
public let associatedPeerId: PeerId?
|
||||
public var associatedPeerControlsNotifications: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
public let notificationSettingsPeerId: PeerId?
|
||||
|
||||
public var timeoutAttribute: UInt32? { return nil }
|
||||
|
@ -28,21 +28,48 @@ public final class EngineChatList: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ForumTopicData: Equatable {
|
||||
public var id: Int64
|
||||
public var title: String
|
||||
public var iconFileId: Int64?
|
||||
public var iconColor: Int32
|
||||
public var maxOutgoingReadMessageId: EngineMessage.Id
|
||||
public var isUnread: Bool
|
||||
public final class ForumTopicData: Equatable {
|
||||
public let id: Int64
|
||||
public let title: String
|
||||
public let iconFileId: Int64?
|
||||
public let iconColor: Int32
|
||||
public let maxOutgoingReadMessageId: EngineMessage.Id
|
||||
public let isUnread: Bool
|
||||
public let threadPeer: EnginePeer?
|
||||
|
||||
public init(id: Int64, title: String, iconFileId: Int64?, iconColor: Int32, maxOutgoingReadMessageId: EngineMessage.Id, isUnread: Bool) {
|
||||
public init(id: Int64, title: String, iconFileId: Int64?, iconColor: Int32, maxOutgoingReadMessageId: EngineMessage.Id, isUnread: Bool, threadPeer: EnginePeer?) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.iconFileId = iconFileId
|
||||
self.iconColor = iconColor
|
||||
self.maxOutgoingReadMessageId = maxOutgoingReadMessageId
|
||||
self.isUnread = isUnread
|
||||
self.threadPeer = threadPeer
|
||||
}
|
||||
|
||||
public static func ==(lhs: ForumTopicData, rhs: ForumTopicData) -> Bool {
|
||||
if lhs.id != rhs.id {
|
||||
return false
|
||||
}
|
||||
if lhs.title != rhs.title {
|
||||
return false
|
||||
}
|
||||
if lhs.iconFileId != rhs.iconFileId {
|
||||
return false
|
||||
}
|
||||
if lhs.iconColor != rhs.iconColor {
|
||||
return false
|
||||
}
|
||||
if lhs.maxOutgoingReadMessageId != rhs.maxOutgoingReadMessageId {
|
||||
return false
|
||||
}
|
||||
if lhs.isUnread != rhs.isUnread {
|
||||
return false
|
||||
}
|
||||
if lhs.threadPeer != rhs.threadPeer {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,15 +534,15 @@ extension EngineChatList.Item {
|
||||
var forumTopicDataValue: EngineChatList.ForumTopicData?
|
||||
if let forumTopicData = forumTopicData {
|
||||
let id = forumTopicData.id
|
||||
if let forumTopicData = forumTopicData.info.data.get(MessageHistoryThreadData.self) {
|
||||
forumTopicDataValue = EngineChatList.ForumTopicData(id: id, title: forumTopicData.info.title, iconFileId: forumTopicData.info.icon, iconColor: forumTopicData.info.iconColor, maxOutgoingReadMessageId: MessageId(peerId: index.messageIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: forumTopicData.maxOutgoingReadId), isUnread: forumTopicData.incomingUnreadCount > 0)
|
||||
if let forumTopicInfo = forumTopicData.info.data.get(MessageHistoryThreadData.self) {
|
||||
forumTopicDataValue = EngineChatList.ForumTopicData(id: id, title: forumTopicInfo.info.title, iconFileId: forumTopicInfo.info.icon, iconColor: forumTopicInfo.info.iconColor, maxOutgoingReadMessageId: MessageId(peerId: index.messageIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: forumTopicInfo.maxOutgoingReadId), isUnread: forumTopicInfo.incomingUnreadCount > 0, threadPeer: forumTopicData.threadPeer.flatMap(EnginePeer.init))
|
||||
}
|
||||
}
|
||||
|
||||
var topForumTopicItems: [EngineChatList.ForumTopicData] = []
|
||||
for item in topForumTopics {
|
||||
if let forumTopicData = item.info.data.get(MessageHistoryThreadData.self) {
|
||||
topForumTopicItems.append(EngineChatList.ForumTopicData(id: item.id, title: forumTopicData.info.title, iconFileId: forumTopicData.info.icon, iconColor: forumTopicData.info.iconColor, maxOutgoingReadMessageId: MessageId(peerId: index.messageIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: forumTopicData.maxOutgoingReadId), isUnread: forumTopicData.incomingUnreadCount > 0))
|
||||
if let forumTopicInfo = item.info.data.get(MessageHistoryThreadData.self) {
|
||||
topForumTopicItems.append(EngineChatList.ForumTopicData(id: item.id, title: forumTopicInfo.info.title, iconFileId: forumTopicInfo.info.icon, iconColor: forumTopicInfo.info.iconColor, maxOutgoingReadMessageId: MessageId(peerId: index.messageIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: forumTopicInfo.maxOutgoingReadId), isUnread: forumTopicInfo.incomingUnreadCount > 0, threadPeer: item.threadPeer.flatMap(EnginePeer.init)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ func _internal_togglePeerMuted(account: Account, peerId: PeerId, threadId: Int64
|
||||
}
|
||||
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ func _internal_togglePeerStoriesMuted(account: Account, peerId: PeerId) -> Signa
|
||||
}
|
||||
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ func _internal_updatePeerMuteSetting(account: Account, transaction: Transaction,
|
||||
}
|
||||
} else {
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ func _internal_updatePeerDisplayPreviewsSetting(account: Account, transaction: T
|
||||
}
|
||||
} else {
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
@ -259,7 +259,7 @@ func _internal_updatePeerStoriesMutedSetting(account: Account, peerId: PeerId, m
|
||||
func _internal_updatePeerStoriesMutedSetting(account: Account, transaction: Transaction, peerId: PeerId, mute: PeerStoryNotificationSettings.Mute) {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
@ -281,7 +281,7 @@ func _internal_updatePeerStoriesMutedSetting(account: Account, transaction: Tran
|
||||
func _internal_updatePeerStoriesHideSenderSetting(account: Account, transaction: Transaction, peerId: PeerId, hideSender: PeerStoryNotificationSettings.HideSender) {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
@ -323,7 +323,7 @@ func _internal_updatePeerNotificationSoundInteractive(account: Account, transact
|
||||
}
|
||||
} else {
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
@ -344,7 +344,7 @@ func _internal_updatePeerNotificationSoundInteractive(account: Account, transact
|
||||
func _internal_updatePeerStoryNotificationSoundInteractive(account: Account, transaction: Transaction, peerId: PeerId, sound: PeerMessageSound) {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
var notificationPeerId = peerId
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
notificationPeerId = associatedPeerId
|
||||
}
|
||||
|
||||
|
@ -632,6 +632,14 @@ public final class EngineRenderedPeer: Equatable {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var chatOrMonoforumMainPeer: EnginePeer? {
|
||||
if case let .channel(channel) = self.peer, channel.flags.contains(.isMonoforum), let linkedMonoforumId = channel.linkedMonoforumId {
|
||||
return self.peers[linkedMonoforumId]
|
||||
} else {
|
||||
return self.chatMainPeer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension EngineRenderedPeer {
|
||||
|
@ -80,7 +80,7 @@ public func _internal_recentlySearchedPeers(postbox: Postbox) -> Signal<[Recentl
|
||||
var presence: TelegramUserPresence?
|
||||
var unreadCount = unreadCounts[peerId] ?? 0
|
||||
if let peer = peerView.peers[peerId] {
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
if peer is TelegramSecretChat, let associatedPeerId = peer.associatedPeerId {
|
||||
presence = peerView.peerPresences[associatedPeerId] as? TelegramUserPresence
|
||||
} else {
|
||||
presence = peerView.peerPresences[peerId] as? TelegramUserPresence
|
||||
|
@ -895,243 +895,6 @@ func _internal_collectCacheUsageStats(account: Account, peerId: PeerId? = nil, a
|
||||
}
|
||||
|> runOn(queue)
|
||||
}
|
||||
|
||||
/*let initialState = CacheUsageStatsState()
|
||||
if let peerId = peerId {
|
||||
initialState.lowerBound = MessageIndex.lowerBound(peerId: peerId)
|
||||
initialState.upperBound = MessageIndex.upperBound(peerId: peerId)
|
||||
}
|
||||
|
||||
let state = Atomic<CacheUsageStatsState>(value: initialState)
|
||||
|
||||
let excludeResourceIds = account.postbox.transaction { transaction -> Set<MediaResourceId> in
|
||||
var result = Set<MediaResourceId>()
|
||||
transaction.enumeratePreferencesEntries({ entry in
|
||||
result.formUnion(entry.relatedResources)
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
return excludeResourceIds
|
||||
|> mapToSignal { excludeResourceIds -> Signal<CacheUsageStatsResult, NoError> in
|
||||
let fetch = account.postbox.transaction { transaction -> ([PeerId : Set<MediaId>], [MediaId : Media], MessageIndex?) in
|
||||
return transaction.enumerateMedia(lowerBound: state.with { $0.lowerBound }, upperBound: state.with { $0.upperBound }, limit: 1000)
|
||||
}
|
||||
|> mapError { _ -> CollectCacheUsageStatsError in }
|
||||
|
||||
let process: ([PeerId : Set<MediaId>], [MediaId : Media], MessageIndex?) -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> = { mediaByPeer, mediaRefs, updatedLowerBound in
|
||||
var mediaIdToPeerId: [MediaId: PeerId] = [:]
|
||||
for (peerId, mediaIds) in mediaByPeer {
|
||||
for id in mediaIds {
|
||||
mediaIdToPeerId[id] = peerId
|
||||
}
|
||||
}
|
||||
|
||||
var resourceIdToMediaId: [MediaResourceId: (MediaId, PeerCacheUsageCategory)] = [:]
|
||||
var mediaResourceIds: [MediaId: [MediaResourceId]] = [:]
|
||||
var resourceIds: [MediaResourceId] = []
|
||||
for (id, media) in mediaRefs {
|
||||
mediaResourceIds[id] = []
|
||||
var parsedMedia: [Media] = []
|
||||
switch media {
|
||||
case let image as TelegramMediaImage:
|
||||
parsedMedia.append(image)
|
||||
case let file as TelegramMediaFile:
|
||||
parsedMedia.append(file)
|
||||
case let webpage as TelegramMediaWebpage:
|
||||
if case let .Loaded(content) = webpage.content {
|
||||
if let image = content.image {
|
||||
parsedMedia.append(image)
|
||||
}
|
||||
if let file = content.file {
|
||||
parsedMedia.append(file)
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
for media in parsedMedia {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
for representation in image.representations {
|
||||
resourceIds.append(representation.resource.id)
|
||||
resourceIdToMediaId[representation.resource.id] = (id, .image)
|
||||
mediaResourceIds[id]!.append(representation.resource.id)
|
||||
}
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
var category: PeerCacheUsageCategory = .file
|
||||
loop: for attribute in file.attributes {
|
||||
switch attribute {
|
||||
case .Video:
|
||||
category = .video
|
||||
break loop
|
||||
case .Audio:
|
||||
category = .audio
|
||||
break loop
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
for representation in file.previewRepresentations {
|
||||
resourceIds.append(representation.resource.id)
|
||||
resourceIdToMediaId[representation.resource.id] = (id, category)
|
||||
mediaResourceIds[id]!.append(representation.resource.id)
|
||||
}
|
||||
resourceIds.append(file.resource.id)
|
||||
resourceIdToMediaId[file.resource.id] = (id, category)
|
||||
mediaResourceIds[id]!.append(file.resource.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return account.postbox.mediaBox.collectResourceCacheUsage(resourceIds)
|
||||
|> mapError { _ -> CollectCacheUsageStatsError in }
|
||||
|> mapToSignal { result -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> in
|
||||
state.with { state -> Void in
|
||||
state.lowerBound = updatedLowerBound
|
||||
for (wrappedId, size) in result {
|
||||
if let (id, category) = resourceIdToMediaId[wrappedId] {
|
||||
if let peerId = mediaIdToPeerId[id] {
|
||||
if state.media[peerId] == nil {
|
||||
state.media[peerId] = [:]
|
||||
}
|
||||
if state.media[peerId]![category] == nil {
|
||||
state.media[peerId]![category] = [:]
|
||||
}
|
||||
var currentSize: Int64 = 0
|
||||
if let current = state.media[peerId]![category]![id] {
|
||||
currentSize = current
|
||||
}
|
||||
state.media[peerId]![category]![id] = currentSize + size
|
||||
}
|
||||
}
|
||||
}
|
||||
for (id, ids) in mediaResourceIds {
|
||||
state.mediaResourceIds[id] = ids
|
||||
for resourceId in ids {
|
||||
state.allResourceIds.insert(resourceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
if updatedLowerBound == nil {
|
||||
if peerId != nil {
|
||||
let (finalMedia, finalMediaResourceIds, _) = state.with { state -> ([PeerId: [PeerCacheUsageCategory: [MediaId: Int64]]], [MediaId: [MediaResourceId]], Set<MediaResourceId>) in
|
||||
return (state.media, state.mediaResourceIds, state.allResourceIds)
|
||||
}
|
||||
return account.postbox.transaction { transaction -> CacheUsageStats in
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for peerId in finalMedia.keys {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
peers[peer.id] = peer
|
||||
if let associatedPeerId = peer.associatedPeerId, let associatedPeer = transaction.getPeer(associatedPeerId) {
|
||||
peers[associatedPeer.id] = associatedPeer
|
||||
}
|
||||
}
|
||||
}
|
||||
return CacheUsageStats(media: finalMedia, mediaResourceIds: finalMediaResourceIds, peers: peers, otherSize: 0, otherPaths: [], cacheSize: 0, tempPaths: [], tempSize: 0, immutableSize: 0)
|
||||
} |> mapError { _ -> CollectCacheUsageStatsError in }
|
||||
|> mapToSignal { stats -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> in
|
||||
return .fail(.done(stats))
|
||||
}
|
||||
}
|
||||
|
||||
let (finalMedia, finalMediaResourceIds, allResourceIds) = state.with { state -> ([PeerId: [PeerCacheUsageCategory: [MediaId: Int64]]], [MediaId: [MediaResourceId]], Set<MediaResourceId>) in
|
||||
return (state.media, state.mediaResourceIds, state.allResourceIds)
|
||||
}
|
||||
|
||||
return account.postbox.mediaBox.collectOtherResourceUsage(excludeIds: excludeResourceIds, combinedExcludeIds: allResourceIds.union(excludeResourceIds))
|
||||
|> mapError { _ -> CollectCacheUsageStatsError in }
|
||||
|> mapToSignal { otherSize, otherPaths, cacheSize in
|
||||
var tempPaths: [String] = []
|
||||
var tempSize: Int64 = 0
|
||||
#if os(iOS)
|
||||
if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: NSTemporaryDirectory()), includingPropertiesForKeys: [.isDirectoryKey, .fileAllocatedSizeKey, .isSymbolicLinkKey]) {
|
||||
for url in enumerator {
|
||||
if let url = url as? URL {
|
||||
if let isDirectoryValue = (try? url.resourceValues(forKeys: Set([.isDirectoryKey])))?.isDirectory, isDirectoryValue {
|
||||
tempPaths.append(url.path)
|
||||
} else if let fileSizeValue = (try? url.resourceValues(forKeys: Set([.fileAllocatedSizeKey])))?.fileAllocatedSize {
|
||||
tempPaths.append(url.path)
|
||||
|
||||
if let isSymbolicLinkValue = (try? url.resourceValues(forKeys: Set([.isSymbolicLinkKey])))?.isSymbolicLink, isSymbolicLinkValue {
|
||||
} else {
|
||||
tempSize += Int64(fileSizeValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
var immutableSize: Int64 = 0
|
||||
if let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: account.basePath + "/postbox/db"), includingPropertiesForKeys: [URLResourceKey.fileSizeKey], options: []) {
|
||||
for url in files {
|
||||
if let fileSize = (try? url.resourceValues(forKeys: Set([.fileSizeKey])))?.fileSize {
|
||||
immutableSize += Int64(fileSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
if let logFilesPath = logFilesPath, let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: logFilesPath), includingPropertiesForKeys: [URLResourceKey.fileSizeKey], options: []) {
|
||||
for url in files {
|
||||
if let fileSize = (try? url.resourceValues(forKeys: Set([.fileSizeKey])))?.fileSize {
|
||||
immutableSize += Int64(fileSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for additionalPath in additionalCachePaths {
|
||||
if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: additionalPath), includingPropertiesForKeys: [.isDirectoryKey, .fileAllocatedSizeKey, .isSymbolicLinkKey]) {
|
||||
for url in enumerator {
|
||||
if let url = url as? URL {
|
||||
if let isDirectoryValue = (try? url.resourceValues(forKeys: Set([.isDirectoryKey])))?.isDirectory, isDirectoryValue {
|
||||
} else if let fileSizeValue = (try? url.resourceValues(forKeys: Set([.fileAllocatedSizeKey])))?.fileAllocatedSize {
|
||||
tempPaths.append(url.path)
|
||||
|
||||
if let isSymbolicLinkValue = (try? url.resourceValues(forKeys: Set([.isSymbolicLinkKey])))?.isSymbolicLink, isSymbolicLinkValue {
|
||||
} else {
|
||||
tempSize += Int64(fileSizeValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> CacheUsageStats in
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for peerId in finalMedia.keys {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
peers[peer.id] = peer
|
||||
if let associatedPeerId = peer.associatedPeerId, let associatedPeer = transaction.getPeer(associatedPeerId) {
|
||||
peers[associatedPeer.id] = associatedPeer
|
||||
}
|
||||
}
|
||||
}
|
||||
return CacheUsageStats(media: finalMedia, mediaResourceIds: finalMediaResourceIds, peers: peers, otherSize: otherSize, otherPaths: otherPaths, cacheSize: cacheSize, tempPaths: tempPaths, tempSize: tempSize, immutableSize: immutableSize)
|
||||
} |> mapError { _ -> CollectCacheUsageStatsError in }
|
||||
|> mapToSignal { stats -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> in
|
||||
return .fail(.done(stats))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let signal = (fetch |> mapToSignal { mediaByPeer, mediaRefs, updatedLowerBound -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> in
|
||||
return process(mediaByPeer, mediaRefs, updatedLowerBound)
|
||||
})
|
||||
|> restart
|
||||
|
||||
return signal |> `catch` { error in
|
||||
switch error {
|
||||
case let .done(result):
|
||||
return .single(.result(result))
|
||||
case .generic:
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
func _internal_clearCachedMediaResources(account: Account, mediaResourceIds: Set<MediaResourceId>) -> Signal<Float, NoError> {
|
||||
|
@ -481,6 +481,14 @@ public extension RenderedPeer {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var chatOrMonoforumMainPeer: Peer? {
|
||||
if let channel = self.peer as? TelegramChannel, channel.flags.contains(.isMonoforum), let linkedMonoforumId = channel.linkedMonoforumId {
|
||||
return self.peers[linkedMonoforumId]
|
||||
} else {
|
||||
return self.chatMainPeer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func isServicePeer(_ peer: Peer) -> Bool {
|
||||
|
@ -403,17 +403,49 @@ public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePee
|
||||
}
|
||||
|
||||
public func chatControllerForForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64) -> Signal<ChatController, NoError> {
|
||||
return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: nil, preload: false)
|
||||
return context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
|
||||
)
|
||||
|> deliverOnMainQueue
|
||||
|> `catch` { _ -> Signal<ReplyThreadInfo, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> map { result in
|
||||
return ChatControllerImpl(
|
||||
context: context,
|
||||
chatLocation: .replyThread(message: result.message),
|
||||
chatLocationContextHolder: result.contextHolder
|
||||
)
|
||||
|> mapToSignal { peer -> Signal<ChatController, NoError> in
|
||||
guard let peer else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isMonoforum) {
|
||||
return .single(ChatControllerImpl(
|
||||
context: context,
|
||||
chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||
peerId: peer.id,
|
||||
threadId: threadId,
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: true,
|
||||
isMonoforumPost: channel.flags.contains(.isMonoforum),
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
unreadCount: 0,
|
||||
initialFilledHoles: IndexSet(),
|
||||
initialAnchor: .automatic,
|
||||
isNotAvailable: false
|
||||
)),
|
||||
chatLocationContextHolder: Atomic(value: nil)
|
||||
))
|
||||
} else {
|
||||
return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: nil, preload: false)
|
||||
|> deliverOnMainQueue
|
||||
|> `catch` { _ -> Signal<ReplyThreadInfo, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> map { result in
|
||||
return ChatControllerImpl(
|
||||
context: context,
|
||||
chatLocation: .replyThread(message: result.message),
|
||||
chatLocationContextHolder: result.contextHolder
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user