mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Tab fixes
This commit is contained in:
parent
7706b763e6
commit
f920b5d00d
@ -5439,7 +5439,7 @@ Any member of this group will be able to see messages in the channel.";
|
|||||||
"ChatListFolder.AddChats" = "Add Chats";
|
"ChatListFolder.AddChats" = "Add Chats";
|
||||||
"ChatListFolder.IncludeSectionInfo" = "Choose chats and types of chats that will appear in this folder.";
|
"ChatListFolder.IncludeSectionInfo" = "Choose chats and types of chats that will appear in this folder.";
|
||||||
"ChatListFolder.ExcludedSectionHeader" = "EXCLUDED CHATS";
|
"ChatListFolder.ExcludedSectionHeader" = "EXCLUDED CHATS";
|
||||||
"ChatListFolder.ExcludeSectionInfo" = "Choose chats and types of chats that will never appear in the folder.";
|
"ChatListFolder.ExcludeSectionInfo" = "Choose chats and types of chats that will never appear in this folder.";
|
||||||
"ChatListFolder.NameNonMuted" = "Not Muted";
|
"ChatListFolder.NameNonMuted" = "Not Muted";
|
||||||
"ChatListFolder.NameUnread" = "Unread";
|
"ChatListFolder.NameUnread" = "Unread";
|
||||||
"ChatListFolder.NameChannels" = "Channels";
|
"ChatListFolder.NameChannels" = "Channels";
|
||||||
|
@ -1148,7 +1148,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.processedFeaturedFilters = true
|
strongSelf.processedFeaturedFilters = true
|
||||||
if !featuredState.isSeen && !featuredState.filters.isEmpty && filters.isEmpty {
|
if !featuredState.isSeen && !featuredState.filters.isEmpty {
|
||||||
let _ = (currentChatListFilters(postbox: strongSelf.context.account.postbox)
|
let _ = (currentChatListFilters(postbox: strongSelf.context.account.postbox)
|
||||||
|> deliverOnMainQueue).start(next: { filters in
|
|> deliverOnMainQueue).start(next: { filters in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
|
@ -280,13 +280,13 @@ private final class ChatListContainerItemNode: ASDisplayNode {
|
|||||||
|
|
||||||
private var validLayout: (CGSize, UIEdgeInsets, CGFloat)?
|
private var validLayout: (CGSize, UIEdgeInsets, CGFloat)?
|
||||||
|
|
||||||
init(context: AccountContext, groupId: PeerGroupId, filter: ChatListFilter?, previewing: Bool, presentationData: PresentationData, becameEmpty: @escaping (ChatListFilter?) -> Void, emptyAction: @escaping (ChatListFilter?) -> Void) {
|
init(context: AccountContext, groupId: PeerGroupId, filter: ChatListFilter?, previewing: Bool, controlsHistoryPreload: Bool, presentationData: PresentationData, becameEmpty: @escaping (ChatListFilter?) -> Void, emptyAction: @escaping (ChatListFilter?) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.becameEmpty = becameEmpty
|
self.becameEmpty = becameEmpty
|
||||||
self.emptyAction = emptyAction
|
self.emptyAction = emptyAction
|
||||||
|
|
||||||
self.listNode = ChatListNode(context: context, groupId: groupId, chatListFilter: filter, previewing: previewing, controlsHistoryPreload: false, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
self.listNode = ChatListNode(context: context, groupId: groupId, chatListFilter: filter, previewing: previewing, fillPreloadItems: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
@ -401,6 +401,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let groupId: PeerGroupId
|
private let groupId: PeerGroupId
|
||||||
private let previewing: Bool
|
private let previewing: Bool
|
||||||
|
private let controlsHistoryPreload: Bool
|
||||||
private let filterBecameEmpty: (ChatListFilter?) -> Void
|
private let filterBecameEmpty: (ChatListFilter?) -> Void
|
||||||
private let filterEmptyAction: (ChatListFilter?) -> Void
|
private let filterEmptyAction: (ChatListFilter?) -> Void
|
||||||
|
|
||||||
@ -498,6 +499,10 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.currentItemStateValue.set(itemNode.listNode.state)
|
self.currentItemStateValue.set(itemNode.listNode.state)
|
||||||
|
|
||||||
|
if self.controlsHistoryPreload {
|
||||||
|
self.context.account.viewTracker.chatListPreloadItems.set(itemNode.listNode.preloadItems.get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var activateSearch: (() -> Void)?
|
var activateSearch: (() -> Void)?
|
||||||
@ -513,12 +518,13 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
var activateChatPreview: ((ChatListItem, ASDisplayNode, ContextGesture?) -> Void)?
|
var activateChatPreview: ((ChatListItem, ASDisplayNode, ContextGesture?) -> Void)?
|
||||||
var addedVisibleChatsWithPeerIds: (([PeerId]) -> Void)?
|
var addedVisibleChatsWithPeerIds: (([PeerId]) -> Void)?
|
||||||
|
|
||||||
init(context: AccountContext, groupId: PeerGroupId, previewing: Bool, presentationData: PresentationData, filterBecameEmpty: @escaping (ChatListFilter?) -> Void, filterEmptyAction: @escaping (ChatListFilter?) -> Void) {
|
init(context: AccountContext, groupId: PeerGroupId, previewing: Bool, controlsHistoryPreload: Bool, presentationData: PresentationData, filterBecameEmpty: @escaping (ChatListFilter?) -> Void, filterEmptyAction: @escaping (ChatListFilter?) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.groupId = groupId
|
self.groupId = groupId
|
||||||
self.previewing = previewing
|
self.previewing = previewing
|
||||||
self.filterBecameEmpty = filterBecameEmpty
|
self.filterBecameEmpty = filterBecameEmpty
|
||||||
self.filterEmptyAction = filterEmptyAction
|
self.filterEmptyAction = filterEmptyAction
|
||||||
|
self.controlsHistoryPreload = controlsHistoryPreload
|
||||||
|
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
|
|
||||||
@ -526,7 +532,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
let itemNode = ChatListContainerItemNode(context: self.context, groupId: self.groupId, filter: nil, previewing: self.previewing, presentationData: presentationData, becameEmpty: { [weak self] filter in
|
let itemNode = ChatListContainerItemNode(context: self.context, groupId: self.groupId, filter: nil, previewing: self.previewing, controlsHistoryPreload: self.controlsHistoryPreload, presentationData: presentationData, becameEmpty: { [weak self] filter in
|
||||||
self?.filterBecameEmpty(filter)
|
self?.filterBecameEmpty(filter)
|
||||||
}, emptyAction: { [weak self] filter in
|
}, emptyAction: { [weak self] filter in
|
||||||
self?.filterEmptyAction(filter)
|
self?.filterEmptyAction(filter)
|
||||||
@ -778,7 +784,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, transition, false)
|
self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, transition, false)
|
||||||
completion?()
|
completion?()
|
||||||
} else if self.pendingItemNode == nil {
|
} else if self.pendingItemNode == nil {
|
||||||
let itemNode = ChatListContainerItemNode(context: self.context, groupId: self.groupId, filter: self.availableFilters[index].filter, previewing: self.previewing, presentationData: self.presentationData, becameEmpty: { [weak self] filter in
|
let itemNode = ChatListContainerItemNode(context: self.context, groupId: self.groupId, filter: self.availableFilters[index].filter, previewing: self.previewing, controlsHistoryPreload: self.controlsHistoryPreload, presentationData: self.presentationData, becameEmpty: { [weak self] filter in
|
||||||
self?.filterBecameEmpty(filter)
|
self?.filterBecameEmpty(filter)
|
||||||
}, emptyAction: { [weak self] filter in
|
}, emptyAction: { [weak self] filter in
|
||||||
self?.filterEmptyAction(filter)
|
self?.filterEmptyAction(filter)
|
||||||
@ -882,7 +888,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
validNodeIds.append(id)
|
validNodeIds.append(id)
|
||||||
|
|
||||||
if self.itemNodes[id] == nil && self.enableAdjacentFilterLoading && !self.disableItemNodeOperationsWhileAnimating {
|
if self.itemNodes[id] == nil && self.enableAdjacentFilterLoading && !self.disableItemNodeOperationsWhileAnimating {
|
||||||
let itemNode = ChatListContainerItemNode(context: self.context, groupId: self.groupId, filter: self.availableFilters[i].filter, previewing: self.previewing, presentationData: self.presentationData, becameEmpty: { [weak self] filter in
|
let itemNode = ChatListContainerItemNode(context: self.context, groupId: self.groupId, filter: self.availableFilters[i].filter, previewing: self.previewing, controlsHistoryPreload: self.controlsHistoryPreload, presentationData: self.presentationData, becameEmpty: { [weak self] filter in
|
||||||
self?.filterBecameEmpty(filter)
|
self?.filterBecameEmpty(filter)
|
||||||
}, emptyAction: { [weak self] filter in
|
}, emptyAction: { [weak self] filter in
|
||||||
self?.filterEmptyAction(filter)
|
self?.filterEmptyAction(filter)
|
||||||
@ -983,7 +989,7 @@ final class ChatListControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
var filterBecameEmpty: ((ChatListFilter?) -> Void)?
|
var filterBecameEmpty: ((ChatListFilter?) -> Void)?
|
||||||
var filterEmptyAction: ((ChatListFilter?) -> Void)?
|
var filterEmptyAction: ((ChatListFilter?) -> Void)?
|
||||||
self.containerNode = ChatListContainerNode(context: context, groupId: groupId, previewing: previewing, presentationData: presentationData, filterBecameEmpty: { filter in
|
self.containerNode = ChatListContainerNode(context: context, groupId: groupId, previewing: previewing, controlsHistoryPreload: controlsHistoryPreload, presentationData: presentationData, filterBecameEmpty: { filter in
|
||||||
filterBecameEmpty?(filter)
|
filterBecameEmpty?(filter)
|
||||||
}, filterEmptyAction: { filter in
|
}, filterEmptyAction: { filter in
|
||||||
filterEmptyAction?(filter)
|
filterEmptyAction?(filter)
|
||||||
|
@ -192,7 +192,7 @@ public class ChatListFilterPresetListSuggestedItemNode: ListViewItemNode, ItemLi
|
|||||||
|
|
||||||
let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Stickers_Install, font: Font.semibold(14.0), textColor: item.presentationData.theme.list.itemCheckColors.foregroundColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Stickers_Install, font: Font.semibold(14.0), textColor: item.presentationData.theme.list.itemCheckColors.foregroundColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
let additionalTextRightInset: CGFloat = buttonTitleLayout.size.width + 16.0
|
let additionalTextRightInset: CGFloat = buttonTitleLayout.size.width + 14.0 * 2.0
|
||||||
|
|
||||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset - rightInset - additionalTextRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset - rightInset - additionalTextRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
@ -200,8 +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)
|
self.shortTitleNode.attributedText = NSAttributedString(string: shortTitle, font: Font.medium(14.0), textColor: isSelected ? presentationData.theme.list.itemAccentColor : presentationData.theme.list.itemSecondaryTextColor)
|
||||||
if unreadCount != 0 {
|
if unreadCount != 0 {
|
||||||
self.badgeTextNode.attributedText = NSAttributedString(string: "\(unreadCount)", font: Font.regular(14.0), textColor: presentationData.theme.list.itemCheckColors.foregroundColor)
|
self.badgeTextNode.attributedText = NSAttributedString(string: "\(unreadCount)", font: Font.regular(14.0), textColor: presentationData.theme.list.itemCheckColors.foregroundColor)
|
||||||
self.badgeBackgroundActiveNode.isHidden = !unreadHasUnmuted
|
self.badgeBackgroundActiveNode.isHidden = !isSelected && !unreadHasUnmuted
|
||||||
self.badgeBackgroundInactiveNode.isHidden = unreadHasUnmuted
|
self.badgeBackgroundInactiveNode.isHidden = isSelected || unreadHasUnmuted
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.isReordering != isReordering {
|
if self.isReordering != isReordering {
|
||||||
|
@ -386,7 +386,7 @@ public enum ChatListNodeEmptyState: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class ChatListNode: ListView {
|
public final class ChatListNode: ListView {
|
||||||
private let controlsHistoryPreload: Bool
|
private let fillPreloadItems: Bool
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let groupId: PeerGroupId
|
private let groupId: PeerGroupId
|
||||||
private let mode: ChatListNodeMode
|
private let mode: ChatListNodeMode
|
||||||
@ -485,12 +485,14 @@ public final class ChatListNode: ListView {
|
|||||||
|
|
||||||
private var hapticFeedback: HapticFeedback?
|
private var hapticFeedback: HapticFeedback?
|
||||||
|
|
||||||
public init(context: AccountContext, groupId: PeerGroupId, chatListFilter: ChatListFilter? = nil, previewing: Bool, controlsHistoryPreload: Bool, mode: ChatListNodeMode, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
let preloadItems = Promise<[ChatHistoryPreloadItem]>([])
|
||||||
|
|
||||||
|
public init(context: AccountContext, groupId: PeerGroupId, chatListFilter: ChatListFilter? = nil, previewing: Bool, fillPreloadItems: Bool, mode: ChatListNodeMode, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.groupId = groupId
|
self.groupId = groupId
|
||||||
self.chatListFilter = chatListFilter
|
self.chatListFilter = chatListFilter
|
||||||
self.chatListFilterValue.set(.single(chatListFilter))
|
self.chatListFilterValue.set(.single(chatListFilter))
|
||||||
self.controlsHistoryPreload = controlsHistoryPreload
|
self.fillPreloadItems = fillPreloadItems
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
var isSelecting = false
|
var isSelecting = false
|
||||||
@ -1285,6 +1287,31 @@ public final class ChatListNode: ListView {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.chatListView = transition.chatListView
|
strongSelf.chatListView = transition.chatListView
|
||||||
|
|
||||||
|
if strongSelf.fillPreloadItems {
|
||||||
|
let filteredEntries = transition.chatListView.filteredEntries
|
||||||
|
var preloadItems: [ChatHistoryPreloadItem] = []
|
||||||
|
if transition.chatListView.originalView.laterIndex == nil {
|
||||||
|
for entry in filteredEntries.reversed() {
|
||||||
|
switch entry {
|
||||||
|
case let .PeerEntry(index, _, _, combinedReadState, isMuted, _, _, _, _, _, _, _, _, isAd, _, _):
|
||||||
|
if !isAd {
|
||||||
|
var hasUnread = false
|
||||||
|
if let combinedReadState = combinedReadState {
|
||||||
|
hasUnread = combinedReadState.count > 0
|
||||||
|
}
|
||||||
|
preloadItems.append(ChatHistoryPreloadItem(index: index, isMuted: isMuted, hasUnread: hasUnread))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if preloadItems.count >= 30 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strongSelf.preloadItems.set(.single(preloadItems))
|
||||||
|
}
|
||||||
|
|
||||||
var pinnedOverscroll = false
|
var pinnedOverscroll = false
|
||||||
if case .chatList = strongSelf.mode {
|
if case .chatList = strongSelf.mode {
|
||||||
let entryCount = transition.chatListView.filteredEntries.count
|
let entryCount = transition.chatListView.filteredEntries.count
|
||||||
|
@ -444,6 +444,12 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if item.maxLength != 0 && newText.count > item.maxLength {
|
if item.maxLength != 0 && newText.count > item.maxLength {
|
||||||
|
self.textNode.layer.addShakeAnimation()
|
||||||
|
let hapticFeedback = HapticFeedback()
|
||||||
|
hapticFeedback.error()
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0, execute: {
|
||||||
|
let _ = hapticFeedback
|
||||||
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -771,22 +771,28 @@ private func notificationsAndSoundsEntries(authorizationStatus: AccessType, warn
|
|||||||
|
|
||||||
entries.append(.messageHeader(presentationData.theme, presentationData.strings.Notifications_MessageNotifications.uppercased()))
|
entries.append(.messageHeader(presentationData.theme, presentationData.strings.Notifications_MessageNotifications.uppercased()))
|
||||||
entries.append(.messageAlerts(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsAlert, globalSettings.privateChats.enabled))
|
entries.append(.messageAlerts(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsAlert, globalSettings.privateChats.enabled))
|
||||||
entries.append(.messagePreviews(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsPreview, globalSettings.privateChats.displayPreviews))
|
if globalSettings.privateChats.enabled || !exceptions.users.isEmpty {
|
||||||
entries.append(.messageSound(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsSound, localizedPeerNotificationSoundString(strings: presentationData.strings, sound: filteredGlobalSound(globalSettings.privateChats.sound)), filteredGlobalSound(globalSettings.privateChats.sound)))
|
entries.append(.messagePreviews(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsPreview, globalSettings.privateChats.displayPreviews))
|
||||||
|
entries.append(.messageSound(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsSound, localizedPeerNotificationSoundString(strings: presentationData.strings, sound: filteredGlobalSound(globalSettings.privateChats.sound)), filteredGlobalSound(globalSettings.privateChats.sound)))
|
||||||
|
}
|
||||||
entries.append(.userExceptions(presentationData.theme, presentationData.strings, presentationData.strings.Notifications_MessageNotificationsExceptions, exceptions.users))
|
entries.append(.userExceptions(presentationData.theme, presentationData.strings, presentationData.strings.Notifications_MessageNotificationsExceptions, exceptions.users))
|
||||||
entries.append(.messageNotice(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsExceptionsHelp))
|
entries.append(.messageNotice(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsExceptionsHelp))
|
||||||
|
|
||||||
entries.append(.groupHeader(presentationData.theme, presentationData.strings.Notifications_GroupNotifications.uppercased()))
|
entries.append(.groupHeader(presentationData.theme, presentationData.strings.Notifications_GroupNotifications.uppercased()))
|
||||||
entries.append(.groupAlerts(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsAlert, globalSettings.groupChats.enabled))
|
entries.append(.groupAlerts(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsAlert, globalSettings.groupChats.enabled))
|
||||||
entries.append(.groupPreviews(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsPreview, globalSettings.groupChats.displayPreviews))
|
if globalSettings.groupChats.enabled || !exceptions.groups.isEmpty {
|
||||||
entries.append(.groupSound(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsSound, localizedPeerNotificationSoundString(strings: presentationData.strings, sound: filteredGlobalSound(globalSettings.groupChats.sound)), filteredGlobalSound(globalSettings.groupChats.sound)))
|
entries.append(.groupPreviews(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsPreview, globalSettings.groupChats.displayPreviews))
|
||||||
|
entries.append(.groupSound(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsSound, localizedPeerNotificationSoundString(strings: presentationData.strings, sound: filteredGlobalSound(globalSettings.groupChats.sound)), filteredGlobalSound(globalSettings.groupChats.sound)))
|
||||||
|
}
|
||||||
entries.append(.groupExceptions(presentationData.theme, presentationData.strings, presentationData.strings.Notifications_MessageNotificationsExceptions, exceptions.groups))
|
entries.append(.groupExceptions(presentationData.theme, presentationData.strings, presentationData.strings.Notifications_MessageNotificationsExceptions, exceptions.groups))
|
||||||
entries.append(.groupNotice(presentationData.theme, presentationData.strings.Notifications_GroupNotificationsExceptionsHelp))
|
entries.append(.groupNotice(presentationData.theme, presentationData.strings.Notifications_GroupNotificationsExceptionsHelp))
|
||||||
|
|
||||||
entries.append(.channelHeader(presentationData.theme, presentationData.strings.Notifications_ChannelNotifications.uppercased()))
|
entries.append(.channelHeader(presentationData.theme, presentationData.strings.Notifications_ChannelNotifications.uppercased()))
|
||||||
entries.append(.channelAlerts(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsAlert, globalSettings.channels.enabled))
|
entries.append(.channelAlerts(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsAlert, globalSettings.channels.enabled))
|
||||||
entries.append(.channelPreviews(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsPreview, globalSettings.channels.displayPreviews))
|
if globalSettings.channels.enabled || !exceptions.channels.isEmpty {
|
||||||
entries.append(.channelSound(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsSound, localizedPeerNotificationSoundString(strings: presentationData.strings, sound: filteredGlobalSound(globalSettings.channels.sound)), filteredGlobalSound(globalSettings.channels.sound)))
|
entries.append(.channelPreviews(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsPreview, globalSettings.channels.displayPreviews))
|
||||||
|
entries.append(.channelSound(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsSound, localizedPeerNotificationSoundString(strings: presentationData.strings, sound: filteredGlobalSound(globalSettings.channels.sound)), filteredGlobalSound(globalSettings.channels.sound)))
|
||||||
|
}
|
||||||
entries.append(.channelExceptions(presentationData.theme, presentationData.strings, presentationData.strings.Notifications_MessageNotificationsExceptions, exceptions.channels))
|
entries.append(.channelExceptions(presentationData.theme, presentationData.strings, presentationData.strings.Notifications_MessageNotificationsExceptions, exceptions.channels))
|
||||||
entries.append(.channelNotice(presentationData.theme, presentationData.strings.Notifications_ChannelNotificationsExceptionsHelp))
|
entries.append(.channelNotice(presentationData.theme, presentationData.strings.Notifications_ChannelNotificationsExceptionsHelp))
|
||||||
|
|
||||||
|
@ -279,12 +279,14 @@ public final class AccountViewTracker {
|
|||||||
|
|
||||||
private let externallyUpdatedPeerIdDisposable = MetaDisposable()
|
private let externallyUpdatedPeerIdDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
public let chatListPreloadItems = Promise<[ChatHistoryPreloadItem]>([])
|
||||||
|
|
||||||
init(account: Account) {
|
init(account: Account) {
|
||||||
self.account = account
|
self.account = account
|
||||||
|
|
||||||
self.historyViewStateValidationContexts = HistoryViewStateValidationContexts(queue: self.queue, postbox: account.postbox, network: account.network, accountPeerId: account.peerId)
|
self.historyViewStateValidationContexts = HistoryViewStateValidationContexts(queue: self.queue, postbox: account.postbox, network: account.network, accountPeerId: account.peerId)
|
||||||
|
|
||||||
self.chatHistoryPreloadManager = ChatHistoryPreloadManager(postbox: account.postbox, network: account.network, accountPeerId: account.peerId, networkState: account.networkState)
|
self.chatHistoryPreloadManager = ChatHistoryPreloadManager(postbox: account.postbox, network: account.network, accountPeerId: account.peerId, networkState: account.networkState, preloadItemsSignal: self.chatListPreloadItems.get())
|
||||||
|
|
||||||
self.externallyUpdatedPeerIdDisposable.set((account.stateManager.externallyUpdatedPeerIds
|
self.externallyUpdatedPeerIdDisposable.set((account.stateManager.externallyUpdatedPeerIds
|
||||||
|> deliverOn(self.queue)).start(next: { [weak self] peerIds in
|
|> deliverOn(self.queue)).start(next: { [weak self] peerIds in
|
||||||
|
@ -4,7 +4,7 @@ import SwiftSignalKit
|
|||||||
|
|
||||||
import SyncCore
|
import SyncCore
|
||||||
|
|
||||||
public struct HistoryPreloadIndex: Comparable, CustomStringConvertible {
|
public struct HistoryPreloadIndex: Hashable, Comparable, CustomStringConvertible {
|
||||||
public let index: ChatListIndex?
|
public let index: ChatListIndex?
|
||||||
public let hasUnread: Bool
|
public let hasUnread: Bool
|
||||||
public let isMuted: Bool
|
public let isMuted: Bool
|
||||||
@ -59,18 +59,10 @@ private struct HistoryPreloadHole: Hashable, Comparable, CustomStringConvertible
|
|||||||
let preloadIndex: HistoryPreloadIndex
|
let preloadIndex: HistoryPreloadIndex
|
||||||
let hole: MessageOfInterestHole
|
let hole: MessageOfInterestHole
|
||||||
|
|
||||||
static func ==(lhs: HistoryPreloadHole, rhs: HistoryPreloadHole) -> Bool {
|
|
||||||
return lhs.preloadIndex == rhs.preloadIndex && lhs.hole == rhs.hole
|
|
||||||
}
|
|
||||||
|
|
||||||
static func <(lhs: HistoryPreloadHole, rhs: HistoryPreloadHole) -> Bool {
|
static func <(lhs: HistoryPreloadHole, rhs: HistoryPreloadHole) -> Bool {
|
||||||
return lhs.preloadIndex < rhs.preloadIndex
|
return lhs.preloadIndex < rhs.preloadIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var hashValue: Int {
|
|
||||||
return self.preloadIndex.index.hashValue &* 31 &+ self.hole.hashValue
|
|
||||||
}
|
|
||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
return "(preloadIndex: \(self.preloadIndex), hole: \(self.hole))"
|
return "(preloadIndex: \(self.preloadIndex), hole: \(self.hole))"
|
||||||
}
|
}
|
||||||
@ -242,6 +234,18 @@ private final class AdditionalPreloadPeerIdsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct ChatHistoryPreloadItem {
|
||||||
|
public let index: ChatListIndex
|
||||||
|
public let isMuted: Bool
|
||||||
|
public let hasUnread: Bool
|
||||||
|
|
||||||
|
public init(index: ChatListIndex, isMuted: Bool, hasUnread: Bool) {
|
||||||
|
self.index = index
|
||||||
|
self.isMuted = isMuted
|
||||||
|
self.hasUnread = hasUnread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final class ChatHistoryPreloadManager {
|
final class ChatHistoryPreloadManager {
|
||||||
private let queue = Queue()
|
private let queue = Queue()
|
||||||
|
|
||||||
@ -266,12 +270,14 @@ final class ChatHistoryPreloadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let additionalPreloadPeerIdsContext: QueueLocalObject<AdditionalPreloadPeerIdsContext>
|
private let additionalPreloadPeerIdsContext: QueueLocalObject<AdditionalPreloadPeerIdsContext>
|
||||||
|
private let preloadItemsSignal: Signal<[ChatHistoryPreloadItem], NoError>
|
||||||
|
|
||||||
init(postbox: Postbox, network: Network, accountPeerId: PeerId, networkState: Signal<AccountNetworkState, NoError>) {
|
init(postbox: Postbox, network: Network, accountPeerId: PeerId, networkState: Signal<AccountNetworkState, NoError>, preloadItemsSignal: Signal<[ChatHistoryPreloadItem], NoError>) {
|
||||||
self.postbox = postbox
|
self.postbox = postbox
|
||||||
self.network = network
|
self.network = network
|
||||||
self.accountPeerId = accountPeerId
|
self.accountPeerId = accountPeerId
|
||||||
self.download.set(network.background())
|
self.download.set(network.background())
|
||||||
|
self.preloadItemsSignal = preloadItemsSignal
|
||||||
|
|
||||||
let queue = Queue.mainQueue()
|
let queue = Queue.mainQueue()
|
||||||
self.additionalPreloadPeerIdsContext = QueueLocalObject(queue: queue, generate: {
|
self.additionalPreloadPeerIdsContext = QueueLocalObject(queue: queue, generate: {
|
||||||
@ -324,32 +330,36 @@ final class ChatHistoryPreloadManager {
|
|||||||
}
|
}
|
||||||
return disposable
|
return disposable
|
||||||
}
|
}
|
||||||
self.automaticChatListDisposable.set((combineLatest(queue: .mainQueue(), self.postbox.tailChatListView(groupId: .root, count: 20, summaryComponents: ChatListEntrySummaryComponents()), additionalPeerIds)
|
|
||||||
|> delay(1.0, queue: .mainQueue())
|
/*let signal = self.postbox.tailChatListView(groupId: .root, count: 20, summaryComponents: ChatListEntrySummaryComponents())
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] view, additionalPeerIds in
|
|> map { view -> [ChatHistoryPreloadItem] in
|
||||||
guard let strongSelf = self else {
|
var result: [ChatHistoryPreloadItem] = []
|
||||||
return
|
|
||||||
}
|
|
||||||
#if DEBUG
|
|
||||||
return
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var indices: [(ChatHistoryPreloadIndex, Bool, Bool)] = []
|
|
||||||
for entry in view.0.entries {
|
for entry in view.0.entries {
|
||||||
if case let .MessageEntry(index, _, readState, notificationSettings, _, _, _, _, _, _) = entry {
|
if case let .MessageEntry(index, _, readState, isMuted, _, _, _, _, _, _) = entry {
|
||||||
var hasUnread = false
|
var hasUnread = false
|
||||||
if let readState = readState {
|
if let readState = readState {
|
||||||
hasUnread = readState.count != 0
|
hasUnread = readState.count != 0
|
||||||
}
|
}
|
||||||
var isMuted = false
|
result.append(ChatHistoryPreloadItem(index: index, isMuted: isMuted, hasUnread: hasUnread))
|
||||||
if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings {
|
|
||||||
if case let .muted(until) = notificationSettings.muteState, until >= Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) {
|
|
||||||
isMuted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
indices.append((ChatHistoryPreloadIndex(index: index, entity: .peer(index.messageIndex.id.peerId)), hasUnread, isMuted))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result
|
||||||
|
}*/
|
||||||
|
|
||||||
|
self.automaticChatListDisposable.set((combineLatest(queue: .mainQueue(), self.preloadItemsSignal, additionalPeerIds)
|
||||||
|
|> delay(1.0, queue: .mainQueue())
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] loadItems, additionalPeerIds in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
#if DEBUG
|
||||||
|
//return
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var indices: [(ChatHistoryPreloadIndex, Bool, Bool)] = []
|
||||||
|
for item in loadItems {
|
||||||
|
indices.append((ChatHistoryPreloadIndex(index: item.index, entity: .peer(item.index.messageIndex.id.peerId)), item.hasUnread, item.isMuted))
|
||||||
|
}
|
||||||
|
|
||||||
strongSelf.update(indices: indices, additionalPeerIds: additionalPeerIds)
|
strongSelf.update(indices: indices, additionalPeerIds: additionalPeerIds)
|
||||||
}))
|
}))
|
||||||
|
@ -86,7 +86,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
if case let .chatSelection(_, selectedChats, additionalCategories) = mode {
|
if case let .chatSelection(_, selectedChats, additionalCategories) = mode {
|
||||||
placeholder = self.presentationData.strings.ChatListFilter_AddChatsTitle
|
placeholder = self.presentationData.strings.ChatListFilter_AddChatsTitle
|
||||||
let chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, controlsHistoryPreload: false, mode: .peers(filter: [.excludeSavedMessages], isSelecting: true, additionalCategories: additionalCategories?.categories ?? []), theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
let chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, fillPreloadItems: false, mode: .peers(filter: [.excludeSavedMessages], isSelecting: true, additionalCategories: additionalCategories?.categories ?? []), theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||||
chatListNode.updateState { state in
|
chatListNode.updateState { state in
|
||||||
var state = state
|
var state = state
|
||||||
for peerId in selectedChats {
|
for peerId in selectedChats {
|
||||||
|
@ -85,7 +85,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||||||
self.segmentedControlNode = nil
|
self.segmentedControlNode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
self.chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, controlsHistoryPreload: false, mode: .peers(filter: filter, isSelecting: false, additionalCategories: []), theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
self.chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, fillPreloadItems: false, mode: .peers(filter: filter, isSelecting: false, additionalCategories: []), theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user