mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Merge branch 'gray-counters'
This commit is contained in:
commit
aa24263bed
@ -1339,8 +1339,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
let (_, items) = countAndFilterItems
|
||||
var filterItems: [ChatListFilterTabEntry] = []
|
||||
filterItems.append(.all(unreadCount: 0))
|
||||
for (filter, unreadCount) in items {
|
||||
filterItems.append(.filter(id: filter.id, text: filter.title, unreadCount: unreadCount))
|
||||
for (filter, unreadCount, hasUnmutedUnread) in items {
|
||||
filterItems.append(.filter(id: filter.id, text: filter.title, unread: ChatListFilterTabEntryUnreadCount(value: unreadCount, hasUnmuted: hasUnmutedUnread)))
|
||||
}
|
||||
|
||||
var resolvedItems = filterItems
|
||||
|
@ -200,7 +200,7 @@ private final class ChatListShimmerNode: ASDisplayNode {
|
||||
}, present: { _ in })
|
||||
|
||||
let items = (0 ..< 2).map { _ -> ChatListItem in
|
||||
return ChatListItem(presentationData: chatListPresentationData, context: context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer1, text: "Text", attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
return ChatListItem(presentationData: chatListPresentationData, context: context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer1, text: "Text", attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
}
|
||||
|
||||
var itemNodes: [ChatListItemNode] = []
|
||||
|
@ -68,7 +68,9 @@ private final class ItemNode: ASDisplayNode {
|
||||
private let shortTitleNode: ImmediateTextNode
|
||||
private let badgeContainerNode: ASDisplayNode
|
||||
private let badgeTextNode: ImmediateTextNode
|
||||
private let badgeBackgroundNode: ASImageNode
|
||||
private let badgeBackgroundActiveNode: ASImageNode
|
||||
private let badgeBackgroundInactiveNode: ASImageNode
|
||||
|
||||
private var deleteButtonNode: ItemNodeDeleteButtonNode?
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
|
||||
@ -101,9 +103,14 @@ private final class ItemNode: ASDisplayNode {
|
||||
self.badgeTextNode = ImmediateTextNode()
|
||||
self.badgeTextNode.displaysAsynchronously = false
|
||||
|
||||
self.badgeBackgroundNode = ASImageNode()
|
||||
self.badgeBackgroundNode.displaysAsynchronously = false
|
||||
self.badgeBackgroundNode.displayWithoutProcessing = true
|
||||
self.badgeBackgroundActiveNode = ASImageNode()
|
||||
self.badgeBackgroundActiveNode.displaysAsynchronously = false
|
||||
self.badgeBackgroundActiveNode.displayWithoutProcessing = true
|
||||
|
||||
self.badgeBackgroundInactiveNode = ASImageNode()
|
||||
self.badgeBackgroundInactiveNode.displaysAsynchronously = false
|
||||
self.badgeBackgroundInactiveNode.displayWithoutProcessing = true
|
||||
self.badgeBackgroundInactiveNode.isHidden = true
|
||||
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
|
||||
@ -112,7 +119,8 @@ private final class ItemNode: ASDisplayNode {
|
||||
self.extractedContainerNode.contentNode.addSubnode(self.extractedBackgroundNode)
|
||||
self.extractedContainerNode.contentNode.addSubnode(self.titleNode)
|
||||
self.extractedContainerNode.contentNode.addSubnode(self.shortTitleNode)
|
||||
self.badgeContainerNode.addSubnode(self.badgeBackgroundNode)
|
||||
self.badgeContainerNode.addSubnode(self.badgeBackgroundActiveNode)
|
||||
self.badgeContainerNode.addSubnode(self.badgeBackgroundInactiveNode)
|
||||
self.badgeContainerNode.addSubnode(self.badgeTextNode)
|
||||
self.extractedContainerNode.contentNode.addSubnode(self.badgeContainerNode)
|
||||
self.extractedContainerNode.contentNode.addSubnode(self.buttonNode)
|
||||
@ -150,11 +158,12 @@ private final class ItemNode: ASDisplayNode {
|
||||
self.pressed()
|
||||
}
|
||||
|
||||
func updateText(title: String, shortTitle: String, unreadCount: Int, isNoFilter: Bool, isSelected: Bool, isEditing: Bool, isAllChats: Bool, isReordering: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) {
|
||||
func updateText(title: String, shortTitle: String, unreadCount: Int, unreadHasUnmuted: Bool, isNoFilter: Bool, isSelected: Bool, isEditing: Bool, isAllChats: Bool, isReordering: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) {
|
||||
if self.theme !== presentationData.theme {
|
||||
self.theme = presentationData.theme
|
||||
|
||||
self.badgeBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 18.0, color: presentationData.theme.list.itemCheckColors.fillColor)
|
||||
self.badgeBackgroundActiveNode.image = generateStretchableFilledCircleImage(diameter: 18.0, color: presentationData.theme.chatList.unreadBadgeActiveBackgroundColor)
|
||||
self.badgeBackgroundInactiveNode.image = generateStretchableFilledCircleImage(diameter: 18.0, color: presentationData.theme.chatList.unreadBadgeInactiveBackgroundColor)
|
||||
}
|
||||
|
||||
self.containerNode.isGestureEnabled = !isNoFilter && !isEditing && !isReordering
|
||||
@ -191,6 +200,8 @@ private final class ItemNode: ASDisplayNode {
|
||||
self.shortTitleNode.attributedText = NSAttributedString(string: shortTitle, font: Font.medium(14.0), textColor: isSelected ? presentationData.theme.list.itemAccentColor : presentationData.theme.list.itemSecondaryTextColor)
|
||||
if unreadCount != 0 {
|
||||
self.badgeTextNode.attributedText = NSAttributedString(string: "\(unreadCount)", font: Font.regular(14.0), textColor: presentationData.theme.list.itemCheckColors.foregroundColor)
|
||||
self.badgeBackgroundActiveNode.isHidden = !unreadHasUnmuted
|
||||
self.badgeBackgroundInactiveNode.isHidden = unreadHasUnmuted
|
||||
}
|
||||
|
||||
if self.isReordering != isReordering {
|
||||
@ -222,7 +233,8 @@ private final class ItemNode: ASDisplayNode {
|
||||
let badgeInset: CGFloat = 4.0
|
||||
let badgeBackgroundFrame = CGRect(origin: CGPoint(x: titleSize.width + 5.0, y: floor((height - 18.0) / 2.0)), size: CGSize(width: max(18.0, badgeSize.width + badgeInset * 2.0), height: 18.0))
|
||||
self.badgeContainerNode.frame = badgeBackgroundFrame
|
||||
self.badgeBackgroundNode.frame = CGRect(origin: CGPoint(), size: badgeBackgroundFrame.size)
|
||||
self.badgeBackgroundActiveNode.frame = CGRect(origin: CGPoint(), size: badgeBackgroundFrame.size)
|
||||
self.badgeBackgroundInactiveNode.frame = CGRect(origin: CGPoint(), size: badgeBackgroundFrame.size)
|
||||
self.badgeTextNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((badgeBackgroundFrame.width - badgeSize.width) / 2.0), y: floor((badgeBackgroundFrame.height - badgeSize.height) / 2.0)), size: badgeSize)
|
||||
|
||||
let width: CGFloat
|
||||
@ -340,9 +352,14 @@ enum ChatListFilterTabEntryId: Hashable {
|
||||
case filter(Int32)
|
||||
}
|
||||
|
||||
struct ChatListFilterTabEntryUnreadCount: Equatable {
|
||||
let value: Int
|
||||
let hasUnmuted: Bool
|
||||
}
|
||||
|
||||
enum ChatListFilterTabEntry: Equatable {
|
||||
case all(unreadCount: Int)
|
||||
case filter(id: Int32, text: String, unreadCount: Int)
|
||||
case filter(id: Int32, text: String, unread: ChatListFilterTabEntryUnreadCount)
|
||||
|
||||
var id: ChatListFilterTabEntryId {
|
||||
switch self {
|
||||
@ -637,18 +654,21 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
|
||||
self.itemNodes[filter.id] = itemNode
|
||||
}
|
||||
let unreadCount: Int
|
||||
let unreadHasUnmuted: Bool
|
||||
var isNoFilter: Bool = false
|
||||
switch filter {
|
||||
case let .all(count):
|
||||
unreadCount = count
|
||||
unreadHasUnmuted = true
|
||||
isNoFilter = true
|
||||
case let .filter(filter):
|
||||
unreadCount = filter.unreadCount
|
||||
unreadCount = filter.unread.value
|
||||
unreadHasUnmuted = filter.unread.hasUnmuted
|
||||
}
|
||||
if !wasAdded && (itemNode.unreadCount != 0) != (unreadCount != 0) {
|
||||
badgeAnimations[filter.id] = (unreadCount != 0) ? .in : .out
|
||||
}
|
||||
itemNode.updateText(title: filter.title(strings: presentationData.strings), shortTitle: filter.shortTitle(strings: presentationData.strings), unreadCount: unreadCount, isNoFilter: isNoFilter, isSelected: selectedFilter == filter.id, isEditing: false, isAllChats: isNoFilter, isReordering: isEditing || isReordering, presentationData: presentationData, transition: itemNodeTransition)
|
||||
itemNode.updateText(title: filter.title(strings: presentationData.strings), shortTitle: filter.shortTitle(strings: presentationData.strings), unreadCount: unreadCount, unreadHasUnmuted: unreadHasUnmuted, isNoFilter: isNoFilter, isSelected: selectedFilter == filter.id, isEditing: false, isAllChats: isNoFilter, isReordering: isEditing || isReordering, presentationData: presentationData, transition: itemNodeTransition)
|
||||
}
|
||||
var removeKeys: [ChatListFilterTabEntryId] = []
|
||||
for (id, _) in self.itemNodes {
|
||||
|
@ -174,7 +174,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
|
||||
|
||||
var isMuted = false
|
||||
if let notificationSettings = peer.notificationSettings {
|
||||
isMuted = notificationSettings.isRemovedFromTotalUnreadCount
|
||||
isMuted = notificationSettings.isRemovedFromTotalUnreadCount(default: false)
|
||||
}
|
||||
var badge: ContactsPeerItemBadge?
|
||||
if peer.unreadCount > 0 {
|
||||
@ -484,7 +484,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
}
|
||||
})
|
||||
case let .message(message, peer, readState, presentationData):
|
||||
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: enableHeaders ? ChatListSearchItemHeader(type: .messages, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: enableHeaders ? ChatListSearchItemHeader(type: .messages, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
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: {
|
||||
interaction.addContact(phoneNumber)
|
||||
|
@ -20,7 +20,7 @@ import ChatListSearchItemNode
|
||||
import ContextUI
|
||||
|
||||
public enum ChatListItemContent {
|
||||
case peer(message: Message?, peer: RenderedPeer, combinedReadState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, embeddedState: PeerChatListEmbeddedInterfaceState?, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool, ignoreUnreadBadge: Bool, displayAsMessage: Bool, hasFailedMessages: Bool)
|
||||
case peer(message: Message?, peer: RenderedPeer, combinedReadState: CombinedPeerReadState?, isRemovedFromTotalUnreadCount: Bool, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, embeddedState: PeerChatListEmbeddedInterfaceState?, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool, ignoreUnreadBadge: Bool, displayAsMessage: Bool, hasFailedMessages: Bool)
|
||||
case groupReference(groupId: PeerGroupId, peers: [ChatListGroupReferencePeer], message: Message?, unreadState: PeerGroupUnreadCountersCombinedSummary, hiddenByDefault: Bool)
|
||||
|
||||
public var chatLocation: ChatLocation? {
|
||||
@ -667,7 +667,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
let contentPeer: ContentPeer
|
||||
let combinedReadState: CombinedPeerReadState?
|
||||
let unreadCount: (count: Int32, unread: Bool, muted: Bool, mutedCount: Int32?)
|
||||
let notificationSettings: PeerNotificationSettings?
|
||||
let isRemovedFromTotalUnreadCount: Bool
|
||||
let peerPresence: PeerPresence?
|
||||
let embeddedState: PeerChatListEmbeddedInterfaceState?
|
||||
let summaryInfo: ChatListMessageTagSummaryInfo
|
||||
@ -680,19 +680,19 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var groupHiddenByDefault = false
|
||||
|
||||
switch item.content {
|
||||
case let .peer(messageValue, peerValue, combinedReadStateValue, notificationSettingsValue, peerPresenceValue, summaryInfoValue, embeddedStateValue, inputActivitiesValue, isAdValue, ignoreUnreadBadge, displayAsMessageValue, hasFailedMessagesValue):
|
||||
case let .peer(messageValue, peerValue, combinedReadStateValue, isRemovedFromTotalUnreadCountValue, peerPresenceValue, summaryInfoValue, embeddedStateValue, inputActivitiesValue, isAdValue, ignoreUnreadBadge, displayAsMessageValue, hasFailedMessagesValue):
|
||||
message = messageValue
|
||||
contentPeer = .chat(peerValue)
|
||||
combinedReadState = combinedReadStateValue
|
||||
if let combinedReadState = combinedReadState, !isAdValue && !ignoreUnreadBadge {
|
||||
unreadCount = (combinedReadState.count, combinedReadState.isUnread, notificationSettingsValue?.isRemovedFromTotalUnreadCount ?? false, nil)
|
||||
unreadCount = (combinedReadState.count, combinedReadState.isUnread, isRemovedFromTotalUnreadCountValue, nil)
|
||||
} else {
|
||||
unreadCount = (0, false, false, nil)
|
||||
}
|
||||
if isAdValue {
|
||||
notificationSettings = nil
|
||||
isRemovedFromTotalUnreadCount = false
|
||||
} else {
|
||||
notificationSettings = notificationSettingsValue
|
||||
isRemovedFromTotalUnreadCount = isRemovedFromTotalUnreadCountValue
|
||||
}
|
||||
peerPresence = peerPresenceValue
|
||||
embeddedState = embeddedStateValue
|
||||
@ -710,7 +710,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
message = messageValue
|
||||
combinedReadState = nil
|
||||
notificationSettings = nil
|
||||
isRemovedFromTotalUnreadCount = false
|
||||
embeddedState = nil
|
||||
summaryInfo = ChatListMessageTagSummaryInfo()
|
||||
inputActivities = nil
|
||||
@ -1038,12 +1038,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
var isMuted = false
|
||||
if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings {
|
||||
if case let .muted(until) = notificationSettings.muteState, until >= Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) {
|
||||
isMuted = true
|
||||
currentMutedIconImage = PresentationResourcesChatList.mutedIcon(item.presentationData.theme)
|
||||
}
|
||||
var isMuted = isRemovedFromTotalUnreadCount
|
||||
if isMuted {
|
||||
currentMutedIconImage = PresentationResourcesChatList.mutedIcon(item.presentationData.theme)
|
||||
}
|
||||
|
||||
let statusWidth: CGFloat
|
||||
|
@ -169,10 +169,10 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
nodeInteraction.additionalCategorySelected(id)
|
||||
}
|
||||
), directionHint: entry.directionHint)
|
||||
case let .PeerEntry(index, presentationData, message, combinedReadState, notificationSettings, embeddedState, peer, presence, summaryInfo, editing, hasActiveRevealControls, selected, inputActivities, isAd, hasFailedMessages, isContact):
|
||||
case let .PeerEntry(index, presentationData, message, combinedReadState, isRemovedFromTotalUnreadCount, embeddedState, peer, presence, summaryInfo, editing, hasActiveRevealControls, selected, inputActivities, isAd, hasFailedMessages, isContact):
|
||||
switch mode {
|
||||
case .chatList:
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(presentationData: presentationData, context: context, peerGroupId: peerGroupId, isInFilter: isInFilter, index: index, content: .peer(message: message, peer: peer, combinedReadState: combinedReadState, notificationSettings: notificationSettings, presence: presence, summaryInfo: summaryInfo, embeddedState: embeddedState, inputActivities: inputActivities, isAd: isAd, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: hasFailedMessages), editing: editing, hasActiveRevealControls: hasActiveRevealControls, selected: selected, header: nil, enableContextActions: true, hiddenOffset: false, interaction: nodeInteraction), directionHint: entry.directionHint)
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(presentationData: presentationData, context: context, peerGroupId: peerGroupId, isInFilter: isInFilter, index: index, content: .peer(message: message, peer: peer, combinedReadState: combinedReadState, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, presence: presence, summaryInfo: summaryInfo, embeddedState: embeddedState, inputActivities: inputActivities, isAd: isAd, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: hasFailedMessages), editing: editing, hasActiveRevealControls: hasActiveRevealControls, selected: selected, header: nil, enableContextActions: true, hiddenOffset: false, interaction: nodeInteraction), directionHint: entry.directionHint)
|
||||
case let .peers(filter, isSelecting, _):
|
||||
let itemPeer = peer.chatMainPeer
|
||||
var chatPeer: Peer?
|
||||
@ -276,10 +276,10 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatListNodeInteraction, peerGroupId: PeerGroupId, isInFilter: Bool, mode: ChatListNodeMode, entries: [ChatListNodeViewTransitionUpdateEntry]) -> [ListViewUpdateItem] {
|
||||
return entries.map { entry -> ListViewUpdateItem in
|
||||
switch entry.entry {
|
||||
case let .PeerEntry(index, presentationData, message, combinedReadState, notificationSettings, embeddedState, peer, presence, summaryInfo, editing, hasActiveRevealControls, selected, inputActivities, isAd, hasFailedMessages, isContact):
|
||||
case let .PeerEntry(index, presentationData, message, combinedReadState, isRemovedFromTotalUnreadCount, embeddedState, peer, presence, summaryInfo, editing, hasActiveRevealControls, selected, inputActivities, isAd, hasFailedMessages, isContact):
|
||||
switch mode {
|
||||
case .chatList:
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(presentationData: presentationData, context: context, peerGroupId: peerGroupId, isInFilter: isInFilter, index: index, content: .peer(message: message, peer: peer, combinedReadState: combinedReadState, notificationSettings: notificationSettings, presence: presence, summaryInfo: summaryInfo, embeddedState: embeddedState, inputActivities: inputActivities, isAd: isAd, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: hasFailedMessages), editing: editing, hasActiveRevealControls: hasActiveRevealControls, selected: selected, header: nil, enableContextActions: true, hiddenOffset: false, interaction: nodeInteraction), directionHint: entry.directionHint)
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(presentationData: presentationData, context: context, peerGroupId: peerGroupId, isInFilter: isInFilter, index: index, content: .peer(message: message, peer: peer, combinedReadState: combinedReadState, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, presence: presence, summaryInfo: summaryInfo, embeddedState: embeddedState, inputActivities: inputActivities, isAd: isAd, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: hasFailedMessages), editing: editing, hasActiveRevealControls: hasActiveRevealControls, selected: selected, header: nil, enableContextActions: true, hiddenOffset: false, interaction: nodeInteraction), directionHint: entry.directionHint)
|
||||
case let .peers(filter, isSelecting, _):
|
||||
let itemPeer = peer.chatMainPeer
|
||||
var chatPeer: Peer?
|
||||
@ -374,11 +374,6 @@ public enum ChatListGlobalScrollOption {
|
||||
case unread
|
||||
}
|
||||
|
||||
private struct ChatListVisibleUnreadCounts: Equatable {
|
||||
var raw: Int32 = 0
|
||||
var filtered: Int32 = 0
|
||||
}
|
||||
|
||||
public enum ChatListNodeScrollPosition {
|
||||
case auto
|
||||
case autoUp
|
||||
@ -478,15 +473,6 @@ public final class ChatListNode: ListView {
|
||||
public var contentOffsetChanged: ((ListViewVisibleContentOffset) -> Void)?
|
||||
public var contentScrollingEnded: ((ListView) -> Bool)?
|
||||
|
||||
private let visibleUnreadCounts = ValuePromise<ChatListVisibleUnreadCounts>(ChatListVisibleUnreadCounts())
|
||||
private var visibleUnreadCountsValue = ChatListVisibleUnreadCounts() {
|
||||
didSet {
|
||||
if self.visibleUnreadCountsValue != oldValue {
|
||||
self.visibleUnreadCounts.set(self.visibleUnreadCountsValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isEmptyUpdated: ((ChatListNodeEmptyState, Bool, ContainedViewLayoutTransition) -> Void)?
|
||||
private var currentIsEmptyState: ChatListNodeEmptyState?
|
||||
|
||||
@ -900,8 +886,6 @@ public final class ChatListNode: ListView {
|
||||
strongSelf.enqueueHistoryPreloadUpdate()
|
||||
}
|
||||
|
||||
var rawUnreadCount: Int32 = 0
|
||||
var filteredUnreadCount: Int32 = 0
|
||||
var archiveVisible = false
|
||||
if let range = range.visibleRange {
|
||||
let entryCount = chatListView.filteredEntries.count
|
||||
@ -911,14 +895,8 @@ public final class ChatListNode: ListView {
|
||||
continue
|
||||
}
|
||||
switch chatListView.filteredEntries[entryCount - i - 1] {
|
||||
case let .PeerEntry(_, _, _, readState, notificationSettings, _, _, _, _, _, _, _, _, _, _, _):
|
||||
if let readState = readState {
|
||||
let count = readState.count
|
||||
rawUnreadCount += count
|
||||
if let notificationSettings = notificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
filteredUnreadCount += count
|
||||
}
|
||||
}
|
||||
case .PeerEntry:
|
||||
break
|
||||
case .GroupReferenceEntry:
|
||||
archiveVisible = true
|
||||
default:
|
||||
@ -926,10 +904,6 @@ public final class ChatListNode: ListView {
|
||||
}
|
||||
}
|
||||
}
|
||||
var visibleUnreadCountsValue = strongSelf.visibleUnreadCountsValue
|
||||
visibleUnreadCountsValue.raw = rawUnreadCount
|
||||
visibleUnreadCountsValue.filtered = filteredUnreadCount
|
||||
strongSelf.visibleUnreadCountsValue = visibleUnreadCountsValue
|
||||
if !archiveVisible && strongSelf.currentState.archiveShouldBeTemporaryRevealed {
|
||||
strongSelf.updateState { state in
|
||||
var state = state
|
||||
@ -1161,25 +1135,10 @@ public final class ChatListNode: ListView {
|
||||
|
||||
self.scrollToTopOptionPromise.set(combineLatest(
|
||||
renderedTotalUnreadCount(accountManager: self.context.sharedContext.accountManager, postbox: self.context.account.postbox) |> deliverOnMainQueue,
|
||||
self.visibleUnreadCounts.get(),
|
||||
self.scrolledAtTop.get()
|
||||
) |> map { badge, visibleUnreadCounts, scrolledAtTop -> ChatListGlobalScrollOption in
|
||||
) |> map { badge, scrolledAtTop -> ChatListGlobalScrollOption in
|
||||
if scrolledAtTop {
|
||||
if badge.0 != 0 {
|
||||
switch badge.1 {
|
||||
case .raw:
|
||||
if visibleUnreadCounts.raw < badge.0 {
|
||||
return .unread
|
||||
}
|
||||
case .filtered:
|
||||
if visibleUnreadCounts.filtered < badge.0 {
|
||||
return .unread
|
||||
}
|
||||
}
|
||||
return .none
|
||||
} else {
|
||||
return .none
|
||||
}
|
||||
return .none
|
||||
} else {
|
||||
return .top
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ enum ChatListNodeEntrySortIndex: Comparable {
|
||||
|
||||
enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
case HeaderEntry
|
||||
case PeerEntry(index: ChatListIndex, presentationData: ChatListPresentationData, message: Message?, readState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, embeddedInterfaceState: PeerChatListEmbeddedInterfaceState?, peer: RenderedPeer, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool, hasFailedMessages: Bool, isContact: Bool)
|
||||
case PeerEntry(index: ChatListIndex, presentationData: ChatListPresentationData, message: Message?, readState: CombinedPeerReadState?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: PeerChatListEmbeddedInterfaceState?, peer: RenderedPeer, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool, hasFailedMessages: Bool, isContact: Bool)
|
||||
case HoleEntry(ChatListHole, theme: PresentationTheme)
|
||||
case GroupReferenceEntry(index: ChatListIndex, presentationData: ChatListPresentationData, groupId: PeerGroupId, peers: [ChatListGroupReferencePeer], message: Message?, editing: Bool, unreadState: PeerGroupUnreadCountersCombinedSummary, revealed: Bool, hiddenByDefault: Bool)
|
||||
case ArchiveIntro(presentationData: ChatListPresentationData)
|
||||
@ -93,9 +93,9 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .PeerEntry(lhsIndex, lhsPresentationData, lhsMessage, lhsUnreadCount, lhsNotificationSettings, lhsEmbeddedState, lhsPeer, lhsPresence, lhsSummaryInfo, lhsEditing, lhsHasRevealControls, lhsSelected, lhsInputActivities, lhsAd, lhsHasFailedMessages, lhsIsContact):
|
||||
case let .PeerEntry(lhsIndex, lhsPresentationData, lhsMessage, lhsUnreadCount, lhsIsRemovedFromTotalUnreadCount, lhsEmbeddedState, lhsPeer, lhsPresence, lhsSummaryInfo, lhsEditing, lhsHasRevealControls, lhsSelected, lhsInputActivities, lhsAd, lhsHasFailedMessages, lhsIsContact):
|
||||
switch rhs {
|
||||
case let .PeerEntry(rhsIndex, rhsPresentationData, rhsMessage, rhsUnreadCount, rhsNotificationSettings, rhsEmbeddedState, rhsPeer, rhsPresence, rhsSummaryInfo, rhsEditing, rhsHasRevealControls, rhsSelected, rhsInputActivities, rhsAd, rhsHasFailedMessages, rhsIsContact):
|
||||
case let .PeerEntry(rhsIndex, rhsPresentationData, rhsMessage, rhsUnreadCount, rhsIsRemovedFromTotalUnreadCount, rhsEmbeddedState, rhsPeer, rhsPresence, rhsSummaryInfo, rhsEditing, rhsHasRevealControls, rhsSelected, rhsInputActivities, rhsAd, rhsHasFailedMessages, rhsIsContact):
|
||||
if lhsIndex != rhsIndex {
|
||||
return false
|
||||
}
|
||||
@ -122,11 +122,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
}
|
||||
if let lhsNotificationSettings = lhsNotificationSettings, let rhsNotificationSettings = rhsNotificationSettings {
|
||||
if !lhsNotificationSettings.isEqual(to: rhsNotificationSettings) {
|
||||
return false
|
||||
}
|
||||
} else if (lhsNotificationSettings != nil) != (rhsNotificationSettings != nil) {
|
||||
if lhsIsRemovedFromTotalUnreadCount != rhsIsRemovedFromTotalUnreadCount {
|
||||
return false
|
||||
}
|
||||
if let lhsPeerPresence = lhsPresence, let rhsPeerPresence = rhsPresence {
|
||||
@ -289,7 +285,7 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
|
||||
}
|
||||
loop: for entry in view.entries {
|
||||
switch entry {
|
||||
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact):
|
||||
case let .MessageEntry(index, message, combinedReadState, isRemovedFromTotalUnreadCount, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact):
|
||||
if let savedMessagesPeer = savedMessagesPeer, savedMessagesPeer.id == index.messageIndex.id.peerId {
|
||||
continue loop
|
||||
}
|
||||
@ -302,7 +298,7 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
|
||||
updatedMessage = nil
|
||||
updatedCombinedReadState = nil
|
||||
}
|
||||
result.append(.PeerEntry(index: offsetPinnedIndex(index, offset: pinnedIndexOffset), presentationData: state.presentationData, message: updatedMessage, readState: updatedCombinedReadState, notificationSettings: notificationSettings, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: false, hasFailedMessages: hasFailed, isContact: isContact))
|
||||
result.append(.PeerEntry(index: offsetPinnedIndex(index, offset: pinnedIndexOffset), presentationData: state.presentationData, message: updatedMessage, readState: updatedCombinedReadState, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: false, hasFailedMessages: hasFailed, isContact: isContact))
|
||||
case let .HoleEntry(hole):
|
||||
if hole.index.timestamp == Int32.max - 1 {
|
||||
return ([.HeaderEntry], true)
|
||||
@ -314,13 +310,13 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
|
||||
var pinningIndex: UInt16 = UInt16(pinnedIndexOffset == 0 ? 0 : (pinnedIndexOffset - 1))
|
||||
|
||||
if let savedMessagesPeer = savedMessagesPeer {
|
||||
result.append(.PeerEntry(index: ChatListIndex.absoluteUpperBound.predecessor, presentationData: state.presentationData, message: nil, readState: nil, notificationSettings: nil, embeddedInterfaceState: nil, peer: RenderedPeer(peerId: savedMessagesPeer.id, peers: SimpleDictionary([savedMessagesPeer.id: savedMessagesPeer])), presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), editing: state.editing, hasActiveRevealControls: false, selected: false, inputActivities: nil, isAd: false, hasFailedMessages: false, isContact: false))
|
||||
result.append(.PeerEntry(index: ChatListIndex.absoluteUpperBound.predecessor, presentationData: state.presentationData, message: nil, readState: nil, isRemovedFromTotalUnreadCount: false, embeddedInterfaceState: nil, peer: RenderedPeer(peerId: savedMessagesPeer.id, peers: SimpleDictionary([savedMessagesPeer.id: savedMessagesPeer])), presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), editing: state.editing, hasActiveRevealControls: false, selected: false, inputActivities: nil, isAd: false, hasFailedMessages: false, isContact: false))
|
||||
} else {
|
||||
if !view.additionalItemEntries.isEmpty {
|
||||
for entry in view.additionalItemEntries.reversed() {
|
||||
switch entry {
|
||||
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact):
|
||||
result.append(.PeerEntry(index: ChatListIndex(pinningIndex: pinningIndex, messageIndex: index.messageIndex), presentationData: state.presentationData, message: message, readState: combinedReadState, notificationSettings: notificationSettings, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: true, hasFailedMessages: hasFailed, isContact: isContact))
|
||||
case let .MessageEntry(index, message, combinedReadState, isRemovedFromTotalUnreadCount, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact):
|
||||
result.append(.PeerEntry(index: ChatListIndex(pinningIndex: pinningIndex, messageIndex: index.messageIndex), presentationData: state.presentationData, message: message, readState: combinedReadState, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: true, hasFailedMessages: hasFailed, isContact: isContact))
|
||||
if pinningIndex != 0 {
|
||||
pinningIndex -= 1
|
||||
}
|
||||
|
@ -10,21 +10,29 @@ import Postbox
|
||||
import TelegramUIPreferences
|
||||
import TelegramCore
|
||||
|
||||
func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilter, Int)]), NoError> {
|
||||
func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilter, Int, Bool)]), NoError> {
|
||||
return updatedChatListFilters(postbox: context.account.postbox)
|
||||
|> distinctUntilChanged
|
||||
|> mapToSignal { filters -> Signal<(Int, [(ChatListFilter, Int)]), NoError> in
|
||||
|> mapToSignal { filters -> Signal<(Int, [(ChatListFilter, Int, Bool)]), NoError> in
|
||||
var unreadCountItems: [UnreadMessageCountsItem] = []
|
||||
unreadCountItems.append(.total(nil))
|
||||
unreadCountItems.append(.totalInGroup(.root))
|
||||
var additionalPeerIds = Set<PeerId>()
|
||||
var additionalGroupIds = Set<PeerGroupId>()
|
||||
for filter in filters {
|
||||
additionalPeerIds.formUnion(filter.data.includePeers)
|
||||
additionalPeerIds.formUnion(filter.data.excludePeers)
|
||||
if !filter.data.excludeArchived {
|
||||
additionalGroupIds.insert(Namespaces.PeerGroup.archive)
|
||||
}
|
||||
}
|
||||
if !additionalPeerIds.isEmpty {
|
||||
for peerId in additionalPeerIds {
|
||||
unreadCountItems.append(.peer(peerId))
|
||||
}
|
||||
}
|
||||
for groupId in additionalGroupIds {
|
||||
unreadCountItems.append(.totalInGroup(groupId))
|
||||
}
|
||||
let unreadKey: PostboxViewKey = .unreadCounts(items: unreadCountItems)
|
||||
var keys: [PostboxViewKey] = []
|
||||
keys.append(unreadKey)
|
||||
@ -36,34 +44,36 @@ func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilt
|
||||
context.account.postbox.combinedView(keys: keys),
|
||||
Signal<Bool, NoError>.single(true)
|
||||
)
|
||||
|> map { view, _ -> (Int, [(ChatListFilter, Int)]) in
|
||||
|> map { view, _ -> (Int, [(ChatListFilter, Int, Bool)]) in
|
||||
guard let unreadCounts = view.views[unreadKey] as? UnreadMessageCountsView else {
|
||||
return (0, [])
|
||||
}
|
||||
|
||||
var result: [(ChatListFilter, Int)] = []
|
||||
var result: [(ChatListFilter, Int, Bool)] = []
|
||||
|
||||
var peerTagAndCount: [PeerId: (PeerSummaryCounterTags, Int)] = [:]
|
||||
var peerTagAndCount: [PeerId: (PeerSummaryCounterTags, Int, Bool)] = [:]
|
||||
|
||||
var totalState: ChatListTotalUnreadState?
|
||||
var totalStates: [PeerGroupId: ChatListTotalUnreadState] = [:]
|
||||
for entry in unreadCounts.entries {
|
||||
switch entry {
|
||||
case let .total(_, totalStateValue):
|
||||
totalState = totalStateValue
|
||||
case let .totalInGroup(groupId, totalGroupState):
|
||||
break
|
||||
case let .total(_, state):
|
||||
totalStates[.root] = state
|
||||
case let .totalInGroup(groupId, state):
|
||||
totalStates[groupId] = state
|
||||
case let .peer(peerId, state):
|
||||
if let state = state, state.isUnread {
|
||||
if let peerView = view.views[.basicPeer(peerId)] as? BasicPeerView, let peer = peerView.peer {
|
||||
let tag = context.account.postbox.seedConfiguration.peerSummaryCounterTags(peer, peerView.isContact)
|
||||
|
||||
var peerCount = Int(state.count)
|
||||
if state.isUnread {
|
||||
peerCount = max(1, peerCount)
|
||||
}
|
||||
|
||||
if let notificationSettings = peerView.notificationSettings as? TelegramPeerNotificationSettings, case .muted = notificationSettings.muteState {
|
||||
peerTagAndCount[peerId] = (tag, 0)
|
||||
peerTagAndCount[peerId] = (tag, peerCount, false)
|
||||
} else {
|
||||
var peerCount = Int(state.count)
|
||||
if state.isUnread {
|
||||
peerCount = max(1, peerCount)
|
||||
}
|
||||
peerTagAndCount[peerId] = (tag, peerCount)
|
||||
peerTagAndCount[peerId] = (tag, peerCount, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,25 +99,57 @@ func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilt
|
||||
if filter.data.categories.contains(.channels) {
|
||||
tags.append(.channel)
|
||||
}
|
||||
|
||||
|
||||
var count = 0
|
||||
if let totalState = totalState {
|
||||
var hasUnmutedUnread = false
|
||||
if let totalState = totalStates[.root] {
|
||||
for tag in tags {
|
||||
if let value = totalState.filteredCounters[tag] {
|
||||
if let value = totalState.absoluteCounters[tag] {
|
||||
count += Int(value.chatCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
for peerId in filter.data.includePeers {
|
||||
if let (tag, peerCount) = peerTagAndCount[peerId] {
|
||||
if !tags.contains(tag) {
|
||||
if peerCount != 0 {
|
||||
count += 1
|
||||
if let value = totalState.filteredCounters[tag] {
|
||||
if value.chatCount != 0 {
|
||||
hasUnmutedUnread = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.append((filter, count))
|
||||
if !filter.data.excludeArchived {
|
||||
if let totalState = totalStates[Namespaces.PeerGroup.archive] {
|
||||
for tag in tags {
|
||||
if let value = totalState.absoluteCounters[tag] {
|
||||
count += Int(value.chatCount)
|
||||
}
|
||||
if let value = totalState.filteredCounters[tag] {
|
||||
if value.chatCount != 0 {
|
||||
hasUnmutedUnread = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for peerId in filter.data.includePeers {
|
||||
if let (tag, peerCount, hasUnmuted) = peerTagAndCount[peerId] {
|
||||
if !tags.contains(tag) {
|
||||
if peerCount != 0 {
|
||||
count += 1
|
||||
if hasUnmuted {
|
||||
hasUnmutedUnread = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for peerId in filter.data.excludePeers {
|
||||
if let (tag, peerCount, _) = peerTagAndCount[peerId] {
|
||||
if tags.contains(tag) {
|
||||
if peerCount != 0 {
|
||||
count -= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.append((filter, count, hasUnmutedUnread))
|
||||
}
|
||||
|
||||
return (totalBadge, result)
|
||||
|
@ -799,10 +799,8 @@ open class NavigationBar: ASDisplayNode {
|
||||
}
|
||||
|
||||
private func requestLayout() {
|
||||
if self.transitionState == nil {
|
||||
self.requestedLayout = true
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
self.requestedLayout = true
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
override open func layout() {
|
||||
|
@ -1,9 +1,5 @@
|
||||
import Foundation
|
||||
|
||||
func shouldPeerParticipateInUnreadCountStats(peer: Peer) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
struct ChatListPeerInclusionIndex {
|
||||
let topMessageIndex: MessageIndex?
|
||||
let inclusion: PeerChatListInclusion
|
||||
@ -175,7 +171,7 @@ final class ChatListIndexTable: Table {
|
||||
assert(self.updatedPreviousPeerCachedIndices.isEmpty)
|
||||
}
|
||||
|
||||
func commitWithTransaction(postbox: Postbox, alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], updatedPeers: [((Peer, Bool)?, (Peer, Bool))], transactionParticipationInTotalUnreadCountUpdates: (added: Set<PeerId>, removed: Set<PeerId>), updatedRootUnreadState: inout ChatListTotalUnreadState?, updatedGroupTotalUnreadSummaries: inout [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], currentUpdatedGroupSummarySynchronizeOperations: inout [PeerGroupAndNamespace: Bool]) {
|
||||
func commitWithTransaction(postbox: Postbox, 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]) {
|
||||
var updatedPeerTags: [PeerId: (previous: PeerSummaryCounterTags, updated: PeerSummaryCounterTags)] = [:]
|
||||
for (previous, updated) in updatedPeers {
|
||||
let previousTags: PeerSummaryCounterTags
|
||||
@ -341,9 +337,11 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
var updatedRootState: ChatListTotalUnreadState?
|
||||
var updatedTotalStates: [PeerGroupId: ChatListTotalUnreadState] = [:]
|
||||
var updatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary] = [:]
|
||||
|
||||
let globalNotificationSettings = postbox.getGlobalNotificationSettings()
|
||||
|
||||
for peerId in alteredPeerIds {
|
||||
guard let peer = postbox.peerTable.get(peerId) else {
|
||||
continue
|
||||
@ -369,14 +367,12 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
|
||||
for groupId in groupIds {
|
||||
var totalRootUnreadState: ChatListTotalUnreadState?
|
||||
var totalGroupUnreadState: ChatListTotalUnreadState
|
||||
var summary: PeerGroupUnreadCountersCombinedSummary
|
||||
if case .root = groupId {
|
||||
if let current = updatedRootState {
|
||||
totalRootUnreadState = current
|
||||
} else {
|
||||
totalRootUnreadState = postbox.messageHistoryMetadataTable.getChatListTotalUnreadState()
|
||||
}
|
||||
if let current = updatedTotalStates[groupId] {
|
||||
totalGroupUnreadState = current
|
||||
} else {
|
||||
totalGroupUnreadState = postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId)
|
||||
}
|
||||
if let current = updatedTotalUnreadSummaries[groupId] {
|
||||
summary = current
|
||||
@ -416,113 +412,105 @@ final class ChatListIndexTable: Table {
|
||||
var initialFilteredValue: (Int32, Bool, Bool) = initialValue
|
||||
var currentFilteredValue: (Int32, Bool, Bool) = currentValue
|
||||
|
||||
var initialFilteredStates: CombinedPeerReadState = initialStates
|
||||
var currentFilteredStates: CombinedPeerReadState = currentStates
|
||||
|
||||
if transactionParticipationInTotalUnreadCountUpdates.added.contains(peerId) || transactionParticipationInTotalUnreadCountUpdates.added.contains(notificationPeerId) {
|
||||
initialFilteredValue = (0, false, false)
|
||||
initialFilteredStates = CombinedPeerReadState(states: [])
|
||||
} else if transactionParticipationInTotalUnreadCountUpdates.removed.contains(peerId) || transactionParticipationInTotalUnreadCountUpdates.removed.contains(notificationPeerId) {
|
||||
currentFilteredValue = (0, false, false)
|
||||
currentFilteredStates = CombinedPeerReadState(states: [])
|
||||
} else {
|
||||
if let notificationSettings = postbox.peerNotificationSettingsTable.getEffective(notificationPeerId), !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
} else {
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationPeerId))
|
||||
|
||||
if isRemovedFromTotalUnreadCount {
|
||||
initialFilteredValue = (0, false, false)
|
||||
currentFilteredValue = (0, false, false)
|
||||
initialFilteredStates = CombinedPeerReadState(states: [])
|
||||
currentFilteredStates = CombinedPeerReadState(states: [])
|
||||
}
|
||||
}
|
||||
|
||||
if var currentTotalRootUnreadState = totalRootUnreadState {
|
||||
var keptTags: PeerSummaryCounterTags = postbox.seedConfiguration.peerSummaryCounterTags(peer, isContact)
|
||||
if let (removedTags, addedTags) = updatedPeerTags[peerId] {
|
||||
keptTags.remove(removedTags)
|
||||
keptTags.remove(addedTags)
|
||||
|
||||
for tag in removedTags {
|
||||
alterTags(¤tTotalRootUnreadState, peerId, tag, { absolute, filtered in
|
||||
var absolute = absolute
|
||||
var filtered = filtered
|
||||
absolute.messageCount -= initialValue.0
|
||||
if initialValue.1 {
|
||||
absolute.chatCount -= 1
|
||||
}
|
||||
if initialValue.2 && initialValue.0 == 0 {
|
||||
absolute.messageCount -= 1
|
||||
}
|
||||
filtered.messageCount -= initialFilteredValue.0
|
||||
if initialFilteredValue.1 {
|
||||
filtered.chatCount -= 1
|
||||
}
|
||||
if initialFilteredValue.2 && initialFilteredValue.0 == 0 {
|
||||
filtered.messageCount -= 1
|
||||
}
|
||||
return (absolute, filtered)
|
||||
})
|
||||
}
|
||||
for tag in addedTags {
|
||||
alterTags(¤tTotalRootUnreadState, peerId, tag, { absolute, filtered in
|
||||
var absolute = absolute
|
||||
var filtered = filtered
|
||||
absolute.messageCount += currentValue.0
|
||||
if currentValue.2 && currentValue.0 == 0 {
|
||||
absolute.messageCount += 1
|
||||
}
|
||||
if currentValue.1 {
|
||||
absolute.chatCount += 1
|
||||
}
|
||||
filtered.messageCount += currentFilteredValue.0
|
||||
if currentFilteredValue.1 {
|
||||
filtered.chatCount += 1
|
||||
}
|
||||
if currentFilteredValue.2 && currentFilteredValue.0 == 0 {
|
||||
filtered.messageCount += 1
|
||||
}
|
||||
return (absolute, filtered)
|
||||
})
|
||||
}
|
||||
}
|
||||
var keptTags: PeerSummaryCounterTags = postbox.seedConfiguration.peerSummaryCounterTags(peer, isContact)
|
||||
if let (removedTags, addedTags) = updatedPeerTags[peerId] {
|
||||
keptTags.remove(removedTags)
|
||||
keptTags.remove(addedTags)
|
||||
|
||||
for tag in keptTags {
|
||||
alterTags(¤tTotalRootUnreadState, peerId, tag, { absolute, filtered in
|
||||
for tag in removedTags {
|
||||
alterTags(&totalGroupUnreadState, peerId, tag, { absolute, filtered in
|
||||
var absolute = absolute
|
||||
var filtered = filtered
|
||||
|
||||
let chatDifference: Int32
|
||||
if initialValue.1 != currentValue.1 {
|
||||
chatDifference = initialValue.1 ? -1 : 1
|
||||
} else {
|
||||
chatDifference = 0
|
||||
absolute.messageCount -= initialValue.0
|
||||
if initialValue.1 {
|
||||
absolute.chatCount -= 1
|
||||
}
|
||||
|
||||
let currentUnreadMark: Int32 = currentValue.2 ? 1 : 0
|
||||
let initialUnreadMark: Int32 = initialValue.2 ? 1 : 0
|
||||
let messageDifference = max(currentValue.0, currentUnreadMark) - max(initialValue.0, initialUnreadMark)
|
||||
|
||||
let chatFilteredDifference: Int32
|
||||
if initialFilteredValue.1 != currentFilteredValue.1 {
|
||||
chatFilteredDifference = initialFilteredValue.1 ? -1 : 1
|
||||
} else {
|
||||
chatFilteredDifference = 0
|
||||
if initialValue.2 && initialValue.0 == 0 {
|
||||
absolute.messageCount -= 1
|
||||
}
|
||||
filtered.messageCount -= initialFilteredValue.0
|
||||
if initialFilteredValue.1 {
|
||||
filtered.chatCount -= 1
|
||||
}
|
||||
if initialFilteredValue.2 && initialFilteredValue.0 == 0 {
|
||||
filtered.messageCount -= 1
|
||||
}
|
||||
return (absolute, filtered)
|
||||
})
|
||||
}
|
||||
for tag in addedTags {
|
||||
alterTags(&totalGroupUnreadState, peerId, tag, { absolute, filtered in
|
||||
var absolute = absolute
|
||||
var filtered = filtered
|
||||
absolute.messageCount += currentValue.0
|
||||
if currentValue.2 && currentValue.0 == 0 {
|
||||
absolute.messageCount += 1
|
||||
}
|
||||
if currentValue.1 {
|
||||
absolute.chatCount += 1
|
||||
}
|
||||
filtered.messageCount += currentFilteredValue.0
|
||||
if currentFilteredValue.1 {
|
||||
filtered.chatCount += 1
|
||||
}
|
||||
if currentFilteredValue.2 && currentFilteredValue.0 == 0 {
|
||||
filtered.messageCount += 1
|
||||
}
|
||||
let currentFilteredUnreadMark: Int32 = currentFilteredValue.2 ? 1 : 0
|
||||
let initialFilteredUnreadMark: Int32 = initialFilteredValue.2 ? 1 : 0
|
||||
let messageFilteredDifference = max(currentFilteredValue.0, currentFilteredUnreadMark) - max(initialFilteredValue.0, initialFilteredUnreadMark)
|
||||
|
||||
absolute.messageCount += messageDifference
|
||||
absolute.chatCount += chatDifference
|
||||
filtered.messageCount += messageFilteredDifference
|
||||
filtered.chatCount += chatFilteredDifference
|
||||
|
||||
return (absolute, filtered)
|
||||
})
|
||||
}
|
||||
|
||||
updatedRootState = currentTotalRootUnreadState
|
||||
}
|
||||
|
||||
for tag in keptTags {
|
||||
alterTags(&totalGroupUnreadState, peerId, tag, { absolute, filtered in
|
||||
var absolute = absolute
|
||||
var filtered = filtered
|
||||
|
||||
let chatDifference: Int32
|
||||
if initialValue.1 != currentValue.1 {
|
||||
chatDifference = initialValue.1 ? -1 : 1
|
||||
} else {
|
||||
chatDifference = 0
|
||||
}
|
||||
|
||||
let currentUnreadMark: Int32 = currentValue.2 ? 1 : 0
|
||||
let initialUnreadMark: Int32 = initialValue.2 ? 1 : 0
|
||||
let messageDifference = max(currentValue.0, currentUnreadMark) - max(initialValue.0, initialUnreadMark)
|
||||
|
||||
let chatFilteredDifference: Int32
|
||||
if initialFilteredValue.1 != currentFilteredValue.1 {
|
||||
chatFilteredDifference = initialFilteredValue.1 ? -1 : 1
|
||||
} else {
|
||||
chatFilteredDifference = 0
|
||||
}
|
||||
let currentFilteredUnreadMark: Int32 = currentFilteredValue.2 ? 1 : 0
|
||||
let initialFilteredUnreadMark: Int32 = initialFilteredValue.2 ? 1 : 0
|
||||
let messageFilteredDifference = max(currentFilteredValue.0, currentFilteredUnreadMark) - max(initialFilteredValue.0, initialFilteredUnreadMark)
|
||||
|
||||
absolute.messageCount += messageDifference
|
||||
absolute.chatCount += chatDifference
|
||||
filtered.messageCount += messageFilteredDifference
|
||||
filtered.chatCount += chatFilteredDifference
|
||||
|
||||
return (absolute, filtered)
|
||||
})
|
||||
}
|
||||
|
||||
updatedTotalStates[groupId] = totalGroupUnreadState
|
||||
|
||||
var namespaces: [MessageId.Namespace] = []
|
||||
for (namespace, _) in initialStates.states {
|
||||
namespaces.append(namespace)
|
||||
@ -549,10 +537,10 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
if let updatedRootState = updatedRootState {
|
||||
if postbox.messageHistoryMetadataTable.getChatListTotalUnreadState() != updatedRootState {
|
||||
postbox.messageHistoryMetadataTable.setChatListTotalUnreadState(updatedRootState)
|
||||
updatedRootUnreadState = updatedRootState
|
||||
for (groupId, state) in updatedTotalStates {
|
||||
if postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId) != state {
|
||||
postbox.messageHistoryMetadataTable.setTotalUnreadState(groupId: groupId, state: state)
|
||||
updatedTotalUnreadStates[groupId] = state
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,13 +557,15 @@ final class ChatListIndexTable: Table {
|
||||
assert(self.updatedPreviousPeerCachedIndices.isEmpty)
|
||||
}
|
||||
|
||||
func debugReindexUnreadCounts(postbox: Postbox) -> (ChatListTotalUnreadState, [PeerGroupId: PeerGroupUnreadCountersCombinedSummary]) {
|
||||
func debugReindexUnreadCounts(postbox: Postbox) -> ([PeerGroupId: ChatListTotalUnreadState], [PeerGroupId: PeerGroupUnreadCountersCombinedSummary]) {
|
||||
let globalNotificationSettings = postbox.getGlobalNotificationSettings()
|
||||
|
||||
var peerIds: [PeerId] = []
|
||||
for groupId in postbox.chatListTable.existingGroups() + [.root] {
|
||||
let groupPeerIds = postbox.chatListTable.allPeerIds(groupId: groupId)
|
||||
peerIds.append(contentsOf: groupPeerIds)
|
||||
}
|
||||
var rootState = ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:])
|
||||
var totalStates: [PeerGroupId: ChatListTotalUnreadState] = [:]
|
||||
var summaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary] = [:]
|
||||
for peerId in peerIds {
|
||||
guard let peer = postbox.peerTable.get(peerId) else {
|
||||
@ -589,46 +579,50 @@ final class ChatListIndexTable: Table {
|
||||
let notificationSettings = postbox.peerNotificationSettingsTable.getEffective(notificationPeerId)
|
||||
let inclusion = self.get(peerId: peerId)
|
||||
if let (groupId, _) = inclusion.includedIndex(peerId: peerId) {
|
||||
if case .root = groupId {
|
||||
let peerMessageCount = combinedState.count
|
||||
|
||||
let summaryTags = postbox.seedConfiguration.peerSummaryCounterTags(peer, isContact)
|
||||
if totalStates[groupId] == nil {
|
||||
totalStates[groupId] = ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:])
|
||||
}
|
||||
|
||||
let peerMessageCount = combinedState.count
|
||||
|
||||
let summaryTags = postbox.seedConfiguration.peerSummaryCounterTags(peer, isContact)
|
||||
for tag in summaryTags {
|
||||
if totalStates[groupId]!.absoluteCounters[tag] == nil {
|
||||
totalStates[groupId]!.absoluteCounters[tag] = ChatListTotalUnreadCounters(messageCount: 0, chatCount: 0)
|
||||
}
|
||||
var messageCount = totalStates[groupId]!.absoluteCounters[tag]!.messageCount
|
||||
messageCount = messageCount &+ peerMessageCount
|
||||
if messageCount < 0 {
|
||||
messageCount = 0
|
||||
}
|
||||
if combinedState.isUnread {
|
||||
totalStates[groupId]!.absoluteCounters[tag]!.chatCount += 1
|
||||
}
|
||||
if combinedState.markedUnread {
|
||||
messageCount = max(1, messageCount)
|
||||
}
|
||||
totalStates[groupId]!.absoluteCounters[tag]!.messageCount = messageCount
|
||||
}
|
||||
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationPeerId))
|
||||
|
||||
if !isRemovedFromTotalUnreadCount {
|
||||
for tag in summaryTags {
|
||||
if rootState.absoluteCounters[tag] == nil {
|
||||
rootState.absoluteCounters[tag] = ChatListTotalUnreadCounters(messageCount: 0, chatCount: 0)
|
||||
if totalStates[groupId]!.filteredCounters[tag] == nil {
|
||||
totalStates[groupId]!.filteredCounters[tag] = ChatListTotalUnreadCounters(messageCount: 0, chatCount: 0)
|
||||
}
|
||||
var messageCount = rootState.absoluteCounters[tag]!.messageCount
|
||||
var messageCount = totalStates[groupId]!.filteredCounters[tag]!.messageCount
|
||||
messageCount = messageCount &+ peerMessageCount
|
||||
if messageCount < 0 {
|
||||
messageCount = 0
|
||||
}
|
||||
if combinedState.isUnread {
|
||||
rootState.absoluteCounters[tag]!.chatCount += 1
|
||||
totalStates[groupId]!.filteredCounters[tag]!.chatCount += 1
|
||||
}
|
||||
if combinedState.markedUnread {
|
||||
messageCount = max(1, messageCount)
|
||||
}
|
||||
rootState.absoluteCounters[tag]!.messageCount = messageCount
|
||||
}
|
||||
|
||||
if let notificationSettings = notificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
for tag in summaryTags {
|
||||
if rootState.filteredCounters[tag] == nil {
|
||||
rootState.filteredCounters[tag] = ChatListTotalUnreadCounters(messageCount: 0, chatCount: 0)
|
||||
}
|
||||
var messageCount = rootState.filteredCounters[tag]!.messageCount
|
||||
messageCount = messageCount &+ peerMessageCount
|
||||
if messageCount < 0 {
|
||||
messageCount = 0
|
||||
}
|
||||
if combinedState.isUnread {
|
||||
rootState.filteredCounters[tag]!.chatCount += 1
|
||||
}
|
||||
if combinedState.markedUnread {
|
||||
messageCount = max(1, messageCount)
|
||||
}
|
||||
rootState.filteredCounters[tag]!.messageCount = messageCount
|
||||
}
|
||||
totalStates[groupId]!.filteredCounters[tag]!.messageCount = messageCount
|
||||
}
|
||||
}
|
||||
|
||||
@ -647,7 +641,7 @@ final class ChatListIndexTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
return (rootState, summaries)
|
||||
return (totalStates, summaries)
|
||||
}
|
||||
|
||||
func reindexPeerGroupUnreadCounts(postbox: Postbox, groupId: PeerGroupId) -> PeerGroupUnreadCountersCombinedSummary {
|
||||
|
@ -246,17 +246,21 @@ final class ChatListTable: Table {
|
||||
}
|
||||
|
||||
func getUnreadChatListPeerIds(postbox: Postbox, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) -> [PeerId] {
|
||||
let globalNotificationSettings = postbox.getGlobalNotificationSettings()
|
||||
|
||||
var result: [PeerId] = []
|
||||
self.valueBox.range(self.table, start: self.upperBound(groupId: groupId), end: self.lowerBound(groupId: groupId), keys: { key in
|
||||
let (_, _, messageIndex, _) = extractKey(key)
|
||||
if let state = postbox.readStateTable.getCombinedState(messageIndex.id.peerId), state.isUnread {
|
||||
|
||||
let passFilter: Bool
|
||||
if let filterPredicate = filterPredicate {
|
||||
if let peer = postbox.peerTable.get(messageIndex.id.peerId) {
|
||||
let isUnread = postbox.readStateTable.getCombinedState(messageIndex.id.peerId)?.isUnread ?? false
|
||||
let isContact = postbox.contactsTable.isContact(peerId: messageIndex.id.peerId)
|
||||
if filterPredicate.includes(peer: peer, groupId: groupId, notificationSettings: postbox.peerNotificationSettingsTable.getEffective(messageIndex.id.peerId), isUnread: isUnread, isContact: isContact) {
|
||||
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(messageIndex.id.peerId))
|
||||
|
||||
if filterPredicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: isContact) {
|
||||
passFilter = true
|
||||
} else {
|
||||
passFilter = false
|
||||
@ -727,7 +731,7 @@ final class ChatListTable: Table {
|
||||
|
||||
func allPeerIds(groupId: PeerGroupId) -> [PeerId] {
|
||||
var peerIds: [PeerId] = []
|
||||
self.valueBox.range(self.table, start: self.upperBound(groupId: groupId), end: self.lowerBound(groupId: groupId), keys: { key in
|
||||
self.valueBox.range(self.table, start: self.lowerBound(groupId: groupId), end: self.upperBound(groupId: groupId), keys: { key in
|
||||
let (_, _, messageIndex, type) = extractKey(key)
|
||||
if type == ChatListEntryType.message.rawValue {
|
||||
peerIds.append(messageIndex.id.peerId)
|
||||
@ -792,6 +796,8 @@ final class ChatListTable: Table {
|
||||
let lower: ValueBoxKey
|
||||
let upper: ValueBoxKey
|
||||
|
||||
let globalNotificationSettings = postbox.getGlobalNotificationSettings()
|
||||
|
||||
switch position {
|
||||
case let .earlier(index):
|
||||
upper = self.upperBound(groupId: groupId)
|
||||
@ -818,18 +824,16 @@ final class ChatListTable: Table {
|
||||
let peerId = index.messageIndex.id.peerId
|
||||
if let readState = postbox.readStateTable.getCombinedState(peerId), readState.isUnread {
|
||||
if filtered {
|
||||
var notificationSettings: PeerNotificationSettings?
|
||||
if let peer = postbox.peerTable.get(peerId) {
|
||||
if let notificationSettingsPeerId = peer.notificationSettingsPeerId {
|
||||
notificationSettings = postbox.peerNotificationSettingsTable.getEffective(notificationSettingsPeerId)
|
||||
} else {
|
||||
notificationSettings = postbox.peerNotificationSettingsTable.getEffective(peerId)
|
||||
let notificationSettingsPeerId = peer.notificationSettingsPeerId ?? peerId
|
||||
let notificationSettings = postbox.peerNotificationSettingsTable.getEffective(notificationSettingsPeerId)
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: notificationSettings)
|
||||
|
||||
if !isRemovedFromTotalUnreadCount {
|
||||
result = index
|
||||
return false
|
||||
}
|
||||
}
|
||||
if let notificationSettings = notificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
result = index
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
result = index
|
||||
return false
|
||||
|
@ -88,7 +88,7 @@ public struct ChatListGroupReferenceEntry: Equatable {
|
||||
}
|
||||
|
||||
public enum ChatListEntry: Comparable {
|
||||
case MessageEntry(ChatListIndex, Message?, CombinedPeerReadState?, PeerNotificationSettings?, PeerChatListEmbeddedInterfaceState?, RenderedPeer, PeerPresence?, ChatListMessageTagSummaryInfo, Bool, Bool)
|
||||
case MessageEntry(index: ChatListIndex, message: Message?, readState: CombinedPeerReadState?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: PeerChatListEmbeddedInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, hasFailed: Bool, isContact: Bool)
|
||||
case HoleEntry(ChatListHole)
|
||||
|
||||
public var index: ChatListIndex {
|
||||
@ -102,9 +102,9 @@ public enum ChatListEntry: Comparable {
|
||||
|
||||
public static func ==(lhs: ChatListEntry, rhs: ChatListEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .MessageEntry(lhsIndex, lhsMessage, lhsReadState, lhsSettings, lhsEmbeddedState, lhsPeer, lhsPresence, lhsInfo, lhsHasFailed, lhsIsContact):
|
||||
case let .MessageEntry(lhsIndex, lhsMessage, lhsReadState, lhsIsRemovedFromTotalUnreadCount, lhsEmbeddedState, lhsPeer, lhsPresence, lhsInfo, lhsHasFailed, lhsIsContact):
|
||||
switch rhs {
|
||||
case let .MessageEntry(rhsIndex, rhsMessage, rhsReadState, rhsSettings, rhsEmbeddedState, rhsPeer, rhsPresence, rhsInfo, rhsHasFailed, rhsIsContact):
|
||||
case let .MessageEntry(rhsIndex, rhsMessage, rhsReadState, rhsIsRemovedFromTotalUnreadCount, rhsEmbeddedState, rhsPeer, rhsPresence, rhsInfo, rhsHasFailed, rhsIsContact):
|
||||
if lhsIndex != rhsIndex {
|
||||
return false
|
||||
}
|
||||
@ -114,11 +114,7 @@ public enum ChatListEntry: Comparable {
|
||||
if lhsMessage?.stableVersion != rhsMessage?.stableVersion {
|
||||
return false
|
||||
}
|
||||
if let lhsSettings = lhsSettings, let rhsSettings = rhsSettings {
|
||||
if !lhsSettings.isEqual(to: rhsSettings) {
|
||||
return false
|
||||
}
|
||||
} else if (lhsSettings != nil) != (rhsSettings != nil) {
|
||||
if lhsIsRemovedFromTotalUnreadCount != rhsIsRemovedFromTotalUnreadCount {
|
||||
return false
|
||||
}
|
||||
if let lhsEmbeddedState = lhsEmbeddedState, let rhsEmbeddedState = rhsEmbeddedState {
|
||||
@ -184,7 +180,7 @@ public enum ChatListEntry: Comparable {
|
||||
|
||||
enum MutableChatListEntry: Equatable {
|
||||
case IntermediateMessageEntry(index: ChatListIndex, messageIndex: MessageIndex?)
|
||||
case MessageEntry(index: ChatListIndex, message: Message?, readState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, embeddedInterfaceState: PeerChatListEmbeddedInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, tagSummaryInfo: ChatListMessageTagSummaryInfo, hasFailedMessages: Bool, isContact: Bool)
|
||||
case MessageEntry(index: ChatListIndex, message: Message?, readState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: PeerChatListEmbeddedInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, tagSummaryInfo: ChatListMessageTagSummaryInfo, hasFailedMessages: Bool, isContact: Bool)
|
||||
case HoleEntry(ChatListHole)
|
||||
|
||||
init(_ intermediateEntry: ChatListIntermediateEntry, cachedDataTable: CachedPeerDataTable, readStateTable: MessageHistoryReadStateTable, messageHistoryTable: MessageHistoryTable) {
|
||||
@ -200,7 +196,7 @@ enum MutableChatListEntry: Equatable {
|
||||
switch self {
|
||||
case let .IntermediateMessageEntry(intermediateMessageEntry):
|
||||
return intermediateMessageEntry.index
|
||||
case let .MessageEntry(index, _, _, _, _, _, _, _, _, _):
|
||||
case let .MessageEntry(index, _, _, _, _, _, _, _, _, _, _):
|
||||
return index
|
||||
case let .HoleEntry(hole):
|
||||
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
|
||||
@ -258,16 +254,16 @@ public struct ChatListFilterPredicate {
|
||||
public var includePeerIds: Set<PeerId>
|
||||
public var excludePeerIds: Set<PeerId>
|
||||
public var includeAdditionalPeerGroupIds: [PeerGroupId]
|
||||
public var include: (Peer, PeerNotificationSettings?, Bool, Bool) -> Bool
|
||||
public var include: (Peer, Bool, Bool, Bool) -> Bool
|
||||
|
||||
public init(includePeerIds: Set<PeerId>, excludePeerIds: Set<PeerId>, includeAdditionalPeerGroupIds: [PeerGroupId], include: @escaping (Peer, PeerNotificationSettings?, Bool, Bool) -> Bool) {
|
||||
public init(includePeerIds: Set<PeerId>, excludePeerIds: Set<PeerId>, includeAdditionalPeerGroupIds: [PeerGroupId], include: @escaping (Peer, Bool, Bool, Bool) -> Bool) {
|
||||
self.includePeerIds = includePeerIds
|
||||
self.excludePeerIds = excludePeerIds
|
||||
self.includeAdditionalPeerGroupIds = includeAdditionalPeerGroupIds
|
||||
self.include = include
|
||||
}
|
||||
|
||||
func includes(peer: Peer, groupId: PeerGroupId, notificationSettings: PeerNotificationSettings?, isUnread: Bool, isContact: Bool) -> Bool {
|
||||
func includes(peer: Peer, groupId: PeerGroupId, isRemovedFromTotalUnreadCount: Bool, isUnread: Bool, isContact: Bool) -> Bool {
|
||||
let includePeerId = peer.associatedPeerId ?? peer.id
|
||||
if self.excludePeerIds.contains(includePeerId) {
|
||||
return false
|
||||
@ -280,7 +276,7 @@ public struct ChatListFilterPredicate {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return self.include(peer, notificationSettings, isUnread, isContact)
|
||||
return self.include(peer, isRemovedFromTotalUnreadCount, isUnread, isContact)
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,9 +420,15 @@ final class MutableChatListView {
|
||||
func replay(postbox: Postbox, operations: [PeerGroupId: [ChatListOperation]], updatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)], updatedPeers: [PeerId: Peer], updatedPeerPresences: [PeerId: PeerPresence], transaction: PostboxTransaction, context: MutableChatListViewReplayContext) -> Bool {
|
||||
var hasChanges = false
|
||||
|
||||
if self.state.replay(postbox: postbox, transaction: transaction) {
|
||||
if transaction.updatedGlobalNotificationSettings {
|
||||
self.state = ChatListViewState(postbox: postbox, spaces: self.spaces, anchorIndex: .absoluteUpperBound, filterPredicate: self.filterPredicate, summaryComponents: self.summaryComponents, halfLimit: self.count)
|
||||
self.sampledState = self.state.sample(postbox: postbox)
|
||||
hasChanges = true
|
||||
} else {
|
||||
if self.state.replay(postbox: postbox, transaction: transaction) {
|
||||
self.sampledState = self.state.sample(postbox: postbox)
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
|
||||
if case .root = self.groupId, self.filterPredicate == nil {
|
||||
@ -620,8 +622,8 @@ public final class ChatListView {
|
||||
var entries: [ChatListEntry] = []
|
||||
for entry in mutableView.sampledState.entries {
|
||||
switch entry {
|
||||
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact):
|
||||
entries.append(.MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact))
|
||||
case let .MessageEntry(index, message, combinedReadState, _, isRemovedFromTotalUnreadCount, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact):
|
||||
entries.append(.MessageEntry(index: index, message: message, readState: combinedReadState, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: embeddedState, renderedPeer: peer, presence: peerPresence, summaryInfo: summaryInfo, hasFailed: hasFailed, isContact: isContact))
|
||||
case let .HoleEntry(hole):
|
||||
entries.append(.HoleEntry(hole))
|
||||
case .IntermediateMessageEntry:
|
||||
|
@ -19,6 +19,7 @@ enum ChatListViewSpace: Hashable {
|
||||
}
|
||||
|
||||
private func mappedChatListFilterPredicate(postbox: Postbox, groupId: PeerGroupId, predicate: ChatListFilterPredicate) -> (ChatListIntermediateEntry) -> Bool {
|
||||
let globalNotificationSettings = postbox.getGlobalNotificationSettings()
|
||||
return { entry in
|
||||
switch entry {
|
||||
case let .message(index, _):
|
||||
@ -26,7 +27,9 @@ private func mappedChatListFilterPredicate(postbox: Postbox, groupId: PeerGroupI
|
||||
let isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false
|
||||
let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id
|
||||
let isContact = postbox.contactsTable.isContact(peerId: notificationsPeerId)
|
||||
if predicate.includes(peer: peer, groupId: groupId, notificationSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId), isUnread: isUnread, isContact: isContact) {
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId))
|
||||
|
||||
if predicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: isContact) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -206,6 +209,7 @@ private final class ChatListViewSpaceState {
|
||||
func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool {
|
||||
var hasUpdates = false
|
||||
var hadRemovals = false
|
||||
var globalNotificationSettings: PostboxGlobalNotificationSettings?
|
||||
for (groupId, operations) in transaction.chatListOperations {
|
||||
let matchesSpace: Bool
|
||||
switch self.space {
|
||||
@ -230,7 +234,17 @@ private final class ChatListViewSpaceState {
|
||||
if let filterPredicate = self.filterPredicate {
|
||||
if let peer = postbox.peerTable.get(updatedIndex.messageIndex.id.peerId) {
|
||||
let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id
|
||||
if !filterPredicate.includes(peer: peer, groupId: groupId, notificationSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId), isUnread: postbox.readStateTable.getCombinedState(peer.id)?.isUnread ?? false, isContact: postbox.contactsTable.isContact(peerId: notificationsPeerId)) {
|
||||
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
||||
if let current = globalNotificationSettings {
|
||||
globalNotificationSettingsValue = current
|
||||
} else {
|
||||
globalNotificationSettingsValue = postbox.getGlobalNotificationSettings()
|
||||
globalNotificationSettings = globalNotificationSettingsValue
|
||||
}
|
||||
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId))
|
||||
|
||||
if !filterPredicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: postbox.readStateTable.getCombinedState(peer.id)?.isUnread ?? false, isContact: postbox.contactsTable.isContact(peerId: notificationsPeerId)) {
|
||||
continue inner
|
||||
}
|
||||
} else {
|
||||
@ -300,8 +314,20 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
if let settingsChange = transaction.currentUpdatedPeerNotificationSettings[entryNotificationsPeerId] {
|
||||
let isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false
|
||||
let wasIncluded = filterPredicate.includes(peer: entryPeer, groupId: groupId, notificationSettings: settingsChange.0, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: entryNotificationsPeerId))
|
||||
let isIncluded = filterPredicate.includes(peer: entryPeer, groupId: groupId, notificationSettings: settingsChange.1, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: entryNotificationsPeerId))
|
||||
|
||||
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
||||
if let current = globalNotificationSettings {
|
||||
globalNotificationSettingsValue = current
|
||||
} else {
|
||||
globalNotificationSettingsValue = postbox.getGlobalNotificationSettings()
|
||||
globalNotificationSettings = globalNotificationSettingsValue
|
||||
}
|
||||
|
||||
let wasRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: entryPeer, peerSettings: settingsChange.0)
|
||||
let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: entryPeer, peerSettings: settingsChange.1)
|
||||
|
||||
let wasIncluded = filterPredicate.includes(peer: entryPeer, groupId: groupId, isRemovedFromTotalUnreadCount: wasRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: entryNotificationsPeerId))
|
||||
let isIncluded = filterPredicate.includes(peer: entryPeer, groupId: groupId, isRemovedFromTotalUnreadCount: nowRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: entryNotificationsPeerId))
|
||||
if wasIncluded != isIncluded {
|
||||
if !isIncluded {
|
||||
removeEntryIndices.append(entry.entryIndex)
|
||||
@ -328,8 +354,20 @@ private final class ChatListViewSpaceState {
|
||||
assert(Set(peers.map { $0.id }).count == peers.count)
|
||||
|
||||
let isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false
|
||||
let wasIncluded = filterPredicate.includes(peer: mainPeer, groupId: groupId, notificationSettings: settingsChange.0, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: peerId))
|
||||
let isIncluded = filterPredicate.includes(peer: mainPeer, groupId: groupId, notificationSettings: settingsChange.1, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: peerId))
|
||||
|
||||
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
||||
if let current = globalNotificationSettings {
|
||||
globalNotificationSettingsValue = current
|
||||
} else {
|
||||
globalNotificationSettingsValue = postbox.getGlobalNotificationSettings()
|
||||
globalNotificationSettings = globalNotificationSettingsValue
|
||||
}
|
||||
|
||||
let wasRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: mainPeer, peerSettings: settingsChange.0)
|
||||
let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: mainPeer, peerSettings: settingsChange.1)
|
||||
|
||||
let wasIncluded = filterPredicate.includes(peer: mainPeer, groupId: groupId, isRemovedFromTotalUnreadCount: wasRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: peerId))
|
||||
let isIncluded = filterPredicate.includes(peer: mainPeer, groupId: groupId, isRemovedFromTotalUnreadCount: nowRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: peerId))
|
||||
if wasIncluded != isIncluded {
|
||||
if isIncluded {
|
||||
for peer in peers {
|
||||
@ -356,13 +394,17 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
|
||||
if !transaction.currentUpdatedPeerNotificationSettings.isEmpty {
|
||||
let globalNotificationSettings = postbox.getGlobalNotificationSettings()
|
||||
|
||||
if self.orderedEntries.mutableScan({ entry in
|
||||
switch entry {
|
||||
case let .MessageEntry(messageEntry):
|
||||
if let peer = messageEntry.renderedPeer.peer {
|
||||
let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id
|
||||
if let (_, updated) = transaction.currentUpdatedPeerNotificationSettings[notificationsPeerId] {
|
||||
return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: updated, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact)
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: updated)
|
||||
|
||||
return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: updated, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -382,7 +424,7 @@ private final class ChatListViewSpaceState {
|
||||
switch entry {
|
||||
case let .MessageEntry(messageEntry):
|
||||
if transaction.updatedFailedMessagePeerIds.contains(messageEntry.index.messageIndex.id.peerId) {
|
||||
return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: postbox.messageHistoryFailedTable.contains(peerId: messageEntry.index.messageIndex.id.peerId), isContact: messageEntry.isContact)
|
||||
return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, isRemovedFromTotalUnreadCount: messageEntry.isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: postbox.messageHistoryFailedTable.contains(peerId: messageEntry.index.messageIndex.id.peerId), isContact: messageEntry.isContact)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -405,7 +447,7 @@ private final class ChatListViewSpaceState {
|
||||
let renderedPeer = updatedRenderedPeer(messageEntry.renderedPeer, updatedPeers: transaction.currentUpdatedPeers)
|
||||
|
||||
if updatedMessage != nil || renderedPeer != nil {
|
||||
return .MessageEntry(index: messageEntry.index, message: updatedMessage ?? messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: renderedPeer ?? messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact)
|
||||
return .MessageEntry(index: messageEntry.index, message: updatedMessage ?? messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, isRemovedFromTotalUnreadCount: messageEntry.isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: renderedPeer ?? messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -426,7 +468,7 @@ private final class ChatListViewSpaceState {
|
||||
presencePeerId = associatedPeerId
|
||||
}
|
||||
if let presence = transaction.currentUpdatedPeerPresences[presencePeerId] {
|
||||
return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact)
|
||||
return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, isRemovedFromTotalUnreadCount: messageEntry.isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -462,7 +504,7 @@ private final class ChatListViewSpaceState {
|
||||
if updatedTagSummaryCount != nil || updatedActionsSummaryCount != nil {
|
||||
let summaryInfo = ChatListMessageTagSummaryInfo(tagSummaryCount: updatedTagSummaryCount ?? messageEntry.tagSummaryInfo.tagSummaryCount, actionsSummaryCount: updatedActionsSummaryCount ?? messageEntry.tagSummaryInfo.actionsSummaryCount)
|
||||
|
||||
return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: summaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact)
|
||||
return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, isRemovedFromTotalUnreadCount: messageEntry.isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: summaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -958,7 +1000,16 @@ struct ChatListViewState {
|
||||
|
||||
let tagSummaryInfo = ChatListMessageTagSummaryInfo(tagSummaryCount: tagSummaryCount, actionsSummaryCount: actionsSummaryCount)
|
||||
|
||||
let updatedEntry: MutableChatListEntry = .MessageEntry(index: index, message: messageIndex.flatMap(postbox.messageHistoryTable.getMessage).flatMap(postbox.renderIntermediateMessage), readState: postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId), notificationSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId), embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId)?.chatListEmbeddedState, renderedPeer: renderedPeer, presence: postbox.peerPresenceTable.get(index.messageIndex.id.peerId), tagSummaryInfo: tagSummaryInfo, hasFailedMessages: false, isContact: postbox.contactsTable.isContact(peerId: index.messageIndex.id.peerId))
|
||||
let notificationSettings = postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId)
|
||||
|
||||
let isRemovedFromTotalUnreadCount: Bool
|
||||
if let peer = renderedPeer.peers[notificationsPeerId] {
|
||||
isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: postbox.getGlobalNotificationSettings(), peer: peer, peerSettings: notificationSettings)
|
||||
} else {
|
||||
isRemovedFromTotalUnreadCount = false
|
||||
}
|
||||
|
||||
let updatedEntry: MutableChatListEntry = .MessageEntry(index: index, message: messageIndex.flatMap(postbox.messageHistoryTable.getMessage).flatMap(postbox.renderIntermediateMessage), readState: postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId), notificationSettings: notificationSettings, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId)?.chatListEmbeddedState, renderedPeer: renderedPeer, presence: postbox.peerPresenceTable.get(index.messageIndex.id.peerId), tagSummaryInfo: tagSummaryInfo, hasFailedMessages: false, isContact: postbox.contactsTable.isContact(peerId: index.messageIndex.id.peerId))
|
||||
if directionIndex == 0 {
|
||||
self.stateBySpace[space]!.orderedEntries.setLowerOrAtAnchorAtArrayIndex(listIndex, to: updatedEntry)
|
||||
} else {
|
||||
|
@ -11,6 +11,7 @@ private enum MetadataPrefix: Int8 {
|
||||
case ShouldReindexUnreadCounts = 8
|
||||
case PeerHistoryInitialized = 9
|
||||
case ShouldReindexUnreadCountsState = 10
|
||||
case TotalUnreadCountStates = 11
|
||||
}
|
||||
|
||||
public struct ChatListTotalUnreadCounters: PostboxCoding, Equatable {
|
||||
@ -58,8 +59,8 @@ final class MessageHistoryMetadataTable: Table {
|
||||
private var nextMessageStableId: UInt32?
|
||||
private var nextMessageStableIdUpdated = false
|
||||
|
||||
private var chatListTotalUnreadState: ChatListTotalUnreadState?
|
||||
private var chatListTotalUnreadStateUpdated = false
|
||||
private var chatListTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState] = [:]
|
||||
private var updatedChatListTotalUnreadStates = Set<PeerGroupId>()
|
||||
|
||||
private var nextPeerOperationLogIndex: UInt32?
|
||||
private var nextPeerOperationLogIndexUpdated = false
|
||||
@ -99,6 +100,23 @@ final class MessageHistoryMetadataTable: Table {
|
||||
return key
|
||||
}
|
||||
|
||||
private func totalUnreadCountStateKey(groupId: PeerGroupId) -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 1 + 4)
|
||||
key.setInt8(0, value: MetadataPrefix.TotalUnreadCountStates.rawValue)
|
||||
key.setInt32(1, value: groupId.rawValue)
|
||||
return key
|
||||
}
|
||||
|
||||
private func totalUnreadCountLowerBound() -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 1)
|
||||
key.setInt8(0, value: MetadataPrefix.TotalUnreadCountStates.rawValue)
|
||||
return key
|
||||
}
|
||||
|
||||
private func totalUnreadCountUpperBound() -> ValueBoxKey {
|
||||
return self.totalUnreadCountLowerBound().successor
|
||||
}
|
||||
|
||||
func setInitializedChatList(groupId: PeerGroupId) {
|
||||
switch groupId {
|
||||
case .root:
|
||||
@ -283,28 +301,38 @@ final class MessageHistoryMetadataTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
func getChatListTotalUnreadState() -> ChatListTotalUnreadState {
|
||||
if let cached = self.chatListTotalUnreadState {
|
||||
func removeAllTotalUnreadStates() {
|
||||
var groupIds: [PeerGroupId] = []
|
||||
self.valueBox.range(self.table, start: self.totalUnreadCountLowerBound(), end: self.totalUnreadCountUpperBound(), keys: { key in
|
||||
let groupId = key.getInt32(1)
|
||||
groupIds.append(PeerGroupId(rawValue: groupId))
|
||||
return true
|
||||
}, limit: 0)
|
||||
for groupId in groupIds {
|
||||
self.setTotalUnreadState(groupId: groupId, state: ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:]))
|
||||
}
|
||||
}
|
||||
|
||||
func getTotalUnreadState(groupId: PeerGroupId) -> ChatListTotalUnreadState {
|
||||
if let cached = self.chatListTotalUnreadStates[groupId] {
|
||||
return cached
|
||||
} else {
|
||||
if let value = self.valueBox.get(self.table, key: self.key(.ChatListTotalUnreadState)), let state = PostboxDecoder(buffer: value).decodeObjectForKey("_", decoder: {
|
||||
ChatListTotalUnreadState(decoder: $0)
|
||||
}) as? ChatListTotalUnreadState {
|
||||
self.chatListTotalUnreadState = state
|
||||
if let value = self.valueBox.get(self.table, key: self.totalUnreadCountStateKey(groupId: groupId)), let state = PostboxDecoder(buffer: value).decodeObjectForKey("_", decoder: { ChatListTotalUnreadState(decoder: $0) }) as? ChatListTotalUnreadState {
|
||||
self.chatListTotalUnreadStates[groupId] = state
|
||||
return state
|
||||
} else {
|
||||
let state = ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:])
|
||||
self.chatListTotalUnreadState = state
|
||||
self.chatListTotalUnreadStates[groupId] = state
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setChatListTotalUnreadState(_ state: ChatListTotalUnreadState) {
|
||||
let current = self.getChatListTotalUnreadState()
|
||||
func setTotalUnreadState(groupId: PeerGroupId, state: ChatListTotalUnreadState) {
|
||||
let current = self.getTotalUnreadState(groupId: groupId)
|
||||
if current != state {
|
||||
self.chatListTotalUnreadState = state
|
||||
self.chatListTotalUnreadStateUpdated = true
|
||||
self.chatListTotalUnreadStates[groupId] = state
|
||||
self.updatedChatListTotalUnreadStates.insert(groupId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,8 +343,8 @@ final class MessageHistoryMetadataTable: Table {
|
||||
self.updatedPeerNextMessageIdByNamespace.removeAll()
|
||||
self.nextMessageStableId = nil
|
||||
self.nextMessageStableIdUpdated = false
|
||||
self.chatListTotalUnreadState = nil
|
||||
self.chatListTotalUnreadStateUpdated = false
|
||||
self.chatListTotalUnreadStates.removeAll()
|
||||
self.updatedChatListTotalUnreadStates.removeAll()
|
||||
}
|
||||
|
||||
override func beforeCommit() {
|
||||
@ -351,13 +379,13 @@ final class MessageHistoryMetadataTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
if self.chatListTotalUnreadStateUpdated {
|
||||
if let state = self.chatListTotalUnreadState {
|
||||
for groupId in self.updatedChatListTotalUnreadStates {
|
||||
if let state = self.chatListTotalUnreadStates[groupId] {
|
||||
let buffer = PostboxEncoder()
|
||||
buffer.encodeObject(state, forKey: "_")
|
||||
self.valueBox.set(self.table, key: self.key(.ChatListTotalUnreadState), value: buffer.readBufferNoCopy())
|
||||
self.valueBox.set(self.table, key: self.totalUnreadCountStateKey(groupId: groupId), value: buffer.readBufferNoCopy())
|
||||
}
|
||||
self.chatListTotalUnreadStateUpdated = false
|
||||
self.updatedChatListTotalUnreadStates.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,23 @@ public enum PeerNotificationSettingsBehavior: PostboxCoding {
|
||||
}
|
||||
|
||||
public protocol PeerNotificationSettings: PostboxCoding {
|
||||
var isRemovedFromTotalUnreadCount: Bool { get }
|
||||
func isRemovedFromTotalUnreadCount(`default`: Bool) -> Bool
|
||||
var behavior: PeerNotificationSettingsBehavior { get }
|
||||
|
||||
func isEqual(to: PeerNotificationSettings) -> Bool
|
||||
}
|
||||
|
||||
public protocol PostboxGlobalNotificationSettings: PostboxCoding {
|
||||
func defaultIncludePeer(peer: Peer) -> Bool
|
||||
|
||||
func isEqualInDefaultPeerInclusion(other: PostboxGlobalNotificationSettings) -> Bool
|
||||
}
|
||||
|
||||
public func resolvedIsRemovedFromTotalUnreadCount(globalSettings: PostboxGlobalNotificationSettings, peer: Peer, peerSettings: PeerNotificationSettings?) -> Bool {
|
||||
let defaultValue = !globalSettings.defaultIncludePeer(peer: peer)
|
||||
if let peerSettings = peerSettings {
|
||||
return peerSettings.isRemovedFromTotalUnreadCount(default: defaultValue)
|
||||
} else {
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
|
@ -199,20 +199,24 @@ final class PeerNotificationSettingsTable: Table {
|
||||
var added = Set<PeerId>()
|
||||
var removed = Set<PeerId>()
|
||||
|
||||
var globalNotificationSettings: PostboxGlobalNotificationSettings?
|
||||
|
||||
for (peerId, initialSettings) in self.updatedInitialSettings {
|
||||
guard let peer = postbox.peerTable.get(peerId) else {
|
||||
continue
|
||||
}
|
||||
var wasParticipating = false
|
||||
let include = shouldPeerParticipateInUnreadCountStats(peer: peer)
|
||||
|
||||
if include, let initialEffective = initialSettings.effective {
|
||||
wasParticipating = !initialEffective.isRemovedFromTotalUnreadCount
|
||||
}
|
||||
var isParticipating = false
|
||||
if include, let resultEffective = self.cachedSettings[peerId]?.effective {
|
||||
isParticipating = !resultEffective.isRemovedFromTotalUnreadCount
|
||||
let globalNotificationSettingsValue: PostboxGlobalNotificationSettings
|
||||
if let current = globalNotificationSettings {
|
||||
globalNotificationSettingsValue = current
|
||||
} else {
|
||||
globalNotificationSettingsValue = postbox.getGlobalNotificationSettings()
|
||||
globalNotificationSettings = globalNotificationSettingsValue
|
||||
}
|
||||
|
||||
let wasParticipating = !resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: peer, peerSettings: initialSettings.effective)
|
||||
let isParticipating = !resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: peer, peerSettings: self.cachedSettings[peerId]?.effective)
|
||||
|
||||
if wasParticipating != isParticipating {
|
||||
if isParticipating {
|
||||
added.insert(peerId)
|
||||
|
@ -212,6 +212,15 @@ public final class Transaction {
|
||||
self.postbox?.setPeerChatState(id, state: state)
|
||||
}
|
||||
|
||||
public func getGlobalNotificationSettings() -> PostboxGlobalNotificationSettings {
|
||||
assert(!self.disposed)
|
||||
if let postbox = self.postbox {
|
||||
return postbox.getGlobalNotificationSettings()
|
||||
} else {
|
||||
preconditionFailure()
|
||||
}
|
||||
}
|
||||
|
||||
/*public func getPeerGroupState(_ id: PeerGroupId) -> PeerGroupState? {
|
||||
assert(!self.disposed)
|
||||
return self.postbox?.peerGroupStateTable.get(id)
|
||||
@ -754,10 +763,10 @@ public final class Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
public func getTotalUnreadState() -> ChatListTotalUnreadState {
|
||||
public func getTotalUnreadState(groupId: PeerGroupId) -> ChatListTotalUnreadState {
|
||||
assert(!self.disposed)
|
||||
if let postbox = self.postbox {
|
||||
return postbox.messageHistoryMetadataTable.getChatListTotalUnreadState()
|
||||
return postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId)
|
||||
} else {
|
||||
return ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:])
|
||||
}
|
||||
@ -775,6 +784,8 @@ public final class Transaction {
|
||||
|
||||
var count = 0
|
||||
|
||||
let globalNotificationSettings = self.getGlobalNotificationSettings()
|
||||
|
||||
var groupIds: [PeerGroupId] = [.root]
|
||||
groupIds.append(contentsOf: predicate.includeAdditionalPeerGroupIds)
|
||||
for groupId in groupIds {
|
||||
@ -783,7 +794,9 @@ public final class Transaction {
|
||||
let isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false
|
||||
let notificationsPeerId = peer.notificationSettingsPeerId ?? peerId
|
||||
let isContact = postbox.contactsTable.isContact(peerId: notificationsPeerId)
|
||||
if predicate.includes(peer: peer, groupId: groupId, notificationSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId), isUnread: isUnread, isContact: isContact) {
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId))
|
||||
|
||||
if predicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: isContact) {
|
||||
includedPeerIds[peer.id] = true
|
||||
return true
|
||||
} else {
|
||||
@ -1123,7 +1136,7 @@ public final class Postbox {
|
||||
private var currentUpdatedCachedPeerData: [PeerId: CachedPeerData] = [:]
|
||||
private var currentUpdatedPeerPresences: [PeerId: PeerPresence] = [:]
|
||||
private var currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?] = [:]
|
||||
private var currentUpdatedTotalUnreadState: ChatListTotalUnreadState?
|
||||
private var currentUpdatedTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState] = [:]
|
||||
private var currentUpdatedGroupTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary] = [:]
|
||||
private var currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation] = []
|
||||
private var currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation] = []
|
||||
@ -1148,6 +1161,8 @@ public final class Postbox {
|
||||
private var currentUpdatedNoticeEntryKeys = Set<NoticeEntryKey>()
|
||||
private var currentUpdatedCacheEntryKeys = Set<ItemCacheEntryId>()
|
||||
|
||||
private var currentNeedsReindexUnreadCounters: Bool = false
|
||||
|
||||
private let statePipe: ValuePipe<PostboxCoding> = ValuePipe()
|
||||
private var masterClientId = Promise<Int64>()
|
||||
|
||||
@ -1384,8 +1399,6 @@ public final class Postbox {
|
||||
return self.cachedPeerDataTable.get(peerId)
|
||||
}, getPeerPresence: { peerId in
|
||||
return self.peerPresenceTable.get(peerId)
|
||||
}, getTotalUnreadState: {
|
||||
return self.messageHistoryMetadataTable.getChatListTotalUnreadState()
|
||||
}, getPeerReadState: { peerId in
|
||||
return self.readStateTable.getCombinedState(peerId)
|
||||
}, operationLogGetOperations: { tag, fromIndex, limit in
|
||||
@ -1415,9 +1428,12 @@ public final class Postbox {
|
||||
if self.messageHistoryMetadataTable.shouldReindexUnreadCounts() {
|
||||
self.groupMessageStatsTable.removeAll()
|
||||
let startTime = CFAbsoluteTimeGetCurrent()
|
||||
let (rootState, summaries) = self.chatListIndexTable.debugReindexUnreadCounts(postbox: self)
|
||||
let (totalStates, summaries) = self.chatListIndexTable.debugReindexUnreadCounts(postbox: self)
|
||||
|
||||
self.messageHistoryMetadataTable.setChatListTotalUnreadState(rootState)
|
||||
self.messageHistoryMetadataTable.removeAllTotalUnreadStates()
|
||||
for (groupId, state) in totalStates {
|
||||
self.messageHistoryMetadataTable.setTotalUnreadState(groupId: groupId, state: state)
|
||||
}
|
||||
for (groupId, summary) in summaries {
|
||||
self.groupMessageStatsTable.set(groupId: groupId, summary: summary)
|
||||
}
|
||||
@ -1746,9 +1762,13 @@ public final class Postbox {
|
||||
}
|
||||
}
|
||||
let transactionParticipationInTotalUnreadCountUpdates = self.peerNotificationSettingsTable.transactionParticipationInTotalUnreadCountUpdates(postbox: self)
|
||||
self.chatListIndexTable.commitWithTransaction(postbox: self, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, updatedPeers: updatedPeers, transactionParticipationInTotalUnreadCountUpdates: transactionParticipationInTotalUnreadCountUpdates, updatedRootUnreadState: &self.currentUpdatedTotalUnreadState, updatedGroupTotalUnreadSummaries: &self.currentUpdatedGroupTotalUnreadSummaries, currentUpdatedGroupSummarySynchronizeOperations: &self.currentUpdatedGroupSummarySynchronizeOperations)
|
||||
self.chatListIndexTable.commitWithTransaction(postbox: self, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, updatedPeers: updatedPeers, transactionParticipationInTotalUnreadCountUpdates: transactionParticipationInTotalUnreadCountUpdates, updatedTotalUnreadStates: &self.currentUpdatedTotalUnreadStates, updatedGroupTotalUnreadSummaries: &self.currentUpdatedGroupTotalUnreadSummaries, currentUpdatedGroupSummarySynchronizeOperations: &self.currentUpdatedGroupSummarySynchronizeOperations)
|
||||
|
||||
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, currentUpdatedTotalUnreadState: self.currentUpdatedTotalUnreadState, 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)
|
||||
if self.currentNeedsReindexUnreadCounters {
|
||||
self.reindexUnreadCounters()
|
||||
}
|
||||
|
||||
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)
|
||||
var updatedTransactionState: Int64?
|
||||
var updatedMasterClientId: Int64?
|
||||
if !transaction.isEmpty {
|
||||
@ -1785,7 +1805,7 @@ public final class Postbox {
|
||||
self.currentUpdatedCachedPeerData.removeAll()
|
||||
self.currentUpdatedPeerPresences.removeAll()
|
||||
self.currentUpdatedPeerChatListEmbeddedStates.removeAll()
|
||||
self.currentUpdatedTotalUnreadState = nil
|
||||
self.currentUpdatedTotalUnreadStates.removeAll()
|
||||
self.currentUpdatedGroupTotalUnreadSummaries.removeAll()
|
||||
self.currentPeerMergedOperationLogOperations.removeAll()
|
||||
self.currentTimestampBasedMessageAttributesOperations.removeAll()
|
||||
@ -1800,6 +1820,7 @@ public final class Postbox {
|
||||
self.currentInvalidateMessageTagSummaries.removeAll()
|
||||
self.currentUpdatedPendingPeerNotificationSettings.removeAll()
|
||||
self.currentGroupIdsWithUpdatedReadStats.removeAll()
|
||||
self.currentNeedsReindexUnreadCounters = false
|
||||
|
||||
for table in self.tables {
|
||||
table.beforeCommit()
|
||||
@ -2421,7 +2442,7 @@ public final class Postbox {
|
||||
case let .peerChatState(peerId):
|
||||
additionalDataEntries.append(.peerChatState(peerId, self.peerChatStateTable.get(peerId) as? PeerChatState))
|
||||
case .totalUnreadState:
|
||||
additionalDataEntries.append(.totalUnreadState(self.messageHistoryMetadataTable.getChatListTotalUnreadState()))
|
||||
additionalDataEntries.append(.totalUnreadState(self.messageHistoryMetadataTable.getTotalUnreadState(groupId: .root)))
|
||||
case let .peerNotificationSettings(peerId):
|
||||
var notificationPeerId = peerId
|
||||
if let peer = self.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId {
|
||||
@ -3063,6 +3084,14 @@ public final class Postbox {
|
||||
}
|
||||
|
||||
fileprivate func setPreferencesEntry(key: ValueBoxKey, value: PreferencesEntry?) {
|
||||
if key == self.seedConfiguration.globalNotificationSettingsPreferencesKey {
|
||||
let current = self.getGlobalNotificationSettings()
|
||||
let updated = value as? PostboxGlobalNotificationSettings ?? self.seedConfiguration.defaultGlobalNotificationSettings
|
||||
if !current.isEqualInDefaultPeerInclusion(other: updated) {
|
||||
self.currentNeedsReindexUnreadCounters = true
|
||||
}
|
||||
}
|
||||
|
||||
self.preferencesTable.set(key: key, value: value, operations: &self.currentPreferencesOperations)
|
||||
}
|
||||
|
||||
@ -3193,6 +3222,10 @@ public final class Postbox {
|
||||
}
|
||||
}
|
||||
|
||||
func getGlobalNotificationSettings() -> PostboxGlobalNotificationSettings {
|
||||
return self.preferencesTable.get(key: self.seedConfiguration.globalNotificationSettingsPreferencesKey) as? PostboxGlobalNotificationSettings ?? self.seedConfiguration.defaultGlobalNotificationSettings
|
||||
}
|
||||
|
||||
public func isMasterClient() -> Signal<Bool, NoError> {
|
||||
return self.transaction { transaction -> Signal<Bool, NoError> in
|
||||
let sessionClientId = self.sessionClientId
|
||||
@ -3238,10 +3271,14 @@ public final class Postbox {
|
||||
fileprivate func reindexUnreadCounters() {
|
||||
self.groupMessageStatsTable.removeAll()
|
||||
let _ = CFAbsoluteTimeGetCurrent()
|
||||
let (rootState, summaries) = self.chatListIndexTable.debugReindexUnreadCounts(postbox: self)
|
||||
let (totalStates, summaries) = self.chatListIndexTable.debugReindexUnreadCounts(postbox: self)
|
||||
|
||||
self.messageHistoryMetadataTable.removeAllTotalUnreadStates()
|
||||
for (groupId, state) in totalStates {
|
||||
self.messageHistoryMetadataTable.setTotalUnreadState(groupId: groupId, state: state)
|
||||
}
|
||||
self.currentUpdatedTotalUnreadStates = totalStates
|
||||
|
||||
self.messageHistoryMetadataTable.setChatListTotalUnreadState(rootState)
|
||||
self.currentUpdatedTotalUnreadState = rootState
|
||||
for (groupId, summary) in summaries {
|
||||
self.groupMessageStatsTable.set(groupId: groupId, summary: summary)
|
||||
self.currentUpdatedGroupTotalUnreadSummaries[groupId] = summary
|
||||
|
@ -12,7 +12,7 @@ final class PostboxTransaction {
|
||||
let currentUpdatedCachedPeerData: [PeerId: CachedPeerData]
|
||||
let currentUpdatedPeerPresences: [PeerId: PeerPresence]
|
||||
let currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?]
|
||||
let currentUpdatedTotalUnreadState: ChatListTotalUnreadState?
|
||||
let currentUpdatedTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState]
|
||||
let currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary]
|
||||
let alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState]
|
||||
let currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation]
|
||||
@ -42,8 +42,7 @@ final class PostboxTransaction {
|
||||
let updatedCacheEntryKeys: Set<ItemCacheEntryId>
|
||||
let updatedFailedMessagePeerIds: Set<PeerId>
|
||||
let updatedFailedMessageIds: Set<MessageId>
|
||||
|
||||
|
||||
let updatedGlobalNotificationSettings: Bool
|
||||
|
||||
var isEmpty: Bool {
|
||||
if currentUpdatedState != nil {
|
||||
@ -100,7 +99,7 @@ final class PostboxTransaction {
|
||||
if currentUpdatedMasterClientId != nil {
|
||||
return false
|
||||
}
|
||||
if currentUpdatedTotalUnreadState != nil {
|
||||
if !currentUpdatedTotalUnreadStates.isEmpty {
|
||||
return false
|
||||
}
|
||||
if !currentUpdatedTotalUnreadSummaries.isEmpty {
|
||||
@ -169,10 +168,13 @@ final class PostboxTransaction {
|
||||
if !updatedFailedMessageIds.isEmpty {
|
||||
return false
|
||||
}
|
||||
if updatedGlobalNotificationSettings {
|
||||
return false
|
||||
}
|
||||
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: [PeerId: PeerChatListEmbeddedInterfaceState?], currentUpdatedTotalUnreadState: 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: [PeerId]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set<PeerId>, updatedFailedMessageIds: Set<MessageId>) {
|
||||
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: [PeerId: PeerChatListEmbeddedInterfaceState?], 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: [PeerId]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set<PeerId>, updatedFailedMessageIds: Set<MessageId>, updatedGlobalNotificationSettings: Bool) {
|
||||
self.currentUpdatedState = currentUpdatedState
|
||||
self.currentPeerHoleOperations = currentPeerHoleOperations
|
||||
self.currentOperationsByPeerId = currentOperationsByPeerId
|
||||
@ -184,7 +186,7 @@ final class PostboxTransaction {
|
||||
self.currentUpdatedCachedPeerData = currentUpdatedCachedPeerData
|
||||
self.currentUpdatedPeerPresences = currentUpdatedPeerPresences
|
||||
self.currentUpdatedPeerChatListEmbeddedStates = currentUpdatedPeerChatListEmbeddedStates
|
||||
self.currentUpdatedTotalUnreadState = currentUpdatedTotalUnreadState
|
||||
self.currentUpdatedTotalUnreadStates = currentUpdatedTotalUnreadStates
|
||||
self.currentUpdatedTotalUnreadSummaries = currentUpdatedTotalUnreadSummaries
|
||||
self.alteredInitialPeerCombinedReadStates = alteredInitialPeerCombinedReadStates
|
||||
self.currentPeerMergedOperationLogOperations = currentPeerMergedOperationLogOperations
|
||||
@ -213,5 +215,6 @@ final class PostboxTransaction {
|
||||
self.updatedCacheEntryKeys = updatedCacheEntryKeys
|
||||
self.updatedFailedMessagePeerIds = updatedFailedMessagePeerIds
|
||||
self.updatedFailedMessageIds = updatedFailedMessageIds
|
||||
self.updatedGlobalNotificationSettings = updatedGlobalNotificationSettings
|
||||
}
|
||||
}
|
||||
|
@ -137,9 +137,9 @@ private func parseNotificationSettings(valueBox: ValueBox, table: ValueBoxTable,
|
||||
value.skip(Int(length))
|
||||
}
|
||||
if let pending = pending {
|
||||
return !pending.isRemovedFromTotalUnreadCount
|
||||
return !pending.isRemovedFromTotalUnreadCount(default: false)
|
||||
} else if let current = current {
|
||||
return !current.isRemovedFromTotalUnreadCount
|
||||
return !current.isRemovedFromTotalUnreadCount(default: false)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
@ -154,12 +154,10 @@ private func getReadStateCount(valueBox: ValueBox, table: ValueBoxTable, peerId:
|
||||
if let value = valueBox.get(table, key: key) {
|
||||
var count: Int32 = 0
|
||||
value.read(&count, offset: 0, length: 4)
|
||||
var stateByNamespace: [MessageId.Namespace: PeerReadState] = [:]
|
||||
for _ in 0 ..< count {
|
||||
var namespaceId: Int32 = 0
|
||||
value.read(&namespaceId, offset: 0, length: 4)
|
||||
|
||||
let state: PeerReadState
|
||||
var kind: Int8 = 0
|
||||
value.read(&kind, offset: 0, length: 1)
|
||||
if kind == 0 {
|
||||
|
@ -137,9 +137,9 @@ private func parseNotificationSettings(valueBox: ValueBox, table: ValueBoxTable,
|
||||
value.skip(Int(length))
|
||||
}
|
||||
if let pending = pending {
|
||||
return !pending.isRemovedFromTotalUnreadCount
|
||||
return !pending.isRemovedFromTotalUnreadCount(default: false)
|
||||
} else if let current = current {
|
||||
return !current.isRemovedFromTotalUnreadCount
|
||||
return !current.isRemovedFromTotalUnreadCount(default: false)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
@ -22,8 +22,10 @@ public final class SeedConfiguration {
|
||||
public let messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>
|
||||
public let defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState]
|
||||
public let chatMessagesNamespaces: Set<MessageId.Namespace>
|
||||
public let globalNotificationSettingsPreferencesKey: ValueBoxKey
|
||||
public let defaultGlobalNotificationSettings: PostboxGlobalNotificationSettings
|
||||
|
||||
public init(globalMessageIdsPeerIdNamespaces: Set<GlobalMessageIdsNamespace>, initializeChatListWithHole: (topLevel: ChatListHole?, groups: ChatListHole?), messageHoles: [PeerId.Namespace: [MessageId.Namespace: Set<MessageTags>]], existingMessageTags: MessageTags, messageTagsWithSummary: MessageTags, existingGlobalMessageTags: GlobalMessageTags, peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace], peerSummaryCounterTags: @escaping (Peer, Bool) -> PeerSummaryCounterTags, additionalChatListIndexNamespace: MessageId.Namespace?, messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>, defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState], chatMessagesNamespaces: Set<MessageId.Namespace>) {
|
||||
public init(globalMessageIdsPeerIdNamespaces: Set<GlobalMessageIdsNamespace>, initializeChatListWithHole: (topLevel: ChatListHole?, groups: ChatListHole?), messageHoles: [PeerId.Namespace: [MessageId.Namespace: Set<MessageTags>]], existingMessageTags: MessageTags, messageTagsWithSummary: MessageTags, existingGlobalMessageTags: GlobalMessageTags, peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace], peerSummaryCounterTags: @escaping (Peer, Bool) -> PeerSummaryCounterTags, additionalChatListIndexNamespace: MessageId.Namespace?, messageNamespacesRequiringGroupStatsValidation: Set<MessageId.Namespace>, defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState], chatMessagesNamespaces: Set<MessageId.Namespace>, globalNotificationSettingsPreferencesKey: ValueBoxKey, defaultGlobalNotificationSettings: PostboxGlobalNotificationSettings) {
|
||||
self.globalMessageIdsPeerIdNamespaces = globalMessageIdsPeerIdNamespaces
|
||||
self.initializeChatListWithHole = initializeChatListWithHole
|
||||
self.messageHoles = messageHoles
|
||||
@ -35,5 +37,7 @@ public final class SeedConfiguration {
|
||||
self.messageNamespacesRequiringGroupStatsValidation = messageNamespacesRequiringGroupStatsValidation
|
||||
self.defaultMessageNamespaceReadStates = defaultMessageNamespaceReadStates
|
||||
self.chatMessagesNamespaces = chatMessagesNamespaces
|
||||
self.globalNotificationSettingsPreferencesKey = globalNotificationSettingsPreferencesKey
|
||||
self.defaultGlobalNotificationSettings = defaultGlobalNotificationSettings
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
|
||||
self.entries = items.map { item in
|
||||
switch item {
|
||||
case let .total(preferencesKey):
|
||||
return .total(preferencesKey.flatMap({ ($0, postbox.preferencesTable.get(key: $0)) }), postbox.messageHistoryMetadataTable.getChatListTotalUnreadState())
|
||||
return .total(preferencesKey.flatMap({ ($0, postbox.preferencesTable.get(key: $0)) }), postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: .root))
|
||||
case let .totalInGroup(groupId):
|
||||
return .totalInGroup(groupId, ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:]))
|
||||
return .totalInGroup(groupId, postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId))
|
||||
case let .peer(peerId):
|
||||
return .peer(peerId, postbox.readStateTable.getCombinedState(peerId))
|
||||
}
|
||||
@ -52,18 +52,23 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
|
||||
}
|
||||
}
|
||||
|
||||
if transaction.currentUpdatedTotalUnreadState != nil || !transaction.alteredInitialPeerCombinedReadStates.isEmpty || updatedPreferencesEntry != nil {
|
||||
if !transaction.currentUpdatedTotalUnreadStates.isEmpty || !transaction.alteredInitialPeerCombinedReadStates.isEmpty || updatedPreferencesEntry != nil {
|
||||
for i in 0 ..< self.entries.count {
|
||||
switch self.entries[i] {
|
||||
case let .total(keyAndEntry, state):
|
||||
if let updatedState = transaction.currentUpdatedTotalUnreadState {
|
||||
if let updatedState = transaction.currentUpdatedTotalUnreadStates[.root] {
|
||||
if updatedState != state {
|
||||
self.entries[i] = .total(keyAndEntry.flatMap({ ($0.0, updatedPreferencesEntry ?? $0.1) }), updatedState)
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
case let .totalInGroup(groupId, state):
|
||||
break
|
||||
if let updatedState = transaction.currentUpdatedTotalUnreadStates[groupId] {
|
||||
if updatedState != state {
|
||||
self.entries[i] = .totalInGroup(groupId, updatedState)
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
case let .peer(peerId, _):
|
||||
if transaction.alteredInitialPeerCombinedReadStates[peerId] != nil {
|
||||
self.entries[i] = .peer(peerId, postbox.readStateTable.getCombinedState(peerId))
|
||||
|
@ -16,7 +16,6 @@ final class ViewTracker {
|
||||
private let getPeerNotificationSettings: (PeerId) -> PeerNotificationSettings?
|
||||
private let getCachedPeerData: (PeerId) -> CachedPeerData?
|
||||
private let getPeerPresence: (PeerId) -> PeerPresence?
|
||||
private let getTotalUnreadState: () -> ChatListTotalUnreadState
|
||||
private let getPeerReadState: (PeerId) -> CombinedPeerReadState?
|
||||
private let operationLogGetOperations: (PeerOperationLogTag, Int32, Int) -> [PeerMergedOperationLogEntry]
|
||||
private let operationLogGetTailIndex: (PeerOperationLogTag) -> Int32?
|
||||
@ -59,14 +58,13 @@ final class ViewTracker {
|
||||
private var failedMessageIdsViews = Bag<(MutableFailedMessageIdsView, ValuePipe<FailedMessageIdsView>)>()
|
||||
|
||||
|
||||
init(queue: Queue, renderMessage: @escaping (IntermediateMessage) -> Message, getPeer: @escaping (PeerId) -> Peer?, getPeerNotificationSettings: @escaping (PeerId) -> PeerNotificationSettings?, getCachedPeerData: @escaping (PeerId) -> CachedPeerData?, getPeerPresence: @escaping (PeerId) -> PeerPresence?, getTotalUnreadState: @escaping () -> ChatListTotalUnreadState, getPeerReadState: @escaping (PeerId) -> CombinedPeerReadState?, operationLogGetOperations: @escaping (PeerOperationLogTag, Int32, Int) -> [PeerMergedOperationLogEntry], operationLogGetTailIndex: @escaping (PeerOperationLogTag) -> Int32?, getTimestampBasedMessageAttributesHead: @escaping (UInt16) -> TimestampBasedMessageAttributesEntry?, getPreferencesEntry: @escaping (ValueBoxKey) -> PreferencesEntry?, unsentMessageIds: [MessageId], synchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||
init(queue: Queue, renderMessage: @escaping (IntermediateMessage) -> Message, getPeer: @escaping (PeerId) -> Peer?, getPeerNotificationSettings: @escaping (PeerId) -> PeerNotificationSettings?, getCachedPeerData: @escaping (PeerId) -> CachedPeerData?, getPeerPresence: @escaping (PeerId) -> PeerPresence?, getPeerReadState: @escaping (PeerId) -> CombinedPeerReadState?, operationLogGetOperations: @escaping (PeerOperationLogTag, Int32, Int) -> [PeerMergedOperationLogEntry], operationLogGetTailIndex: @escaping (PeerOperationLogTag) -> Int32?, getTimestampBasedMessageAttributesHead: @escaping (UInt16) -> TimestampBasedMessageAttributesEntry?, getPreferencesEntry: @escaping (ValueBoxKey) -> PreferencesEntry?, unsentMessageIds: [MessageId], synchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||
self.queue = queue
|
||||
self.renderMessage = renderMessage
|
||||
self.getPeer = getPeer
|
||||
self.getPeerNotificationSettings = getPeerNotificationSettings
|
||||
self.getCachedPeerData = getCachedPeerData
|
||||
self.getPeerPresence = getPeerPresence
|
||||
self.getTotalUnreadState = getTotalUnreadState
|
||||
self.getPeerReadState = getPeerReadState
|
||||
self.operationLogGetOperations = operationLogGetOperations
|
||||
self.operationLogGetTailIndex = operationLogGetTailIndex
|
||||
|
@ -234,22 +234,22 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
let timestamp = self.referenceTimestamp
|
||||
|
||||
let timestamp1 = timestamp + 120
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let presenceTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + 60 * 60)
|
||||
let timestamp2 = timestamp + 3660
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: "", attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: nil, notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: [(peer2, .typingText)], isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: "", attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: [(peer2, .typingText)], isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let timestamp3 = timestamp + 3200
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let timestamp4 = timestamp + 3000
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let timestamp5 = timestamp + 1000
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer5.id, namespace: 0, id: 0), timestamp: timestamp5)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp5, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer5, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer5), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer5.id, namespace: 0, id: 0), timestamp: timestamp5)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp5, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer5, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer5), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer6.id, namespace: 0, id: 0), timestamp: timestamp - 360)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer6.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 360, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer6), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer6.id, namespace: 0, id: 0), timestamp: timestamp - 360)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer6.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 360, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer6), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let width: CGFloat
|
||||
if case .regular = layout.metrics.widthClass {
|
||||
|
@ -785,17 +785,17 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
let timestamp = self.referenceTimestamp
|
||||
|
||||
let timestamp1 = timestamp + 120
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let presenceTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + 60 * 60)
|
||||
let timestamp2 = timestamp + 3660
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), isRemovedFromTotalUnreadCount: false, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let timestamp3 = timestamp + 3200
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let timestamp4 = timestamp + 3000
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, availableHeight: layout.size.height)
|
||||
if let chatNodes = self.chatNodes {
|
||||
|
@ -372,24 +372,24 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
let timestamp = self.referenceTimestamp
|
||||
|
||||
let timestamp1 = timestamp + 120
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let presenceTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + 60 * 60)
|
||||
let timestamp2 = timestamp + 3660
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: "", attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: nil, notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: [(peer2, .typingText)], isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: "", attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: [(peer2, .typingText)], isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let timestamp3 = timestamp + 3200
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let timestamp4 = timestamp + 3000
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let timestamp5 = timestamp + 1000
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer5.id, namespace: 0, id: 0), timestamp: timestamp5)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp5, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer5, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer5), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer5.id, namespace: 0, id: 0), timestamp: timestamp5)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp5, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer5, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer5), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer6.id, namespace: 0, id: 0), timestamp: timestamp - 360)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer6.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 360, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer6), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer6.id, namespace: 0, id: 0), timestamp: timestamp - 360)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer6.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 360, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer6), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer7.id, namespace: 0, id: 0), timestamp: timestamp - 420)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer7.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 420, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer7), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer7.id, namespace: 0, id: 0), timestamp: timestamp - 420)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer7.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 420, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer7), combinedReadState: nil, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
|
||||
|
||||
let width: CGFloat
|
||||
if case .regular = layout.metrics.widthClass {
|
||||
|
@ -60,7 +60,7 @@ public struct GlobalNotificationSettingsSet: PostboxCoding, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct GlobalNotificationSettings: PreferencesEntry, Equatable {
|
||||
public struct GlobalNotificationSettings: PreferencesEntry, Equatable, PostboxGlobalNotificationSettings {
|
||||
public var toBeSynchronized: GlobalNotificationSettingsSet?
|
||||
public var remote: GlobalNotificationSettingsSet
|
||||
|
||||
@ -74,6 +74,44 @@ public struct GlobalNotificationSettings: PreferencesEntry, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public func defaultIncludePeer(peer: Peer) -> Bool {
|
||||
let settings = self.effective
|
||||
if peer is TelegramUser || peer is TelegramSecretChat {
|
||||
return settings.privateChats.enabled
|
||||
} else if peer is TelegramGroup {
|
||||
return settings.groupChats.enabled
|
||||
} else if let channel = peer as? TelegramChannel {
|
||||
switch channel.info {
|
||||
case .group:
|
||||
return settings.groupChats.enabled
|
||||
case .broadcast:
|
||||
return settings.channels.enabled
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public func isEqualInDefaultPeerInclusion(other: PostboxGlobalNotificationSettings) -> Bool {
|
||||
guard let other = other as? GlobalNotificationSettings else {
|
||||
return false
|
||||
}
|
||||
let settings = self.effective
|
||||
let otherSettings = other.effective
|
||||
|
||||
if settings.privateChats.enabled != otherSettings.privateChats.enabled {
|
||||
return false
|
||||
}
|
||||
if settings.groupChats.enabled != otherSettings.groupChats.enabled {
|
||||
return false
|
||||
}
|
||||
if settings.channels.enabled != otherSettings.channels.enabled {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public init(toBeSynchronized: GlobalNotificationSettingsSet?, remote: GlobalNotificationSettingsSet) {
|
||||
self.toBeSynchronized = toBeSynchronized
|
||||
self.remote = remote
|
||||
|
@ -46,7 +46,7 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
||||
assertionFailure()
|
||||
return .nonContact
|
||||
}
|
||||
}, additionalChatListIndexNamespace: Namespaces.Message.Cloud, messageNamespacesRequiringGroupStatsValidation: [Namespaces.Message.Cloud], defaultMessageNamespaceReadStates: [Namespaces.Message.Local: .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false)], chatMessagesNamespaces: Set([Namespaces.Message.Cloud, Namespaces.Message.Local, Namespaces.Message.SecretIncoming]))
|
||||
}, additionalChatListIndexNamespace: Namespaces.Message.Cloud, messageNamespacesRequiringGroupStatsValidation: [Namespaces.Message.Cloud], defaultMessageNamespaceReadStates: [Namespaces.Message.Local: .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false)], chatMessagesNamespaces: Set([Namespaces.Message.Cloud, Namespaces.Message.Local, Namespaces.Message.SecretIncoming]), globalNotificationSettingsPreferencesKey: PreferencesKeys.globalNotifications, defaultGlobalNotificationSettings: GlobalNotificationSettings.defaultSettings)
|
||||
}()
|
||||
|
||||
public func accountTransaction<T>(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, transaction: @escaping (Transaction) -> T) -> Signal<T, NoError> {
|
||||
|
@ -145,14 +145,14 @@ public final class TelegramPeerNotificationSettings: PeerNotificationSettings, E
|
||||
return TelegramPeerNotificationSettings(muteState: .unmuted, messageSound: .default, displayPreviews: .default)
|
||||
}
|
||||
|
||||
public var isRemovedFromTotalUnreadCount: Bool {
|
||||
public func isRemovedFromTotalUnreadCount(`default`: Bool) -> Bool {
|
||||
switch self.muteState {
|
||||
case .unmuted:
|
||||
return false
|
||||
case .muted:
|
||||
return true
|
||||
case .default:
|
||||
return false
|
||||
return `default`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2948,7 +2948,9 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
||||
let currentInclusion = transaction.getPeerChatListInclusion(peerId)
|
||||
if let groupId = currentInclusion.groupId, groupId == Namespaces.PeerGroup.archive {
|
||||
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
|
||||
if let notificationSettings = transaction.getPeerNotificationSettings(peer.regularPeerId) as? TelegramPeerNotificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: transaction.getGlobalNotificationSettings(), peer: peer, peerSettings: transaction.getPeerNotificationSettings(peer.regularPeerId))
|
||||
|
||||
if !isRemovedFromTotalUnreadCount {
|
||||
transaction.updatePeerChatListInclusion(peerId, inclusion: currentInclusion.withGroupId(groupId: .root))
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,17 @@ public func togglePeerMuted(account: Account, peerId: PeerId) -> Signal<Void, No
|
||||
|
||||
let updatedSettings: TelegramPeerNotificationSettings
|
||||
switch previousSettings.muteState {
|
||||
case .unmuted, .default:
|
||||
case .default:
|
||||
let globalNotificationSettings = transaction.getGlobalNotificationSettings()
|
||||
if resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: previousSettings) {
|
||||
updatedSettings = previousSettings.withUpdatedMuteState(.unmuted)
|
||||
} else {
|
||||
updatedSettings = previousSettings.withUpdatedMuteState(.muted(until: Int32.max))
|
||||
case .muted:
|
||||
updatedSettings = previousSettings.withUpdatedMuteState(.default)
|
||||
}
|
||||
case .unmuted:
|
||||
updatedSettings = previousSettings.withUpdatedMuteState(.muted(until: Int32.max))
|
||||
case .muted:
|
||||
updatedSettings = previousSettings.withUpdatedMuteState(.unmuted)
|
||||
}
|
||||
transaction.updatePendingPeerNotificationSettings(peerId: notificationPeerId, settings: updatedSettings)
|
||||
}
|
||||
|
@ -2736,7 +2736,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let (count, _) = renderedTotalUnreadCount(inAppSettings: inAppSettings, totalUnreadState: peerReadStateData.totalState ?? ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:]))
|
||||
|
||||
var globalRemainingUnreadChatCount = count
|
||||
if !notificationSettings.isRemovedFromTotalUnreadCount && peerReadStateData.unreadCount > 0 {
|
||||
if !notificationSettings.isRemovedFromTotalUnreadCount(default: false) && peerReadStateData.unreadCount > 0 {
|
||||
if case .messages = inAppSettings.totalUnreadCountDisplayCategory {
|
||||
globalRemainingUnreadChatCount -= peerReadStateData.unreadCount
|
||||
} else {
|
||||
@ -4432,7 +4432,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
if let view = views.views[notificationSettingsKey] as? PeerNotificationSettingsView, let notificationSettings = view.notificationSettings[peerId] {
|
||||
var globalRemainingUnreadChatCount = totalChatCount
|
||||
if !notificationSettings.isRemovedFromTotalUnreadCount && unreadCount > 0 {
|
||||
if !notificationSettings.isRemovedFromTotalUnreadCount(default: false) && unreadCount > 0 {
|
||||
if case .messages = inAppSettings.totalUnreadCountDisplayCategory {
|
||||
globalRemainingUnreadChatCount -= unreadCount
|
||||
} else {
|
||||
|
@ -78,7 +78,7 @@ private enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
public func item(context: AccountContext, interaction: ChatListNodeInteraction) -> ListViewItem {
|
||||
switch self {
|
||||
case let .message(message, peer, readState, presentationData):
|
||||
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true, displayAsMessage: true, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, isInFilter: false, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true, displayAsMessage: true, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public enum RenderedTotalUnreadCountType {
|
||||
}
|
||||
|
||||
public func renderedTotalUnreadCount(inAppNotificationSettings: InAppNotificationSettings, transaction: Transaction) -> (Int32, RenderedTotalUnreadCountType) {
|
||||
let totalUnreadState = transaction.getTotalUnreadState()
|
||||
let totalUnreadState = transaction.getTotalUnreadState(groupId: .root)
|
||||
return renderedTotalUnreadCount(inAppSettings: inAppNotificationSettings, totalUnreadState: totalUnreadState)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user