Merge branch 'gray-counters'

This commit is contained in:
Ali 2020-03-12 15:30:30 +05:30
commit aa24263bed
34 changed files with 595 additions and 393 deletions

View File

@ -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

View File

@ -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] = []

View File

@ -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 {

View File

@ -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)

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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() {

View File

@ -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(&currentTotalRootUnreadState, 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(&currentTotalRootUnreadState, 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(&currentTotalRootUnreadState, 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 {

View File

@ -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

View File

@ -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:

View File

@ -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 {

View File

@ -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()
}
}
}

View File

@ -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
}
}

View File

@ -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)

View File

@ -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

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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))

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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> {

View File

@ -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`
}
}

View File

@ -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))
}
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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)
}
}
}

View File

@ -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)
}