From 3910ecdca2c956b8f720d07837bb6e88b5287e05 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 23 May 2025 23:03:52 +0800 Subject: [PATCH] Monoforums --- .../Sources/ChatListController.swift | 2 + .../Sources/DebugController.swift | 14 ++--- .../Postbox/Sources/ChatListViewState.swift | 52 +++++++++++++--- ...yncCore_StandaloneAccountTransaction.swift | 6 +- .../ApplyMaxReadIndexInteractively.swift | 4 +- .../ChatEmptyNode/Sources/ChatEmptyNode.swift | 26 ++++---- .../Sources/ChatLoadingNode.swift | 6 +- .../Sources/ChatSideTopicsPanel.swift | 50 +++++++++------ .../Sources/ChatIntroItemComponent.swift | 2 + .../Sources/ChatControllerNode.swift | 61 +++++++++++-------- .../ChatInterfaceTitlePanelNodes.swift | 2 +- ...ChatTopicListTitleAccessoryPanelNode.swift | 50 ++++++++------- .../Sources/NavigateToChatController.swift | 24 +++++--- .../Sources/TelegramRootController.swift | 2 +- .../Sources/ExperimentalUISettings.swift | 10 ++- 15 files changed, 196 insertions(+), 115 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 69a8689ebf..269bc6efcb 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1067,6 +1067,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController if case let .channel(channel) = peer, channel.flags.contains(.isMonoforum) { openAsInlineForum = false + } else if case let .channel(channel) = peer, channel.flags.contains(.displayForumAsTabs) { + openAsInlineForum = false } else { if let cachedData = cachedDataView.cachedPeerData as? CachedChannelData, case let .known(viewForumAsMessages) = cachedData.viewForumAsMessages, viewForumAsMessages { openAsInlineForum = false diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index 143f6d3439..66d1765b66 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -96,7 +96,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { case enableDebugDataDisplay(Bool) case rippleEffect(Bool) case browserExperiment(Bool) - case localTranscription(Bool) + case allForumsHaveTabs(Bool) case enableReactionOverrides(Bool) case compressedEmojiCache(Bool) case storiesJpegExperiment(Bool) @@ -133,7 +133,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.web.rawValue case .keepChatNavigationStack, .skipReadHistory, .dustEffect, .crashOnSlowQueries, .crashOnMemoryPressure: return DebugControllerSection.experiments.rawValue - case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .compressedEmojiCache, .storiesJpegExperiment, .checkSerializedData, .enableQuickReactionSwitch, .experimentalCompatibility, .enableDebugDataDisplay, .rippleEffect, .browserExperiment, .localTranscription, .enableReactionOverrides, .restorePurchases, .disableReloginTokens, .liveStreamV2, .experimentalCallMute, .playerV2, .devRequests, .fakeAds, .enableLocalTranslation: + case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .compressedEmojiCache, .storiesJpegExperiment, .checkSerializedData, .enableQuickReactionSwitch, .experimentalCompatibility, .enableDebugDataDisplay, .rippleEffect, .browserExperiment, .allForumsHaveTabs, .enableReactionOverrides, .restorePurchases, .disableReloginTokens, .liveStreamV2, .experimentalCallMute, .playerV2, .devRequests, .fakeAds, .enableLocalTranslation: return DebugControllerSection.experiments.rawValue case .logTranslationRecognition, .resetTranslationStates: return DebugControllerSection.translation.rawValue @@ -226,7 +226,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 39 case .browserExperiment: return 40 - case .localTranscription: + case .allForumsHaveTabs: return 41 case .enableReactionOverrides: return 42 @@ -1264,12 +1264,12 @@ private enum DebugControllerEntry: ItemListNodeEntry { }) }).start() }) - case let .localTranscription(value): - return ItemListSwitchItem(presentationData: presentationData, title: "Local Transcription", value: value, sectionId: self.section, style: .blocks, updated: { value in + case let .allForumsHaveTabs(value): + return ItemListSwitchItem(presentationData: presentationData, title: "Forum Tabs Debug", value: value, sectionId: self.section, style: .blocks, updated: { value in let _ = arguments.sharedContext.accountManager.transaction ({ transaction in transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings - settings.localTranscription = value + settings.allForumsHaveTabs = value return PreferencesEntry(settings) }) }).start() @@ -1526,7 +1526,7 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present entries.append(.browserExperiment(experimentalSettings.browserExperiment)) } #endif - entries.append(.localTranscription(experimentalSettings.localTranscription)) + entries.append(.allForumsHaveTabs(experimentalSettings.allForumsHaveTabs)) if case .internal = sharedContext.applicationBindings.appBuildType { entries.append(.enableReactionOverrides(experimentalSettings.enableReactionOverrides)) } diff --git a/submodules/Postbox/Sources/ChatListViewState.swift b/submodules/Postbox/Sources/ChatListViewState.swift index 4743642867..29dc942b51 100644 --- a/submodules/Postbox/Sources/ChatListViewState.swift +++ b/submodules/Postbox/Sources/ChatListViewState.swift @@ -65,7 +65,11 @@ private func mappedChatListFilterPredicate(postbox: PostboxImpl, currentTransact if let cachedPeerData = postbox.cachedPeerDataTable.get(peer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } - if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value && !displayAsRegularChat { + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value + if !isThreadBased { + displayAsRegularChat = true + } + if isThreadBased && !displayAsRegularChat { isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.effectiveUnreadCount ?? 0) > 0 } else { isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false @@ -435,13 +439,17 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(peer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value + if !isThreadBased { + displayAsRegularChat = true + } let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId)) let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peer.id, threadId: nil, calculation: filterPredicate.messageTagSummary) var isUnread: Bool - if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value && !displayAsRegularChat { + if isThreadBased && !displayAsRegularChat { isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.effectiveUnreadCount ?? 0) > 0 } else { isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false @@ -569,9 +577,13 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(entryPeer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer).value + if !isThreadBased { + displayAsRegularChat = true + } var isUnread: Bool - if postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer).value && !displayAsRegularChat { + if isThreadBased && !displayAsRegularChat { isUnread = (postbox.peerThreadsSummaryTable.get(peerId: entryPeer.id)?.effectiveUnreadCount ?? 0) > 0 } else { isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false @@ -618,9 +630,13 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(mainPeer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer).value + if !isThreadBased { + displayAsRegularChat = true + } var isUnread: Bool - if postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer).value && !displayAsRegularChat { + if isThreadBased && !displayAsRegularChat { isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0) > 0 } else { isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false @@ -800,9 +816,13 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(entryPeer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer).value + if !isThreadBased { + displayAsRegularChat = true + } var isUnread: Bool - if postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer).value && !displayAsRegularChat { + if isThreadBased && !displayAsRegularChat { isUnread = (postbox.peerThreadsSummaryTable.get(peerId: entryPeer.id)?.effectiveUnreadCount ?? 0) > 0 } else { isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false @@ -858,9 +878,13 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(mainPeer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer).value + if !isThreadBased { + displayAsRegularChat = true + } var isUnread: Bool - if postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer).value && !displayAsRegularChat { + if isThreadBased && !displayAsRegularChat { isUnread = (postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0) > 0 } else { isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false @@ -952,10 +976,19 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(entryData.index.messageIndex.id.peerId), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } + let isThreadBased: Bool + if let peer = postbox.peerTable.get(entryData.index.messageIndex.id.peerId) { + isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value + } else { + isThreadBased = false + } + if !isThreadBased { + displayAsRegularChat = true + } var updatedReadState = entryData.readState - if let peer = postbox.peerTable.get(entryData.index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value, !displayAsRegularChat { - let summary = postbox.peerThreadsSummaryTable.get(peerId: peer.id) + if isThreadBased, !displayAsRegularChat { + let summary = postbox.peerThreadsSummaryTable.get(peerId: entryData.index.messageIndex.id.peerId) var count: Int32 = 0 var isMuted: Bool = false @@ -1605,6 +1638,9 @@ struct ChatListViewState { autoremoveTimeout = postbox.seedConfiguration.decodeAutoremoveTimeout(cachedData) displayAsRegularChat = postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedData) } + if !isThreadBased { + displayAsRegularChat = true + } var topForumTopics: [ChatListForumTopicData] = [] let readState: ChatListViewReadState? diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift index e9bd0743d6..5bc38f77ae 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift @@ -76,7 +76,11 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = { peerSummaryIsThreadBased: { peer in if let channel = peer as? TelegramChannel { if channel.flags.contains(.isForum) { - return (true, false) + if channel.flags.contains(.displayForumAsTabs) { + return (false, false) + } else { + return (true, false) + } } else if channel.flags.contains(.isMonoforum) { return (true, true) } else { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift index 596614cfe2..0610057116 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift @@ -208,7 +208,9 @@ func _internal_togglePeerUnreadMarkInteractively(transaction: Transaction, netwo } var displayAsRegularChat: Bool = false - if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData { + if let channel = peer as? TelegramChannel, channel.flags.contains(.displayForumAsTabs) { + displayAsRegularChat = true + } else if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData { displayAsRegularChat = cachedData.viewForumAsMessages.knownValue ?? false } diff --git a/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift index 55a2210293..535c0b7a65 100644 --- a/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift @@ -26,7 +26,7 @@ import LottieComponent import BundleIconComponent private protocol ChatEmptyNodeContent { - func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize + func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize } private let titleFont = Font.semibold(15.0) @@ -46,7 +46,7 @@ private final class ChatEmptyNodeRegularChatContent: ASDisplayNode, ChatEmptyNod self.addSubnode(self.textNode) } - func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { self.currentTheme = interfaceState.theme self.currentStrings = interfaceState.strings @@ -155,7 +155,7 @@ public final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNod let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file._parse()), false, self.view, self.stickerNode.bounds, nil, []) } - public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { let isFirstTime = self.currentTheme == nil if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { @@ -363,7 +363,7 @@ public final class ChatEmptyNodeNearbyChatContent: ASDisplayNode, ChatEmptyNodeS let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file._parse()), false, self.view, self.stickerNode.bounds, nil, []) } - public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { self.currentTheme = interfaceState.theme self.currentStrings = interfaceState.strings @@ -496,7 +496,7 @@ private final class ChatEmptyNodeSecretChatContent: ASDisplayNode, ChatEmptyNode self.addSubnode(self.subtitleNode) } - func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { self.currentTheme = interfaceState.theme self.currentStrings = interfaceState.strings @@ -630,7 +630,7 @@ private final class ChatEmptyNodeGroupChatContent: ASDisplayNode, ChatEmptyNodeC self.addSubnode(self.subtitleNode) } - func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { self.currentTheme = interfaceState.theme self.currentStrings = interfaceState.strings @@ -759,7 +759,7 @@ private final class ChatEmptyNodeCloudChatContent: ASDisplayNode, ChatEmptyNodeC self.shareBusinessLink?(businessLink.url) } - func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { var maxWidth: CGFloat = size.width var centerText = false @@ -1125,7 +1125,7 @@ public final class ChatEmptyNodeTopicChatContent: ASDisplayNode, ChatEmptyNodeCo self.addSubnode(self.textNode) } - public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { let serviceColor = serviceMessageColorComponents(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper) if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { self.currentTheme = interfaceState.theme @@ -1266,7 +1266,7 @@ public final class ChatEmptyNodePremiumRequiredChatContent: ASDisplayNode, ChatE } } - public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { let serviceColor = serviceMessageColorComponents(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper) let maxWidth = min(270.0, size.width) @@ -1778,7 +1778,7 @@ public final class ChatEmptyNode: ASDisplayNode { } } - public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: Subject, loadingNode: ChatLoadingNode?, backgroundNode: WallpaperBackgroundNode?, size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) { + public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: Subject, loadingNode: ChatLoadingNode?, backgroundNode: WallpaperBackgroundNode?, size: CGSize, insets: UIEdgeInsets, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) { self.wallpaperBackgroundNode = backgroundNode if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { @@ -1912,14 +1912,14 @@ public final class ChatEmptyNode: ASDisplayNode { var contentSize = CGSize() if let contentNode = self.content?.1 { - contentSize = contentNode.updateLayout(interfaceState: interfaceState, subject: subject, size: displayRect.size, transition: contentTransition) + contentSize = contentNode.updateLayout(interfaceState: interfaceState, subject: subject, size: displayRect.size, leftInset: leftInset, rightInset: rightInset, transition: contentTransition) if updateGreetingSticker { self.context.prefetchManager?.prepareNextGreetingSticker() } } - let contentFrame = CGRect(origin: CGPoint(x: displayRect.minX + floor((displayRect.width - contentSize.width) / 2.0), y: displayRect.minY + floor((displayRect.height - contentSize.height) / 2.0)), size: contentSize) + let contentFrame = CGRect(origin: CGPoint(x: displayRect.minX + leftInset + floor((displayRect.width - leftInset - rightInset - contentSize.width) / 2.0), y: displayRect.minY + floor((displayRect.height - contentSize.height) / 2.0)), size: contentSize) if let contentNode = self.content?.1 { contentTransition.updateFrame(node: contentNode, frame: contentFrame) } @@ -1980,7 +1980,7 @@ public final class ChatEmptyNode: ASDisplayNode { wallpaperBackgroundNode: backgroundNode, constrainedSize: CGSize(width: size.width - insets.left - insets.right, height: 200.0) ) - let attachedDescriptionFrame = CGRect(origin: CGPoint(x: floor((size.width - attachedDescriptionSize.width) * 0.5), y: contentFrame.maxY + 4.0), size: attachedDescriptionSize) + let attachedDescriptionFrame = CGRect(origin: CGPoint(x: leftInset + floor((size.width - leftInset - rightInset - attachedDescriptionSize.width) * 0.5), y: contentFrame.maxY + 4.0), size: attachedDescriptionSize) transition.updateFrame(node: attachedDescriptionNode, frame: attachedDescriptionFrame) if let (rect, containerSize) = self.absolutePosition { diff --git a/submodules/TelegramUI/Components/Chat/ChatLoadingNode/Sources/ChatLoadingNode.swift b/submodules/TelegramUI/Components/Chat/ChatLoadingNode/Sources/ChatLoadingNode.swift index 760609e3c5..79537cbef6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatLoadingNode/Sources/ChatLoadingNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatLoadingNode/Sources/ChatLoadingNode.swift @@ -126,7 +126,7 @@ public final class ChatLoadingPlaceholderMessageContainer { } if let avatarNode = self.avatarNode, let avatarBorderNode = self.avatarBorderNode { - let avatarFrame = CGRect(origin: CGPoint(x: 3.0, y: rect.maxY + 1.0 - avatarSize.height), size: avatarSize) + let avatarFrame = CGRect(origin: CGPoint(x: rect.minX + 3.0, y: rect.maxY + 1.0 - avatarSize.height), size: avatarSize) transition.updateFrame(node: avatarNode, frame: avatarFrame) transition.updateFrame(node: avatarBorderNode, frame: avatarFrame) @@ -134,7 +134,7 @@ public final class ChatLoadingPlaceholderMessageContainer { avatarOffset += avatarSize.width - 1.0 } - let bubbleFrame = CGRect(origin: CGPoint(x: 3.0 + avatarOffset, y: rect.origin.y), size: CGSize(width: rect.width, height: rect.height)) + let bubbleFrame = CGRect(origin: CGPoint(x: rect.minX + 3.0 + avatarOffset, y: rect.origin.y), size: CGSize(width: rect.width, height: rect.height)) transition.updateFrame(node: self.bubbleNode, frame: bubbleFrame) transition.updateFrame(node: self.bubbleBorderNode, frame: bubbleFrame) } @@ -484,7 +484,7 @@ public final class ChatLoadingPlaceholderNode: ASDisplayNode { for messageContainer in self.messageContainers { let messageSize = dimensions[index % 14] - messageContainer.update(size: bounds.size, hasAvatar: self.chatType != .channel && self.chatType != .user, rect: CGRect(origin: CGPoint(x: 0.0, y: bounds.size.height - insets.bottom - offset - messageSize.height), size: messageSize), transition: transition) + messageContainer.update(size: bounds.size, hasAvatar: self.chatType != .channel && self.chatType != .user, rect: CGRect(origin: CGPoint(x: insets.left, y: bounds.size.height - insets.bottom - offset - messageSize.height), size: messageSize), transition: transition) offset += messageSize.height index += 1 } diff --git a/submodules/TelegramUI/Components/Chat/ChatSideTopicsPanel/Sources/ChatSideTopicsPanel.swift b/submodules/TelegramUI/Components/Chat/ChatSideTopicsPanel/Sources/ChatSideTopicsPanel.swift index 06dcda5e87..b5b43da910 100644 --- a/submodules/TelegramUI/Components/Chat/ChatSideTopicsPanel/Sources/ChatSideTopicsPanel.swift +++ b/submodules/TelegramUI/Components/Chat/ChatSideTopicsPanel/Sources/ChatSideTopicsPanel.swift @@ -590,6 +590,8 @@ public final class ChatSideTopicsPanel: Component { public final class View: UIView { private let scrollView: ScrollView + private let scrollContainerView: UIView + private let scrollViewMask: UIImageView private let background = ComponentView() private let separatorLayer: SimpleLayer @@ -612,13 +614,20 @@ public final class ChatSideTopicsPanel: Component { self.selectedLineView = UIImageView() self.scrollView = ScrollView(frame: CGRect()) + self.scrollContainerView = UIView() + self.scrollViewMask = UIImageView(image: generateGradientImage(size: CGSize(width: 8.0, height: 8.0), colors: [ + UIColor(white: 1.0, alpha: 0.0), + UIColor(white: 1.0, alpha: 1.0) + ], locations: [0.0, 1.0], direction: .vertical)?.stretchableImage(withLeftCapWidth: 0, topCapHeight: 8)) + self.scrollContainerView.mask = self.scrollViewMask + self.separatorLayer = SimpleLayer() super.init(frame: frame) self.scrollView.delaysContentTouches = false self.scrollView.canCancelContentTouches = true - self.scrollView.clipsToBounds = false + self.scrollView.clipsToBounds = true self.scrollView.contentInsetAdjustmentBehavior = .never if #available(iOS 13.0, *) { self.scrollView.automaticallyAdjustsScrollIndicatorInsets = false @@ -629,7 +638,8 @@ public final class ChatSideTopicsPanel: Component { self.scrollView.alwaysBounceVertical = false self.scrollView.scrollsToTop = false - self.addSubview(self.scrollView) + self.addSubview(self.scrollContainerView) + self.scrollContainerView.addSubview(self.scrollView) self.scrollView.addSubview(self.selectedLineView) } @@ -709,7 +719,7 @@ public final class ChatSideTopicsPanel: Component { if let backgroundView = self.background.view { if backgroundView.superview == nil { - self.insertSubview(backgroundView, belowSubview: self.scrollView) + self.insertSubview(backgroundView, at: 0) } transition.setFrame(view: backgroundView, frame: CGRect(origin: CGPoint(), size: availableSize)) } @@ -735,20 +745,9 @@ public final class ChatSideTopicsPanel: Component { let itemSpacing: CGFloat = 24.0 - var contentSize = CGSize(width: panelWidth, height: 0.0) - contentSize.height += containerInsets.top - - var validIds: [Item.Id] = [] - var isFirst = true - var selectedItemFrame: CGRect? + var topContainerInset: CGFloat = containerInsets.top do { - if isFirst { - isFirst = false - } else { - contentSize.height += itemSpacing - } - var itemTransition = transition var animateIn = false let itemView: TabItemView @@ -764,11 +763,11 @@ public final class ChatSideTopicsPanel: Component { component.togglePanel() }) self.tabItemView = itemView - self.scrollView.addSubview(itemView) + self.addSubview(itemView) } let itemSize = itemView.update(context: component.context, theme: component.theme, width: panelWidth, transition: .immediate) - let itemFrame = CGRect(origin: CGPoint(x: containerInsets.left, y: contentSize.height), size: itemSize) + let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: topContainerInset), size: itemSize) itemTransition.setPosition(layer: itemView.layer, position: itemFrame.center) itemTransition.setBounds(layer: itemView.layer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) @@ -778,10 +777,17 @@ public final class ChatSideTopicsPanel: Component { transition.containedViewLayoutTransition.animateTransformScale(view: itemView, from: 0.001) } - contentSize.height += itemSize.height - contentSize.height -= 20.0 + topContainerInset += itemSize.height + topContainerInset -= 24.0 } + var contentSize = CGSize(width: panelWidth, height: 0.0) + contentSize.height += 36.0 + + var validIds: [Item.Id] = [] + var isFirst = true + var selectedItemFrame: CGRect? + do { if isFirst { isFirst = false @@ -931,7 +937,11 @@ public final class ChatSideTopicsPanel: Component { contentSize.height += containerInsets.bottom - let scrollSize = CGSize(width: availableSize.width, height: availableSize.height) + let scrollSize = CGSize(width: availableSize.width, height: availableSize.height - topContainerInset) + + self.scrollContainerView.frame = CGRect(origin: CGPoint(x: 0.0, y: topContainerInset), size: scrollSize) + self.scrollViewMask.frame = CGRect(origin: CGPoint(x: 0.0, y: topContainerInset), size: scrollSize) + if self.scrollView.bounds.size != scrollSize { self.scrollView.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: scrollSize) } diff --git a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/ChatIntroItemComponent.swift b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/ChatIntroItemComponent.swift index f84b0ddd68..a6811b04db 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/ChatIntroItemComponent.swift +++ b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/ChatIntroItemComponent.swift @@ -145,6 +145,8 @@ final class ChatIntroItemComponent: Component { backgroundNode: backgroundNode, size: size, insets: UIEdgeInsets(), + leftInset: 0.0, + rightInset: 0.0, transition: .immediate ) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index a4fb3b63b4..78d67d979b 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -195,7 +195,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { private var emptyNode: ChatEmptyNode? private(set) var emptyType: ChatHistoryNodeLoadState.EmptyType? private var didDisplayEmptyGreeting = false - private var validEmptyNodeLayout: (CGSize, UIEdgeInsets)? + private var validEmptyNodeLayout: (CGSize, UIEdgeInsets, CGFloat, CGFloat)? var restrictedNode: ChatRecentActionsEmptyNode? private(set) var validLayout: (ContainerViewLayout, CGFloat)? @@ -1019,7 +1019,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { self.contentContainerNode.contentNode.insertSubnode(emptyNode, aboveSubnode: self.historyNodeContainer) } - if let (size, insets) = self.validEmptyNodeLayout { + if let (size, insets, leftInset, rightInset) = self.validEmptyNodeLayout { let mappedType: ChatEmptyNode.Subject.EmptyType switch emptyType { case .generic: @@ -1033,7 +1033,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { case .botInfo: mappedType = .botInfo } - emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, subject: .emptyChat(mappedType), loadingNode: wasLoading && self.loadingNode.supernode != nil ? self.loadingNode : nil, backgroundNode: self.backgroundNode, size: size, insets: insets, transition: .immediate) + emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, subject: .emptyChat(mappedType), loadingNode: wasLoading && self.loadingNode.supernode != nil ? self.loadingNode : nil, backgroundNode: self.backgroundNode, size: size, insets: insets, leftInset: leftInset, rightInset: rightInset, transition: .immediate) emptyNode.frame = CGRect(origin: CGPoint(), size: size) } if animated { @@ -2199,28 +2199,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { } } - var emptyNodeInsets = insets - emptyNodeInsets.bottom += inputPanelsHeight - self.validEmptyNodeLayout = (contentBounds.size, emptyNodeInsets) - if let emptyNode = self.emptyNode, let emptyType = self.emptyType { - let mappedType: ChatEmptyNode.Subject.EmptyType - switch emptyType { - case .generic: - mappedType = .generic - case .joined: - mappedType = .joined - case .clearedHistory: - mappedType = .clearedHistory - case .topic: - mappedType = .topic - case .botInfo: - mappedType = .botInfo - } - emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, subject: .emptyChat(mappedType), loadingNode: nil, backgroundNode: self.backgroundNode, size: contentBounds.size, insets: emptyNodeInsets, transition: transition) - transition.updateFrame(node: emptyNode, frame: contentBounds) - emptyNode.update(rect: contentBounds, within: contentBounds.size, transition: transition) - } - var contentBottomInset: CGFloat = inputPanelsHeight + 4.0 if let scrollContainerNode = self.scrollContainerNode { @@ -2239,10 +2217,17 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { let visibleAreaInset = UIEdgeInsets(top: containerInsets.top, left: 0.0, bottom: containerInsets.bottom + inputPanelsHeight, right: 0.0) self.visibleAreaInset = visibleAreaInset - self.loadingNode.updateLayout(size: contentBounds.size, insets: visibleAreaInset, transition: transition) + + var loadingNodeInsets = visibleAreaInset + loadingNodeInsets.left = layout.safeInsets.left + loadingNodeInsets.right = layout.safeInsets.right + if let leftPanelSize { + loadingNodeInsets.left += leftPanelSize.width + } + self.loadingNode.updateLayout(size: contentBounds.size, insets: loadingNodeInsets, transition: transition) if let loadingPlaceholderNode = self.loadingPlaceholderNode { - loadingPlaceholderNode.updateLayout(size: contentBounds.size, insets: visibleAreaInset, metrics: layout.metrics, transition: transition) + loadingPlaceholderNode.updateLayout(size: contentBounds.size, insets: loadingNodeInsets, metrics: layout.metrics, transition: transition) loadingPlaceholderNode.update(rect: contentBounds, within: contentBounds.size, transition: transition) } @@ -2293,6 +2278,28 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { listInsets.left += leftPanelSize.width } + var emptyNodeInsets = insets + emptyNodeInsets.bottom += inputPanelsHeight + self.validEmptyNodeLayout = (contentBounds.size, emptyNodeInsets, listInsets.left, listInsets.right) + if let emptyNode = self.emptyNode, let emptyType = self.emptyType { + let mappedType: ChatEmptyNode.Subject.EmptyType + switch emptyType { + case .generic: + mappedType = .generic + case .joined: + mappedType = .joined + case .clearedHistory: + mappedType = .clearedHistory + case .topic: + mappedType = .topic + case .botInfo: + mappedType = .botInfo + } + emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, subject: .emptyChat(mappedType), loadingNode: nil, backgroundNode: self.backgroundNode, size: contentBounds.size, insets: emptyNodeInsets, leftInset: listInsets.left, rightInset: listInsets.right, transition: transition) + transition.updateFrame(node: emptyNode, frame: contentBounds) + emptyNode.update(rect: contentBounds, within: contentBounds.size, transition: transition) + } + var displayTopDimNode = false let ensureTopInsetForOverlayHighlightedItems: CGFloat? = nil var expandTopDimNode = false diff --git a/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift index a6c73537f1..1513f1b4fd 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift @@ -241,7 +241,7 @@ func titleTopicsPanelForChatPresentationInterfaceState(_ chatPresentationInterfa return panel } } - } else if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForum, chatPresentationInterfaceState.search == nil { + } else if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForum, (channel.flags.contains(.displayForumAsTabs) || context.sharedContext.immediateExperimentalUISettings.allForumsHaveTabs), chatPresentationInterfaceState.search == nil { let topicListDisplayMode = chatPresentationInterfaceState.topicListDisplayMode ?? .top if case .top = topicListDisplayMode, let peerId = chatPresentationInterfaceState.chatLocation.peerId { if let currentPanel = currentPanel as? ChatTopicListTitleAccessoryPanelNode { diff --git a/submodules/TelegramUI/Sources/ChatTopicListTitleAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ChatTopicListTitleAccessoryPanelNode.swift index a5fb16ae2d..ed821174ce 100644 --- a/submodules/TelegramUI/Sources/ChatTopicListTitleAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTopicListTitleAccessoryPanelNode.swift @@ -182,7 +182,7 @@ private final class CustomBadgeComponent: Component { } } -final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, ChatControllerCustomNavigationPanelNode, ASScrollViewDelegate { +final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, ChatControllerCustomNavigationPanelNode { private struct Params: Equatable { var width: CGFloat var leftInset: CGFloat @@ -736,6 +736,8 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C private let isMonoforum: Bool private let scrollView: ScrollView + private let scrollViewContainer: UIView + private let scrollViewMask: UIImageView private var params: Params? @@ -756,12 +758,18 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C self.selectedLineView = UIImageView() self.scrollView = ScrollView(frame: CGRect()) + self.scrollViewMask = UIImageView(image: generateGradientImage(size: CGSize(width: 8.0, height: 8.0), colors: [ + UIColor(white: 1.0, alpha: 0.0), + UIColor(white: 1.0, alpha: 1.0) + ], locations: [0.0, 1.0], direction: .horizontal)?.stretchableImage(withLeftCapWidth: 8, topCapHeight: 0)) + + self.scrollViewContainer = UIView() super.init() self.scrollView.delaysContentTouches = false self.scrollView.canCancelContentTouches = true - self.scrollView.clipsToBounds = false + self.scrollView.clipsToBounds = true self.scrollView.contentInsetAdjustmentBehavior = .never if #available(iOS 13.0, *) { self.scrollView.automaticallyAdjustsScrollIndicatorInsets = false @@ -771,9 +779,11 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C self.scrollView.alwaysBounceHorizontal = false self.scrollView.alwaysBounceVertical = false self.scrollView.scrollsToTop = false - self.scrollView.delegate = self.wrappedScrollViewDelegate - self.view.addSubview(self.scrollView) + self.scrollViewContainer.addSubview(self.scrollView) + self.scrollViewContainer.mask = self.scrollViewMask + + self.view.addSubview(self.scrollViewContainer) self.scrollView.addSubview(self.selectedLineView) @@ -843,20 +853,9 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C let containerInsets = UIEdgeInsets(top: 0.0, left: params.leftInset + 16.0, bottom: 0.0, right: params.rightInset + 16.0) let itemSpacing: CGFloat = 24.0 - var contentSize = CGSize(width: 0.0, height: panelHeight) - contentSize.width += containerInsets.left + 8.0 - - var validIds: [Item.Id] = [] - var isFirst = true - var selectedItemFrame: CGRect? + var leftContentInset: CGFloat = containerInsets.left + 8.0 do { - if isFirst { - isFirst = false - } else { - contentSize.width += itemSpacing - } - var itemTransition = transition var animateIn = false let itemView: TabItemView @@ -872,11 +871,11 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C self.interfaceInteraction?.toggleChatSidebarMode() }) self.tabItemView = itemView - self.scrollView.addSubview(itemView) + self.view.addSubview(itemView) } let itemSize = itemView.update(context: self.context, theme: params.interfaceState.theme, height: panelHeight, transition: .immediate) - let itemFrame = CGRect(origin: CGPoint(x: contentSize.width, y: -5.0), size: itemSize) + let itemFrame = CGRect(origin: CGPoint(x: leftContentInset, y: -5.0), size: itemSize) itemTransition.updatePosition(layer: itemView.layer, position: itemFrame.center) itemTransition.updateBounds(layer: itemView.layer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) @@ -886,9 +885,15 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C transition.animateTransformScale(view: itemView, from: 0.001) } - contentSize.width += itemSize.width + leftContentInset += itemSize.width + 8.0 } + var contentSize = CGSize(width: itemSpacing - 8.0, height: panelHeight) + + var validIds: [Item.Id] = [] + var isFirst = true + var selectedItemFrame: CGRect? + do { if isFirst { isFirst = false @@ -1034,9 +1039,12 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C contentSize.width += containerInsets.right - let scrollSize = CGSize(width: params.width, height: contentSize.height) + let scrollSize = CGSize(width: params.width - leftContentInset, height: contentSize.height) + self.scrollViewContainer.frame = CGRect(origin: CGPoint(x: leftContentInset, y: 0.0), size: scrollSize) + self.scrollViewMask.frame = CGRect(origin: CGPoint(), size: scrollSize) + if self.scrollView.bounds.size != scrollSize { - self.scrollView.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: scrollSize) + self.scrollView.frame = CGRect(origin: CGPoint(), size: scrollSize) } if self.scrollView.contentSize != contentSize { self.scrollView.contentSize = contentSize diff --git a/submodules/TelegramUI/Sources/NavigateToChatController.swift b/submodules/TelegramUI/Sources/NavigateToChatController.swift index 23a121900f..478a10afa0 100644 --- a/submodules/TelegramUI/Sources/NavigateToChatController.swift +++ b/submodules/TelegramUI/Sources/NavigateToChatController.swift @@ -42,16 +42,20 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam viewForumAsMessages = .single(false) } } else if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum) { - viewForumAsMessages = params.context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peer.id)]) - |> take(1) - |> map { combinedView in - guard let cachedDataView = combinedView.views[.cachedPeerData(peerId: peer.id)] as? CachedPeerDataView else { - return false - } - if let cachedData = cachedDataView.cachedPeerData as? CachedChannelData, case let .known(viewForumAsMessages) = cachedData.viewForumAsMessages, viewForumAsMessages { - return true - } else { - return false + if channel.flags.contains(.displayForumAsTabs) { + viewForumAsMessages = .single(true) + } else { + viewForumAsMessages = params.context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peer.id)]) + |> take(1) + |> map { combinedView in + guard let cachedDataView = combinedView.views[.cachedPeerData(peerId: peer.id)] as? CachedPeerDataView else { + return false + } + if let cachedData = cachedDataView.cachedPeerData as? CachedChannelData, case let .known(viewForumAsMessages) = cachedData.viewForumAsMessages, viewForumAsMessages { + return true + } else { + return false + } } } } else if case let .peer(peer) = params.chatLocation, peer.id == params.context.account.peerId { diff --git a/submodules/TelegramUI/Sources/TelegramRootController.swift b/submodules/TelegramUI/Sources/TelegramRootController.swift index 40951c029f..a887ae8853 100644 --- a/submodules/TelegramUI/Sources/TelegramRootController.swift +++ b/submodules/TelegramUI/Sources/TelegramRootController.swift @@ -64,7 +64,7 @@ private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceh self.wallpaperBackgroundNode.updateLayout(size: size, displayMode: needsTiling ? .aspectFit : .aspectFill, transition: transition) transition.updateFrame(node: self.wallpaperBackgroundNode, frame: contentBounds) - self.emptyNode.updateLayout(interfaceState: self.presentationInterfaceState, subject: .detailsPlaceholder, loadingNode: nil, backgroundNode: self.wallpaperBackgroundNode, size: contentBounds.size, insets: .zero, transition: transition) + self.emptyNode.updateLayout(interfaceState: self.presentationInterfaceState, subject: .detailsPlaceholder, loadingNode: nil, backgroundNode: self.wallpaperBackgroundNode, size: contentBounds.size, insets: .zero, leftInset: 0.0, rightInset: 0.0, transition: transition) transition.updateFrame(node: self.emptyNode, frame: CGRect(origin: .zero, size: size)) self.emptyNode.update(rect: contentBounds, within: contentBounds.size, transition: transition) } diff --git a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift index f98202cd0b..b453452d14 100644 --- a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift +++ b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift @@ -66,6 +66,7 @@ public struct ExperimentalUISettings: Codable, Equatable { public var fakeAds: Bool public var conferenceDebug: Bool public var checkSerializedData: Bool + public var allForumsHaveTabs: Bool public static var defaultSettings: ExperimentalUISettings { return ExperimentalUISettings( @@ -109,7 +110,8 @@ public struct ExperimentalUISettings: Codable, Equatable { devRequests: false, fakeAds: false, conferenceDebug: false, - checkSerializedData: false + checkSerializedData: false, + allForumsHaveTabs: false ) } @@ -154,7 +156,8 @@ public struct ExperimentalUISettings: Codable, Equatable { devRequests: Bool, fakeAds: Bool, conferenceDebug: Bool, - checkSerializedData: Bool + checkSerializedData: Bool, + allForumsHaveTabs: Bool ) { self.keepChatNavigationStack = keepChatNavigationStack self.skipReadHistory = skipReadHistory @@ -197,6 +200,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.fakeAds = fakeAds self.conferenceDebug = conferenceDebug self.checkSerializedData = checkSerializedData + self.allForumsHaveTabs = allForumsHaveTabs } public init(from decoder: Decoder) throws { @@ -243,6 +247,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.fakeAds = try container.decodeIfPresent(Bool.self, forKey: "fakeAds") ?? false self.conferenceDebug = try container.decodeIfPresent(Bool.self, forKey: "conferenceDebug") ?? false self.checkSerializedData = try container.decodeIfPresent(Bool.self, forKey: "checkSerializedData") ?? false + self.allForumsHaveTabs = try container.decodeIfPresent(Bool.self, forKey: "allForumsHaveTabs") ?? false } public func encode(to encoder: Encoder) throws { @@ -289,6 +294,7 @@ public struct ExperimentalUISettings: Codable, Equatable { try container.encodeIfPresent(self.fakeAds, forKey: "fakeAds") try container.encodeIfPresent(self.conferenceDebug, forKey: "conferenceDebug") try container.encodeIfPresent(self.checkSerializedData, forKey: "checkSerializedData") + try container.encodeIfPresent(self.allForumsHaveTabs, forKey: "allForumsHaveTabs") } }