mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-24 09:06:30 +00:00
[WIP] Topics
This commit is contained in:
parent
c2d84dc649
commit
ddf208edfb
@ -1330,6 +1330,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
strongSelf.deletePeerThread(peerId: peerId, threadId: threadId)
|
strongSelf.deletePeerThread(peerId: peerId, threadId: threadId)
|
||||||
}
|
}
|
||||||
|
self.chatListDisplayNode.containerNode.setPeerThreadStopped = { [weak self] peerId, threadId, isStopped in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.setPeerThreadStopped(peerId: peerId, threadId: threadId, isStopped: isStopped)
|
||||||
|
}
|
||||||
|
|
||||||
self.chatListDisplayNode.containerNode.peerSelected = { [weak self] peer, threadId, animated, activateInput, promoInfo in
|
self.chatListDisplayNode.containerNode.peerSelected = { [weak self] peer, threadId, animated, activateInput, promoInfo in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@ -3675,6 +3681,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func setPeerThreadStopped(peerId: EnginePeer.Id, threadId: Int64, isStopped: Bool) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public func maybeAskForPeerChatRemoval(peer: EngineRenderedPeer, joined: Bool = false, deleteGloballyIfPossible: Bool = false, completion: @escaping (Bool) -> Void, removed: @escaping () -> Void) {
|
public func maybeAskForPeerChatRemoval(peer: EngineRenderedPeer, joined: Bool = false, deleteGloballyIfPossible: Bool = false, completion: @escaping (Bool) -> Void, removed: @escaping () -> Void) {
|
||||||
guard let chatPeer = peer.peers[peer.peerId], let mainPeer = peer.chatMainPeer else {
|
guard let chatPeer = peer.peers[peer.peerId], let mainPeer = peer.chatMainPeer else {
|
||||||
completion(false)
|
completion(false)
|
||||||
|
|||||||
@ -183,7 +183,7 @@ private final class ChatListShimmerNode: ASDisplayNode {
|
|||||||
let timestamp1: Int32 = 100000
|
let timestamp1: Int32 = 100000
|
||||||
let peers: [EnginePeer.Id: EnginePeer] = [:]
|
let peers: [EnginePeer.Id: EnginePeer] = [:]
|
||||||
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture, _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in })
|
}, present: { _ in })
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ private final class ChatListShimmerNode: ASDisplayNode {
|
|||||||
)
|
)
|
||||||
let readState = EnginePeerReadCounters()
|
let readState = EnginePeerReadCounters()
|
||||||
|
|
||||||
return ChatListItem(presentationData: chatListPresentationData, context: context, chatListLocation: .chatList(groupId: .root), filterData: nil, index: .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: 0, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1))), content: .peer(messages: [message], peer: EngineRenderedPeer(peer: peer1), threadInfo: nil, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, draftState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false, forumThreadTitle: nil), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
return ChatListItem(presentationData: chatListPresentationData, context: context, chatListLocation: .chatList(groupId: .root), filterData: nil, index: .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: 0, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1))), content: .peer(messages: [message], peer: EngineRenderedPeer(peer: peer1), threadInfo: nil, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, draftState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false, forumTopicData: nil), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemNodes: [ChatListItemNode] = []
|
var itemNodes: [ChatListItemNode] = []
|
||||||
@ -505,6 +505,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
previousItemNode.listNode.hidePsa = nil
|
previousItemNode.listNode.hidePsa = nil
|
||||||
previousItemNode.listNode.deletePeerChat = nil
|
previousItemNode.listNode.deletePeerChat = nil
|
||||||
previousItemNode.listNode.deletePeerThread = nil
|
previousItemNode.listNode.deletePeerThread = nil
|
||||||
|
previousItemNode.listNode.setPeerThreadStopped = nil
|
||||||
previousItemNode.listNode.peerSelected = nil
|
previousItemNode.listNode.peerSelected = nil
|
||||||
previousItemNode.listNode.groupSelected = nil
|
previousItemNode.listNode.groupSelected = nil
|
||||||
previousItemNode.listNode.updatePeerGrouping = nil
|
previousItemNode.listNode.updatePeerGrouping = nil
|
||||||
@ -543,6 +544,9 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
itemNode.listNode.deletePeerThread = { [weak self] peerId, threadId in
|
itemNode.listNode.deletePeerThread = { [weak self] peerId, threadId in
|
||||||
self?.deletePeerThread?(peerId, threadId)
|
self?.deletePeerThread?(peerId, threadId)
|
||||||
}
|
}
|
||||||
|
itemNode.listNode.setPeerThreadStopped = { [weak self] peerId, threadId, isStopped in
|
||||||
|
self?.setPeerThreadStopped?(peerId, threadId, isStopped)
|
||||||
|
}
|
||||||
itemNode.listNode.peerSelected = { [weak self] peerId, threadId, animated, activateInput, promoInfo in
|
itemNode.listNode.peerSelected = { [weak self] peerId, threadId, animated, activateInput, promoInfo in
|
||||||
self?.peerSelected?(peerId, threadId, animated, activateInput, promoInfo)
|
self?.peerSelected?(peerId, threadId, animated, activateInput, promoInfo)
|
||||||
}
|
}
|
||||||
@ -602,6 +606,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
var hidePsa: ((EnginePeer.Id) -> Void)?
|
var hidePsa: ((EnginePeer.Id) -> Void)?
|
||||||
var deletePeerChat: ((EnginePeer.Id, Bool) -> Void)?
|
var deletePeerChat: ((EnginePeer.Id, Bool) -> Void)?
|
||||||
var deletePeerThread: ((EnginePeer.Id, Int64) -> Void)?
|
var deletePeerThread: ((EnginePeer.Id, Int64) -> Void)?
|
||||||
|
var setPeerThreadStopped: ((EnginePeer.Id, Int64, Bool) -> Void)?
|
||||||
var peerSelected: ((EnginePeer, Int64?, Bool, Bool, ChatListNodeEntryPromoInfo?) -> Void)?
|
var peerSelected: ((EnginePeer, Int64?, Bool, Bool, ChatListNodeEntryPromoInfo?) -> Void)?
|
||||||
var groupSelected: ((EngineChatList.Group) -> Void)?
|
var groupSelected: ((EngineChatList.Group) -> Void)?
|
||||||
var updatePeerGrouping: ((EnginePeer.Id, Bool) -> Void)?
|
var updatePeerGrouping: ((EnginePeer.Id, Bool) -> Void)?
|
||||||
|
|||||||
@ -694,7 +694,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
if isMedia {
|
if isMedia {
|
||||||
return ListMessageItem(presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: .builtin(WallpaperSettings())), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0.0, auxiliaryRadius: 0.0, mergeBubbleCorners: false)), context: context, chatLocation: .peer(id: peer.peerId), interaction: listInteraction, message: message._asMessage(), selection: selection, displayHeader: enableHeaders && !displayCustomHeader, customHeader: key == .downloads ? header : nil, hintIsLink: tagMask == .webPage, isGlobalSearchResult: key != .downloads, isDownloadList: key == .downloads)
|
return ListMessageItem(presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: .builtin(WallpaperSettings())), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0.0, auxiliaryRadius: 0.0, mergeBubbleCorners: false)), context: context, chatLocation: .peer(id: peer.peerId), interaction: listInteraction, message: message._asMessage(), selection: selection, displayHeader: enableHeaders && !displayCustomHeader, customHeader: key == .downloads ? header : nil, hintIsLink: tagMask == .webPage, isGlobalSearchResult: key != .downloads, isDownloadList: key == .downloads)
|
||||||
} else {
|
} else {
|
||||||
return ChatListItem(presentationData: presentationData, context: context, chatListLocation: .chatList(groupId: .root), filterData: nil, index: .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)), content: .peer(messages: [message], peer: peer, threadInfo: nil, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, draftState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: true, displayAsMessage: false, hasFailedMessages: false, forumThreadTitle: nil), editing: false, hasActiveRevealControls: false, selected: false, header: tagMask == nil ? header : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
return ChatListItem(presentationData: presentationData, context: context, chatListLocation: .chatList(groupId: .root), filterData: nil, index: .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)), content: .peer(messages: [message], peer: peer, threadInfo: nil, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, draftState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: true, displayAsMessage: false, hasFailedMessages: false, forumTopicData: nil), editing: false, hasActiveRevealControls: false, selected: false, header: tagMask == nil ? header : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||||
}
|
}
|
||||||
case let .addContact(phoneNumber, theme, strings):
|
case let .addContact(phoneNumber, theme, strings):
|
||||||
return ContactsAddItem(theme: theme, strings: strings, phoneNumber: phoneNumber, header: ChatListSearchItemHeader(type: .phoneNumber, theme: theme, strings: strings, actionTitle: nil, action: nil), action: {
|
return ContactsAddItem(theme: theme, strings: strings, phoneNumber: phoneNumber, header: ChatListSearchItemHeader(type: .phoneNumber, theme: theme, strings: strings, actionTitle: nil, action: nil), action: {
|
||||||
@ -1744,6 +1744,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
}, setPeerThreadMuted: { _, _, _ in
|
}, setPeerThreadMuted: { _, _, _ in
|
||||||
}, deletePeer: { _, _ in
|
}, deletePeer: { _, _ in
|
||||||
}, deletePeerThread: { _, _ in
|
}, deletePeerThread: { _, _ in
|
||||||
|
}, setPeerThreadStopped: { _, _, _ in
|
||||||
}, updatePeerGrouping: { _, _ in
|
}, updatePeerGrouping: { _, _ in
|
||||||
}, togglePeerMarkedUnread: { _, _ in
|
}, togglePeerMarkedUnread: { _, _ in
|
||||||
}, toggleArchivedFolderHiddenByDefault: {
|
}, toggleArchivedFolderHiddenByDefault: {
|
||||||
@ -2953,7 +2954,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
|
|||||||
var peers: [EnginePeer.Id: EnginePeer] = [:]
|
var peers: [EnginePeer.Id: EnginePeer] = [:]
|
||||||
peers[peer1.id] = peer1
|
peers[peer1.id] = peer1
|
||||||
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture, _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in })
|
}, present: { _ in })
|
||||||
|
|
||||||
@ -2984,7 +2985,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
|
|||||||
associatedMedia: [:]
|
associatedMedia: [:]
|
||||||
)
|
)
|
||||||
let readState = EnginePeerReadCounters()
|
let readState = EnginePeerReadCounters()
|
||||||
return ChatListItem(presentationData: chatListPresentationData, context: context, chatListLocation: .chatList(groupId: .root), filterData: nil, index: .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: 0, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1))), content: .peer(messages: [message], peer: EngineRenderedPeer(peer: peer1), threadInfo: nil, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, draftState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false, forumThreadTitle: nil), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
return ChatListItem(presentationData: chatListPresentationData, context: context, chatListLocation: .chatList(groupId: .root), filterData: nil, index: .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: 0, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1))), content: .peer(messages: [message], peer: EngineRenderedPeer(peer: peer1), threadInfo: nil, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, draftState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false, forumTopicData: nil), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||||
case .media:
|
case .media:
|
||||||
return nil
|
return nil
|
||||||
case .links:
|
case .links:
|
||||||
|
|||||||
@ -59,7 +59,7 @@ public enum ChatListItemContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case peer(messages: [EngineMessage], peer: EngineRenderedPeer, threadInfo: ThreadInfo?, combinedReadState: EnginePeerReadCounters?, isRemovedFromTotalUnreadCount: Bool, presence: EnginePeer.Presence?, hasUnseenMentions: Bool, hasUnseenReactions: Bool, draftState: DraftState?, inputActivities: [(EnginePeer, PeerInputActivity)]?, promoInfo: ChatListNodeEntryPromoInfo?, ignoreUnreadBadge: Bool, displayAsMessage: Bool, hasFailedMessages: Bool, forumThreadTitle: String?)
|
case peer(messages: [EngineMessage], peer: EngineRenderedPeer, threadInfo: ThreadInfo?, combinedReadState: EnginePeerReadCounters?, isRemovedFromTotalUnreadCount: Bool, presence: EnginePeer.Presence?, hasUnseenMentions: Bool, hasUnseenReactions: Bool, draftState: DraftState?, inputActivities: [(EnginePeer, PeerInputActivity)]?, promoInfo: ChatListNodeEntryPromoInfo?, ignoreUnreadBadge: Bool, displayAsMessage: Bool, hasFailedMessages: Bool, forumTopicData: EngineChatList.ForumTopicData?)
|
||||||
case groupReference(groupId: EngineChatList.Group, peers: [EngineChatList.GroupItem.Item], message: EngineMessage?, unreadCount: Int, hiddenByDefault: Bool)
|
case groupReference(groupId: EngineChatList.Group, peers: [EngineChatList.GroupItem.Item], message: EngineMessage?, unreadCount: Int, hiddenByDefault: Bool)
|
||||||
|
|
||||||
public var chatLocation: ChatLocation? {
|
public var chatLocation: ChatLocation? {
|
||||||
@ -1045,12 +1045,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let displayAsMessage: Bool
|
let displayAsMessage: Bool
|
||||||
let hasFailedMessages: Bool
|
let hasFailedMessages: Bool
|
||||||
var threadInfo: ChatListItemContent.ThreadInfo?
|
var threadInfo: ChatListItemContent.ThreadInfo?
|
||||||
var forumThreadTitle: String?
|
var forumTopicData: EngineChatList.ForumTopicData?
|
||||||
|
|
||||||
var groupHiddenByDefault = false
|
var groupHiddenByDefault = false
|
||||||
|
|
||||||
switch item.content {
|
switch item.content {
|
||||||
case let .peer(messagesValue, peerValue, threadInfoValue, combinedReadStateValue, isRemovedFromTotalUnreadCountValue, peerPresenceValue, hasUnseenMentionsValue, hasUnseenReactionsValue, draftStateValue, inputActivitiesValue, promoInfoValue, ignoreUnreadBadge, displayAsMessageValue, _, forumThreadTitleValue):
|
case let .peer(messagesValue, peerValue, threadInfoValue, combinedReadStateValue, isRemovedFromTotalUnreadCountValue, peerPresenceValue, hasUnseenMentionsValue, hasUnseenReactionsValue, draftStateValue, inputActivitiesValue, promoInfoValue, ignoreUnreadBadge, displayAsMessageValue, _, forumTopicDataValue):
|
||||||
messages = messagesValue
|
messages = messagesValue
|
||||||
contentPeer = .chat(peerValue)
|
contentPeer = .chat(peerValue)
|
||||||
combinedReadState = combinedReadStateValue
|
combinedReadState = combinedReadStateValue
|
||||||
@ -1071,7 +1071,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
threadInfo = threadInfoValue
|
threadInfo = threadInfoValue
|
||||||
hasUnseenMentions = hasUnseenMentionsValue
|
hasUnseenMentions = hasUnseenMentionsValue
|
||||||
hasUnseenReactions = hasUnseenReactionsValue
|
hasUnseenReactions = hasUnseenReactionsValue
|
||||||
forumThreadTitle = forumThreadTitleValue
|
forumTopicData = forumTopicDataValue
|
||||||
|
|
||||||
switch peerValue.peer {
|
switch peerValue.peer {
|
||||||
case .user, .secretChat:
|
case .user, .secretChat:
|
||||||
@ -1272,8 +1272,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let peerTextValue = peerText, case let .channel(channel) = itemPeer.chatMainPeer, channel.flags.contains(.isForum), threadInfo == nil {
|
if let peerTextValue = peerText, case let .channel(channel) = itemPeer.chatMainPeer, channel.flags.contains(.isForum), threadInfo == nil {
|
||||||
if let forumThreadTitle = forumThreadTitle {
|
if let forumTopicData = forumTopicData {
|
||||||
peerText = "\(peerTextValue) → \(forumThreadTitle)"
|
peerText = "\(peerTextValue) → \(forumTopicData.title)"
|
||||||
} else {
|
} else {
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
peerText = "\(peerTextValue) → General"
|
peerText = "\(peerTextValue) → General"
|
||||||
@ -1547,6 +1547,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
} else {
|
} else {
|
||||||
statusState = .delivered(item.presentationData.theme.chatList.checkmarkColor)
|
statusState = .delivered(item.presentationData.theme.chatList.checkmarkColor)
|
||||||
}
|
}
|
||||||
|
} else if case .forum = item.chatListLocation {
|
||||||
|
if let forumTopicData = forumTopicData, message.id.namespace == forumTopicData.maxOutgoingReadMessageId.namespace, message.id.id >= forumTopicData.maxOutgoingReadMessageId.id {
|
||||||
|
statusState = .read(item.presentationData.theme.chatList.checkmarkColor)
|
||||||
|
} else {
|
||||||
|
statusState = .delivered(item.presentationData.theme.chatList.checkmarkColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2690,6 +2696,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
case RevealOptionKey.unmute.rawValue:
|
case RevealOptionKey.unmute.rawValue:
|
||||||
item.interaction.setPeerThreadMuted(peerId, threadId, false)
|
item.interaction.setPeerThreadMuted(peerId, threadId, false)
|
||||||
close = false
|
close = false
|
||||||
|
case RevealOptionKey.close.rawValue:
|
||||||
|
item.interaction.setPeerThreadStopped(peerId, threadId, true)
|
||||||
|
case RevealOptionKey.open.rawValue:
|
||||||
|
item.interaction.setPeerThreadStopped(peerId, threadId, false)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,7 @@ public final class ChatListNodeInteraction {
|
|||||||
let setPeerThreadMuted: (EnginePeer.Id, Int64?, Bool) -> Void
|
let setPeerThreadMuted: (EnginePeer.Id, Int64?, Bool) -> Void
|
||||||
let deletePeer: (EnginePeer.Id, Bool) -> Void
|
let deletePeer: (EnginePeer.Id, Bool) -> Void
|
||||||
let deletePeerThread: (EnginePeer.Id, Int64) -> Void
|
let deletePeerThread: (EnginePeer.Id, Int64) -> Void
|
||||||
|
let setPeerThreadStopped: (EnginePeer.Id, Int64, Bool) -> Void
|
||||||
let updatePeerGrouping: (EnginePeer.Id, Bool) -> Void
|
let updatePeerGrouping: (EnginePeer.Id, Bool) -> Void
|
||||||
let togglePeerMarkedUnread: (EnginePeer.Id, Bool) -> Void
|
let togglePeerMarkedUnread: (EnginePeer.Id, Bool) -> Void
|
||||||
let toggleArchivedFolderHiddenByDefault: () -> Void
|
let toggleArchivedFolderHiddenByDefault: () -> Void
|
||||||
@ -102,6 +103,7 @@ public final class ChatListNodeInteraction {
|
|||||||
setPeerThreadMuted: @escaping (EnginePeer.Id, Int64?, Bool) -> Void,
|
setPeerThreadMuted: @escaping (EnginePeer.Id, Int64?, Bool) -> Void,
|
||||||
deletePeer: @escaping (EnginePeer.Id, Bool) -> Void,
|
deletePeer: @escaping (EnginePeer.Id, Bool) -> Void,
|
||||||
deletePeerThread: @escaping (EnginePeer.Id, Int64) -> Void,
|
deletePeerThread: @escaping (EnginePeer.Id, Int64) -> Void,
|
||||||
|
setPeerThreadStopped: @escaping (EnginePeer.Id, Int64, Bool) -> Void,
|
||||||
updatePeerGrouping: @escaping (EnginePeer.Id, Bool) -> Void,
|
updatePeerGrouping: @escaping (EnginePeer.Id, Bool) -> Void,
|
||||||
togglePeerMarkedUnread: @escaping (EnginePeer.Id, Bool) -> Void,
|
togglePeerMarkedUnread: @escaping (EnginePeer.Id, Bool) -> Void,
|
||||||
toggleArchivedFolderHiddenByDefault: @escaping () -> Void,
|
toggleArchivedFolderHiddenByDefault: @escaping () -> Void,
|
||||||
@ -124,6 +126,7 @@ public final class ChatListNodeInteraction {
|
|||||||
self.setPeerThreadMuted = setPeerThreadMuted
|
self.setPeerThreadMuted = setPeerThreadMuted
|
||||||
self.deletePeer = deletePeer
|
self.deletePeer = deletePeer
|
||||||
self.deletePeerThread = deletePeerThread
|
self.deletePeerThread = deletePeerThread
|
||||||
|
self.setPeerThreadStopped = setPeerThreadStopped
|
||||||
self.updatePeerGrouping = updatePeerGrouping
|
self.updatePeerGrouping = updatePeerGrouping
|
||||||
self.togglePeerMarkedUnread = togglePeerMarkedUnread
|
self.togglePeerMarkedUnread = togglePeerMarkedUnread
|
||||||
self.toggleArchivedFolderHiddenByDefault = toggleArchivedFolderHiddenByDefault
|
self.toggleArchivedFolderHiddenByDefault = toggleArchivedFolderHiddenByDefault
|
||||||
@ -248,7 +251,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
nodeInteraction.additionalCategorySelected(id)
|
nodeInteraction.additionalCategorySelected(id)
|
||||||
}
|
}
|
||||||
), directionHint: entry.directionHint)
|
), directionHint: entry.directionHint)
|
||||||
case let .PeerEntry(index, presentationData, messages, combinedReadState, isRemovedFromTotalUnreadCount, draftState, peer, threadInfo, presence, hasUnseenMentions, hasUnseenReactions, editing, hasActiveRevealControls, selected, inputActivities, promoInfo, hasFailedMessages, isContact, forumThreadTitle):
|
case let .PeerEntry(index, presentationData, messages, combinedReadState, isRemovedFromTotalUnreadCount, draftState, peer, threadInfo, presence, hasUnseenMentions, hasUnseenReactions, editing, hasActiveRevealControls, selected, inputActivities, promoInfo, hasFailedMessages, isContact, forumTopicData):
|
||||||
switch mode {
|
switch mode {
|
||||||
case .chatList:
|
case .chatList:
|
||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(
|
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(
|
||||||
@ -272,7 +275,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
ignoreUnreadBadge: false,
|
ignoreUnreadBadge: false,
|
||||||
displayAsMessage: false,
|
displayAsMessage: false,
|
||||||
hasFailedMessages: hasFailedMessages,
|
hasFailedMessages: hasFailedMessages,
|
||||||
forumThreadTitle: forumThreadTitle
|
forumTopicData: forumTopicData
|
||||||
),
|
),
|
||||||
editing: editing,
|
editing: editing,
|
||||||
hasActiveRevealControls: hasActiveRevealControls,
|
hasActiveRevealControls: hasActiveRevealControls,
|
||||||
@ -439,7 +442,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatListNodeInteraction, location: ChatListControllerLocation, filterData: ChatListItemFilterData?, mode: ChatListNodeMode, entries: [ChatListNodeViewTransitionUpdateEntry]) -> [ListViewUpdateItem] {
|
private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatListNodeInteraction, location: ChatListControllerLocation, filterData: ChatListItemFilterData?, mode: ChatListNodeMode, entries: [ChatListNodeViewTransitionUpdateEntry]) -> [ListViewUpdateItem] {
|
||||||
return entries.map { entry -> ListViewUpdateItem in
|
return entries.map { entry -> ListViewUpdateItem in
|
||||||
switch entry.entry {
|
switch entry.entry {
|
||||||
case let .PeerEntry(index, presentationData, messages, combinedReadState, isRemovedFromTotalUnreadCount, draftState, peer, threadInfo, presence, hasUnseenMentions, hasUnseenReactions, editing, hasActiveRevealControls, selected, inputActivities, promoInfo, hasFailedMessages, isContact, forumThreadTitle):
|
case let .PeerEntry(index, presentationData, messages, combinedReadState, isRemovedFromTotalUnreadCount, draftState, peer, threadInfo, presence, hasUnseenMentions, hasUnseenReactions, editing, hasActiveRevealControls, selected, inputActivities, promoInfo, hasFailedMessages, isContact, forumTopicData):
|
||||||
switch mode {
|
switch mode {
|
||||||
case .chatList:
|
case .chatList:
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(
|
||||||
@ -463,7 +466,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
ignoreUnreadBadge: false,
|
ignoreUnreadBadge: false,
|
||||||
displayAsMessage: false,
|
displayAsMessage: false,
|
||||||
hasFailedMessages: hasFailedMessages,
|
hasFailedMessages: hasFailedMessages,
|
||||||
forumThreadTitle: forumThreadTitle
|
forumTopicData: forumTopicData
|
||||||
),
|
),
|
||||||
editing: editing,
|
editing: editing,
|
||||||
hasActiveRevealControls: hasActiveRevealControls,
|
hasActiveRevealControls: hasActiveRevealControls,
|
||||||
@ -662,6 +665,7 @@ public final class ChatListNode: ListView {
|
|||||||
public var activateSearch: (() -> Void)?
|
public var activateSearch: (() -> Void)?
|
||||||
public var deletePeerChat: ((EnginePeer.Id, Bool) -> Void)?
|
public var deletePeerChat: ((EnginePeer.Id, Bool) -> Void)?
|
||||||
public var deletePeerThread: ((EnginePeer.Id, Int64) -> Void)?
|
public var deletePeerThread: ((EnginePeer.Id, Int64) -> Void)?
|
||||||
|
public var setPeerThreadStopped: ((EnginePeer.Id, Int64, Bool) -> Void)?
|
||||||
public var updatePeerGrouping: ((EnginePeer.Id, Bool) -> Void)?
|
public var updatePeerGrouping: ((EnginePeer.Id, Bool) -> Void)?
|
||||||
public var presentAlert: ((String) -> Void)?
|
public var presentAlert: ((String) -> Void)?
|
||||||
public var present: ((ViewController) -> Void)?
|
public var present: ((ViewController) -> Void)?
|
||||||
@ -973,6 +977,8 @@ public final class ChatListNode: ListView {
|
|||||||
self?.deletePeerChat?(peerId, joined)
|
self?.deletePeerChat?(peerId, joined)
|
||||||
}, deletePeerThread: { [weak self] peerId, threadId in
|
}, deletePeerThread: { [weak self] peerId, threadId in
|
||||||
self?.deletePeerThread?(peerId, threadId)
|
self?.deletePeerThread?(peerId, threadId)
|
||||||
|
}, setPeerThreadStopped: { [weak self] peerId, threadId, isStopped in
|
||||||
|
self?.setPeerThreadStopped?(peerId, threadId, isStopped)
|
||||||
}, updatePeerGrouping: { [weak self] peerId, group in
|
}, updatePeerGrouping: { [weak self] peerId, group in
|
||||||
self?.updatePeerGrouping?(peerId, group)
|
self?.updatePeerGrouping?(peerId, group)
|
||||||
}, togglePeerMarkedUnread: { [weak self, weak context] peerId, animated in
|
}, togglePeerMarkedUnread: { [weak self, weak context] peerId, animated in
|
||||||
|
|||||||
@ -66,7 +66,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
promoInfo: ChatListNodeEntryPromoInfo?,
|
promoInfo: ChatListNodeEntryPromoInfo?,
|
||||||
hasFailedMessages: Bool,
|
hasFailedMessages: Bool,
|
||||||
isContact: Bool,
|
isContact: Bool,
|
||||||
forumThreadTitle: String?
|
forumTopicData: EngineChatList.ForumTopicData?
|
||||||
)
|
)
|
||||||
case HoleEntry(EngineMessage.Index, theme: PresentationTheme)
|
case HoleEntry(EngineMessage.Index, theme: PresentationTheme)
|
||||||
case GroupReferenceEntry(index: EngineChatList.Item.Index, presentationData: ChatListPresentationData, groupId: EngineChatList.Group, peers: [EngineChatList.GroupItem.Item], message: EngineMessage?, editing: Bool, unreadCount: Int, revealed: Bool, hiddenByDefault: Bool)
|
case GroupReferenceEntry(index: EngineChatList.Item.Index, presentationData: ChatListPresentationData, groupId: EngineChatList.Group, peers: [EngineChatList.GroupItem.Item], message: EngineMessage?, editing: Bool, unreadCount: Int, revealed: Bool, hiddenByDefault: Bool)
|
||||||
@ -386,7 +386,7 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
result.append(.PeerEntry(index: offsetPinnedIndex(entry.index, offset: pinnedIndexOffset), presentationData: state.presentationData, messages: updatedMessages, readState: updatedCombinedReadState, isRemovedFromTotalUnreadCount: entry.isMuted, draftState: draftState, peer: entry.renderedPeer, threadInfo: entry.threadInfo.flatMap { ChatListItemContent.ThreadInfo(id: threadId, info: $0) }, presence: entry.presence, hasUnseenMentions: entry.hasUnseenMentions, hasUnseenReactions: entry.hasUnseenReactions, editing: state.editing, hasActiveRevealControls: hasActiveRevealControls, selected: isSelected, inputActivities: inputActivities, promoInfo: nil, hasFailedMessages: entry.hasFailed, isContact: entry.isContact, forumThreadTitle: entry.forumTopicTitle))
|
result.append(.PeerEntry(index: offsetPinnedIndex(entry.index, offset: pinnedIndexOffset), presentationData: state.presentationData, messages: updatedMessages, readState: updatedCombinedReadState, isRemovedFromTotalUnreadCount: entry.isMuted, draftState: draftState, peer: entry.renderedPeer, threadInfo: entry.threadInfo.flatMap { ChatListItemContent.ThreadInfo(id: threadId, info: $0) }, presence: entry.presence, hasUnseenMentions: entry.hasUnseenMentions, hasUnseenReactions: entry.hasUnseenReactions, editing: state.editing, hasActiveRevealControls: hasActiveRevealControls, selected: isSelected, inputActivities: inputActivities, promoInfo: nil, hasFailedMessages: entry.hasFailed, isContact: entry.isContact, forumTopicData: entry.forumTopicData))
|
||||||
}
|
}
|
||||||
if !view.hasLater {
|
if !view.hasLater {
|
||||||
var pinningIndex: UInt16 = UInt16(pinnedIndexOffset == 0 ? 0 : (pinnedIndexOffset - 1))
|
var pinningIndex: UInt16 = UInt16(pinnedIndexOffset == 0 ? 0 : (pinnedIndexOffset - 1))
|
||||||
@ -420,7 +420,7 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
|||||||
promoInfo: nil,
|
promoInfo: nil,
|
||||||
hasFailedMessages: false,
|
hasFailedMessages: false,
|
||||||
isContact: false,
|
isContact: false,
|
||||||
forumThreadTitle: nil
|
forumTopicData: nil
|
||||||
))
|
))
|
||||||
if foundPinningIndex != 0 {
|
if foundPinningIndex != 0 {
|
||||||
foundPinningIndex -= 1
|
foundPinningIndex -= 1
|
||||||
@ -428,7 +428,7 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.append(.PeerEntry(index: .chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.predecessor), presentationData: state.presentationData, messages: [], readState: nil, isRemovedFromTotalUnreadCount: false, draftState: nil, peer: EngineRenderedPeer(peerId: savedMessagesPeer.id, peers: [savedMessagesPeer.id: savedMessagesPeer], associatedMedia: [:]), threadInfo: nil, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, editing: state.editing, hasActiveRevealControls: false, selected: state.selectedPeerIds.contains(savedMessagesPeer.id), inputActivities: nil, promoInfo: nil, hasFailedMessages: false, isContact: false, forumThreadTitle: nil))
|
result.append(.PeerEntry(index: .chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.predecessor), presentationData: state.presentationData, messages: [], readState: nil, isRemovedFromTotalUnreadCount: false, draftState: nil, peer: EngineRenderedPeer(peerId: savedMessagesPeer.id, peers: [savedMessagesPeer.id: savedMessagesPeer], associatedMedia: [:]), threadInfo: nil, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, editing: state.editing, hasActiveRevealControls: false, selected: state.selectedPeerIds.contains(savedMessagesPeer.id), inputActivities: nil, promoInfo: nil, hasFailedMessages: false, isContact: false, forumTopicData: nil))
|
||||||
} else {
|
} else {
|
||||||
if !filteredAdditionalItemEntries.isEmpty {
|
if !filteredAdditionalItemEntries.isEmpty {
|
||||||
for item in filteredAdditionalItemEntries.reversed() {
|
for item in filteredAdditionalItemEntries.reversed() {
|
||||||
@ -475,7 +475,7 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
|||||||
promoInfo: promoInfo,
|
promoInfo: promoInfo,
|
||||||
hasFailedMessages: item.item.hasFailed,
|
hasFailedMessages: item.item.hasFailed,
|
||||||
isContact: item.item.isContact,
|
isContact: item.item.isContact,
|
||||||
forumThreadTitle: item.item.forumTopicTitle
|
forumTopicData: item.item.forumTopicData
|
||||||
))
|
))
|
||||||
if pinningIndex != 0 {
|
if pinningIndex != 0 {
|
||||||
pinningIndex -= 1
|
pinningIndex -= 1
|
||||||
|
|||||||
@ -237,7 +237,7 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
|||||||
presence: nil,
|
presence: nil,
|
||||||
hasUnseenMentions: hasUnseenMentions,
|
hasUnseenMentions: hasUnseenMentions,
|
||||||
hasUnseenReactions: hasUnseenReactions,
|
hasUnseenReactions: hasUnseenReactions,
|
||||||
forumTopicTitle: nil,
|
forumTopicData: nil,
|
||||||
hasFailed: false,
|
hasFailed: false,
|
||||||
isContact: false
|
isContact: false
|
||||||
))
|
))
|
||||||
|
|||||||
@ -79,6 +79,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
|||||||
}, setPeerThreadMuted: { _, _, _ in
|
}, setPeerThreadMuted: { _, _, _ in
|
||||||
}, deletePeer: { _, _ in
|
}, deletePeer: { _, _ in
|
||||||
}, deletePeerThread: { _, _ in
|
}, deletePeerThread: { _, _ in
|
||||||
|
}, setPeerThreadStopped: { _, _, _ in
|
||||||
}, updatePeerGrouping: { _, _ in
|
}, updatePeerGrouping: { _, _ in
|
||||||
}, togglePeerMarkedUnread: { _, _ in
|
}, togglePeerMarkedUnread: { _, _ in
|
||||||
}, toggleArchivedFolderHiddenByDefault: {
|
}, toggleArchivedFolderHiddenByDefault: {
|
||||||
|
|||||||
@ -170,8 +170,9 @@ final class ChatListIndexTable: Table {
|
|||||||
assert(self.updatedPreviousPeerCachedIndices.isEmpty)
|
assert(self.updatedPreviousPeerCachedIndices.isEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
func commitWithTransaction(postbox: PostboxImpl, currentTransaction: Transaction, alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], updatedPeers: [((Peer, Bool)?, (Peer, Bool))], transactionParticipationInTotalUnreadCountUpdates: (added: Set<PeerId>, removed: Set<PeerId>), updatedTotalUnreadStates: inout [PeerGroupId: ChatListTotalUnreadState], updatedGroupTotalUnreadSummaries: inout [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], currentUpdatedGroupSummarySynchronizeOperations: inout [PeerGroupAndNamespace: Bool]) {
|
func commitWithTransaction(postbox: PostboxImpl, currentTransaction: Transaction, alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], updatedPeers: [((Peer, Bool)?, (Peer, Bool))], transactionParticipationInTotalUnreadCountUpdates: (added: Set<PeerId>, removed: Set<PeerId>), alteredInitialPeerThreadsSummaries: [PeerId: StoredPeerThreadsSummary], updatedTotalUnreadStates: inout [PeerGroupId: ChatListTotalUnreadState], updatedGroupTotalUnreadSummaries: inout [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], currentUpdatedGroupSummarySynchronizeOperations: inout [PeerGroupAndNamespace: Bool]) {
|
||||||
var updatedPeerTags: [PeerId: (previous: PeerSummaryCounterTags, updated: PeerSummaryCounterTags)] = [:]
|
var updatedPeerTags: [PeerId: (previous: PeerSummaryCounterTags, updated: PeerSummaryCounterTags)] = [:]
|
||||||
|
var updatedIsThreadBased: [PeerId: Bool] = [:]
|
||||||
for (previous, updated) in updatedPeers {
|
for (previous, updated) in updatedPeers {
|
||||||
let previousTags: PeerSummaryCounterTags
|
let previousTags: PeerSummaryCounterTags
|
||||||
if let (previous, previousIsContact) = previous {
|
if let (previous, previousIsContact) = previous {
|
||||||
@ -183,9 +184,16 @@ final class ChatListIndexTable: Table {
|
|||||||
if previousTags != updatedTags {
|
if previousTags != updatedTags {
|
||||||
updatedPeerTags[updated.0.id] = (previousTags, updatedTags)
|
updatedPeerTags[updated.0.id] = (previousTags, updatedTags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let previous = previous {
|
||||||
|
let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(updated.0)
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(previous.0) != isThreadBased {
|
||||||
|
updatedIsThreadBased[updated.0.id] = isThreadBased
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.updatedPreviousPeerCachedIndices.isEmpty || !alteredInitialPeerCombinedReadStates.isEmpty || !updatedPeerTags.isEmpty || !transactionParticipationInTotalUnreadCountUpdates.added.isEmpty || !transactionParticipationInTotalUnreadCountUpdates.removed.isEmpty {
|
if !self.updatedPreviousPeerCachedIndices.isEmpty || !alteredInitialPeerCombinedReadStates.isEmpty || !updatedPeerTags.isEmpty || !transactionParticipationInTotalUnreadCountUpdates.added.isEmpty || !transactionParticipationInTotalUnreadCountUpdates.removed.isEmpty || !alteredInitialPeerThreadsSummaries.isEmpty {
|
||||||
var addedToGroupPeerIds: [PeerId: PeerGroupId] = [:]
|
var addedToGroupPeerIds: [PeerId: PeerGroupId] = [:]
|
||||||
var removedFromGroupPeerIds: [PeerId: PeerGroupId] = [:]
|
var removedFromGroupPeerIds: [PeerId: PeerGroupId] = [:]
|
||||||
var addedToIndexPeerIds = Set<PeerId>()
|
var addedToIndexPeerIds = Set<PeerId>()
|
||||||
@ -272,6 +280,10 @@ final class ChatListIndexTable: Table {
|
|||||||
for (peerId, _) in alteredInitialPeerCombinedReadStates {
|
for (peerId, _) in alteredInitialPeerCombinedReadStates {
|
||||||
alteredPeerIds.insert(peerId)
|
alteredPeerIds.insert(peerId)
|
||||||
}
|
}
|
||||||
|
for (peerId, _) in alteredInitialPeerThreadsSummaries {
|
||||||
|
alteredPeerIds.insert(peerId)
|
||||||
|
}
|
||||||
|
|
||||||
alteredPeerIds.formUnion(addedToGroupPeerIds.keys)
|
alteredPeerIds.formUnion(addedToGroupPeerIds.keys)
|
||||||
alteredPeerIds.formUnion(removedFromGroupPeerIds.keys)
|
alteredPeerIds.formUnion(removedFromGroupPeerIds.keys)
|
||||||
alteredPeerIds.formUnion(transactionParticipationInTotalUnreadCountUpdates.added)
|
alteredPeerIds.formUnion(transactionParticipationInTotalUnreadCountUpdates.added)
|
||||||
@ -281,6 +293,10 @@ final class ChatListIndexTable: Table {
|
|||||||
alteredPeerIds.insert(peerId)
|
alteredPeerIds.insert(peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for peerId in updatedIsThreadBased.keys {
|
||||||
|
alteredPeerIds.insert(peerId)
|
||||||
|
}
|
||||||
|
|
||||||
var additionalAlteredPeerIds = Set<PeerId>()
|
var additionalAlteredPeerIds = Set<PeerId>()
|
||||||
for peerId in alteredPeerIds {
|
for peerId in alteredPeerIds {
|
||||||
guard let peer = postbox.peerTable.get(peerId) else {
|
guard let peer = postbox.peerTable.get(peerId) else {
|
||||||
@ -347,8 +363,42 @@ final class ChatListIndexTable: Table {
|
|||||||
}
|
}
|
||||||
let isContact = postbox.contactsTable.isContact(peerId: peerId)
|
let isContact = postbox.contactsTable.isContact(peerId: peerId)
|
||||||
let notificationPeerId: PeerId = peer.associatedPeerId ?? peerId
|
let notificationPeerId: PeerId = peer.associatedPeerId ?? peerId
|
||||||
let initialReadState = alteredInitialPeerCombinedReadStates[peerId] ?? postbox.readStateTable.getCombinedState(peerId)
|
|
||||||
let currentReadState = postbox.readStateTable.getCombinedState(peerId)
|
let initialReadState: CombinedPeerReadState?
|
||||||
|
if let updated = updatedIsThreadBased[peerId] {
|
||||||
|
if updated {
|
||||||
|
// was not thread-based, use peer read state
|
||||||
|
initialReadState = alteredInitialPeerCombinedReadStates[peerId] ?? postbox.readStateTable.getCombinedState(peerId)
|
||||||
|
} else {
|
||||||
|
let previousCount: Int32
|
||||||
|
if let previousSummary = alteredInitialPeerThreadsSummaries[peerId] {
|
||||||
|
previousCount = previousSummary.unreadCount
|
||||||
|
} else {
|
||||||
|
previousCount = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.unreadCount ?? 0
|
||||||
|
}
|
||||||
|
initialReadState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: previousCount, markedUnread: false))])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let previousCount: Int32
|
||||||
|
if let previousSummary = alteredInitialPeerThreadsSummaries[peerId] {
|
||||||
|
previousCount = previousSummary.unreadCount
|
||||||
|
} else {
|
||||||
|
previousCount = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.unreadCount ?? 0
|
||||||
|
}
|
||||||
|
initialReadState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: previousCount, markedUnread: false))])
|
||||||
|
} else {
|
||||||
|
initialReadState = alteredInitialPeerCombinedReadStates[peerId] ?? postbox.readStateTable.getCombinedState(peerId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentReadState: CombinedPeerReadState?
|
||||||
|
if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let count = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.unreadCount ?? 0
|
||||||
|
currentReadState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: count, markedUnread: false))])
|
||||||
|
} else {
|
||||||
|
currentReadState = postbox.readStateTable.getCombinedState(peerId)
|
||||||
|
}
|
||||||
|
|
||||||
var groupIds: [PeerGroupId] = []
|
var groupIds: [PeerGroupId] = []
|
||||||
if let (groupId, _) = self.get(peerId: peerId).includedIndex(peerId: peerId) {
|
if let (groupId, _) = self.get(peerId: peerId).includedIndex(peerId: peerId) {
|
||||||
@ -574,9 +624,19 @@ final class ChatListIndexTable: Table {
|
|||||||
guard let peer = postbox.peerTable.get(peerId) else {
|
guard let peer = postbox.peerTable.get(peerId) else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
guard let combinedState = postbox.readStateTable.getCombinedState(peerId) else {
|
|
||||||
|
let combinedState: CombinedPeerReadState?
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let count: Int32 = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.unreadCount ?? 0
|
||||||
|
combinedState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: count, markedUnread: false))])
|
||||||
|
} else {
|
||||||
|
combinedState = postbox.readStateTable.getCombinedState(peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let combinedState = combinedState else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let isContact = postbox.contactsTable.isContact(peerId: peerId)
|
let isContact = postbox.contactsTable.isContact(peerId: peerId)
|
||||||
let notificationPeerId: PeerId = peer.associatedPeerId ?? peerId
|
let notificationPeerId: PeerId = peer.associatedPeerId ?? peerId
|
||||||
let inclusion = self.get(peerId: peerId)
|
let inclusion = self.get(peerId: peerId)
|
||||||
@ -653,7 +713,19 @@ final class ChatListIndexTable: Table {
|
|||||||
if peerId.namespace == .max {
|
if peerId.namespace == .max {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let combinedState = postbox.readStateTable.getCombinedState(peerId) else {
|
guard let peer = postbox.peerTable.get(peerId) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let combinedState: CombinedPeerReadState?
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let count: Int32 = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.unreadCount ?? 0
|
||||||
|
combinedState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: count, markedUnread: false))])
|
||||||
|
} else {
|
||||||
|
combinedState = postbox.readStateTable.getCombinedState(peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let combinedState = combinedState else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -101,7 +101,7 @@ public struct ChatListGroupReferenceEntry: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum ChatListEntry: Comparable {
|
public enum ChatListEntry: Comparable {
|
||||||
case MessageEntry(index: ChatListIndex, messages: [Message], readState: CombinedPeerReadState?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: StoredPeerChatInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, summaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo], forumTopicData: CodableEntry?, hasFailed: Bool, isContact: Bool)
|
case MessageEntry(index: ChatListIndex, messages: [Message], readState: CombinedPeerReadState?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: StoredPeerChatInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, summaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo], forumTopicData: StoredMessageHistoryThreadInfo?, hasFailed: Bool, isContact: Bool)
|
||||||
case HoleEntry(ChatListHole)
|
case HoleEntry(ChatListHole)
|
||||||
|
|
||||||
public var index: ChatListIndex {
|
public var index: ChatListIndex {
|
||||||
@ -184,7 +184,7 @@ public enum ChatListEntry: Comparable {
|
|||||||
|
|
||||||
enum MutableChatListEntry: Equatable {
|
enum MutableChatListEntry: Equatable {
|
||||||
case IntermediateMessageEntry(index: ChatListIndex, messageIndex: MessageIndex?)
|
case IntermediateMessageEntry(index: ChatListIndex, messageIndex: MessageIndex?)
|
||||||
case MessageEntry(index: ChatListIndex, messages: [Message], readState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: StoredPeerChatInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, tagSummaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo], forumTopicData: CodableEntry?, hasFailedMessages: Bool, isContact: Bool)
|
case MessageEntry(index: ChatListIndex, messages: [Message], readState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: StoredPeerChatInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, tagSummaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo], forumTopicData: StoredMessageHistoryThreadInfo?, hasFailedMessages: Bool, isContact: Bool)
|
||||||
case HoleEntry(ChatListHole)
|
case HoleEntry(ChatListHole)
|
||||||
|
|
||||||
init(_ intermediateEntry: ChatListIntermediateEntry, cachedDataTable: CachedPeerDataTable, readStateTable: MessageHistoryReadStateTable, messageHistoryTable: MessageHistoryTable) {
|
init(_ intermediateEntry: ChatListIntermediateEntry, cachedDataTable: CachedPeerDataTable, readStateTable: MessageHistoryReadStateTable, messageHistoryTable: MessageHistoryTable) {
|
||||||
@ -489,7 +489,15 @@ final class MutableChatListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let renderedPeer = RenderedPeer(peerId: peer.id, peers: peers, associatedMedia: renderAssociatedMediaForPeers(postbox: postbox, peers: peers))
|
let renderedPeer = RenderedPeer(peerId: peer.id, peers: peers, associatedMedia: renderAssociatedMediaForPeers(postbox: postbox, peers: peers))
|
||||||
let isUnread = postbox.readStateTable.getCombinedState(peer.id)?.isUnread ?? false
|
|
||||||
|
let isUnread: Bool
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let count = postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.unreadCount ?? 0
|
||||||
|
isUnread = count > 0
|
||||||
|
} else {
|
||||||
|
isUnread = postbox.readStateTable.getCombinedState(peer.id)?.isUnread ?? false
|
||||||
|
}
|
||||||
|
|
||||||
renderedPeers.append(ChatListGroupReferencePeer(peer: renderedPeer, isUnread: isUnread))
|
renderedPeers.append(ChatListGroupReferencePeer(peer: renderedPeer, isUnread: isUnread))
|
||||||
|
|
||||||
if foundIndices.count == 1 && message == nil {
|
if foundIndices.count == 1 && message == nil {
|
||||||
@ -559,7 +567,15 @@ final class MutableChatListView {
|
|||||||
for i in 0 ..< self.groupEntries.count {
|
for i in 0 ..< self.groupEntries.count {
|
||||||
for j in 0 ..< groupEntries[i].renderedPeers.count {
|
for j in 0 ..< groupEntries[i].renderedPeers.count {
|
||||||
if transaction.alteredInitialPeerCombinedReadStates[groupEntries[i].renderedPeers[j].peer.peerId] != nil {
|
if transaction.alteredInitialPeerCombinedReadStates[groupEntries[i].renderedPeers[j].peer.peerId] != nil {
|
||||||
let isUnread = postbox.readStateTable.getCombinedState(groupEntries[i].renderedPeers[j].peer.peerId)?.isUnread ?? false
|
|
||||||
|
let isUnread: Bool
|
||||||
|
if let peer = groupEntries[i].renderedPeers[j].peer.peer, postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let count = postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.unreadCount ?? 0
|
||||||
|
isUnread = count > 0
|
||||||
|
} else {
|
||||||
|
isUnread = postbox.readStateTable.getCombinedState(groupEntries[i].renderedPeers[j].peer.peerId)?.isUnread ?? false
|
||||||
|
}
|
||||||
|
|
||||||
if isUnread != groupEntries[i].renderedPeers[j].isUnread {
|
if isUnread != groupEntries[i].renderedPeers[j].isUnread {
|
||||||
var renderedPeers = self.groupEntries[i].renderedPeers
|
var renderedPeers = self.groupEntries[i].renderedPeers
|
||||||
renderedPeers[j] = ChatListGroupReferencePeer(peer: groupEntries[i].renderedPeers[j].peer, isUnread: isUnread)
|
renderedPeers[j] = ChatListGroupReferencePeer(peer: groupEntries[i].renderedPeers[j].peer, isUnread: isUnread)
|
||||||
@ -641,12 +657,20 @@ final class MutableChatListView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var forumTopicData: CodableEntry?
|
var forumTopicData: StoredMessageHistoryThreadInfo?
|
||||||
if let message = renderedMessages.first, let threadId = message.threadId {
|
if let message = renderedMessages.first, let threadId = message.threadId {
|
||||||
forumTopicData = postbox.messageHistoryThreadIndexTable.get(peerId: message.id.peerId, threadId: threadId)
|
forumTopicData = postbox.messageHistoryThreadIndexTable.get(peerId: message.id.peerId, threadId: threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .MessageEntry(index: index, messages: renderedMessages, readState: postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId), notificationSettings: notificationSettings, isRemovedFromTotalUnreadCount: false, embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId), renderedPeer: RenderedPeer(peerId: index.messageIndex.id.peerId, peers: peers, associatedMedia: renderAssociatedMediaForPeers(postbox: postbox, peers: peers)), presence: presence, tagSummaryInfo: [:], forumTopicData: forumTopicData, hasFailedMessages: postbox.messageHistoryFailedTable.contains(peerId: index.messageIndex.id.peerId), isContact: isContact)
|
let readState: CombinedPeerReadState?
|
||||||
|
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let count = postbox.peerThreadsSummaryTable.get(peerId: index.messageIndex.id.peerId)?.unreadCount ?? 0
|
||||||
|
readState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: count, markedUnread: false))])
|
||||||
|
} else {
|
||||||
|
readState = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return .MessageEntry(index: index, messages: renderedMessages, readState: readState, notificationSettings: notificationSettings, isRemovedFromTotalUnreadCount: false, embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId), renderedPeer: RenderedPeer(peerId: index.messageIndex.id.peerId, peers: peers, associatedMedia: renderAssociatedMediaForPeers(postbox: postbox, peers: peers)), presence: presence, tagSummaryInfo: [:], forumTopicData: forumTopicData, hasFailedMessages: postbox.messageHistoryFailedTable.contains(peerId: index.messageIndex.id.peerId), isContact: isContact)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,7 +59,13 @@ private func mappedChatListFilterPredicate(postbox: PostboxImpl, currentTransact
|
|||||||
switch entry {
|
switch entry {
|
||||||
case let .message(index, _):
|
case let .message(index, _):
|
||||||
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId) {
|
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId) {
|
||||||
let isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false
|
var isUnread: Bool
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.unreadCount ?? 0) > 0
|
||||||
|
} else {
|
||||||
|
isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false
|
||||||
|
}
|
||||||
|
|
||||||
let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id
|
let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id
|
||||||
let isContact = postbox.contactsTable.isContact(peerId: notificationsPeerId)
|
let isContact = postbox.contactsTable.isContact(peerId: notificationsPeerId)
|
||||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId))
|
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId))
|
||||||
@ -404,7 +410,14 @@ private final class ChatListViewSpaceState {
|
|||||||
|
|
||||||
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peer.id, threadId: nil, calculation: filterPredicate.messageTagSummary)
|
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peer.id, threadId: nil, calculation: filterPredicate.messageTagSummary)
|
||||||
|
|
||||||
if !filterPredicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: postbox.readStateTable.getCombinedState(peer.id)?.isUnread ?? false, isContact: postbox.contactsTable.isContact(peerId: notificationsPeerId), messageTagSummaryResult: messageTagSummaryResult) {
|
var isUnread: Bool
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.unreadCount ?? 0) > 0
|
||||||
|
} else {
|
||||||
|
isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !filterPredicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: notificationsPeerId), messageTagSummaryResult: messageTagSummaryResult) {
|
||||||
continue inner
|
continue inner
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -496,7 +509,7 @@ private final class ChatListViewSpaceState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !transaction.currentUpdatedPeerNotificationSettings.isEmpty, case let .group(groupId, pinned, maybeFilterPredicate) = self.space, let filterPredicate = maybeFilterPredicate {
|
if (!transaction.currentUpdatedPeerNotificationSettings.isEmpty || !transaction.updatedPeerThreadsSummaries.isEmpty), case let .group(groupId, pinned, maybeFilterPredicate) = self.space, let filterPredicate = maybeFilterPredicate {
|
||||||
var removeEntryIndices: [MutableChatListEntryIndex] = []
|
var removeEntryIndices: [MutableChatListEntryIndex] = []
|
||||||
let _ = self.orderedEntries.mutableScan { entry -> MutableChatListEntry? in
|
let _ = self.orderedEntries.mutableScan { entry -> MutableChatListEntry? in
|
||||||
let entryPeer: Peer
|
let entryPeer: Peer
|
||||||
@ -519,8 +532,15 @@ private final class ChatListViewSpaceState {
|
|||||||
case .HoleEntry:
|
case .HoleEntry:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if let settingsChange = transaction.currentUpdatedPeerNotificationSettings[entryNotificationsPeerId] {
|
|
||||||
let isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false
|
let settingsChange = transaction.currentUpdatedPeerNotificationSettings[entryNotificationsPeerId]
|
||||||
|
if settingsChange != nil || transaction.updatedPeerThreadsSummaries.contains(entryNotificationsPeerId) {
|
||||||
|
var isUnread: Bool
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer) {
|
||||||
|
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: entryPeer.id)?.unreadCount ?? 0) > 0
|
||||||
|
} else {
|
||||||
|
isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false
|
||||||
|
}
|
||||||
|
|
||||||
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
||||||
if let current = globalNotificationSettings {
|
if let current = globalNotificationSettings {
|
||||||
@ -530,7 +550,7 @@ private final class ChatListViewSpaceState {
|
|||||||
globalNotificationSettings = globalNotificationSettingsValue
|
globalNotificationSettings = globalNotificationSettingsValue
|
||||||
}
|
}
|
||||||
|
|
||||||
let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: entryPeer, peerSettings: settingsChange.1)
|
let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: entryPeer, peerSettings: settingsChange?.1 ?? postbox.peerNotificationSettingsTable.getEffective(entryNotificationsPeerId))
|
||||||
|
|
||||||
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: entryPeer.id, threadId: nil, calculation: filterPredicate.messageTagSummary)
|
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: entryPeer.id, threadId: nil, calculation: filterPredicate.messageTagSummary)
|
||||||
|
|
||||||
@ -548,7 +568,8 @@ private final class ChatListViewSpaceState {
|
|||||||
let _ = self.orderedEntries.remove(index: index)
|
let _ = self.orderedEntries.remove(index: index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (peerId, settingsChange) in transaction.currentUpdatedPeerNotificationSettings {
|
|
||||||
|
for peerId in transaction.updatedPeerThreadsSummaries.union(transaction.currentUpdatedPeerNotificationSettings.keys) {
|
||||||
if let mainPeer = postbox.peerTable.get(peerId) {
|
if let mainPeer = postbox.peerTable.get(peerId) {
|
||||||
var peers: [Peer] = [mainPeer]
|
var peers: [Peer] = [mainPeer]
|
||||||
for associatedId in postbox.reverseAssociatedPeerTable.get(peerId: mainPeer.id) {
|
for associatedId in postbox.reverseAssociatedPeerTable.get(peerId: mainPeer.id) {
|
||||||
@ -558,7 +579,12 @@ private final class ChatListViewSpaceState {
|
|||||||
}
|
}
|
||||||
assert(Set(peers.map { $0.id }).count == peers.count)
|
assert(Set(peers.map { $0.id }).count == peers.count)
|
||||||
|
|
||||||
let isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false
|
var isUnread: Bool
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer) {
|
||||||
|
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peerId)?.unreadCount ?? 0) > 0
|
||||||
|
} else {
|
||||||
|
isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false
|
||||||
|
}
|
||||||
|
|
||||||
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
||||||
if let current = globalNotificationSettings {
|
if let current = globalNotificationSettings {
|
||||||
@ -568,7 +594,7 @@ private final class ChatListViewSpaceState {
|
|||||||
globalNotificationSettings = globalNotificationSettingsValue
|
globalNotificationSettings = globalNotificationSettingsValue
|
||||||
}
|
}
|
||||||
|
|
||||||
let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: mainPeer, peerSettings: settingsChange.1)
|
let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: mainPeer, peerSettings: transaction.currentUpdatedPeerNotificationSettings[mainPeer.id]?.1 ?? postbox.peerNotificationSettingsTable.getEffective(mainPeer.id))
|
||||||
|
|
||||||
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peerId, threadId: nil, calculation: filterPredicate.messageTagSummary)
|
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peerId, threadId: nil, calculation: filterPredicate.messageTagSummary)
|
||||||
|
|
||||||
@ -756,7 +782,12 @@ private final class ChatListViewSpaceState {
|
|||||||
let updatedActionsSummary = transaction.currentUpdatedMessageActionsSummaries[PendingMessageActionsSummaryKey(type: filterMessageTagSummary.subtractCount.type, peerId: entryPeer.id, namespace: filterMessageTagSummary.subtractCount.namespace)]
|
let updatedActionsSummary = transaction.currentUpdatedMessageActionsSummaries[PendingMessageActionsSummaryKey(type: filterMessageTagSummary.subtractCount.type, peerId: entryPeer.id, namespace: filterMessageTagSummary.subtractCount.namespace)]
|
||||||
|
|
||||||
if updatedMessageSummary != nil || updatedActionsSummary != nil {
|
if updatedMessageSummary != nil || updatedActionsSummary != nil {
|
||||||
let isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false
|
var isUnread: Bool
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer) {
|
||||||
|
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: entryPeer.id)?.unreadCount ?? 0) > 0
|
||||||
|
} else {
|
||||||
|
isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false
|
||||||
|
}
|
||||||
|
|
||||||
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
||||||
if let current = globalNotificationSettings {
|
if let current = globalNotificationSettings {
|
||||||
@ -801,7 +832,12 @@ private final class ChatListViewSpaceState {
|
|||||||
}
|
}
|
||||||
assert(Set(peers.map { $0.id }).count == peers.count)
|
assert(Set(peers.map { $0.id }).count == peers.count)
|
||||||
|
|
||||||
let isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false
|
var isUnread: Bool
|
||||||
|
if postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer) {
|
||||||
|
isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peerId)?.unreadCount ?? 0) > 0
|
||||||
|
} else {
|
||||||
|
isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false
|
||||||
|
}
|
||||||
|
|
||||||
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
||||||
if let current = globalNotificationSettings {
|
if let current = globalNotificationSettings {
|
||||||
@ -842,7 +878,7 @@ private final class ChatListViewSpaceState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageActionsSummaries.isEmpty {
|
if !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageActionsSummaries.isEmpty || !transaction.updatedPeerThreadsSummaries.isEmpty {
|
||||||
if self.orderedEntries.mutableScan({ entry in
|
if self.orderedEntries.mutableScan({ entry in
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .MessageEntry(index, messages, readState, notificationSettings, isRemovedFromTotalUnreadCount, embeddedInterfaceState, entryRenderedPeer, presence, tagSummaryInfo, forumTopicData, hasFailedMessages, isContact):
|
case let .MessageEntry(index, messages, readState, notificationSettings, isRemovedFromTotalUnreadCount, embeddedInterfaceState, entryRenderedPeer, presence, tagSummaryInfo, forumTopicData, hasFailedMessages, isContact):
|
||||||
@ -875,11 +911,23 @@ private final class ChatListViewSpaceState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var updatedReadState = readState
|
||||||
|
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let count = postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.unreadCount ?? 0
|
||||||
|
updatedReadState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: count, markedUnread: false))])
|
||||||
|
} else {
|
||||||
|
updatedReadState = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if updatedReadState != readState {
|
||||||
|
didUpdateSummaryInfo = true
|
||||||
|
}
|
||||||
|
|
||||||
if didUpdateSummaryInfo {
|
if didUpdateSummaryInfo {
|
||||||
return .MessageEntry(
|
return .MessageEntry(
|
||||||
index: index,
|
index: index,
|
||||||
messages: messages,
|
messages: messages,
|
||||||
readState: readState,
|
readState: updatedReadState,
|
||||||
notificationSettings: notificationSettings,
|
notificationSettings: notificationSettings,
|
||||||
isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount,
|
isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount,
|
||||||
embeddedInterfaceState: embeddedInterfaceState,
|
embeddedInterfaceState: embeddedInterfaceState,
|
||||||
@ -1461,12 +1509,20 @@ struct ChatListViewState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var forumTopicData: CodableEntry?
|
var forumTopicData: StoredMessageHistoryThreadInfo?
|
||||||
if let message = renderedMessages.first, let threadId = message.threadId {
|
if let message = renderedMessages.first, let threadId = message.threadId {
|
||||||
forumTopicData = postbox.messageHistoryThreadIndexTable.get(peerId: message.id.peerId, threadId: threadId)
|
forumTopicData = postbox.messageHistoryThreadIndexTable.get(peerId: message.id.peerId, threadId: threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
let updatedEntry: MutableChatListEntry = .MessageEntry(index: index, messages: renderedMessages, readState: postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId), notificationSettings: notificationSettings, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId), renderedPeer: renderedPeer, presence: presence, tagSummaryInfo: tagSummaryInfo, forumTopicData: forumTopicData, hasFailedMessages: false, isContact: postbox.contactsTable.isContact(peerId: index.messageIndex.id.peerId))
|
let readState: CombinedPeerReadState?
|
||||||
|
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||||
|
let count = postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.unreadCount ?? 0
|
||||||
|
readState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: count, markedUnread: false))])
|
||||||
|
} else {
|
||||||
|
readState = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
let updatedEntry: MutableChatListEntry = .MessageEntry(index: index, messages: renderedMessages, readState: readState, notificationSettings: notificationSettings, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId), renderedPeer: renderedPeer, presence: presence, tagSummaryInfo: tagSummaryInfo, forumTopicData: forumTopicData, hasFailedMessages: false, isContact: postbox.contactsTable.isContact(peerId: index.messageIndex.id.peerId))
|
||||||
if directionIndex == 0 {
|
if directionIndex == 0 {
|
||||||
self.stateBySpace[space]!.orderedEntries.setLowerOrAtAnchorAtArrayIndex(listIndex, to: updatedEntry)
|
self.stateBySpace[space]!.orderedEntries.setLowerOrAtAnchorAtArrayIndex(listIndex, to: updatedEntry)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -67,7 +67,7 @@ final class MutableMessageHistoryThreadIndexView: MutablePostboxView {
|
|||||||
self.items.append(Item(
|
self.items.append(Item(
|
||||||
id: item.threadId,
|
id: item.threadId,
|
||||||
index: item.index,
|
index: item.index,
|
||||||
info: item.info,
|
info: item.info.data,
|
||||||
tagSummaryInfo: tagSummaryInfo,
|
tagSummaryInfo: tagSummaryInfo,
|
||||||
topMessage: postbox.getMessage(item.index.id)
|
topMessage: postbox.getMessage(item.index.id)
|
||||||
))
|
))
|
||||||
@ -170,7 +170,7 @@ final class MutableMessageHistoryThreadInfoView: MutablePostboxView {
|
|||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
private let threadId: Int64
|
private let threadId: Int64
|
||||||
|
|
||||||
fileprivate var info: CodableEntry?
|
fileprivate var info: StoredMessageHistoryThreadInfo?
|
||||||
|
|
||||||
init(postbox: PostboxImpl, peerId: PeerId, threadId: Int64) {
|
init(postbox: PostboxImpl, peerId: PeerId, threadId: Int64) {
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
@ -207,7 +207,7 @@ final class MutableMessageHistoryThreadInfoView: MutablePostboxView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class MessageHistoryThreadInfoView: PostboxView {
|
public final class MessageHistoryThreadInfoView: PostboxView {
|
||||||
public let info: CodableEntry?
|
public let info: StoredMessageHistoryThreadInfo?
|
||||||
|
|
||||||
init(_ view: MutableMessageHistoryThreadInfoView) {
|
init(_ view: MutableMessageHistoryThreadInfoView) {
|
||||||
self.info = view.info
|
self.info = view.info
|
||||||
|
|||||||
@ -1,5 +1,49 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
public struct StoredMessageHistoryThreadInfo: Equatable, PostboxCoding {
|
||||||
|
public struct Summary: Equatable, PostboxCoding {
|
||||||
|
public var totalUnreadCount: Int32
|
||||||
|
public var mutedUntil: Int32?
|
||||||
|
|
||||||
|
public init(totalUnreadCount: Int32, mutedUntil: Int32?) {
|
||||||
|
self.totalUnreadCount = totalUnreadCount
|
||||||
|
self.mutedUntil = mutedUntil
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(decoder: PostboxDecoder) {
|
||||||
|
self.totalUnreadCount = decoder.decodeInt32ForKey("u", orElse: 0)
|
||||||
|
self.mutedUntil = decoder.decodeOptionalInt32ForKey("m")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
|
encoder.encodeInt32(self.totalUnreadCount, forKey: "u")
|
||||||
|
if let mutedUntil = self.mutedUntil {
|
||||||
|
encoder.encodeInt32(mutedUntil, forKey: "m")
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: "m")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var data: CodableEntry
|
||||||
|
public var summary: Summary
|
||||||
|
|
||||||
|
public init(data: CodableEntry, summary: Summary) {
|
||||||
|
self.data = data
|
||||||
|
self.summary = summary
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(decoder: PostboxDecoder) {
|
||||||
|
self.data = CodableEntry(data: decoder.decodeDataForKey("d")!)
|
||||||
|
self.summary = decoder.decodeObjectForKey("s", decoder: { return Summary(decoder: $0) }) as! Summary
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
|
encoder.encodeData(self.data.data, forKey: "d")
|
||||||
|
encoder.encodeObject(self.summary, forKey: "s")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func extractKey(_ key: ValueBoxKey) -> MessageIndex {
|
private func extractKey(_ key: ValueBoxKey) -> MessageIndex {
|
||||||
return MessageIndex(id: MessageId(peerId: PeerId(key.getInt64(0)), namespace: key.getInt32(8 + 8), id: key.getInt32(8 + 8 + 4 + 4)), timestamp: key.getInt32(8 + 8 + 4))
|
return MessageIndex(id: MessageId(peerId: PeerId(key.getInt64(0)), namespace: key.getInt32(8 + 8), id: key.getInt32(8 + 8 + 4 + 4)), timestamp: key.getInt32(8 + 8 + 4))
|
||||||
}
|
}
|
||||||
@ -65,7 +109,13 @@ class MessageHistoryThreadIndexTable: Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private struct UpdatedEntry {
|
private struct UpdatedEntry {
|
||||||
var value: CodableEntry?
|
var value: StoredMessageHistoryThreadInfo?
|
||||||
|
}
|
||||||
|
|
||||||
|
enum IndexBoundary {
|
||||||
|
case lowerBound
|
||||||
|
case upperBound
|
||||||
|
case index(StoredPeerThreadCombinedState.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
private let reverseIndexTable: MessageHistoryThreadReverseIndexTable
|
private let reverseIndexTable: MessageHistoryThreadReverseIndexTable
|
||||||
@ -114,14 +164,16 @@ class MessageHistoryThreadIndexTable: Table {
|
|||||||
return self.lowerBound(peerId: peerId).successor
|
return self.lowerBound(peerId: peerId).successor
|
||||||
}
|
}
|
||||||
|
|
||||||
func get(peerId: PeerId, threadId: Int64) -> CodableEntry? {
|
func get(peerId: PeerId, threadId: Int64) -> StoredMessageHistoryThreadInfo? {
|
||||||
if let updated = self.updatedInfoItems[MessageHistoryThreadsTable.ItemId(peerId: peerId, threadId: threadId)] {
|
if let updated = self.updatedInfoItems[MessageHistoryThreadsTable.ItemId(peerId: peerId, threadId: threadId)] {
|
||||||
return updated.value
|
return updated.value
|
||||||
} else {
|
} else {
|
||||||
if let itemIndex = self.reverseIndexTable.get(peerId: peerId, threadId: threadId) {
|
if let itemIndex = self.reverseIndexTable.get(peerId: peerId, threadId: threadId) {
|
||||||
if let value = self.valueBox.get(self.table, key: self.key(peerId: itemIndex.id.peerId, timestamp: itemIndex.timestamp, threadId: threadId, namespace: itemIndex.id.namespace, id: itemIndex.id.id, key: self.sharedKey)) {
|
if let value = self.valueBox.get(self.table, key: self.key(peerId: itemIndex.id.peerId, timestamp: itemIndex.timestamp, threadId: threadId, namespace: itemIndex.id.namespace, id: itemIndex.id.id, key: self.sharedKey)) {
|
||||||
if value.length != 0 {
|
if value.length != 0 {
|
||||||
return CodableEntry(data: value.makeData())
|
let decoder = PostboxDecoder(buffer: value)
|
||||||
|
let state = StoredMessageHistoryThreadInfo(decoder: decoder)
|
||||||
|
return state
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -134,7 +186,7 @@ class MessageHistoryThreadIndexTable: Table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func set(peerId: PeerId, threadId: Int64, info: CodableEntry?) {
|
func set(peerId: PeerId, threadId: Int64, info: StoredMessageHistoryThreadInfo?) {
|
||||||
self.updatedInfoItems[MessageHistoryThreadsTable.ItemId(peerId: peerId, threadId: threadId)] = UpdatedEntry(value: info)
|
self.updatedInfoItems[MessageHistoryThreadsTable.ItemId(peerId: peerId, threadId: threadId)] = UpdatedEntry(value: info)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +212,9 @@ class MessageHistoryThreadIndexTable: Table {
|
|||||||
}
|
}
|
||||||
if let updatedInfo = self.updatedInfoItems[itemId] {
|
if let updatedInfo = self.updatedInfoItems[itemId] {
|
||||||
if let value = updatedInfo.value {
|
if let value = updatedInfo.value {
|
||||||
info = ReadBuffer(data: value.data)
|
let encoder = PostboxEncoder()
|
||||||
|
value.encode(encoder)
|
||||||
|
info = encoder.makeReadBufferAndReset()
|
||||||
} else {
|
} else {
|
||||||
info = nil
|
info = nil
|
||||||
}
|
}
|
||||||
@ -185,15 +239,52 @@ class MessageHistoryThreadIndexTable: Table {
|
|||||||
return peerIds
|
return peerIds
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAll(peerId: PeerId) -> [(threadId: Int64, index: MessageIndex, info: CodableEntry)] {
|
func fetch(peerId: PeerId, namespace: MessageId.Namespace, start: IndexBoundary, end: IndexBoundary, limit: Int) -> [(threadId: Int64, index: MessageIndex, info: StoredMessageHistoryThreadInfo)] {
|
||||||
var result: [(threadId: Int64, index: MessageIndex, info: CodableEntry)] = []
|
let startKey: ValueBoxKey
|
||||||
|
switch start {
|
||||||
|
case let .index(index):
|
||||||
|
startKey = self.key(peerId: peerId, timestamp: index.timestamp, threadId: index.threadId, namespace: namespace, id: index.messageId, key: ValueBoxKey(length: self.sharedKey.length))
|
||||||
|
case .lowerBound:
|
||||||
|
startKey = self.lowerBound(peerId: peerId)
|
||||||
|
case .upperBound:
|
||||||
|
startKey = self.upperBound(peerId: peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
let endKey: ValueBoxKey
|
||||||
|
switch end {
|
||||||
|
case let .index(index):
|
||||||
|
endKey = self.key(peerId: peerId, timestamp: index.timestamp, threadId: index.threadId, namespace: namespace, id: index.messageId, key: ValueBoxKey(length: self.sharedKey.length))
|
||||||
|
case .lowerBound:
|
||||||
|
endKey = self.lowerBound(peerId: peerId)
|
||||||
|
case .upperBound:
|
||||||
|
endKey = self.upperBound(peerId: peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result: [(threadId: Int64, index: MessageIndex, info: StoredMessageHistoryThreadInfo)] = []
|
||||||
|
self.valueBox.range(self.table, start: startKey, end: endKey, values: { key, value in
|
||||||
|
let keyData = MessageHistoryThreadIndexTable.extract(key: key)
|
||||||
|
if value.length == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
let decoder = PostboxDecoder(buffer: value)
|
||||||
|
let state = StoredMessageHistoryThreadInfo(decoder: decoder)
|
||||||
|
result.append((keyData.threadId, keyData.index, state))
|
||||||
|
return true
|
||||||
|
}, limit: limit)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAll(peerId: PeerId) -> [(threadId: Int64, index: MessageIndex, info: StoredMessageHistoryThreadInfo)] {
|
||||||
|
var result: [(threadId: Int64, index: MessageIndex, info: StoredMessageHistoryThreadInfo)] = []
|
||||||
self.valueBox.range(self.table, start: self.upperBound(peerId: peerId), end: self.lowerBound(peerId: peerId), values: { key, value in
|
self.valueBox.range(self.table, start: self.upperBound(peerId: peerId), end: self.lowerBound(peerId: peerId), values: { key, value in
|
||||||
let keyData = MessageHistoryThreadIndexTable.extract(key: key)
|
let keyData = MessageHistoryThreadIndexTable.extract(key: key)
|
||||||
if value.length == 0 {
|
if value.length == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
let info = CodableEntry(data: value.makeData())
|
let decoder = PostboxDecoder(buffer: value)
|
||||||
result.append((keyData.threadId, keyData.index, info))
|
let state = StoredMessageHistoryThreadInfo(decoder: decoder)
|
||||||
|
result.append((keyData.threadId, keyData.index, state))
|
||||||
return true
|
return true
|
||||||
}, limit: 100000)
|
}, limit: 100000)
|
||||||
|
|
||||||
|
|||||||
@ -357,6 +357,16 @@ public func arePeerDictionariesEqual(_ lhs: [PeerId: Peer], _ rhs: [PeerId: Peer
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct PeerSummaryCounterData: Equatable {
|
||||||
|
public var tags: PeerSummaryCounterTags
|
||||||
|
public var usesThreadSummary: Bool
|
||||||
|
|
||||||
|
public init(tags: PeerSummaryCounterTags, usesThreadSummary: Bool) {
|
||||||
|
self.tags = tags
|
||||||
|
self.usesThreadSummary = usesThreadSummary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public struct PeerSummaryCounterTags: OptionSet, Sequence, Hashable {
|
public struct PeerSummaryCounterTags: OptionSet, Sequence, Hashable {
|
||||||
public var rawValue: Int32
|
public var rawValue: Int32
|
||||||
|
|
||||||
|
|||||||
193
submodules/Postbox/Sources/PeerThreadCombinedStateTable.swift
Normal file
193
submodules/Postbox/Sources/PeerThreadCombinedStateTable.swift
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct StoredPeerThreadCombinedState: Equatable, Codable {
|
||||||
|
public struct Index: Equatable, Comparable, Codable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case timestamp = "t"
|
||||||
|
case threadId = "i"
|
||||||
|
case messageId = "m"
|
||||||
|
}
|
||||||
|
|
||||||
|
public var timestamp: Int32
|
||||||
|
public var threadId: Int64
|
||||||
|
public var messageId: Int32
|
||||||
|
|
||||||
|
public init(timestamp: Int32, threadId: Int64, messageId: Int32) {
|
||||||
|
self.timestamp = timestamp
|
||||||
|
self.threadId = threadId
|
||||||
|
self.messageId = messageId
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func <(lhs: Index, rhs: Index) -> Bool {
|
||||||
|
if lhs.timestamp != rhs.timestamp {
|
||||||
|
return lhs.timestamp < rhs.timestamp
|
||||||
|
}
|
||||||
|
if lhs.threadId != rhs.threadId {
|
||||||
|
return lhs.threadId < rhs.threadId
|
||||||
|
}
|
||||||
|
return lhs.messageId < rhs.messageId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case data = "d"
|
||||||
|
case validIndexBoundary = "r"
|
||||||
|
}
|
||||||
|
|
||||||
|
var data: CodableEntry
|
||||||
|
var validIndexBoundary: Index?
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.data = CodableEntry(data: try container.decode(Data.self, forKey: .data))
|
||||||
|
self.validIndexBoundary = try container.decodeIfPresent(Index.self, forKey: .validIndexBoundary)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.data.data, forKey: .data)
|
||||||
|
try container.encodeIfPresent(self.validIndexBoundary, forKey: .validIndexBoundary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PeerThreadCombinedStateTable: Table {
|
||||||
|
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
||||||
|
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private let sharedKey = ValueBoxKey(length: 8)
|
||||||
|
|
||||||
|
private(set) var updatedIds = Set<PeerId>()
|
||||||
|
|
||||||
|
override init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
|
||||||
|
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func key(peerId: PeerId) -> ValueBoxKey {
|
||||||
|
self.sharedKey.setInt64(0, value: peerId.toInt64())
|
||||||
|
return self.sharedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(peerId: PeerId, state: StoredPeerThreadCombinedState?) {
|
||||||
|
if let state = state {
|
||||||
|
do {
|
||||||
|
let data = try AdaptedPostboxEncoder().encode(state)
|
||||||
|
self.valueBox.set(self.table, key: self.key(peerId: peerId), value: MemoryBuffer(data: data))
|
||||||
|
} catch {
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.valueBox.remove(self.table, key: self.key(peerId: peerId), secure: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func get(peerId: PeerId) -> StoredPeerThreadCombinedState? {
|
||||||
|
do {
|
||||||
|
guard let value = self.valueBox.get(self.table, key: self.key(peerId: peerId)) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let state = try withExtendedLifetime(value, {
|
||||||
|
return try AdaptedPostboxDecoder().decode(StoredPeerThreadCombinedState.self, from: value.dataNoCopy())
|
||||||
|
})
|
||||||
|
return state
|
||||||
|
} catch {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func beforeCommit() {
|
||||||
|
super.beforeCommit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StoredPeerThreadsSummary: Equatable, Codable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case unreadCount = "u"
|
||||||
|
}
|
||||||
|
|
||||||
|
var unreadCount: Int32
|
||||||
|
|
||||||
|
init(unreadCount: Int32) {
|
||||||
|
self.unreadCount = unreadCount
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.unreadCount = try container.decode(Int32.self, forKey: .unreadCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.unreadCount, forKey: .unreadCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PeerThreadsSummaryTable: Table {
|
||||||
|
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
||||||
|
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private let sharedKey = ValueBoxKey(length: 8)
|
||||||
|
|
||||||
|
private(set) var updatedIds = Set<PeerId>()
|
||||||
|
|
||||||
|
override init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
|
||||||
|
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func key(peerId: PeerId) -> ValueBoxKey {
|
||||||
|
self.sharedKey.setInt64(0, value: peerId.toInt64())
|
||||||
|
return self.sharedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
private func set(peerId: PeerId, state: StoredPeerThreadsSummary) {
|
||||||
|
do {
|
||||||
|
let data = try AdaptedPostboxEncoder().encode(state)
|
||||||
|
self.valueBox.set(self.table, key: self.key(peerId: peerId), value: MemoryBuffer(data: data))
|
||||||
|
} catch {
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func get(peerId: PeerId) -> StoredPeerThreadsSummary? {
|
||||||
|
do {
|
||||||
|
guard let value = self.valueBox.get(self.table, key: self.key(peerId: peerId)) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let state = try withExtendedLifetime(value, {
|
||||||
|
return try AdaptedPostboxDecoder().decode(StoredPeerThreadsSummary.self, from: value.dataNoCopy())
|
||||||
|
})
|
||||||
|
return state
|
||||||
|
} catch {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(peerIds: Set<PeerId>, indexTable: MessageHistoryThreadIndexTable, combinedStateTable: PeerThreadCombinedStateTable) -> [PeerId: StoredPeerThreadsSummary] {
|
||||||
|
var updatedInitialSummaries: [PeerId: StoredPeerThreadsSummary] = [:]
|
||||||
|
|
||||||
|
for peerId in peerIds {
|
||||||
|
var unreadCount: Int32 = 0
|
||||||
|
for item in indexTable.fetch(peerId: peerId, namespace: 0, start: .upperBound, end: .lowerBound, limit: 20) {
|
||||||
|
if item.info.summary.mutedUntil == nil {
|
||||||
|
unreadCount += item.info.summary.totalUnreadCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let current = self.get(peerId: peerId)
|
||||||
|
if current?.unreadCount != unreadCount {
|
||||||
|
updatedInitialSummaries[peerId] = current ?? StoredPeerThreadsSummary(unreadCount: 0)
|
||||||
|
self.set(peerId: peerId, state: StoredPeerThreadsSummary(unreadCount: unreadCount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedInitialSummaries
|
||||||
|
}
|
||||||
|
|
||||||
|
override func beforeCommit() {
|
||||||
|
super.beforeCommit()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1153,20 +1153,30 @@ public final class Transaction {
|
|||||||
self.postbox?.removePeerTimeoutAttributeEntry(peerId: peerId, timestamp: timestamp)
|
self.postbox?.removePeerTimeoutAttributeEntry(peerId: peerId, timestamp: timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getMessageHistoryThreadIndex(peerId: PeerId) -> [(threadId: Int64, index: MessageIndex, info: CodableEntry)] {
|
public func getMessageHistoryThreadIndex(peerId: PeerId) -> [(threadId: Int64, index: MessageIndex, info: StoredMessageHistoryThreadInfo)] {
|
||||||
assert(!self.disposed)
|
assert(!self.disposed)
|
||||||
return self.postbox!.messageHistoryThreadIndexTable.getAll(peerId: peerId)
|
return self.postbox!.messageHistoryThreadIndexTable.getAll(peerId: peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getMessageHistoryThreadInfo(peerId: PeerId, threadId: Int64) -> CodableEntry? {
|
public func getMessageHistoryThreadInfo(peerId: PeerId, threadId: Int64) -> StoredMessageHistoryThreadInfo? {
|
||||||
assert(!self.disposed)
|
assert(!self.disposed)
|
||||||
return self.postbox!.messageHistoryThreadIndexTable.get(peerId: peerId, threadId: threadId)
|
return self.postbox!.messageHistoryThreadIndexTable.get(peerId: peerId, threadId: threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setMessageHistoryThreadInfo(peerId: PeerId, threadId: Int64, info: CodableEntry?) {
|
public func setMessageHistoryThreadInfo(peerId: PeerId, threadId: Int64, info: StoredMessageHistoryThreadInfo?) {
|
||||||
assert(!self.disposed)
|
assert(!self.disposed)
|
||||||
self.postbox!.messageHistoryThreadIndexTable.set(peerId: peerId, threadId: threadId, info: info)
|
self.postbox!.messageHistoryThreadIndexTable.set(peerId: peerId, threadId: threadId, info: info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func getPeerThreadCombinedState(peerId: PeerId) -> StoredPeerThreadCombinedState? {
|
||||||
|
assert(!self.disposed)
|
||||||
|
return self.postbox!.peerThreadCombinedStateTable.get(peerId: peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func setPeerThreadCombinedState(peerId: PeerId, state: StoredPeerThreadCombinedState?) {
|
||||||
|
assert(!self.disposed)
|
||||||
|
return self.postbox!.setPeerThreadCombinedState(peerId: peerId, state: state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PostboxResult {
|
public enum PostboxResult {
|
||||||
@ -1398,6 +1408,8 @@ final class PostboxImpl {
|
|||||||
private var currentUpdatedNoticeEntryKeys = Set<NoticeEntryKey>()
|
private var currentUpdatedNoticeEntryKeys = Set<NoticeEntryKey>()
|
||||||
private var currentUpdatedCacheEntryKeys = Set<ItemCacheEntryId>()
|
private var currentUpdatedCacheEntryKeys = Set<ItemCacheEntryId>()
|
||||||
|
|
||||||
|
private var currentUpdatedPeerThreadCombinedStates = Set<PeerId>()
|
||||||
|
|
||||||
private var currentNeedsReindexUnreadCounters: Bool = false
|
private var currentNeedsReindexUnreadCounters: Bool = false
|
||||||
|
|
||||||
private let statePipe: ValuePipe<PostboxCoding> = ValuePipe()
|
private let statePipe: ValuePipe<PostboxCoding> = ValuePipe()
|
||||||
@ -1441,6 +1453,8 @@ final class PostboxImpl {
|
|||||||
let messageHistoryFailedTable: MessageHistoryFailedTable
|
let messageHistoryFailedTable: MessageHistoryFailedTable
|
||||||
let messageHistoryTagsTable: MessageHistoryTagsTable
|
let messageHistoryTagsTable: MessageHistoryTagsTable
|
||||||
let messageHistoryThreadsTable: MessageHistoryThreadsTable
|
let messageHistoryThreadsTable: MessageHistoryThreadsTable
|
||||||
|
let peerThreadCombinedStateTable: PeerThreadCombinedStateTable
|
||||||
|
let peerThreadsSummaryTable: PeerThreadsSummaryTable
|
||||||
let messageHistoryThreadTagsTable: MessageHistoryThreadTagsTable
|
let messageHistoryThreadTagsTable: MessageHistoryThreadTagsTable
|
||||||
let messageHistoryThreadHoleIndexTable: MessageHistoryThreadHoleIndexTable
|
let messageHistoryThreadHoleIndexTable: MessageHistoryThreadHoleIndexTable
|
||||||
let messageHistoryThreadReverseIndexTable: MessageHistoryThreadReverseIndexTable
|
let messageHistoryThreadReverseIndexTable: MessageHistoryThreadReverseIndexTable
|
||||||
@ -1519,10 +1533,12 @@ final class PostboxImpl {
|
|||||||
self.pendingMessageActionsTable = PendingMessageActionsTable(valueBox: self.valueBox, table: PendingMessageActionsTable.tableSpec(46), useCaches: useCaches, metadataTable: self.pendingMessageActionsMetadataTable)
|
self.pendingMessageActionsTable = PendingMessageActionsTable(valueBox: self.valueBox, table: PendingMessageActionsTable.tableSpec(46), useCaches: useCaches, metadataTable: self.pendingMessageActionsMetadataTable)
|
||||||
self.messageHistoryTagsTable = MessageHistoryTagsTable(valueBox: self.valueBox, table: MessageHistoryTagsTable.tableSpec(12), useCaches: useCaches, seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable)
|
self.messageHistoryTagsTable = MessageHistoryTagsTable(valueBox: self.valueBox, table: MessageHistoryTagsTable.tableSpec(12), useCaches: useCaches, seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable)
|
||||||
self.messageHistoryThreadsTable = MessageHistoryThreadsTable(valueBox: self.valueBox, table: MessageHistoryThreadsTable.tableSpec(62), useCaches: useCaches)
|
self.messageHistoryThreadsTable = MessageHistoryThreadsTable(valueBox: self.valueBox, table: MessageHistoryThreadsTable.tableSpec(62), useCaches: useCaches)
|
||||||
|
self.peerThreadCombinedStateTable = PeerThreadCombinedStateTable(valueBox: self.valueBox, table: PeerThreadCombinedStateTable.tableSpec(74), useCaches: useCaches)
|
||||||
|
self.peerThreadsSummaryTable = PeerThreadsSummaryTable(valueBox: self.valueBox, table: PeerThreadsSummaryTable.tableSpec(75), useCaches: useCaches)
|
||||||
self.messageHistoryThreadTagsTable = MessageHistoryThreadTagsTable(valueBox: self.valueBox, table: MessageHistoryThreadTagsTable.tableSpec(71), useCaches: useCaches, seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable)
|
self.messageHistoryThreadTagsTable = MessageHistoryThreadTagsTable(valueBox: self.valueBox, table: MessageHistoryThreadTagsTable.tableSpec(71), useCaches: useCaches, seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable)
|
||||||
self.messageHistoryThreadHoleIndexTable = MessageHistoryThreadHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadHoleIndexTable.tableSpec(63), useCaches: useCaches, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
self.messageHistoryThreadHoleIndexTable = MessageHistoryThreadHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadHoleIndexTable.tableSpec(63), useCaches: useCaches, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
||||||
self.messageHistoryThreadReverseIndexTable = MessageHistoryThreadReverseIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadReverseIndexTable.tableSpec(69), useCaches: useCaches)
|
self.messageHistoryThreadReverseIndexTable = MessageHistoryThreadReverseIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadReverseIndexTable.tableSpec(72), useCaches: useCaches)
|
||||||
self.messageHistoryThreadIndexTable = MessageHistoryThreadIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadIndexTable.tableSpec(70), reverseIndexTable: self.messageHistoryThreadReverseIndexTable, useCaches: useCaches)
|
self.messageHistoryThreadIndexTable = MessageHistoryThreadIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadIndexTable.tableSpec(73), reverseIndexTable: self.messageHistoryThreadReverseIndexTable, useCaches: useCaches)
|
||||||
self.globalMessageHistoryTagsTable = GlobalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(39), useCaches: useCaches)
|
self.globalMessageHistoryTagsTable = GlobalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(39), useCaches: useCaches)
|
||||||
self.localMessageHistoryTagsTable = LocalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(52), useCaches: useCaches)
|
self.localMessageHistoryTagsTable = LocalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(52), useCaches: useCaches)
|
||||||
self.messageHistoryIndexTable = MessageHistoryIndexTable(valueBox: self.valueBox, table: MessageHistoryIndexTable.tableSpec(4), useCaches: useCaches, messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, globalMessageIdsTable: self.globalMessageIdsTable, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
self.messageHistoryIndexTable = MessageHistoryIndexTable(valueBox: self.valueBox, table: MessageHistoryIndexTable.tableSpec(4), useCaches: useCaches, messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, globalMessageIdsTable: self.globalMessageIdsTable, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
||||||
@ -1578,6 +1594,8 @@ final class PostboxImpl {
|
|||||||
tables.append(self.messageHistoryFailedTable)
|
tables.append(self.messageHistoryFailedTable)
|
||||||
tables.append(self.messageHistoryTagsTable)
|
tables.append(self.messageHistoryTagsTable)
|
||||||
tables.append(self.messageHistoryThreadsTable)
|
tables.append(self.messageHistoryThreadsTable)
|
||||||
|
tables.append(self.peerThreadCombinedStateTable)
|
||||||
|
tables.append(self.peerThreadsSummaryTable)
|
||||||
tables.append(self.messageHistoryThreadTagsTable)
|
tables.append(self.messageHistoryThreadTagsTable)
|
||||||
tables.append(self.messageHistoryThreadHoleIndexTable)
|
tables.append(self.messageHistoryThreadHoleIndexTable)
|
||||||
tables.append(self.messageHistoryThreadReverseIndexTable)
|
tables.append(self.messageHistoryThreadReverseIndexTable)
|
||||||
@ -2016,11 +2034,13 @@ final class PostboxImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let transactionParticipationInTotalUnreadCountUpdates = self.peerNotificationSettingsTable.transactionParticipationInTotalUnreadCountUpdates(postbox: self, transaction: currentTransaction)
|
let transactionParticipationInTotalUnreadCountUpdates = self.peerNotificationSettingsTable.transactionParticipationInTotalUnreadCountUpdates(postbox: self, transaction: currentTransaction)
|
||||||
self.chatListIndexTable.commitWithTransaction(postbox: self, currentTransaction: currentTransaction, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, updatedPeers: updatedPeers, transactionParticipationInTotalUnreadCountUpdates: transactionParticipationInTotalUnreadCountUpdates, updatedTotalUnreadStates: &self.currentUpdatedTotalUnreadStates, updatedGroupTotalUnreadSummaries: &self.currentUpdatedGroupTotalUnreadSummaries, currentUpdatedGroupSummarySynchronizeOperations: &self.currentUpdatedGroupSummarySynchronizeOperations)
|
|
||||||
|
|
||||||
self.peerTable.commitDependentTables()
|
|
||||||
|
|
||||||
let updatedMessageThreadPeerIds = self.messageHistoryThreadIndexTable.replay(threadsTable: self.messageHistoryThreadsTable, namespaces: self.seedConfiguration.chatMessagesNamespaces, updatedIds: self.messageHistoryThreadsTable.updatedIds)
|
let updatedMessageThreadPeerIds = self.messageHistoryThreadIndexTable.replay(threadsTable: self.messageHistoryThreadsTable, namespaces: self.seedConfiguration.chatMessagesNamespaces, updatedIds: self.messageHistoryThreadsTable.updatedIds)
|
||||||
|
let alteredInitialPeerThreadsSummaries = self.peerThreadsSummaryTable.update(peerIds: updatedMessageThreadPeerIds.union(self.currentUpdatedPeerThreadCombinedStates), indexTable: self.messageHistoryThreadIndexTable, combinedStateTable: self.peerThreadCombinedStateTable)
|
||||||
|
|
||||||
|
self.chatListIndexTable.commitWithTransaction(postbox: self, currentTransaction: currentTransaction, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, updatedPeers: updatedPeers, transactionParticipationInTotalUnreadCountUpdates: transactionParticipationInTotalUnreadCountUpdates, alteredInitialPeerThreadsSummaries: alteredInitialPeerThreadsSummaries, updatedTotalUnreadStates: &self.currentUpdatedTotalUnreadStates, updatedGroupTotalUnreadSummaries: &self.currentUpdatedGroupTotalUnreadSummaries, currentUpdatedGroupSummarySynchronizeOperations: &self.currentUpdatedGroupSummarySynchronizeOperations)
|
||||||
|
|
||||||
|
self.peerTable.commitDependentTables()
|
||||||
|
|
||||||
if self.currentNeedsReindexUnreadCounters {
|
if self.currentNeedsReindexUnreadCounters {
|
||||||
self.reindexUnreadCounters(currentTransaction: currentTransaction)
|
self.reindexUnreadCounters(currentTransaction: currentTransaction)
|
||||||
@ -2028,7 +2048,7 @@ final class PostboxImpl {
|
|||||||
|
|
||||||
let updatedPeerTimeoutAttributes = self.peerTimeoutPropertiesTable.hasUpdates
|
let updatedPeerTimeoutAttributes = self.peerTimeoutPropertiesTable.hasUpdates
|
||||||
|
|
||||||
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadStates: self.currentUpdatedTotalUnreadStates, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId, updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds, updatedFailedMessageIds: self.messageHistoryFailedTable.updatedMessageIds, updatedGlobalNotificationSettings: self.currentNeedsReindexUnreadCounters, updatedPeerTimeoutAttributes: updatedPeerTimeoutAttributes, updatedMessageThreadPeerIds: updatedMessageThreadPeerIds)
|
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadStates: self.currentUpdatedTotalUnreadStates, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId, updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds, updatedFailedMessageIds: self.messageHistoryFailedTable.updatedMessageIds, updatedGlobalNotificationSettings: self.currentNeedsReindexUnreadCounters, updatedPeerTimeoutAttributes: updatedPeerTimeoutAttributes, updatedMessageThreadPeerIds: updatedMessageThreadPeerIds, updatedPeerThreadCombinedStates: self.currentUpdatedPeerThreadCombinedStates, updatedPeerThreadsSummaries: Set(alteredInitialPeerThreadsSummaries.keys))
|
||||||
var updatedTransactionState: Int64?
|
var updatedTransactionState: Int64?
|
||||||
var updatedMasterClientId: Int64?
|
var updatedMasterClientId: Int64?
|
||||||
if !transaction.isEmpty {
|
if !transaction.isEmpty {
|
||||||
@ -2059,6 +2079,7 @@ final class PostboxImpl {
|
|||||||
self.currentReplacedAdditionalChatListItems = nil
|
self.currentReplacedAdditionalChatListItems = nil
|
||||||
self.currentUpdatedNoticeEntryKeys.removeAll()
|
self.currentUpdatedNoticeEntryKeys.removeAll()
|
||||||
self.currentUpdatedCacheEntryKeys.removeAll()
|
self.currentUpdatedCacheEntryKeys.removeAll()
|
||||||
|
self.currentUpdatedPeerThreadCombinedStates.removeAll()
|
||||||
self.currentUpdatedMasterClientId = nil
|
self.currentUpdatedMasterClientId = nil
|
||||||
self.currentUpdatedPeerNotificationSettings.removeAll()
|
self.currentUpdatedPeerNotificationSettings.removeAll()
|
||||||
self.currentUpdatedPeerNotificationBehaviorTimestamps.removeAll()
|
self.currentUpdatedPeerNotificationBehaviorTimestamps.removeAll()
|
||||||
@ -3685,6 +3706,11 @@ final class PostboxImpl {
|
|||||||
self.peerTimeoutPropertiesTable.remove(peerId: peerId, timestamp: timestamp)
|
self.peerTimeoutPropertiesTable.remove(peerId: peerId, timestamp: timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate func setPeerThreadCombinedState(peerId: PeerId, state: StoredPeerThreadCombinedState?) {
|
||||||
|
self.currentUpdatedPeerThreadCombinedStates.insert(peerId)
|
||||||
|
self.peerThreadCombinedStateTable.set(peerId: peerId, state: state)
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate func reindexUnreadCounters(currentTransaction: Transaction) {
|
fileprivate func reindexUnreadCounters(currentTransaction: Transaction) {
|
||||||
self.groupMessageStatsTable.removeAll()
|
self.groupMessageStatsTable.removeAll()
|
||||||
let _ = CFAbsoluteTimeGetCurrent()
|
let _ = CFAbsoluteTimeGetCurrent()
|
||||||
|
|||||||
@ -45,6 +45,8 @@ final class PostboxTransaction {
|
|||||||
let updatedGlobalNotificationSettings: Bool
|
let updatedGlobalNotificationSettings: Bool
|
||||||
let updatedPeerTimeoutAttributes: Bool
|
let updatedPeerTimeoutAttributes: Bool
|
||||||
let updatedMessageThreadPeerIds: Set<PeerId>
|
let updatedMessageThreadPeerIds: Set<PeerId>
|
||||||
|
let updatedPeerThreadCombinedStates: Set<PeerId>
|
||||||
|
let updatedPeerThreadsSummaries: Set<PeerId>
|
||||||
|
|
||||||
var isEmpty: Bool {
|
var isEmpty: Bool {
|
||||||
if currentUpdatedState != nil {
|
if currentUpdatedState != nil {
|
||||||
@ -179,10 +181,16 @@ final class PostboxTransaction {
|
|||||||
if !self.updatedMessageThreadPeerIds.isEmpty {
|
if !self.updatedMessageThreadPeerIds.isEmpty {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if !self.updatedPeerThreadCombinedStates.isEmpty {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !self.updatedPeerThreadsSummaries.isEmpty {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: Set<PeerId>, currentUpdatedTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState], currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, replacedAdditionalChatListItems: [AdditionalChatListItem]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set<PeerId>, updatedFailedMessageIds: Set<MessageId>, updatedGlobalNotificationSettings: Bool, updatedPeerTimeoutAttributes: Bool, updatedMessageThreadPeerIds: Set<PeerId>) {
|
init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: Set<PeerId>, currentUpdatedTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState], currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, replacedAdditionalChatListItems: [AdditionalChatListItem]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set<PeerId>, updatedFailedMessageIds: Set<MessageId>, updatedGlobalNotificationSettings: Bool, updatedPeerTimeoutAttributes: Bool, updatedMessageThreadPeerIds: Set<PeerId>, updatedPeerThreadCombinedStates: Set<PeerId>, updatedPeerThreadsSummaries: Set<PeerId>) {
|
||||||
self.currentUpdatedState = currentUpdatedState
|
self.currentUpdatedState = currentUpdatedState
|
||||||
self.currentPeerHoleOperations = currentPeerHoleOperations
|
self.currentPeerHoleOperations = currentPeerHoleOperations
|
||||||
self.currentOperationsByPeerId = currentOperationsByPeerId
|
self.currentOperationsByPeerId = currentOperationsByPeerId
|
||||||
@ -226,5 +234,7 @@ final class PostboxTransaction {
|
|||||||
self.updatedGlobalNotificationSettings = updatedGlobalNotificationSettings
|
self.updatedGlobalNotificationSettings = updatedGlobalNotificationSettings
|
||||||
self.updatedPeerTimeoutAttributes = updatedPeerTimeoutAttributes
|
self.updatedPeerTimeoutAttributes = updatedPeerTimeoutAttributes
|
||||||
self.updatedMessageThreadPeerIds = updatedMessageThreadPeerIds
|
self.updatedMessageThreadPeerIds = updatedMessageThreadPeerIds
|
||||||
|
self.updatedPeerThreadCombinedStates = updatedPeerThreadCombinedStates
|
||||||
|
self.updatedPeerThreadsSummaries = updatedPeerThreadsSummaries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,6 +65,7 @@ public final class SeedConfiguration {
|
|||||||
public let existingGlobalMessageTags: GlobalMessageTags
|
public let existingGlobalMessageTags: GlobalMessageTags
|
||||||
public let peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace]
|
public let peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace]
|
||||||
public let peerSummaryCounterTags: (Peer, Bool) -> PeerSummaryCounterTags
|
public let peerSummaryCounterTags: (Peer, Bool) -> PeerSummaryCounterTags
|
||||||
|
public let peerSummaryIsThreadBased: (Peer) -> Bool
|
||||||
public let additionalChatListIndexNamespace: MessageId.Namespace?
|
public let additionalChatListIndexNamespace: MessageId.Namespace?
|
||||||
public let messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>
|
public let messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>
|
||||||
public let defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState]
|
public let defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState]
|
||||||
@ -87,6 +88,7 @@ public final class SeedConfiguration {
|
|||||||
existingGlobalMessageTags: GlobalMessageTags,
|
existingGlobalMessageTags: GlobalMessageTags,
|
||||||
peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace],
|
peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace],
|
||||||
peerSummaryCounterTags: @escaping (Peer, Bool) -> PeerSummaryCounterTags,
|
peerSummaryCounterTags: @escaping (Peer, Bool) -> PeerSummaryCounterTags,
|
||||||
|
peerSummaryIsThreadBased: @escaping (Peer) -> Bool,
|
||||||
additionalChatListIndexNamespace: MessageId.Namespace?,
|
additionalChatListIndexNamespace: MessageId.Namespace?,
|
||||||
messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>,
|
messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>,
|
||||||
defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState],
|
defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState],
|
||||||
@ -104,6 +106,7 @@ public final class SeedConfiguration {
|
|||||||
self.existingGlobalMessageTags = existingGlobalMessageTags
|
self.existingGlobalMessageTags = existingGlobalMessageTags
|
||||||
self.peerNamespacesRequiringMessageTextIndex = peerNamespacesRequiringMessageTextIndex
|
self.peerNamespacesRequiringMessageTextIndex = peerNamespacesRequiringMessageTextIndex
|
||||||
self.peerSummaryCounterTags = peerSummaryCounterTags
|
self.peerSummaryCounterTags = peerSummaryCounterTags
|
||||||
|
self.peerSummaryIsThreadBased = peerSummaryIsThreadBased
|
||||||
self.additionalChatListIndexNamespace = additionalChatListIndexNamespace
|
self.additionalChatListIndexNamespace = additionalChatListIndexNamespace
|
||||||
self.messageNamespacesRequiringGroupStatsValidation = messageNamespacesRequiringGroupStatsValidation
|
self.messageNamespacesRequiringGroupStatsValidation = messageNamespacesRequiringGroupStatsValidation
|
||||||
self.defaultMessageNamespaceReadStates = defaultMessageNamespaceReadStates
|
self.defaultMessageNamespaceReadStates = defaultMessageNamespaceReadStates
|
||||||
|
|||||||
@ -219,7 +219,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
|||||||
var items: [ChatListItem] = []
|
var items: [ChatListItem] = []
|
||||||
|
|
||||||
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
|
||||||
}, activateChatPreview: { _, _, gesture, _ in
|
}, activateChatPreview: { _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in })
|
}, present: { _ in })
|
||||||
@ -283,7 +283,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
|||||||
ignoreUnreadBadge: false,
|
ignoreUnreadBadge: false,
|
||||||
displayAsMessage: false,
|
displayAsMessage: false,
|
||||||
hasFailedMessages: false,
|
hasFailedMessages: false,
|
||||||
forumThreadTitle: nil
|
forumTopicData: nil
|
||||||
),
|
),
|
||||||
editing: false,
|
editing: false,
|
||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
|
|||||||
@ -839,7 +839,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
var items: [ChatListItem] = []
|
var items: [ChatListItem] = []
|
||||||
|
|
||||||
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
|
||||||
}, activateChatPreview: { _, _, gesture, _ in
|
}, activateChatPreview: { _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in
|
}, present: { _ in
|
||||||
@ -903,7 +903,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
ignoreUnreadBadge: false,
|
ignoreUnreadBadge: false,
|
||||||
displayAsMessage: false,
|
displayAsMessage: false,
|
||||||
hasFailedMessages: false,
|
hasFailedMessages: false,
|
||||||
forumThreadTitle: nil
|
forumTopicData: nil
|
||||||
),
|
),
|
||||||
editing: false,
|
editing: false,
|
||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
|
|||||||
@ -363,7 +363,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
var items: [ChatListItem] = []
|
var items: [ChatListItem] = []
|
||||||
|
|
||||||
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
|
||||||
}, activateChatPreview: { _, _, gesture, _ in
|
}, activateChatPreview: { _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in
|
}, present: { _ in
|
||||||
@ -426,7 +426,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
ignoreUnreadBadge: false,
|
ignoreUnreadBadge: false,
|
||||||
displayAsMessage: false,
|
displayAsMessage: false,
|
||||||
hasFailedMessages: false,
|
hasFailedMessages: false,
|
||||||
forumThreadTitle: nil
|
forumTopicData: nil
|
||||||
),
|
),
|
||||||
editing: false,
|
editing: false,
|
||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
|
|||||||
@ -55,14 +55,102 @@ public extension EngineMessageHistoryThread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct MessageHistoryThreadData: Codable, Equatable {
|
public struct MessageHistoryThreadData: Codable, Equatable {
|
||||||
|
private enum CodingKeys: CodingKey {
|
||||||
|
case creationDate
|
||||||
|
case isOwnedByMe
|
||||||
|
case author
|
||||||
|
case info
|
||||||
|
case incomingUnreadCount
|
||||||
|
case maxIncomingReadId
|
||||||
|
case maxKnownMessageId
|
||||||
|
case maxOutgoingReadId
|
||||||
|
case isClosed
|
||||||
|
case notificationSettings
|
||||||
|
}
|
||||||
|
|
||||||
public var creationDate: Int32
|
public var creationDate: Int32
|
||||||
|
public var isOwnedByMe: Bool
|
||||||
public var author: PeerId
|
public var author: PeerId
|
||||||
public var info: EngineMessageHistoryThread.Info
|
public var info: EngineMessageHistoryThread.Info
|
||||||
public var incomingUnreadCount: Int32
|
public var incomingUnreadCount: Int32
|
||||||
public var maxIncomingReadId: Int32
|
public var maxIncomingReadId: Int32
|
||||||
public var maxKnownMessageId: Int32
|
public var maxKnownMessageId: Int32
|
||||||
public var maxOutgoingReadId: Int32
|
public var maxOutgoingReadId: Int32
|
||||||
|
public var isClosed: Bool
|
||||||
public var notificationSettings: TelegramPeerNotificationSettings
|
public var notificationSettings: TelegramPeerNotificationSettings
|
||||||
|
|
||||||
|
public init(
|
||||||
|
creationDate: Int32,
|
||||||
|
isOwnedByMe: Bool,
|
||||||
|
author: PeerId,
|
||||||
|
info: EngineMessageHistoryThread.Info,
|
||||||
|
incomingUnreadCount: Int32,
|
||||||
|
maxIncomingReadId: Int32,
|
||||||
|
maxKnownMessageId: Int32,
|
||||||
|
maxOutgoingReadId: Int32,
|
||||||
|
isClosed: Bool,
|
||||||
|
notificationSettings: TelegramPeerNotificationSettings
|
||||||
|
) {
|
||||||
|
self.creationDate = creationDate
|
||||||
|
self.isOwnedByMe = isOwnedByMe
|
||||||
|
self.author = author
|
||||||
|
self.info = info
|
||||||
|
self.incomingUnreadCount = incomingUnreadCount
|
||||||
|
self.maxIncomingReadId = maxIncomingReadId
|
||||||
|
self.maxKnownMessageId = maxKnownMessageId
|
||||||
|
self.maxOutgoingReadId = maxOutgoingReadId
|
||||||
|
self.isClosed = isClosed
|
||||||
|
self.notificationSettings = notificationSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.creationDate = try container.decode(Int32.self, forKey: .creationDate)
|
||||||
|
self.isOwnedByMe = try container.decodeIfPresent(Bool.self, forKey: .isOwnedByMe) ?? false
|
||||||
|
self.author = try container.decode(PeerId.self, forKey: .author)
|
||||||
|
self.info = try container.decode(EngineMessageHistoryThread.Info.self, forKey: .info)
|
||||||
|
self.incomingUnreadCount = try container.decode(Int32.self, forKey: .incomingUnreadCount)
|
||||||
|
self.maxIncomingReadId = try container.decode(Int32.self, forKey: .maxIncomingReadId)
|
||||||
|
self.maxKnownMessageId = try container.decode(Int32.self, forKey: .maxKnownMessageId)
|
||||||
|
self.maxOutgoingReadId = try container.decode(Int32.self, forKey: .maxOutgoingReadId)
|
||||||
|
self.isClosed = try container.decodeIfPresent(Bool.self, forKey: .isClosed) ?? false
|
||||||
|
self.notificationSettings = try container.decode(TelegramPeerNotificationSettings.self, forKey: .notificationSettings)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.creationDate, forKey: .creationDate)
|
||||||
|
try container.encode(self.isOwnedByMe, forKey: .isOwnedByMe)
|
||||||
|
try container.encode(self.author, forKey: .author)
|
||||||
|
try container.encode(self.info, forKey: .info)
|
||||||
|
try container.encode(self.incomingUnreadCount, forKey: .incomingUnreadCount)
|
||||||
|
try container.encode(self.maxIncomingReadId, forKey: .maxIncomingReadId)
|
||||||
|
try container.encode(self.maxKnownMessageId, forKey: .maxKnownMessageId)
|
||||||
|
try container.encode(self.maxOutgoingReadId, forKey: .maxOutgoingReadId)
|
||||||
|
try container.encode(self.isClosed, forKey: .isClosed)
|
||||||
|
try container.encode(self.notificationSettings, forKey: .notificationSettings)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension StoredMessageHistoryThreadInfo {
|
||||||
|
init?(_ data: MessageHistoryThreadData) {
|
||||||
|
guard let entry = CodableEntry(data) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var mutedUntil: Int32?
|
||||||
|
switch data.notificationSettings.muteState {
|
||||||
|
case let .muted(until):
|
||||||
|
mutedUntil = until
|
||||||
|
case .unmuted, .default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
self.init(data: entry, summary: Summary(
|
||||||
|
totalUnreadCount: data.incomingUnreadCount,
|
||||||
|
mutedUntil: mutedUntil
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StoreMessageHistoryThreadData {
|
struct StoreMessageHistoryThreadData {
|
||||||
@ -165,13 +253,13 @@ func _internal_editForumChannelTopic(account: Account, peerId: PeerId, threadId:
|
|||||||
account.stateManager.addUpdates(result)
|
account.stateManager.addUpdates(result)
|
||||||
|
|
||||||
return account.postbox.transaction { transaction -> Void in
|
return account.postbox.transaction { transaction -> Void in
|
||||||
if let initialData = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) {
|
if let initialData = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
var data = initialData
|
var data = initialData
|
||||||
|
|
||||||
data.info = EngineMessageHistoryThread.Info(title: title, icon: iconFileId, iconColor: data.info.iconColor)
|
data.info = EngineMessageHistoryThread.Info(title: title, icon: iconFileId, iconColor: data.info.iconColor)
|
||||||
|
|
||||||
if data != initialData {
|
if data != initialData {
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,9 +356,10 @@ func _internal_loadMessageHistoryThreads(account: Account, peerId: PeerId) -> Si
|
|||||||
|
|
||||||
for topic in topics {
|
for topic in topics {
|
||||||
switch topic {
|
switch topic {
|
||||||
case let .forumTopic(_, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings):
|
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings):
|
||||||
let data = MessageHistoryThreadData(
|
let data = MessageHistoryThreadData(
|
||||||
creationDate: date,
|
creationDate: date,
|
||||||
|
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||||
author: fromId.peerId,
|
author: fromId.peerId,
|
||||||
info: EngineMessageHistoryThread.Info(
|
info: EngineMessageHistoryThread.Info(
|
||||||
title: title,
|
title: title,
|
||||||
@ -281,9 +370,10 @@ func _internal_loadMessageHistoryThreads(account: Account, peerId: PeerId) -> Si
|
|||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
isClosed: (flags & (1 << 2)) != 0,
|
||||||
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||||
)
|
)
|
||||||
guard let info = CodableEntry(data) else {
|
guard let info = StoredMessageHistoryThreadInfo(data) else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: Int64(id), info: info)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: Int64(id), info: info)
|
||||||
|
|||||||
@ -1694,12 +1694,13 @@ func resolveForumThreads(postbox: Postbox, network: Network, state: AccountMutab
|
|||||||
|
|
||||||
for topic in topics {
|
for topic in topics {
|
||||||
switch topic {
|
switch topic {
|
||||||
case let .forumTopic(_, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings):
|
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings):
|
||||||
state.operations.append(.ResetForumTopic(
|
state.operations.append(.ResetForumTopic(
|
||||||
topicId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id),
|
topicId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id),
|
||||||
data: StoreMessageHistoryThreadData(
|
data: StoreMessageHistoryThreadData(
|
||||||
data: MessageHistoryThreadData(
|
data: MessageHistoryThreadData(
|
||||||
creationDate: date,
|
creationDate: date,
|
||||||
|
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||||
author: fromId.peerId,
|
author: fromId.peerId,
|
||||||
info: EngineMessageHistoryThread.Info(
|
info: EngineMessageHistoryThread.Info(
|
||||||
title: title,
|
title: title,
|
||||||
@ -1710,6 +1711,7 @@ func resolveForumThreads(postbox: Postbox, network: Network, state: AccountMutab
|
|||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
isClosed: (flags & (1 << 2)) != 0,
|
||||||
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||||
),
|
),
|
||||||
topMessageId: topMessage,
|
topMessageId: topMessage,
|
||||||
@ -1790,9 +1792,10 @@ func resolveForumThreads(postbox: Postbox, network: Network, ids: [MessageId]) -
|
|||||||
|
|
||||||
for topic in topics {
|
for topic in topics {
|
||||||
switch topic {
|
switch topic {
|
||||||
case let .forumTopic(_, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings):
|
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings):
|
||||||
let data = MessageHistoryThreadData(
|
let data = MessageHistoryThreadData(
|
||||||
creationDate: date,
|
creationDate: date,
|
||||||
|
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||||
author: fromId.peerId,
|
author: fromId.peerId,
|
||||||
info: EngineMessageHistoryThread.Info(
|
info: EngineMessageHistoryThread.Info(
|
||||||
title: title,
|
title: title,
|
||||||
@ -1803,9 +1806,10 @@ func resolveForumThreads(postbox: Postbox, network: Network, ids: [MessageId]) -
|
|||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
isClosed: (flags & (1 << 2)) != 0,
|
||||||
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||||
)
|
)
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: Int64(id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: Int64(id), info: entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1906,10 +1910,11 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
|||||||
|
|
||||||
for topic in topics {
|
for topic in topics {
|
||||||
switch topic {
|
switch topic {
|
||||||
case let .forumTopic(_, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings):
|
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings):
|
||||||
fetchedChatList.threadInfos[MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)] = StoreMessageHistoryThreadData(
|
fetchedChatList.threadInfos[MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)] = StoreMessageHistoryThreadData(
|
||||||
data: MessageHistoryThreadData(
|
data: MessageHistoryThreadData(
|
||||||
creationDate: date,
|
creationDate: date,
|
||||||
|
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||||
author: fromId.peerId,
|
author: fromId.peerId,
|
||||||
info: EngineMessageHistoryThread.Info(
|
info: EngineMessageHistoryThread.Info(
|
||||||
title: title,
|
title: title,
|
||||||
@ -1920,6 +1925,7 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
|||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
isClosed: (flags & (1 << 2)) != 0,
|
||||||
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||||
),
|
),
|
||||||
topMessageId: topMessage,
|
topMessageId: topMessage,
|
||||||
@ -2994,7 +3000,7 @@ func replayFinalState(
|
|||||||
if let action = media as? TelegramMediaAction {
|
if let action = media as? TelegramMediaAction {
|
||||||
switch action.action {
|
switch action.action {
|
||||||
case let .topicEdited(components):
|
case let .topicEdited(components):
|
||||||
if let initialData = transaction.getMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) {
|
if let initialData = transaction.getMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
var data = initialData
|
var data = initialData
|
||||||
|
|
||||||
for component in components {
|
for component in components {
|
||||||
@ -3009,7 +3015,7 @@ func replayFinalState(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if data != initialData {
|
if data != initialData {
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId, info: entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3028,12 +3034,12 @@ func replayFinalState(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if message.flags.contains(.Incoming) {
|
if message.flags.contains(.Incoming) {
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
if id.id >= data.maxKnownMessageId {
|
if id.id >= data.maxKnownMessageId {
|
||||||
data.maxKnownMessageId = id.id
|
data.maxKnownMessageId = id.id
|
||||||
data.incomingUnreadCount += 1
|
data.incomingUnreadCount += 1
|
||||||
|
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId, info: entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3297,7 +3303,7 @@ func replayFinalState(
|
|||||||
updatedIncomingThreadReadStates[threadMessageId] = readMaxId
|
updatedIncomingThreadReadStates[threadMessageId] = readMaxId
|
||||||
}
|
}
|
||||||
if let channel = transaction.getPeer(threadMessageId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
if let channel = transaction.getPeer(threadMessageId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id))?.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id))?.data.get(MessageHistoryThreadData.self) {
|
||||||
if readMaxId > data.maxIncomingReadId {
|
if readMaxId > data.maxIncomingReadId {
|
||||||
if let toIndex = transaction.getMessage(MessageId(peerId: threadMessageId.peerId, namespace: threadMessageId.namespace, id: readMaxId))?.index {
|
if let toIndex = transaction.getMessage(MessageId(peerId: threadMessageId.peerId, namespace: threadMessageId.namespace, id: readMaxId))?.index {
|
||||||
if let count = transaction.getThreadMessageCount(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), namespace: threadMessageId.namespace, fromIdExclusive: data.maxIncomingReadId, toIndex: toIndex) {
|
if let count = transaction.getThreadMessageCount(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), namespace: threadMessageId.namespace, fromIdExclusive: data.maxIncomingReadId, toIndex: toIndex) {
|
||||||
@ -3307,7 +3313,7 @@ func replayFinalState(
|
|||||||
|
|
||||||
data.maxKnownMessageId = max(data.maxKnownMessageId, readMaxId)
|
data.maxKnownMessageId = max(data.maxKnownMessageId, readMaxId)
|
||||||
|
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3338,11 +3344,11 @@ func replayFinalState(
|
|||||||
updatedOutgoingThreadReadStates[threadMessageId] = readMaxId
|
updatedOutgoingThreadReadStates[threadMessageId] = readMaxId
|
||||||
}
|
}
|
||||||
if let channel = transaction.getPeer(threadMessageId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
if let channel = transaction.getPeer(threadMessageId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id))?.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id))?.data.get(MessageHistoryThreadData.self) {
|
||||||
if readMaxId >= data.maxOutgoingReadId {
|
if readMaxId >= data.maxOutgoingReadId {
|
||||||
data.maxOutgoingReadId = readMaxId
|
data.maxOutgoingReadId = readMaxId
|
||||||
|
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3954,7 +3960,7 @@ func replayFinalState(
|
|||||||
case let .ResetForumTopic(topicId, data, pts):
|
case let .ResetForumTopic(topicId, data, pts):
|
||||||
if finalState.state.resetForumTopicLists[topicId.peerId] == nil {
|
if finalState.state.resetForumTopicLists[topicId.peerId] == nil {
|
||||||
let _ = pts
|
let _ = pts
|
||||||
if let entry = CodableEntry(data.data) {
|
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: topicId.peerId, threadId: Int64(topicId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: topicId.peerId, threadId: Int64(topicId.id), info: entry)
|
||||||
} else {
|
} else {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
|
|||||||
@ -1520,14 +1520,14 @@ public final class AccountViewTracker {
|
|||||||
signal = combineLatest(signal, postbox.combinedView(keys: [viewKey]))
|
signal = combineLatest(signal, postbox.combinedView(keys: [viewKey]))
|
||||||
|> map { view, additionalViews -> (MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?) in
|
|> map { view, additionalViews -> (MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?) in
|
||||||
var view = view
|
var view = view
|
||||||
if let threadInfo = additionalViews.views[viewKey] as? MessageHistoryThreadInfoView, let data = threadInfo.info?.get(MessageHistoryThreadData.self) {
|
if let threadInfo = additionalViews.views[viewKey] as? MessageHistoryThreadInfoView, let data = threadInfo.info?.data.get(MessageHistoryThreadData.self) {
|
||||||
let readState = CombinedPeerReadState(states: [(Namespaces.Message.Cloud, .idBased(maxIncomingReadId: data.maxIncomingReadId, maxOutgoingReadId: data.maxOutgoingReadId, maxKnownId: data.maxKnownMessageId, count: data.incomingUnreadCount, markedUnread: false))])
|
let readState = CombinedPeerReadState(states: [(Namespaces.Message.Cloud, .idBased(maxIncomingReadId: data.maxIncomingReadId, maxOutgoingReadId: data.maxOutgoingReadId, maxKnownId: data.maxKnownMessageId, count: data.incomingUnreadCount, markedUnread: false))])
|
||||||
|
|
||||||
let fixed = fixedReadStates.modify { current in
|
let fixed = fixedReadStates.modify { current in
|
||||||
if let current = current {
|
if let current = current {
|
||||||
return current
|
return current
|
||||||
} else {
|
} else {
|
||||||
return view.0.fixedReadStates ?? .peer([peerId: readState])
|
return /*view.0.fixedReadStates ?? */.peer([peerId: readState])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1701,8 +1701,8 @@ public final class AccountViewTracker {
|
|||||||
if let account = self.account {
|
if let account = self.account {
|
||||||
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>
|
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>
|
||||||
if let peerId = chatLocation.peerId, let threadId = chatLocation.threadId, tagMask == nil {
|
if let peerId = chatLocation.peerId, let threadId = chatLocation.threadId, tagMask == nil {
|
||||||
return account.postbox.transaction { transaction -> MessageHistoryThreadData? in
|
signal = account.postbox.transaction { transaction -> MessageHistoryThreadData? in
|
||||||
return transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self)
|
return transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self)
|
||||||
}
|
}
|
||||||
|> mapToSignal { threadInfo -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in
|
|> mapToSignal { threadInfo -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in
|
||||||
if let threadInfo = threadInfo {
|
if let threadInfo = threadInfo {
|
||||||
|
|||||||
@ -751,7 +751,7 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
|
|||||||
})
|
})
|
||||||
|
|
||||||
for (threadMessageId, data) in fetchedChats.threadInfos {
|
for (threadMessageId, data) in fetchedChats.threadInfos {
|
||||||
if let entry = CodableEntry(data.data) {
|
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
||||||
}
|
}
|
||||||
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: data.unreadMentionCount, maxId: data.topMessageId)
|
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: data.unreadMentionCount, maxId: data.topMessageId)
|
||||||
|
|||||||
@ -98,7 +98,7 @@ func pushPeerNotificationSettings(postbox: Postbox, network: Network, peerId: Pe
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let threadId = threadId {
|
if let threadId = threadId {
|
||||||
if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) {
|
if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
let settings = data.notificationSettings
|
let settings = data.notificationSettings
|
||||||
|
|
||||||
let showPreviews: Api.Bool?
|
let showPreviews: Api.Bool?
|
||||||
|
|||||||
@ -66,15 +66,27 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
|||||||
return .channel
|
return .channel
|
||||||
case .group:
|
case .group:
|
||||||
if channel.flags.contains(.isForum) {
|
if channel.flags.contains(.isForum) {
|
||||||
return []
|
return .group
|
||||||
|
} else {
|
||||||
|
return .group
|
||||||
}
|
}
|
||||||
return .group
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
return .nonContact
|
return .nonContact
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
peerSummaryIsThreadBased: { peer in
|
||||||
|
if let channel = peer as? TelegramChannel {
|
||||||
|
if channel.flags.contains(.isForum) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
additionalChatListIndexNamespace: Namespaces.Message.Cloud,
|
additionalChatListIndexNamespace: Namespaces.Message.Cloud,
|
||||||
messageNamespacesRequiringGroupStatsValidation: [Namespaces.Message.Cloud],
|
messageNamespacesRequiringGroupStatsValidation: [Namespaces.Message.Cloud],
|
||||||
defaultMessageNamespaceReadStates: [Namespaces.Message.Local: .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false)],
|
defaultMessageNamespaceReadStates: [Namespaces.Message.Local: .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false)],
|
||||||
|
|||||||
@ -278,7 +278,7 @@ public extension TelegramEngine.EngineData.Item {
|
|||||||
guard let view = view as? MessageHistoryThreadInfoView else {
|
guard let view = view as? MessageHistoryThreadInfoView else {
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
}
|
}
|
||||||
guard let data = view.info?.get(MessageHistoryThreadData.self) else {
|
guard let data = view.info?.data.get(MessageHistoryThreadData.self) else {
|
||||||
return EnginePeer.NotificationSettings(TelegramPeerNotificationSettings.defaultSettings)
|
return EnginePeer.NotificationSettings(TelegramPeerNotificationSettings.defaultSettings)
|
||||||
}
|
}
|
||||||
return EnginePeer.NotificationSettings(data.notificationSettings)
|
return EnginePeer.NotificationSettings(data.notificationSettings)
|
||||||
|
|||||||
@ -27,6 +27,16 @@ public final class EngineChatList: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct ForumTopicData: Equatable {
|
||||||
|
public var title: String
|
||||||
|
public var maxOutgoingReadMessageId: EngineMessage.Id
|
||||||
|
|
||||||
|
public init(title: String, maxOutgoingReadMessageId: EngineMessage.Id) {
|
||||||
|
self.title = title
|
||||||
|
self.maxOutgoingReadMessageId = maxOutgoingReadMessageId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final class Item: Equatable {
|
public final class Item: Equatable {
|
||||||
public enum Id: Hashable {
|
public enum Id: Hashable {
|
||||||
case chatList(EnginePeer.Id)
|
case chatList(EnginePeer.Id)
|
||||||
@ -77,7 +87,7 @@ public final class EngineChatList: Equatable {
|
|||||||
public let presence: EnginePeer.Presence?
|
public let presence: EnginePeer.Presence?
|
||||||
public let hasUnseenMentions: Bool
|
public let hasUnseenMentions: Bool
|
||||||
public let hasUnseenReactions: Bool
|
public let hasUnseenReactions: Bool
|
||||||
public let forumTopicTitle: String?
|
public let forumTopicData: ForumTopicData?
|
||||||
public let hasFailed: Bool
|
public let hasFailed: Bool
|
||||||
public let isContact: Bool
|
public let isContact: Bool
|
||||||
|
|
||||||
@ -93,7 +103,7 @@ public final class EngineChatList: Equatable {
|
|||||||
presence: EnginePeer.Presence?,
|
presence: EnginePeer.Presence?,
|
||||||
hasUnseenMentions: Bool,
|
hasUnseenMentions: Bool,
|
||||||
hasUnseenReactions: Bool,
|
hasUnseenReactions: Bool,
|
||||||
forumTopicTitle: String?,
|
forumTopicData: ForumTopicData?,
|
||||||
hasFailed: Bool,
|
hasFailed: Bool,
|
||||||
isContact: Bool
|
isContact: Bool
|
||||||
) {
|
) {
|
||||||
@ -108,7 +118,7 @@ public final class EngineChatList: Equatable {
|
|||||||
self.presence = presence
|
self.presence = presence
|
||||||
self.hasUnseenMentions = hasUnseenMentions
|
self.hasUnseenMentions = hasUnseenMentions
|
||||||
self.hasUnseenReactions = hasUnseenReactions
|
self.hasUnseenReactions = hasUnseenReactions
|
||||||
self.forumTopicTitle = forumTopicTitle
|
self.forumTopicData = forumTopicData
|
||||||
self.hasFailed = hasFailed
|
self.hasFailed = hasFailed
|
||||||
self.isContact = isContact
|
self.isContact = isContact
|
||||||
}
|
}
|
||||||
@ -147,7 +157,7 @@ public final class EngineChatList: Equatable {
|
|||||||
if lhs.hasUnseenReactions != rhs.hasUnseenReactions {
|
if lhs.hasUnseenReactions != rhs.hasUnseenReactions {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.forumTopicTitle != rhs.forumTopicTitle {
|
if lhs.forumTopicData != rhs.forumTopicData {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.hasFailed != rhs.hasFailed {
|
if lhs.hasFailed != rhs.hasFailed {
|
||||||
@ -383,16 +393,12 @@ extension EngineChatList.Item {
|
|||||||
hasUnseenReactions = (info.tagSummaryCount ?? 0) != 0// > (info.actionsSummaryCount ?? 0)
|
hasUnseenReactions = (info.tagSummaryCount ?? 0) != 0// > (info.actionsSummaryCount ?? 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var forumTopicTitle: String?
|
var forumTopicDataValue: EngineChatList.ForumTopicData?
|
||||||
if let forumTopicData = forumTopicData?.get(MessageHistoryThreadData.self) {
|
if let forumTopicData = forumTopicData?.data.get(MessageHistoryThreadData.self) {
|
||||||
forumTopicTitle = forumTopicData.info.title
|
forumTopicDataValue = EngineChatList.ForumTopicData(title: forumTopicData.info.title, maxOutgoingReadMessageId: MessageId(peerId: index.messageIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: forumTopicData.maxOutgoingReadId))
|
||||||
}
|
}
|
||||||
|
|
||||||
var readCounters = readState.flatMap(EnginePeerReadCounters.init)
|
let readCounters = readState.flatMap(EnginePeerReadCounters.init)
|
||||||
|
|
||||||
if let channel = renderedPeer.peer as? TelegramChannel, channel.flags.contains(.isForum) {
|
|
||||||
readCounters = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
self.init(
|
self.init(
|
||||||
id: .chatList(index.messageIndex.id.peerId),
|
id: .chatList(index.messageIndex.id.peerId),
|
||||||
@ -406,7 +412,7 @@ extension EngineChatList.Item {
|
|||||||
presence: presence.flatMap(EnginePeer.Presence.init),
|
presence: presence.flatMap(EnginePeer.Presence.init),
|
||||||
hasUnseenMentions: hasUnseenMentions,
|
hasUnseenMentions: hasUnseenMentions,
|
||||||
hasUnseenReactions: hasUnseenReactions,
|
hasUnseenReactions: hasUnseenReactions,
|
||||||
forumTopicTitle: forumTopicTitle,
|
forumTopicData: forumTopicDataValue,
|
||||||
hasFailed: hasFailed,
|
hasFailed: hasFailed,
|
||||||
isContact: isContact
|
isContact: isContact
|
||||||
)
|
)
|
||||||
|
|||||||
@ -337,7 +337,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
let account = self.account
|
let account = self.account
|
||||||
|
|
||||||
let _ = (self.account.postbox.transaction { transaction -> (Api.InputPeer?, MessageId?, Int?) in
|
let _ = (self.account.postbox.transaction { transaction -> (Api.InputPeer?, MessageId?, Int?) in
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: messageId.peerId, threadId: Int64(messageId.id))?.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: messageId.peerId, threadId: Int64(messageId.id))?.data.get(MessageHistoryThreadData.self) {
|
||||||
if messageIndex.id.id >= data.maxIncomingReadId {
|
if messageIndex.id.id >= data.maxIncomingReadId {
|
||||||
if let count = transaction.getThreadMessageCount(peerId: messageId.peerId, threadId: Int64(messageId.id), namespace: messageId.namespace, fromIdExclusive: data.maxIncomingReadId, toIndex: messageIndex) {
|
if let count = transaction.getThreadMessageCount(peerId: messageId.peerId, threadId: Int64(messageId.id), namespace: messageId.namespace, fromIdExclusive: data.maxIncomingReadId, toIndex: messageIndex) {
|
||||||
data.incomingUnreadCount = max(0, data.incomingUnreadCount - Int32(count))
|
data.incomingUnreadCount = max(0, data.incomingUnreadCount - Int32(count))
|
||||||
@ -346,7 +346,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
|
|
||||||
data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id)
|
data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id)
|
||||||
|
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: messageId.peerId, threadId: Int64(messageId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: messageId.peerId, threadId: Int64(messageId.id), info: entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,7 +598,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
|||||||
|
|
||||||
let replyInfo = Promise<MessageHistoryThreadData?>()
|
let replyInfo = Promise<MessageHistoryThreadData?>()
|
||||||
replyInfo.set(account.postbox.transaction { transaction -> MessageHistoryThreadData? in
|
replyInfo.set(account.postbox.transaction { transaction -> MessageHistoryThreadData? in
|
||||||
return transaction.getMessageHistoryThreadInfo(peerId: messageId.peerId, threadId: Int64(messageId.id))?.get(MessageHistoryThreadData.self)
|
return transaction.getMessageHistoryThreadInfo(peerId: messageId.peerId, threadId: Int64(messageId.id))?.data.get(MessageHistoryThreadData.self)
|
||||||
})
|
})
|
||||||
|
|
||||||
let remoteDiscussionMessageSignal: Signal<DiscussionMessage?, NoError> = account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: messageId.id))
|
let remoteDiscussionMessageSignal: Signal<DiscussionMessage?, NoError> = account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: messageId.id))
|
||||||
|
|||||||
@ -15,7 +15,7 @@ func _internal_togglePeerMuted(account: Account, peerId: PeerId, threadId: Int64
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let threadId = threadId {
|
if let threadId = threadId {
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
var updatedSettings: TelegramPeerNotificationSettings
|
var updatedSettings: TelegramPeerNotificationSettings
|
||||||
switch data.notificationSettings.muteState {
|
switch data.notificationSettings.muteState {
|
||||||
case .default:
|
case .default:
|
||||||
@ -27,7 +27,7 @@ func _internal_togglePeerMuted(account: Account, peerId: PeerId, threadId: Int64
|
|||||||
}
|
}
|
||||||
data.notificationSettings = updatedSettings
|
data.notificationSettings = updatedSettings
|
||||||
|
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
|
|
||||||
//TODO:loc
|
//TODO:loc
|
||||||
@ -71,7 +71,7 @@ func _internal_updatePeerMuteSetting(account: Account, peerId: PeerId, threadId:
|
|||||||
func _internal_updatePeerMuteSetting(account: Account, transaction: Transaction, peerId: PeerId, threadId: Int64?, muteInterval: Int32?) {
|
func _internal_updatePeerMuteSetting(account: Account, transaction: Transaction, peerId: PeerId, threadId: Int64?, muteInterval: Int32?) {
|
||||||
if let peer = transaction.getPeer(peerId) {
|
if let peer = transaction.getPeer(peerId) {
|
||||||
if let threadId = threadId {
|
if let threadId = threadId {
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings
|
let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings
|
||||||
|
|
||||||
let muteState: PeerMuteState
|
let muteState: PeerMuteState
|
||||||
@ -93,7 +93,7 @@ func _internal_updatePeerMuteSetting(account: Account, transaction: Transaction,
|
|||||||
|
|
||||||
data.notificationSettings = previousSettings.withUpdatedMuteState(muteState)
|
data.notificationSettings = previousSettings.withUpdatedMuteState(muteState)
|
||||||
|
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,12 +146,12 @@ func _internal_updatePeerDisplayPreviewsSetting(account: Account, peerId: PeerId
|
|||||||
func _internal_updatePeerDisplayPreviewsSetting(account: Account, transaction: Transaction, peerId: PeerId, threadId: Int64?, displayPreviews: PeerNotificationDisplayPreviews) {
|
func _internal_updatePeerDisplayPreviewsSetting(account: Account, transaction: Transaction, peerId: PeerId, threadId: Int64?, displayPreviews: PeerNotificationDisplayPreviews) {
|
||||||
if let peer = transaction.getPeer(peerId) {
|
if let peer = transaction.getPeer(peerId) {
|
||||||
if let threadId = threadId {
|
if let threadId = threadId {
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings
|
let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings
|
||||||
|
|
||||||
data.notificationSettings = previousSettings.withUpdatedDisplayPreviews(displayPreviews)
|
data.notificationSettings = previousSettings.withUpdatedDisplayPreviews(displayPreviews)
|
||||||
|
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,12 +187,12 @@ func _internal_updatePeerNotificationSoundInteractive(account: Account, peerId:
|
|||||||
func _internal_updatePeerNotificationSoundInteractive(account: Account, transaction: Transaction, peerId: PeerId, threadId: Int64?, sound: PeerMessageSound) {
|
func _internal_updatePeerNotificationSoundInteractive(account: Account, transaction: Transaction, peerId: PeerId, threadId: Int64?, sound: PeerMessageSound) {
|
||||||
if let peer = transaction.getPeer(peerId) {
|
if let peer = transaction.getPeer(peerId) {
|
||||||
if let threadId = threadId {
|
if let threadId = threadId {
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings
|
let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings
|
||||||
|
|
||||||
data.notificationSettings = previousSettings.withUpdatedMessageSound(sound)
|
data.notificationSettings = previousSettings.withUpdatedMessageSound(sound)
|
||||||
|
|
||||||
if let entry = CodableEntry(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -365,7 +365,7 @@ public final class AccountContextImpl: AccountContext {
|
|||||||
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: data.messageId.peerId, threadId: Int64(data.messageId.id))
|
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: data.messageId.peerId, threadId: Int64(data.messageId.id))
|
||||||
return self.account.postbox.combinedView(keys: [viewKey])
|
return self.account.postbox.combinedView(keys: [viewKey])
|
||||||
|> map { views -> MessageId? in
|
|> map { views -> MessageId? in
|
||||||
if let threadInfo = views.views[viewKey] as? MessageHistoryThreadInfoView, let data = threadInfo.info?.get(MessageHistoryThreadData.self) {
|
if let threadInfo = views.views[viewKey] as? MessageHistoryThreadInfoView, let data = threadInfo.info?.data.get(MessageHistoryThreadData.self) {
|
||||||
return MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: data.maxOutgoingReadId)
|
return MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: data.maxOutgoingReadId)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
@ -402,7 +402,7 @@ public final class AccountContextImpl: AccountContext {
|
|||||||
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: data.messageId.peerId, threadId: Int64(data.messageId.id))
|
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: data.messageId.peerId, threadId: Int64(data.messageId.id))
|
||||||
return self.account.postbox.combinedView(keys: [viewKey])
|
return self.account.postbox.combinedView(keys: [viewKey])
|
||||||
|> map { views -> Int in
|
|> map { views -> Int in
|
||||||
if let threadInfo = views.views[viewKey] as? MessageHistoryThreadInfoView, let data = threadInfo.info?.get(MessageHistoryThreadData.self) {
|
if let threadInfo = views.views[viewKey] as? MessageHistoryThreadInfoView, let data = threadInfo.info?.data.get(MessageHistoryThreadData.self) {
|
||||||
return Int(data.incomingUnreadCount)
|
return Int(data.incomingUnreadCount)
|
||||||
} else {
|
} else {
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@ -4753,7 +4753,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
guard let view = views.views[viewKey] as? MessageHistoryThreadInfoView else {
|
guard let view = views.views[viewKey] as? MessageHistoryThreadInfoView else {
|
||||||
return (message, nil)
|
return (message, nil)
|
||||||
}
|
}
|
||||||
return (message, view.info?.get(MessageHistoryThreadData.self))
|
return (message, view.info?.data.get(MessageHistoryThreadData.self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -100,7 +100,7 @@ private enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
ignoreUnreadBadge: true,
|
ignoreUnreadBadge: true,
|
||||||
displayAsMessage: true,
|
displayAsMessage: true,
|
||||||
hasFailedMessages: false,
|
hasFailedMessages: false,
|
||||||
forumThreadTitle: nil
|
forumTopicData: nil
|
||||||
),
|
),
|
||||||
editing: false,
|
editing: false,
|
||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
@ -232,6 +232,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
|
|||||||
}, setPeerThreadMuted: { _, _, _ in
|
}, setPeerThreadMuted: { _, _, _ in
|
||||||
}, deletePeer: { _, _ in
|
}, deletePeer: { _, _ in
|
||||||
}, deletePeerThread: { _, _ in
|
}, deletePeerThread: { _, _ in
|
||||||
|
}, setPeerThreadStopped: { _, _, _ in
|
||||||
}, updatePeerGrouping: { _, _ in
|
}, updatePeerGrouping: { _, _ in
|
||||||
}, togglePeerMarkedUnread: { _, _ in
|
}, togglePeerMarkedUnread: { _, _ in
|
||||||
}, toggleArchivedFolderHiddenByDefault: {
|
}, toggleArchivedFolderHiddenByDefault: {
|
||||||
|
|||||||
@ -824,7 +824,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
guard let view = views.views[viewKey] as? MessageHistoryThreadInfoView else {
|
guard let view = views.views[viewKey] as? MessageHistoryThreadInfoView else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return view.info?.get(MessageHistoryThreadData.self)
|
return view.info?.data.get(MessageHistoryThreadData.self)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
threadData = .single(nil)
|
threadData = .single(nil)
|
||||||
|
|||||||
@ -495,7 +495,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
|
|||||||
|
|
||||||
self.containerNode.isGestureEnabled = !isSettings
|
self.containerNode.isGestureEnabled = !isSettings
|
||||||
|
|
||||||
if let video = videoRepresentations.last, let peerReference = PeerReference(peer) {
|
if threadInfo == nil, let video = videoRepresentations.last, let peerReference = PeerReference(peer) {
|
||||||
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.representation.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.representation.dimensions, flags: [])]))
|
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.representation.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.representation.dimensions, flags: [])]))
|
||||||
let videoContent = NativeVideoContent(id: .profileVideo(videoId, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, captureProtected: peer.isCopyProtectionEnabled)
|
let videoContent = NativeVideoContent(id: .profileVideo(videoId, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, captureProtected: peer.isCopyProtectionEnabled)
|
||||||
if videoContent.id != self.videoContent?.id {
|
if videoContent.id != self.videoContent?.id {
|
||||||
@ -799,7 +799,7 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let video = videoRepresentations.last, let peerReference = PeerReference(peer) {
|
if threadData == nil, let video = videoRepresentations.last, let peerReference = PeerReference(peer) {
|
||||||
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.representation.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.representation.dimensions, flags: [])]))
|
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.representation.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.representation.dimensions, flags: [])]))
|
||||||
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, captureProtected: peer.isCopyProtectionEnabled)
|
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, captureProtected: peer.isCopyProtectionEnabled)
|
||||||
if videoContent.id != self.videoContent?.id {
|
if videoContent.id != self.videoContent?.id {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user