From 05ffb47c1cd7f52f5c756a6054263c8fa09ceada Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 9 Mar 2020 13:39:06 +0400 Subject: [PATCH] Folder improvements --- .../ChatListUI/Sources/ChatContextMenus.swift | 34 ++++---- .../Sources/ChatListController.swift | 36 +++++++- .../ChatListFilterPresetController.swift | 83 ++++++++++--------- .../ChatListFilterPresetListController.swift | 40 ++++++--- .../ChatListFilterTabContainerNode.swift | 4 +- .../Sources/Node/ChatListHoleItem.swift | 49 +---------- .../TabBarChatListFilterController.swift | 23 ++--- .../ContextUI/Sources/ContextController.swift | 17 ++-- submodules/Display/Source/NavigationBar.swift | 6 +- .../Display/Source/Nodes/ButtonNode.swift | 38 ++++++++- .../Display/Source/TabBarController.swift | 7 ++ .../GalleryUI/Sources/GalleryPagerNode.swift | 16 ++-- .../Sources/MutableBasicPeerView.swift | 11 +++ .../Sources/UnreadMessageCountsView.swift | 11 ++- .../Sources/SegmentedControlNode.swift | 1 + .../Sources/SettingsController.swift | 1 + ...essageContextControllerContentSource.swift | 1 + .../TooltipUI/Sources/TooltipScreen.swift | 14 +++- 18 files changed, 237 insertions(+), 155 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index 28ca57540d..8894256308 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -18,7 +18,7 @@ func archiveContextMenuItems(context: AccountContext, groupId: PeerGroupId, chat var items: [ContextMenuItem] = [] if !transaction.getUnreadChatListPeerIds(groupId: groupId, filterPredicate: nil).isEmpty { - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAllAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { [weak chatListController] _, f in + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAllAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in let _ = (context.account.postbox.transaction { transaction in markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: groupId, filterPredicate: nil) } @@ -40,7 +40,7 @@ func archiveContextMenuItems(context: AccountContext, groupId: PeerGroupId, chat } enum ChatContextMenuSource { - case chatList + case chatList(isFilter: Bool) case search(ChatListSearchContextActionSource) } @@ -146,20 +146,22 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, source: ChatC }))) } - let isPinned = index.pinningIndex != nil - items.append(.action(ContextMenuActionItem(text: isPinned ? strings.ChatList_Context_Unpin : strings.ChatList_Context_Pin, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin" : "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { _, f in - let _ = (toggleItemPinned(postbox: context.account.postbox, groupId: group, itemId: .peer(peerId)) - |> deliverOnMainQueue).start(next: { result in - switch result { - case .done: - break - case let .limitExceeded(maxCount): - break - //strongSelf.presentAlert?(strongSelf.currentState.presentationData.strings.DialogList_PinLimitError("\(maxCount)").0) - } - f(.default) - }) - }))) + if case .chatList(false) = source { + let isPinned = index.pinningIndex != nil + items.append(.action(ContextMenuActionItem(text: isPinned ? strings.ChatList_Context_Unpin : strings.ChatList_Context_Pin, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin" : "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { _, f in + let _ = (toggleItemPinned(postbox: context.account.postbox, groupId: group, itemId: .peer(peerId)) + |> deliverOnMainQueue).start(next: { result in + switch result { + case .done: + break + case let .limitExceeded(maxCount): + break + //strongSelf.presentAlert?(strongSelf.currentState.presentationData.strings.DialogList_PinLimitError("\(maxCount)").0) + } + f(.default) + }) + }))) + } if !isSavedMessages, let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings { var isMuted = false diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index afb6f7776c..b8aa99dc98 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -294,6 +294,28 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, let title = !state.selectedPeerIds.isEmpty ? strongSelf.presentationData.strings.ChatList_SelectedChats(Int32(state.selectedPeerIds.count)) : defaultTitle strongSelf.titleView.title = NetworkStatusTitle(text: title, activity: false, hasProxy: false, connectsViaProxy: false, isPasscodeSet: false, isManuallyLocked: false) + } else if isReorderingTabs { + if strongSelf.groupId == .root { + strongSelf.navigationItem.rightBarButtonItem = nil + } + let leftBarButtonItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.reorderingDonePressed)) + strongSelf.navigationItem.leftBarButtonItem = leftBarButtonItem + + let (_, connectsViaProxy) = proxy + switch networkState { + case .waitingForNetwork: + strongSelf.titleView.title = NetworkStatusTitle(text: strongSelf.presentationData.strings.State_WaitingForNetwork, activity: true, hasProxy: false, connectsViaProxy: connectsViaProxy, isPasscodeSet: false, isManuallyLocked: false) + case let .connecting(proxy): + var text = strongSelf.presentationData.strings.State_Connecting + if let layout = strongSelf.validLayout, proxy != nil && layout.metrics.widthClass != .regular && layout.size.width > 320.0 { + text = strongSelf.presentationData.strings.State_ConnectingToProxy + } + strongSelf.titleView.title = NetworkStatusTitle(text: text, activity: true, hasProxy: false, connectsViaProxy: connectsViaProxy, isPasscodeSet: false, isManuallyLocked: false) + case .updating: + strongSelf.titleView.title = NetworkStatusTitle(text: strongSelf.presentationData.strings.State_Updating, activity: true, hasProxy: false, connectsViaProxy: connectsViaProxy, isPasscodeSet: false, isManuallyLocked: false) + case .online: + strongSelf.titleView.title = NetworkStatusTitle(text: defaultTitle, activity: false, hasProxy: false, connectsViaProxy: connectsViaProxy, isPasscodeSet: false, isManuallyLocked: false) + } } else { var isRoot = false if case .root = strongSelf.groupId { @@ -908,7 +930,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, case let .peer(peer): let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.peer.peerId), subject: nil, botStart: nil, mode: .standard(previewing: true)) chatController.canReadHistory.set(false) - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.peer.peerId, source: .chatList, chatListController: strongSelf), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.peer.peerId, source: .chatList(isFilter: strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter != nil), chatListController: strongSelf), reactionItems: [], gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) } } @@ -1148,7 +1170,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, } else { text = "Hold to organize your chats with folders." } - parentController.present(TooltipScreen(text: text, location: CGPoint(x: absoluteFrame.midX - 14.0, y: absoluteFrame.minY - 8.0)), in: .current) + parentController.present(TooltipScreen(text: text, location: CGPoint(x: absoluteFrame.midX - 14.0, y: absoluteFrame.minY - 8.0), shouldDismissOnTouch: { point in + guard let strongSelf = self, let parentController = strongSelf.parent as? TabBarController else { + return true + } + if parentController.isPointInsideContentArea(point: point) { + return false + } + return true + }), in: .current) } }) } @@ -2450,6 +2480,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, private final class ChatListTabBarContextExtractedContentSource: ContextExtractedContentSource { let keepInPlace: Bool = true + let ignoreContentTouches: Bool = true private let controller: ChatListController private let sourceNode: ContextExtractedContentContainingNode @@ -2470,6 +2501,7 @@ private final class ChatListTabBarContextExtractedContentSource: ContextExtracte private final class ChatListHeaderBarContextExtractedContentSource: ContextExtractedContentSource { let keepInPlace: Bool = false + let ignoreContentTouches: Bool = true private let controller: ChatListController private let sourceNode: ContextExtractedContentContainingNode diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index 148141f4e8..77d90cfe25 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -849,6 +849,44 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat } var attemptNavigationImpl: (() -> Bool)? + var applyImpl: (() -> Void)? = { + let state = stateValue.with { $0 } + let preset = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: state.additionallyIncludePeers, excludePeers: state.additionallyExcludePeers)) + let _ = (updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in + var preset = preset + if currentPreset == nil { + preset.id = max(2, settings.filters.map({ $0.id + 1 }).max() ?? 2) + } + var settings = settings + if let _ = currentPreset { + var found = false + for i in 0 ..< settings.filters.count { + if settings.filters[i].id == preset.id { + settings.filters[i] = preset + found = true + } + } + if !found { + settings.filters = settings.filters.filter { listFilter in + if listFilter.title == preset.title && listFilter.data == preset.data { + return false + } + return true + } + settings.filters.append(preset) + } + } else { + settings.filters.append(preset) + } + return settings + }) + |> deliverOnMainQueue).start(next: { settings in + updated(settings.filters) + dismissImpl?() + + let _ = replaceRemoteChatListFilters(account: context.account).start() + }) + } let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, @@ -864,42 +902,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat } }) let rightNavigationButton = ItemListNavigationButton(content: .text(currentPreset == nil ? presentationData.strings.Common_Create : presentationData.strings.Common_Done), style: .bold, enabled: state.isComplete, action: { - let state = stateValue.with { $0 } - let preset = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: state.additionallyIncludePeers, excludePeers: state.additionallyExcludePeers)) - let _ = (updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in - var preset = preset - if currentPreset == nil { - preset.id = max(2, settings.filters.map({ $0.id + 1 }).max() ?? 2) - } - var settings = settings - if let _ = currentPreset { - var found = false - for i in 0 ..< settings.filters.count { - if settings.filters[i].id == preset.id { - settings.filters[i] = preset - found = true - } - } - if !found { - settings.filters = settings.filters.filter { listFilter in - if listFilter.title == preset.title && listFilter.data == preset.data { - return false - } - return true - } - settings.filters.append(preset) - } - } else { - settings.filters.append(preset) - } - return settings - }) - |> deliverOnMainQueue).start(next: { settings in - updated(settings.filters) - dismissImpl?() - - let _ = replaceRemoteChatListFilters(account: context.account).start() - }) + applyImpl?() }) let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(currentPreset != nil ? "Folder" : "Create Folder"), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) @@ -935,8 +938,12 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat } let displaySaveAlert: () -> Void = { let presentationData = context.sharedContext.currentPresentationData.with { $0 } - presentControllerImpl?(textAlertController(context: context, title: nil, text: "Are you sure you want to discard this folder?", actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: { - dismissImpl?() + presentControllerImpl?(textAlertController(context: context, title: nil, text: "You have changed the filter. Apply changes?", actions: [ + TextAlertAction(type: .genericAction, title: "Discard", action: { + dismissImpl?() + }), + TextAlertAction(type: .defaultAction, title: "Apply", action: { + applyImpl?() })]), nil) } attemptNavigationImpl = { diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift index 8a2d3a7e3f..4d2a6b13c7 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -52,6 +52,7 @@ private enum ChatListFilterPresetListEntryStableId: Hashable { case screenHeader case suggestedListHeader case suggestedPreset(ChatListFilterData) + case suggestedAddCustom case listHeader case preset(Int32) case addItem @@ -70,6 +71,7 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { case screenHeader(String) case suggestedListHeader(String) case suggestedPreset(index: PresetIndex, title: String, label: String, preset: ChatListFilterData) + case suggestedAddCustom(String) case listHeader(String) case preset(index: PresetIndex, title: String, label: String, preset: ChatListFilter, canBeReordered: Bool, canBeDeleted: Bool, isEditing: Bool) case addItem(text: String, isEditing: Bool) @@ -79,7 +81,7 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { switch self { case .screenHeader: return ChatListFilterPresetListSection.screenHeader.rawValue - case .suggestedListHeader, .suggestedPreset: + case .suggestedListHeader, .suggestedPreset, .suggestedAddCustom: return ChatListFilterPresetListSection.suggested.rawValue case .listHeader, .preset, .addItem, .listFooter: return ChatListFilterPresetListSection.list.rawValue @@ -102,6 +104,8 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { return 1002 case let .suggestedPreset(suggestedPreset): return 1003 + suggestedPreset.index.value + case .suggestedAddCustom: + return 2000 } } @@ -113,6 +117,8 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { return .suggestedListHeader case let .suggestedPreset(suggestedPreset): return .suggestedPreset(suggestedPreset.preset) + case .suggestedAddCustom: + return .suggestedAddCustom case .listHeader: return .listHeader case let .preset(preset): @@ -139,6 +145,10 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { return ChatListFilterPresetListSuggestedItem(presentationData: presentationData, title: title, label: label, sectionId: self.section, style: .blocks, installAction: { arguments.addSuggestedPresed(title, preset) }, tag: nil) + case let .suggestedAddCustom(text): + return ItemListPeerActionItem(presentationData: presentationData, icon: nil, title: text, sectionId: self.section, height: .generic, editing: false, action: { + arguments.addNew() + }) case let .listHeader(text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, multiline: true, sectionId: self.section) case let .preset(_, title, label, preset, canBeReordered, canBeDeleted, isEditing): @@ -183,6 +193,7 @@ private func filtersWithAppliedOrder(filters: [(ChatListFilter, Int)], order: [I private func chatListFilterPresetListControllerEntries(presentationData: PresentationData, state: ChatListFilterPresetListControllerState, filters: [(ChatListFilter, Int)], updatedFilterOrder: [Int32]?, suggestedFilters: [ChatListFeaturedFilter], settings: ChatListFilterSettings) -> [ChatListFilterPresetListEntry] { var entries: [ChatListFilterPresetListEntry] = [] + entries.append(.screenHeader("Create folders for different groups of chats and\nquickly switch between them.")) let filteredSuggestedFilters = suggestedFilters.filter { suggestedFilter in @@ -194,21 +205,26 @@ private func chatListFilterPresetListControllerEntries(presentationData: Present return true } - entries.append(.listHeader("FOLDERS")) - - for (filter, chatCount) in filtersWithAppliedOrder(filters: filters, order: updatedFilterOrder) { - entries.append(.preset(index: PresetIndex(value: entries.count), title: filter.title, label: chatCount == 0 ? "" : "\(chatCount)", preset: filter, canBeReordered: filters.count > 1, canBeDeleted: true, isEditing: state.isEditing)) + if !filters.isEmpty || suggestedFilters.isEmpty { + entries.append(.listHeader("FOLDERS")) + + for (filter, chatCount) in filtersWithAppliedOrder(filters: filters, order: updatedFilterOrder) { + entries.append(.preset(index: PresetIndex(value: entries.count), title: filter.title, label: chatCount == 0 ? "" : "\(chatCount)", preset: filter, canBeReordered: filters.count > 1, canBeDeleted: true, isEditing: state.isEditing)) + } + if filters.count < 10 { + entries.append(.addItem(text: "Create New Folder", isEditing: state.isEditing)) + } + entries.append(.listFooter("Tap \"Edit\" to change the order or delete folders.")) } - if filters.count < 10 { - entries.append(.addItem(text: "Create New Folder", isEditing: state.isEditing)) - } - entries.append(.listFooter("Tap \"Edit\" to change the order or delete folders.")) if !filteredSuggestedFilters.isEmpty { entries.append(.suggestedListHeader("RECOMMENDED FOLDERS")) for filter in filteredSuggestedFilters { entries.append(.suggestedPreset(index: PresetIndex(value: entries.count), title: filter.title, label: filter.description, preset: filter.data)) } + if filters.isEmpty { + entries.append(.suggestedAddCustom("Add Custom Folder")) + } } return entries @@ -332,7 +348,7 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch dismissImpl?() }) } - let rightNavigationButton: ItemListNavigationButton + let rightNavigationButton: ItemListNavigationButton? if state.isEditing { rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: { let _ = (updatedFilterOrder.get() @@ -381,7 +397,7 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch } }) }) - } else { + } else if !filtersWithCountsValue.isEmpty { rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: { updateState { state in var state = state @@ -389,6 +405,8 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch return state } }) + } else { + rightNavigationButton = nil } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Folders"), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) diff --git a/submodules/ChatListUI/Sources/ChatListFilterTabContainerNode.swift b/submodules/ChatListUI/Sources/ChatListFilterTabContainerNode.swift index e7d228ae38..4c4738333b 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterTabContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterTabContainerNode.swift @@ -785,7 +785,9 @@ final class ChatListFilterTabContainerNode: ASDisplayNode { if let previousSelectedFrame = self.previousSelectedFrame { let previousContentOffsetX = max(0.0, min(previousContentWidth - previousScrollBounds.width, floor(previousSelectedFrame.midX - previousScrollBounds.width / 2.0))) - focusOnSelectedFilter = abs(previousContentOffsetX - previousScrollBounds.minX) < 1.0 + if abs(previousContentOffsetX - previousScrollBounds.minX) < 1.0 { + focusOnSelectedFilter = true + } } if focusOnSelectedFilter && self.reorderingItem == nil { diff --git a/submodules/ChatListUI/Sources/Node/ChatListHoleItem.swift b/submodules/ChatListUI/Sources/Node/ChatListHoleItem.swift index ccce665a4c..f69ff4eb35 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListHoleItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListHoleItem.swift @@ -6,8 +6,6 @@ import Display import SwiftSignalKit import TelegramPresentationData -private let titleFont = Font.regular(17.0) - class ChatListHoleItem: ListViewItem { let theme: PresentationTheme @@ -45,9 +43,6 @@ class ChatListHoleItem: ListViewItem { Queue.mainQueue().async { completion(nodeLayout, { _ in apply() - if let nodeValue = node() as? ChatListHoleItemNode { - nodeValue.updateBackgroundAndSeparatorsLayout() - } }) } } @@ -56,25 +51,11 @@ class ChatListHoleItem: ListViewItem { } } -private let separatorHeight = 1.0 / UIScreen.main.scale - class ChatListHoleItemNode: ListViewItemNode { - let separatorNode: ASDisplayNode - let labelNode: TextNode - var relativePosition: (first: Bool, last: Bool) = (false, false) required init() { - self.separatorNode = ASDisplayNode() - self.separatorNode.backgroundColor = UIColor(rgb: 0xc8c7cc) - self.separatorNode.isLayerBacked = true - - self.labelNode = TextNode() - super.init(layerBacked: false, dynamicBounce: false) - - self.addSubnode(self.separatorNode) - self.addSubnode(self.labelNode) } override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) { @@ -84,45 +65,17 @@ class ChatListHoleItemNode: ListViewItemNode { } func asyncLayout() -> (_ item: ChatListHoleItem, _ params: ListViewItemLayoutParams, _ first: Bool, _ last: Bool) -> (ListViewItemNodeLayout, () -> Void) { - let labelNodeLayout = TextNode.asyncLayout(self.labelNode) - return { item, params, first, last in - let baseWidth = params.width - params.leftInset - params.rightInset - - let (labelLayout, labelApply) = labelNodeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "", font: titleFont, textColor: item.theme.chatList.messageTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: baseWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - - let insets = ChatListItemNode.insets(first: first, last: last, firstWithHeader: false) - let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 68.0), insets: insets) - - let separatorInset: CGFloat - if last { - separatorInset = 0.0 - } else { - separatorInset = 80.0 + params.leftInset - } + let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 0.0), insets: UIEdgeInsets()) return (layout, { [weak self] in if let strongSelf = self { strongSelf.relativePosition = (first, last) - let _ = labelApply() - - strongSelf.separatorNode.backgroundColor = item.theme.chatList.itemSeparatorColor - - strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: floor((params.width - labelLayout.size.width) / 2.0), y: floor((layout.contentSize.height - labelLayout.size.height) / 2.0)), size: labelLayout.size) - - strongSelf.separatorNode.frame = CGRect(origin: CGPoint(x: separatorInset, y: 68.0 - separatorHeight), size: CGSize(width: params.width - separatorInset, height: separatorHeight)) - strongSelf.contentSize = layout.contentSize strongSelf.insets = layout.insets - strongSelf.updateBackgroundAndSeparatorsLayout() } }) } } - - func updateBackgroundAndSeparatorsLayout() { - //let size = self.bounds.size - //let insets = self.insets - } } diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift index 184dc615f3..3b922318da 100644 --- a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -42,25 +42,13 @@ func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilt return combineLatest(queue: context.account.postbox.queue, context.account.postbox.combinedView(keys: keys), - context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.inAppNotificationSettings]) + Signal.single(true) ) - |> map { view, sharedData -> (Int, [(ChatListFilter, Int)]) in + |> map { view, _ -> (Int, [(ChatListFilter, Int)]) in guard let unreadCounts = view.views[unreadKey] as? UnreadMessageCountsView else { return (0, []) } - let inAppSettings: InAppNotificationSettings - if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.inAppNotificationSettings] as? InAppNotificationSettings { - inAppSettings = value - } else { - inAppSettings = .defaultSettings - } - let type: RenderedTotalUnreadCountType - switch inAppSettings.totalUnreadCountDisplayStyle { - case .filtered: - type = .filtered - } - var result: [(ChatListFilter, Int)] = [] var peerTagAndCount: [PeerId: (PeerSummaryCounterTags, Int)] = [:] @@ -70,6 +58,8 @@ func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilt switch entry { case let .total(_, totalStateValue): totalState = totalStateValue + case let .totalInGroup(groupId, totalGroupState): + break case let .peer(peerId, state): if let state = state, state.isUnread { if let peerView = view.views[.basicPeer(peerId)] as? BasicPeerView, let peer = peerView.peer { @@ -88,10 +78,7 @@ func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilt } } - var totalBadge = 0 - if let totalState = totalState { - totalBadge = Int(totalState.count(for: inAppSettings.totalUnreadCountDisplayStyle.category, in: inAppSettings.totalUnreadCountDisplayCategory.statsType, with: inAppSettings.totalUnreadCountIncludeTags)) - } + let totalBadge = 0 for filter in filters { var tags: [PeerSummaryCounterTags] = [] diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index e8f603e52c..955437af01 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -1363,12 +1363,16 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi if let maybeContentNode = self.contentContainerNode.contentNode { switch maybeContentNode { case let .extracted(contentParentNode, _): - let contentPoint = self.view.convert(point, to: contentParentNode.contentNode.view) - if let result = contentParentNode.contentNode.hitTest(contentPoint, with: event) { - if result is TextSelectionNodeView { - return result - } else if contentParentNode.contentRect.contains(contentPoint) { - return contentParentNode.contentNode.view + if case let .extracted(source) = self.source { + if !source.ignoreContentTouches { + let contentPoint = self.view.convert(point, to: contentParentNode.contentNode.view) + if let result = contentParentNode.contentNode.hitTest(contentPoint, with: event) { + if result is TextSelectionNodeView { + return result + } else if contentParentNode.contentRect.contains(contentPoint) { + return contentParentNode.contentNode.view + } + } } } case let .controller(controller): @@ -1429,6 +1433,7 @@ public final class ContextControllerPutBackViewInfo { public protocol ContextExtractedContentSource: class { var keepInPlace: Bool { get } + var ignoreContentTouches: Bool { get } func takeView() -> ContextControllerTakeViewInfo? func putBack() -> ContextControllerPutBackViewInfo? diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 43bf27a4eb..4389657b7b 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -799,8 +799,10 @@ open class NavigationBar: ASDisplayNode { } private func requestLayout() { - self.requestedLayout = true - self.setNeedsLayout() + if self.transitionState == nil { + self.requestedLayout = true + self.setNeedsLayout() + } } override open func layout() { diff --git a/submodules/Display/Source/Nodes/ButtonNode.swift b/submodules/Display/Source/Nodes/ButtonNode.swift index 190e52f732..927eea4f7e 100644 --- a/submodules/Display/Source/Nodes/ButtonNode.swift +++ b/submodules/Display/Source/Nodes/ButtonNode.swift @@ -5,6 +5,7 @@ import AsyncDisplayKit open class ASButtonNode: ASControlNode { public let titleNode: ImmediateTextNode public let highlightedTitleNode: ImmediateTextNode + public let disabledTitleNode: ImmediateTextNode public let imageNode: ASImageNode public let disabledImageNode: ASImageNode public let backgroundImageNode: ASImageNode @@ -48,6 +49,7 @@ open class ASButtonNode: ASControlNode { private var calculatedTitleSize: CGSize = CGSize() private var calculatedHighlightedTitleSize: CGSize = CGSize() + private var calculatedDisabledTitleSize: CGSize = CGSize() override public init() { self.titleNode = ImmediateTextNode() @@ -58,6 +60,10 @@ open class ASButtonNode: ASControlNode { self.highlightedTitleNode.isUserInteractionEnabled = false self.highlightedTitleNode.displaysAsynchronously = false + self.disabledTitleNode = ImmediateTextNode() + self.disabledTitleNode.isUserInteractionEnabled = false + self.disabledTitleNode.displaysAsynchronously = false + self.imageNode = ASImageNode() self.imageNode.isUserInteractionEnabled = false self.imageNode.displaysAsynchronously = false @@ -86,6 +92,8 @@ open class ASButtonNode: ASControlNode { self.addSubnode(self.titleNode) self.addSubnode(self.highlightedTitleNode) self.highlightedTitleNode.isHidden = true + self.addSubnode(self.disabledTitleNode) + self.disabledTitleNode.isHidden = true self.addSubnode(self.imageNode) self.addSubnode(self.disabledImageNode) self.disabledImageNode.isHidden = true @@ -108,6 +116,7 @@ open class ASButtonNode: ASControlNode { self.calculatedTitleSize = normalTitleSize let highlightedTitleSize = self.highlightedTitleNode.updateLayout(CGSize(width: widthForTitle, height: max(1.0, constrainedSize.height - verticalInsets))) self.calculatedHighlightedTitleSize = highlightedTitleSize + self.calculatedDisabledTitleSize = self.disabledTitleNode.updateLayout(CGSize(width: widthForTitle, height: max(1.0, constrainedSize.height - verticalInsets))) let titleSize = CGSize(width: max(normalTitleSize.width, highlightedTitleSize.width), height: max(normalTitleSize.height, highlightedTitleSize.height)) @@ -161,6 +170,17 @@ open class ASButtonNode: ASControlNode { self.setNeedsLayout() } self.highlightedTitleNode.attributedText = title + } else if state == .disabled { + if let attributedText = self.disabledTitleNode.attributedText { + if !attributedText.isEqual(to: title) { + self.invalidateCalculatedLayout() + self.setNeedsLayout() + } + } else { + self.invalidateCalculatedLayout() + self.setNeedsLayout() + } + self.disabledTitleNode.attributedText = title } else { if let attributedText = self.titleNode.attributedText { if !attributedText.isEqual(to: title) { @@ -178,6 +198,8 @@ open class ASButtonNode: ASControlNode { open func attributedTitle(for state: UIControl.State) -> NSAttributedString? { if state == .highlighted || state == .selected { return self.highlightedTitleNode.attributedText + } else if state == .disabled { + return self.disabledTitleNode.attributedText } else { return self.titleNode.attributedText } @@ -255,6 +277,14 @@ open class ASButtonNode: ASControlNode { override open var isEnabled: Bool { didSet { if self.isEnabled != oldValue { + if self.isEnabled || self.disabledTitleNode.attributedText == nil { + self.titleNode.isHidden = false + self.disabledTitleNode.isHidden = true + } else { + self.titleNode.isHidden = true + self.disabledTitleNode.isHidden = false + } + if self.isEnabled || self.disabledImageNode.image == nil { self.imageNode.isHidden = false self.disabledImageNode.isHidden = true @@ -275,6 +305,7 @@ open class ASButtonNode: ASControlNode { let titleOrigin: CGPoint let highlightedTitleOrigin: CGPoint + let disabledTitleOrigin: CGPoint let imageOrigin: CGPoint if self.laysOutHorizontally { @@ -282,14 +313,17 @@ open class ASButtonNode: ASControlNode { case .left: titleOrigin = CGPoint(x: contentRect.minX, y: contentRect.minY + floor((contentRect.height - self.calculatedTitleSize.height) / 2.0)) highlightedTitleOrigin = CGPoint(x: contentRect.minX, y: contentRect.minY + floor((contentRect.height - self.calculatedHighlightedTitleSize.height) / 2.0)) + disabledTitleOrigin = CGPoint(x: contentRect.minX, y: contentRect.minY + floor((contentRect.height - self.calculatedDisabledTitleSize.height) / 2.0)) imageOrigin = CGPoint(x: titleOrigin.x + self.calculatedTitleSize.width + self.contentSpacing, y: contentRect.minY + floor((contentRect.height - imageSize.height) / 2.0)) case .right: titleOrigin = CGPoint(x: contentRect.maxX - self.calculatedTitleSize.width, y: contentRect.minY + floor((contentRect.height - self.calculatedTitleSize.height) / 2.0)) highlightedTitleOrigin = CGPoint(x: contentRect.maxX - self.calculatedHighlightedTitleSize.width, y: contentRect.minY + floor((contentRect.height - self.calculatedHighlightedTitleSize.height) / 2.0)) + disabledTitleOrigin = CGPoint(x: contentRect.maxX - self.calculatedDisabledTitleSize.width, y: contentRect.minY + floor((contentRect.height - self.calculatedDisabledTitleSize.height) / 2.0)) imageOrigin = CGPoint(x: titleOrigin.x - self.contentSpacing - imageSize.width, y: contentRect.minY + floor((contentRect.height - imageSize.height) / 2.0)) default: - titleOrigin = CGPoint(x: contentRect.minY + floor((contentRect.width - self.calculatedTitleSize.width) / 2.0), y: contentRect.minY + floor((contentRect.height - self.calculatedTitleSize.height) / 2.0)) + titleOrigin = CGPoint(x: contentRect.minX + floor((contentRect.width - self.calculatedTitleSize.width) / 2.0), y: contentRect.minY + floor((contentRect.height - self.calculatedTitleSize.height) / 2.0)) highlightedTitleOrigin = CGPoint(x: floor((contentRect.width - self.calculatedHighlightedTitleSize.width) / 2.0), y: contentRect.minY + floor((contentRect.height - self.calculatedHighlightedTitleSize.height) / 2.0)) + disabledTitleOrigin = CGPoint(x: floor((contentRect.width - self.calculatedDisabledTitleSize.width) / 2.0), y: contentRect.minY + floor((contentRect.height - self.calculatedDisabledTitleSize.height) / 2.0)) imageOrigin = CGPoint(x: floor((contentRect.width - imageSize.width) / 2.0), y: contentRect.minY + floor((contentRect.height - imageSize.height) / 2.0)) } } else { @@ -300,11 +334,13 @@ open class ASButtonNode: ASControlNode { let contentY = contentRect.minY + floor((contentRect.height - contentHeight) / 2.0) titleOrigin = CGPoint(x: contentRect.minX + floor((contentRect.width - self.calculatedTitleSize.width) / 2.0), y: contentY + contentHeight - self.calculatedTitleSize.height) highlightedTitleOrigin = CGPoint(x: contentRect.minX + floor((contentRect.width - self.calculatedHighlightedTitleSize.width) / 2.0), y: contentY + contentHeight - self.calculatedHighlightedTitleSize.height) + disabledTitleOrigin = CGPoint(x: contentRect.minX + floor((contentRect.width - self.calculatedDisabledTitleSize.width) / 2.0), y: contentY + contentHeight - self.calculatedDisabledTitleSize.height) imageOrigin = CGPoint(x: floor((contentRect.width - imageSize.width) / 2.0), y: contentY) } self.titleNode.frame = CGRect(origin: titleOrigin, size: self.calculatedTitleSize) self.highlightedTitleNode.frame = CGRect(origin: highlightedTitleOrigin, size: self.calculatedHighlightedTitleSize) + self.disabledTitleNode.frame = CGRect(origin: disabledTitleOrigin, size: self.calculatedDisabledTitleSize) self.imageNode.frame = CGRect(origin: imageOrigin, size: imageSize) self.disabledImageNode.frame = CGRect(origin: imageOrigin, size: imageSize) diff --git a/submodules/Display/Source/TabBarController.swift b/submodules/Display/Source/TabBarController.swift index d8102845b4..36b93c9b5f 100644 --- a/submodules/Display/Source/TabBarController.swift +++ b/submodules/Display/Source/TabBarController.swift @@ -174,6 +174,13 @@ open class TabBarController: ViewController { } } + public func isPointInsideContentArea(point: CGPoint) -> Bool { + if point.y < self.tabBarControllerNode.tabBarNode.frame.minY { + return true + } + return false + } + override open func loadDisplayNode() { self.displayNode = TabBarControllerNode(theme: self.theme, navigationBar: self.navigationBar, itemSelected: { [weak self] index, longTap, itemNodes in if let strongSelf = self { diff --git a/submodules/GalleryUI/Sources/GalleryPagerNode.swift b/submodules/GalleryUI/Sources/GalleryPagerNode.swift index edae0ad81f..d07e240f34 100644 --- a/submodules/GalleryUI/Sources/GalleryPagerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryPagerNode.swift @@ -5,7 +5,9 @@ import Display import SwiftSignalKit import Postbox -private let edgeWidth: CGFloat = 44.0 +private func edgeWidth(width: CGFloat) -> CGFloat { + return min(44.0, floor(width / 6.0)) +} private let leftFadeImage = generateImage(CGSize(width: 64.0, height: 1.0), opaque: false, rotatedContext: { size, context in let bounds = CGRect(origin: CGPoint(), size: size) @@ -153,11 +155,11 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest let size = strongSelf.bounds var highlightedSide: Bool? - if point.x < edgeWidth && strongSelf.canGoToPreviousItem() { + if point.x < edgeWidth(width: size.width) && strongSelf.canGoToPreviousItem() { if strongSelf.items.count > 1 { highlightedSide = false } - } else if point.x > size.width - edgeWidth && strongSelf.canGoToNextItem() { + } else if point.x > size.width - edgeWidth(width: size.width) && strongSelf.canGoToNextItem() { if strongSelf.items.count > 1 { highlightedSide = true } @@ -180,11 +182,11 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest var highlightedSide: Bool? if let point = point { - if point.x < edgeWidth && strongSelf.canGoToPreviousItem() { + if point.x < edgeWidth(width: size.width) && strongSelf.canGoToPreviousItem() { if strongSelf.items.count > 1 { highlightedSide = false } - } else if point.x > size.width - edgeWidth && strongSelf.canGoToNextItem() { + } else if point.x > size.width - edgeWidth(width: size.width) && strongSelf.canGoToNextItem() { if strongSelf.items.count > 1 { highlightedSide = true } @@ -233,9 +235,9 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation { if case .tap = gesture { let size = self.bounds.size - if location.x < edgeWidth && self.canGoToPreviousItem() { + if location.x < edgeWidth(width: size.width) && self.canGoToPreviousItem() { self.goToPreviousItem() - } else if location.x > size.width - edgeWidth && self.canGoToNextItem() { + } else if location.x > size.width - edgeWidth(width: size.width) && self.canGoToNextItem() { self.goToNextItem() } } diff --git a/submodules/Postbox/Sources/MutableBasicPeerView.swift b/submodules/Postbox/Sources/MutableBasicPeerView.swift index c1b0d584c4..db8f3b1b74 100644 --- a/submodules/Postbox/Sources/MutableBasicPeerView.swift +++ b/submodules/Postbox/Sources/MutableBasicPeerView.swift @@ -5,12 +5,14 @@ final class MutableBasicPeerView: MutablePostboxView { fileprivate var peer: Peer? fileprivate var notificationSettings: PeerNotificationSettings? fileprivate var isContact: Bool + fileprivate var groupId: PeerGroupId? init(postbox: Postbox, peerId: PeerId) { self.peerId = peerId self.peer = postbox.peerTable.get(peerId) self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(peerId) self.isContact = postbox.contactsTable.isContact(peerId: self.peerId) + self.groupId = postbox.chatListIndexTable.get(peerId: peerId).inclusion.groupId } func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool { @@ -30,6 +32,13 @@ final class MutableBasicPeerView: MutablePostboxView { updated = true } } + if transaction.currentUpdatedChatListInclusions[self.peerId] != nil { + let groupId = postbox.chatListIndexTable.get(peerId: peerId).inclusion.groupId + if self.groupId != groupId { + self.groupId = groupId + updated = true + } + } return updated } @@ -43,10 +52,12 @@ public final class BasicPeerView: PostboxView { public let peer: Peer? public let notificationSettings: PeerNotificationSettings? public let isContact: Bool + public let groupId: PeerGroupId? init(_ view: MutableBasicPeerView) { self.peer = view.peer self.notificationSettings = view.notificationSettings self.isContact = view.isContact + self.groupId = view.groupId } } diff --git a/submodules/Postbox/Sources/UnreadMessageCountsView.swift b/submodules/Postbox/Sources/UnreadMessageCountsView.swift index 2f229445fc..7246860341 100644 --- a/submodules/Postbox/Sources/UnreadMessageCountsView.swift +++ b/submodules/Postbox/Sources/UnreadMessageCountsView.swift @@ -2,16 +2,19 @@ import Foundation public enum UnreadMessageCountsItem: Equatable { case total(ValueBoxKey?) + case totalInGroup(PeerGroupId) case peer(PeerId) } private enum MutableUnreadMessageCountsItemEntry { case total((ValueBoxKey, PreferencesEntry?)?, ChatListTotalUnreadState) + case totalInGroup(PeerGroupId, ChatListTotalUnreadState) case peer(PeerId, CombinedPeerReadState?) } public enum UnreadMessageCountsItemEntry { case total(PreferencesEntry?, ChatListTotalUnreadState) + case totalInGroup(PeerGroupId, ChatListTotalUnreadState) case peer(PeerId, CombinedPeerReadState?) } @@ -23,6 +26,8 @@ final class MutableUnreadMessageCountsView: MutablePostboxView { switch item { case let .total(preferencesKey): return .total(preferencesKey.flatMap({ ($0, postbox.preferencesTable.get(key: $0)) }), postbox.messageHistoryMetadataTable.getChatListTotalUnreadState()) + case let .totalInGroup(groupId): + return .totalInGroup(groupId, ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:])) case let .peer(peerId): return .peer(peerId, postbox.readStateTable.getCombinedState(peerId)) } @@ -57,6 +62,8 @@ final class MutableUnreadMessageCountsView: MutablePostboxView { updated = true } } + case let .totalInGroup(groupId, state): + break case let .peer(peerId, _): if transaction.alteredInitialPeerCombinedReadStates[peerId] != nil { self.entries[i] = .peer(peerId, postbox.readStateTable.getCombinedState(peerId)) @@ -82,6 +89,8 @@ public final class UnreadMessageCountsView: PostboxView { switch entry { case let .total(keyAndValue, state): return .total(keyAndValue?.1, state) + case let .totalInGroup(groupId, state): + return .totalInGroup(groupId, state) case let .peer(peerId, count): return .peer(peerId, count) } @@ -103,7 +112,7 @@ public final class UnreadMessageCountsView: PostboxView { public func count(for item: UnreadMessageCountsItem) -> Int32? { for entry in self.entries { switch entry { - case .total: + case .total, .totalInGroup: break case let .peer(peerId, state): if case .peer(peerId) = item { diff --git a/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift b/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift index da4106824a..098d323223 100644 --- a/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift +++ b/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift @@ -315,6 +315,7 @@ public final class SegmentedControlNode: ASDisplayNode, UIGestureRecognizerDeleg for i in 0 ..< self.itemNodes.count { let itemNode = self.itemNodes[i] + let _ = itemNode.measure(itemSize) transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: itemSize.width * CGFloat(i), y: (size.height - itemSize.height) / 2.0), size: itemSize)) let isSelected = selectedIndex == i diff --git a/submodules/SettingsUI/Sources/SettingsController.swift b/submodules/SettingsUI/Sources/SettingsController.swift index 1cdee54516..665b5a5051 100644 --- a/submodules/SettingsUI/Sources/SettingsController.swift +++ b/submodules/SettingsUI/Sources/SettingsController.swift @@ -878,6 +878,7 @@ private final class SettingsControllerImpl: ItemListController, SettingsControll private final class SettingsTabBarContextExtractedContentSource: ContextExtractedContentSource { let keepInPlace: Bool = true + let ignoreContentTouches: Bool = true private let controller: ViewController private let sourceNode: ContextExtractedContentContainingNode diff --git a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift index 2b3bf7c229..a307509514 100644 --- a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift +++ b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift @@ -6,6 +6,7 @@ import Postbox final class ChatMessageContextExtractedContentSource: ContextExtractedContentSource { let keepInPlace: Bool = false + let ignoreContentTouches: Bool = false private weak var chatNode: ChatControllerNode? private let message: Message diff --git a/submodules/TooltipUI/Sources/TooltipScreen.swift b/submodules/TooltipUI/Sources/TooltipScreen.swift index bd4824836f..456e98ab58 100644 --- a/submodules/TooltipUI/Sources/TooltipScreen.swift +++ b/submodules/TooltipUI/Sources/TooltipScreen.swift @@ -8,6 +8,7 @@ import AppBundle private final class TooltipScreenNode: ViewControllerTracingNode { private let location: CGPoint + private let shouldDismissOnTouch: (CGPoint) -> Bool private let requestDismiss: () -> Void private let containerNode: ASDisplayNode @@ -16,8 +17,9 @@ private final class TooltipScreenNode: ViewControllerTracingNode { private let animatedStickerNode: AnimatedStickerNode private let textNode: ImmediateTextNode - init(text: String, location: CGPoint, requestDismiss: @escaping () -> Void) { + init(text: String, location: CGPoint, shouldDismissOnTouch: @escaping (CGPoint) -> Bool, requestDismiss: @escaping () -> Void) { self.location = location + self.shouldDismissOnTouch = shouldDismissOnTouch self.requestDismiss = requestDismiss self.containerNode = ASDisplayNode() @@ -90,7 +92,9 @@ private final class TooltipScreenNode: ViewControllerTracingNode { eventIsPresses = event.type == .presses } if event.type == .touches || eventIsPresses { - //self.requestDismiss() + if self.shouldDismissOnTouch(point) { + self.requestDismiss() + } return nil } } @@ -119,6 +123,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode { public final class TooltipScreen: ViewController { private let text: String private let location: CGPoint + private let shouldDismissOnTouch: (CGPoint) -> Bool private var controllerNode: TooltipScreenNode { return self.displayNode as! TooltipScreenNode @@ -127,9 +132,10 @@ public final class TooltipScreen: ViewController { private var validLayout: ContainerViewLayout? private var isDismissed: Bool = false - public init(text: String, location: CGPoint) { + public init(text: String, location: CGPoint, shouldDismissOnTouch: @escaping (CGPoint) -> Bool) { self.text = text self.location = location + self.shouldDismissOnTouch = shouldDismissOnTouch super.init(navigationBarPresentationData: nil) @@ -151,7 +157,7 @@ public final class TooltipScreen: ViewController { } override public func loadDisplayNode() { - self.displayNode = TooltipScreenNode(text: self.text, location: self.location, requestDismiss: { [weak self] in + self.displayNode = TooltipScreenNode(text: self.text, location: self.location, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in guard let strongSelf = self else { return }