From 44fab3078a107a425499b16e5ac501f0d83dfef9 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 6 Feb 2026 11:39:09 +0400 Subject: [PATCH 01/11] Temp --- .../Sources/ChatItemGalleryFooterContentNode.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 8054669644..187ef43d59 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -1340,13 +1340,14 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll isOpen: false ))), action: { [weak self] in - guard let self, let buttonPanelView = self.buttonPanel.view as? GlassControlPanelComponent.View, let centerItemView = buttonPanelView.centerItemView else { + guard let self, let buttonPanelView = self.buttonPanel.view as? GlassControlPanelComponent.View else { return } - guard let itemView = centerItemView.itemView(id: AnyHashable("settings")) else { - return + if let centerItemView = buttonPanelView.centerItemView, let itemView = centerItemView.itemView(id: AnyHashable("settings")) { + self.settingsButtonPressed(sourceView: itemView) + } else if let rightItemView = buttonPanelView.rightItemView, let itemView = rightItemView.itemView(id: AnyHashable("settings")) { + self.settingsButtonPressed(sourceView: itemView) } - self.settingsButtonPressed(sourceView: itemView) } )) } From 45b1306274cc860221fffa02eaf63e481222d995 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 6 Feb 2026 15:18:17 +0400 Subject: [PATCH 02/11] Various improvements --- .../Source/_ASDisplayViewAccessiblity.mm | 125 +++++++++++------- ...uthorizationSequenceSignUpController.swift | 4 +- .../Sources/ChatListController.swift | 4 +- .../Sources/ChatListSearchListPaneNode.swift | 8 +- .../Sources/ReactionButtonListComponent.swift | 2 +- .../Items/UniversalVideoGalleryItem.swift | 6 +- .../StorageUsageExceptionsScreen.swift | 2 +- .../MediaNavigationAccessoryHeaderNode.swift | 2 +- .../Sources/VideoChatScreenMoreMenu.swift | 8 +- .../Sources/ChatTextInputPanelNode.swift | 3 - .../Sources/ContextActionsContainerNode.swift | 12 +- .../ContextControllerActionsStackNode.swift | 3 +- .../GiftAttributeListContextItem.swift | 4 +- .../Sources/GlassBackgroundComponent.swift | 8 +- .../Sources/LegacyMessageInputPanel.swift | 6 +- .../Sources/MediaEditorScreen.swift | 2 +- .../MediaNavigationAccessoryHeaderNode.swift | 2 +- .../Sources/AffiliateProgramSetupScreen.swift | 2 +- ...eerInfoScreenDisplayGiftsContextMenu.swift | 12 +- .../Sources/AddGiftsScreen.swift | 12 +- .../Sources/PeerInfoGiftsPaneNode.swift | 2 +- .../Sources/PeerSelectionController.swift | 2 +- .../Sources/PeerSelectionControllerNode.swift | 10 +- .../Sources/ShareWithPeersScreen.swift | 2 +- .../Sources/StorageUsageScreen.swift | 2 +- .../StoryItemSetContainerComponent.swift | 2 +- .../StoryItemSetViewListComponent.swift | 6 +- .../VideoPlaybackControlsComponent.swift | 2 + .../Sources/ChatHistoryListNode.swift | 4 +- .../Sources/CreateGroupController.swift | 4 +- .../NotificationItemContainerNode.swift | 4 +- .../Sources/OverlayPlayerControlsNode.swift | 2 +- .../UIViewController+Navigation.m | 6 +- 33 files changed, 158 insertions(+), 117 deletions(-) diff --git a/submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.mm b/submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.mm index 6e0b33541b..61b34afc75 100644 --- a/submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.mm +++ b/submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.mm @@ -203,56 +203,87 @@ static void CollectAccessibilityElementsForContainer(ASDisplayNode *container, U /// Collect all accessibliity elements for a given view and view node static void CollectAccessibilityElementsForView(UIView *view, NSMutableArray *elements) { - ASDisplayNodeCAssertNotNil(elements, @"Should pass in a NSMutableArray"); - - ASDisplayNode *node = view.asyncdisplaykit_node; - - static Class displayListViewClass = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - displayListViewClass = NSClassFromString(@"Display.ListView"); - }); - BOOL anySubNodeIsCollection = (nil != ASDisplayNodeFindFirstNode(node, - ^BOOL(ASDisplayNode *nodeToCheck) { + ASDisplayNodeCAssertNotNil(elements, @"Should pass in a NSMutableArray"); + + ASDisplayNode *node = view.asyncdisplaykit_node; + + static Class displayListViewClass = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + displayListViewClass = NSClassFromString(@"Display.ListView"); + }); + BOOL anySubNodeIsCollection = (nil != ASDisplayNodeFindFirstNode(node, + ^BOOL(ASDisplayNode *nodeToCheck) { if (displayListViewClass != nil && [nodeToCheck isKindOfClass:displayListViewClass]) { - return true; + return true; + } + return false; + /*return ASDynamicCast(nodeToCheck, ASCollectionNode) != nil || + ASDynamicCast(nodeToCheck, ASTableNode) != nil;*/ + })); + + if (node.isAccessibilityContainer && !anySubNodeIsCollection) { + CollectAccessibilityElementsForContainer(node, view, elements); + return; + } + + // Handle rasterize case + if (node.rasterizesSubtree) { + CollectUIAccessibilityElementsForNode(node, node, view, elements); + return; + } + + if (!node.isLayerBacked) { + for (UIView *subview in node.view.subviews) { + ASDisplayNode *subnode = subview.asyncdisplaykit_node; + if (subnode) { + if (subnode.isAccessibilityElement) { + // An accessiblityElement can either be a UIView or a UIAccessibilityElement + if (subnode.isLayerBacked) { + // No view for layer backed nodes exist. It's necessary to create a UIAccessibilityElement that represents this node + UIAccessibilityElement *accessiblityElement = [ASAccessibilityElement accessibilityElementWithContainer:view node:subnode containerNode:node]; + [elements addObject:accessiblityElement]; + } else { + // Accessiblity element is not layer backed just add the view as accessibility element + [elements addObject:subnode.view]; + } + } else if (subnode.isLayerBacked) { + // Go down the hierarchy of the layer backed subnode and collect all of the UIAccessibilityElement + CollectUIAccessibilityElementsForNode(subnode, node, view, elements); + } else if ([subnode accessibilityElementCount] > 0) { + // UIView is itself a UIAccessibilityContainer just add it + [elements addObject:subnode.view]; + } + } else { + // Plain UIView without an associated ASDisplayNode + if (subview.isAccessibilityElement) { + [elements addObject:subview]; + } else if ([subview accessibilityElementCount] > 0) { + [elements addObject:subview]; + } + } + } + } else { + for (ASDisplayNode *subnode in node.subnodes) { + if (subnode.isAccessibilityElement) { + // An accessiblityElement can either be a UIView or a UIAccessibilityElement + if (subnode.isLayerBacked) { + // No view for layer backed nodes exist. It's necessary to create a UIAccessibilityElement that represents this node + UIAccessibilityElement *accessiblityElement = [ASAccessibilityElement accessibilityElementWithContainer:view node:subnode containerNode:node]; + [elements addObject:accessiblityElement]; + } else { + // Accessiblity element is not layer backed just add the view as accessibility element + [elements addObject:subnode.view]; + } + } else if (subnode.isLayerBacked) { + // Go down the hierarchy of the layer backed subnode and collect all of the UIAccessibilityElement + CollectUIAccessibilityElementsForNode(subnode, node, view, elements); + } else if ([subnode accessibilityElementCount] > 0) { + // UIView is itself a UIAccessibilityContainer just add it + [elements addObject:subnode.view]; + } } - return false; - /*return ASDynamicCast(nodeToCheck, ASCollectionNode) != nil || - ASDynamicCast(nodeToCheck, ASTableNode) != nil;*/ - })); - - if (node.isAccessibilityContainer && !anySubNodeIsCollection) { - CollectAccessibilityElementsForContainer(node, view, elements); - return; - } - - // Handle rasterize case - if (node.rasterizesSubtree) { - CollectUIAccessibilityElementsForNode(node, node, view, elements); - return; - } - - for (ASDisplayNode *subnode in node.subnodes) { - if (subnode.isAccessibilityElement) { - - // An accessiblityElement can either be a UIView or a UIAccessibilityElement - if (subnode.isLayerBacked) { - // No view for layer backed nodes exist. It's necessary to create a UIAccessibilityElement that represents this node - UIAccessibilityElement *accessiblityElement = [ASAccessibilityElement accessibilityElementWithContainer:view node:subnode containerNode:node]; - [elements addObject:accessiblityElement]; - } else { - // Accessiblity element is not layer backed just add the view as accessibility element - [elements addObject:subnode.view]; - } - } else if (subnode.isLayerBacked) { - // Go down the hierarchy of the layer backed subnode and collect all of the UIAccessibilityElement - CollectUIAccessibilityElementsForNode(subnode, node, view, elements); - } else if ([subnode accessibilityElementCount] > 0) { - // UIView is itself a UIAccessibilityContainer just add it - [elements addObject:subnode.view]; } - } } @interface _ASDisplayView () { diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequenceSignUpController.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequenceSignUpController.swift index 74d988bf45..d09dee51a0 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequenceSignUpController.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequenceSignUpController.swift @@ -117,7 +117,7 @@ final class AuthorizationSequenceSignUpController: ViewController { items.append(.separator) items.append(.action(ContextMenuActionItem(text: presentationData.strings.Login_Announce_Notify, icon: { theme in if !announceSignUp { - return nil + return UIImage() } return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) }, iconPosition: .left, action: { [weak self] _, a in @@ -128,7 +128,7 @@ final class AuthorizationSequenceSignUpController: ViewController { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Login_Announce_DontNotify, icon: { theme in if announceSignUp { - return nil + return UIImage() } return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) }, iconPosition: .left, action: { [weak self] _, a in diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 183df4dc5a..ea091d519a 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -3742,7 +3742,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController items.append(.action(ContextMenuActionItem(text: strings.Chat_ContextViewAsTopics, icon: { theme in if !isViewingAsTopics { - return nil + return UIImage() } return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) }, action: { [weak sourceController] _, a in @@ -3778,7 +3778,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController }))) items.append(.action(ContextMenuActionItem(text: strings.Chat_ContextViewAsMessages, icon: { theme in if isViewingAsTopics { - return nil + return UIImage() } return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) }, action: { [weak sourceController] _, a in diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 9f74cd0ce5..988eb0aa81 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -5587,7 +5587,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } var items: [ContextMenuItem] = [] items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.ChatList_Search_Messages_Menu_AllChats, icon: { theme in - return scope == .everywhere ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return scope == .everywhere ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { [weak self] _, f in guard let self else { return @@ -5596,7 +5596,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { self.searchScopePromise.set(.everywhere) }))) items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.ChatList_Search_Messages_Menu_PrivateChats, icon: { theme in - return scope == .privateChats ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return scope == .privateChats ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { [weak self] _, f in guard let self else { return @@ -5605,7 +5605,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { self.searchScopePromise.set(.privateChats) }))) items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.ChatList_Search_Messages_Menu_GroupChats, icon: { theme in - return scope == .groups ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return scope == .groups ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { [weak self] _, f in guard let self else { return @@ -5614,7 +5614,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { self.searchScopePromise.set(.groups) }))) items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.ChatList_Search_Messages_Menu_Channels, icon: { theme in - return scope == .channels ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return scope == .channels ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { [weak self] _, f in guard let self else { return diff --git a/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift b/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift index 785965b4b4..36cb9dabbe 100644 --- a/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift +++ b/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift @@ -896,7 +896,7 @@ public final class ReactionButtonAsyncNode: ContextControllerSourceView { ) } counterLayout = counterValue - if spec.component.count != 0 { + if spec.component.count != 0 || hasTitle { size.width += spacing + counterValue.size.width } else { size.width -= 1.0 diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 48790dabae..9faf3d495b 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -3350,7 +3350,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if isSelected && value == nil { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: .white) } else { - return nil + return UIImage() } }), action: { _, f in f(.default) @@ -3383,7 +3383,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if isSelected { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: .white) } else { - return nil + return UIImage() } }, action: { [weak strongSelf] _, f in f(.default) @@ -3437,7 +3437,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if isSelected { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: .white) } else { - return nil + return UIImage() } }, action: { [weak self] _, f in f(.default) diff --git a/submodules/SettingsUI/Sources/Data and Storage/StorageUsageExceptionsScreen.swift b/submodules/SettingsUI/Sources/Data and Storage/StorageUsageExceptionsScreen.swift index 7d21c5f759..7be3cda903 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/StorageUsageExceptionsScreen.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/StorageUsageExceptionsScreen.swift @@ -401,7 +401,7 @@ public func storageUsageExceptionsScreen( if currentValue == value { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }, action: { _, f in applyValue(value) diff --git a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift index 2e0a541e51..7e5ef1c723 100644 --- a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift +++ b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift @@ -571,7 +571,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, ASScrollVi if isSelected && value == nil { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }), action: { [weak self] _, f in scheduleTooltip(nil) diff --git a/submodules/TelegramCallsUI/Sources/VideoChatScreenMoreMenu.swift b/submodules/TelegramCallsUI/Sources/VideoChatScreenMoreMenu.swift index 423d5311dd..b47e6d164a 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatScreenMoreMenu.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatScreenMoreMenu.swift @@ -338,7 +338,7 @@ extension VideoChatScreenComponent.View { if isSelected { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: .white) } else { - return nil + return UIImage() } }, action: { [weak self] _, f in f(.default) @@ -730,7 +730,7 @@ extension VideoChatScreenComponent.View { if output == currentOutput { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.actionSheet.primaryTextColor) } else { - return nil + return UIImage() } }, action: { [weak self] _, f in f(.default) @@ -763,7 +763,7 @@ extension VideoChatScreenComponent.View { items.append(.separator) items.append(.action(ContextMenuActionItem(text: environment.strings.VoiceChat_SpeakPermissionEveryone, icon: { theme in if isMuted { - return nil + return UIImage() } else { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.actionSheet.primaryTextColor) } @@ -777,7 +777,7 @@ extension VideoChatScreenComponent.View { }))) items.append(.action(ContextMenuActionItem(text: environment.strings.VoiceChat_SpeakPermissionAdmin, icon: { theme in if !isMuted { - return nil + return UIImage() } else { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.actionSheet.primaryTextColor) } diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index d61d72ce43..7ffcf2916a 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -1172,9 +1172,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg self.touchDownGestureRecognizer = recognizer textInputNode.textView.accessibilityHint = self.textPlaceholderNode.attributedText?.string - - self.isAccessibilityContainer = true - self.accessibilityElements = [textInputNode.textView] } private func textFieldMaxHeight(_ maxHeight: CGFloat, metrics: LayoutMetrics, bottomInset: CGFloat) -> CGFloat { diff --git a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextActionsContainerNode.swift b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextActionsContainerNode.swift index bc21e267ef..2393e57cfc 100644 --- a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextActionsContainerNode.swift +++ b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextActionsContainerNode.swift @@ -549,18 +549,18 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { shimmeringForegroundColor = presentationData.theme.contextMenu.primaryColor.withMultipliedAlpha(0.07) } - let textRightInset: CGFloat + let textRightInset: CGFloat = 8.0 + var textLeftInset: CGFloat = horizontalInset + if let _ = self.iconNode.image { - textRightInset = iconSize.width - 2.0 - } else { - textRightInset = 0.0 + textLeftInset = 60.0 } let makeTextLayout = TextNodeWithEntities.asyncLayout(self.textNode) - let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, minimumNumberOfLines: 0, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - horizontalInset * 2.0 - textRightInset, height: .greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.12, cutout: nil, insets: UIEdgeInsets(), lineColor: nil, textShadowColor: nil, textStroke: nil)) + let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, minimumNumberOfLines: 0, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - textLeftInset - textRightInset, height: .greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.12, cutout: nil, insets: UIEdgeInsets(), lineColor: nil, textShadowColor: nil, textStroke: nil)) let _ = textApply(self.arguments?.withUpdatedPlaceholderColor(shimmeringForegroundColor)) - let textFrame = CGRect(origin: CGPoint(x: horizontalInset, y: topInset), size: textLayout.size) + let textFrame = CGRect(origin: CGPoint(x: textLeftInset, y: topInset), size: textLayout.size) transition.updateFrame(node: self.textNode.textNode, frame: textFrame) if textFrame.size.height.isZero { self.textNode.textNode.alpha = 0.0 diff --git a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerActionsStackNode.swift b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerActionsStackNode.swift index 482829fcef..cc6168d58e 100644 --- a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerActionsStackNode.swift +++ b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerActionsStackNode.swift @@ -1488,7 +1488,6 @@ public final class ContextControllerActionsStackNodeImpl: ASDisplayNode, Context } } - self.sourceExtractableContainer = nil self.contentContainer.frame = CGRect(origin: CGPoint(), size: sourceSize) self.contentContainer.layer.cornerRadius = normalCornerRadius @@ -1553,7 +1552,7 @@ public final class ContextControllerActionsStackNodeImpl: ASDisplayNode, Context self.backgroundView.update(size: size, cornerRadius: min(30.0, size.height * 0.5), isDark: presentationData.theme.overallDarkAppearance, tintColor: .init(kind: .panel), isInteractive: true, transition: transition) if let sourceExtractableContainer = self.sourceExtractableContainer { - transition.setFrame(view: sourceExtractableContainer.extractableContentView, frame: CGRect(origin: CGPoint(), size: size)) + transition.setFrame(view: sourceExtractableContainer.extractableContentView, frame: CGRect(origin: CGPoint(x: self.backgroundContainerInset, y: self.backgroundContainerInset), size: size)) sourceExtractableContainer.updateState(state: .extracted(size: size, cornerRadius: min(30.0, size.height * 0.5), state: .animatedIn), transition: .transition(transition.containedViewLayoutTransition), completion: nil) } } diff --git a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftAttributeListContextItem.swift b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftAttributeListContextItem.swift index 2defbe16a3..ac2c3e8a56 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftAttributeListContextItem.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftAttributeListContextItem.swift @@ -120,7 +120,7 @@ private func actionForAttribute(attribute: StarGift.UniqueGift.Attribute, presen return ContextMenuActionItem(text: title, entities: entities, entityFiles: entityFiles, enableEntityAnimations: false, customTextInsets: UIEdgeInsets(top: 0.0, left: 18.0 + 5.0, bottom: 0.0, right: 0.0), parseMarkdown: true, icon: { _ in return nil }, additionalLeftIcon: { theme in - return isSelected ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return isSelected ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in getController()?.dismiss(result: .dismissWithoutContent, completion: nil) @@ -181,7 +181,7 @@ private func actionForAttribute(attribute: StarGift.UniqueGift.Attribute, presen return ContextMenuActionItem(text: title, entities: entities, icon: { _ in return generateGradientFilledCircleImage(diameter: 24.0, colors: [UIColor(rgb: UInt32(bitPattern: innerColor)).cgColor, UIColor(rgb: UInt32(bitPattern: outerColor)).cgColor]) }, additionalLeftIcon: { theme in - return isSelected ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return isSelected ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in getController()?.dismiss(result: .dismissWithoutContent, completion: nil) diff --git a/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift b/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift index 603a4cead6..22b6ad70fc 100644 --- a/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift +++ b/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift @@ -598,6 +598,9 @@ public class GlassBackgroundView: UIView { } } + if let nativeParamsView = self.nativeParamsView { + transition.setFrame(view: nativeParamsView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size)) + } transition.setFrame(view: self.maskContainerView, frame: CGRect(origin: CGPoint(), size: CGSize(width: size.width + shadowInset * 2.0, height: size.height + shadowInset * 2.0))) transition.setFrame(view: self.maskContentView, frame: CGRect(origin: CGPoint(x: shadowInset, y: shadowInset), size: size)) if let foregroundView = self.foregroundView { @@ -631,7 +634,7 @@ public final class GlassBackgroundContainerView: UIView { } public override init(frame: CGRect) { - if #available(iOS 26.0, *) { + if #available(iOS 26.0, *), !GlassBackgroundView.useCustomGlassImpl { let effect = UIGlassContainerEffect() effect.spacing = 7.0 let nativeView = UIVisualEffectView(effect: effect) @@ -707,6 +710,9 @@ public final class GlassBackgroundContainerView: UIView { nativeParamsView.lumaMin = 0.8 nativeParamsView.lumaMax = 0.801 } + if let nativeParamsView = self.nativeParamsView { + transition.setFrame(view: nativeParamsView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size)) + } transition.animateView { nativeView.frame = CGRect(origin: CGPoint(), size: size) diff --git a/submodules/TelegramUI/Components/LegacyMessageInputPanel/Sources/LegacyMessageInputPanel.swift b/submodules/TelegramUI/Components/LegacyMessageInputPanel/Sources/LegacyMessageInputPanel.swift index 99893fe804..783cd74b77 100644 --- a/submodules/TelegramUI/Components/LegacyMessageInputPanel/Sources/LegacyMessageInputPanel.swift +++ b/submodules/TelegramUI/Components/LegacyMessageInputPanel/Sources/LegacyMessageInputPanel.swift @@ -408,7 +408,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView { items.append(.action(ContextMenuActionItem(text: title, textLayout: .multiline, textFont: .small, icon: { _ in return nil }, action: emptyAction))) items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaPicker_Timer_ViewOnce, icon: { theme in - return currentValue == viewOnceTimeout ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return currentValue == viewOnceTimeout ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, a in a(.default) @@ -419,7 +419,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView { for value in values { items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaPicker_Timer_Seconds(value), icon: { theme in - return currentValue == value ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return currentValue == value ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, a in a(.default) @@ -428,7 +428,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView { } items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaPicker_Timer_DoNotDelete, icon: { theme in - return currentValue == nil ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return currentValue == nil ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, a in a(.default) diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 91567bcc58..39239758ff 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -7286,7 +7286,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID color: theme.contextMenu.primaryColor ) } else { - return nil + return UIImage() } }, action: { [weak self] _, a in diff --git a/submodules/TelegramUI/Components/MediaPlaybackHeaderPanelComponent/Sources/MediaNavigationAccessoryHeaderNode.swift b/submodules/TelegramUI/Components/MediaPlaybackHeaderPanelComponent/Sources/MediaNavigationAccessoryHeaderNode.swift index 01562c6935..0bddee3634 100644 --- a/submodules/TelegramUI/Components/MediaPlaybackHeaderPanelComponent/Sources/MediaNavigationAccessoryHeaderNode.swift +++ b/submodules/TelegramUI/Components/MediaPlaybackHeaderPanelComponent/Sources/MediaNavigationAccessoryHeaderNode.swift @@ -561,7 +561,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, ASScrollVi if isSelected && value == nil { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }), action: { [weak self] _, f in scheduleTooltip(nil) diff --git a/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/AffiliateProgramSetupScreen.swift b/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/AffiliateProgramSetupScreen.swift index 276942da8a..deb9abef7b 100644 --- a/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/AffiliateProgramSetupScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/AffiliateProgramSetupScreen.swift @@ -476,7 +476,7 @@ final class AffiliateProgramSetupScreenComponent: Component { if isSelected { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.actionSheet.primaryTextColor) } else { - return nil + return UIImage() } }, action: { [weak self] _, f in f(.default) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreenDisplayGiftsContextMenu.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreenDisplayGiftsContextMenu.swift index d767bdda1e..b43ac185cc 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreenDisplayGiftsContextMenu.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreenDisplayGiftsContextMenu.swift @@ -172,28 +172,28 @@ extension PeerInfoScreenNode { } items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unlimited, icon: { theme in - return filter.contains(.unlimited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.unlimited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.unlimited) }, longPressAction: { _, f in switchToFilter(.unlimited) }))) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Limited, icon: { theme in - return filter.contains(.limitedNonUpgradable) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.limitedNonUpgradable) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.limitedNonUpgradable) }, longPressAction: { _, f in switchToFilter(.limitedNonUpgradable) }))) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Upgradable, icon: { theme in - return filter.contains(.limitedUpgradable) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.limitedUpgradable) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.limitedUpgradable) }, longPressAction: { _, f in switchToFilter(.limitedUpgradable) }))) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unique, icon: { theme in - return filter.contains(.unique) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.unique) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.unique) }, longPressAction: { _, f in @@ -204,14 +204,14 @@ extension PeerInfoScreenNode { items.append(.separator) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Displayed, icon: { theme in - return filter.contains(.displayed) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.displayed) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.displayed) }, longPressAction: { _, f in switchToVisiblityFilter(.displayed) }))) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Hidden, icon: { theme in - return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.hidden) }, longPressAction: { _, f in diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/AddGiftsScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/AddGiftsScreen.swift index 5c5b6d91e1..dad0464fe4 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/AddGiftsScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/AddGiftsScreen.swift @@ -381,28 +381,28 @@ public final class AddGiftsScreen: ViewControllerComponentContainer { } items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unlimited, icon: { theme in - return filter.contains(.unlimited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.unlimited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.unlimited) }, longPressAction: { _, f in switchToFilter(.unlimited) }))) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Limited, icon: { theme in - return filter.contains(.limitedNonUpgradable) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.limitedNonUpgradable) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.limitedNonUpgradable) }, longPressAction: { _, f in switchToFilter(.limitedNonUpgradable) }))) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Upgradable, icon: { theme in - return filter.contains(.limitedUpgradable) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.limitedUpgradable) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.limitedUpgradable) }, longPressAction: { _, f in switchToFilter(.limitedUpgradable) }))) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unique, icon: { theme in - return filter.contains(.unique) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.unique) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.unique) }, longPressAction: { _, f in @@ -412,14 +412,14 @@ public final class AddGiftsScreen: ViewControllerComponentContainer { items.append(.separator) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Displayed, icon: { theme in - return filter.contains(.displayed) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.displayed) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.displayed) }, longPressAction: { _, f in switchToVisiblityFilter(.displayed) }))) items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Hidden, icon: { theme in - return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil + return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage() }, action: { _, f in toggleFilter(.hidden) }, longPressAction: { _, f in diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift index e407168dcb..e12b0171b2 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift @@ -1033,7 +1033,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr let isAdded = gift.collectionIds?.contains(collection.id) ?? false subItems.append(.action(ContextMenuActionItem(text: title, entities: entities, entityFiles: entityFiles, enableEntityAnimations: false, icon: { theme in - return entities.isEmpty ? generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/Collection"), color: theme.contextMenu.primaryColor) : (isAdded ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil) + return entities.isEmpty ? generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/Collection"), color: theme.contextMenu.primaryColor) : (isAdded ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : UIImage()) }, iconPosition: collection.icon == nil ? .left : .right, action: { [weak self] _, f in f(.default) diff --git a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift index d5361bc583..2c9cc45a15 100644 --- a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift +++ b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift @@ -306,7 +306,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon return } - if mainChannel.hasPermission(.manageDirect) { + if !mainChannel.isMonoForum || mainChannel.hasPermission(.manageDirect) { let displayPeer = EnginePeer(mainChannel) let controller = PeerSelectionControllerImpl( diff --git a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift index 9dee157d98..d6d8688428 100644 --- a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift @@ -286,10 +286,12 @@ final class PeerSelectionControllerNode: ASDisplayNode { return } self.chatListNode?.clearHighlightAnimated(true) + self.mainContainerNode?.currentItemNode.clearHighlightAnimated(true) self.requestOpenPeer?(mainPeer, peer.id.toInt64()) }) } else { self.chatListNode?.clearHighlightAnimated(true) + self.mainContainerNode?.currentItemNode.clearHighlightAnimated(true) self.requestOpenPeer?(peer, threadId) } } @@ -488,7 +490,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { if canHideNames { items.append(.action(ContextMenuActionItem(text: uniquePeerIds.count == 1 ? presentationData.strings.Conversation_ForwardOptions_ShowSendersName : presentationData.strings.Conversation_ForwardOptions_ShowSendersNames, icon: { theme in if hideNames { - return nil + return UIImage() } else { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } @@ -506,7 +508,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { if hideNames { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }, action: { _, f in self?.interfaceInteraction?.updateForwardOptionsState({ current in @@ -523,7 +525,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { if hasCaptions { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ForwardOptions_ShowCaption, icon: { theme in if hideCaptions { - return nil + return UIImage() } else { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } @@ -543,7 +545,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { if hideCaptions { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }, action: { _, f in self?.interfaceInteraction?.updateForwardOptionsState({ current in diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift index 822bac6fd8..120b2b2f5c 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift @@ -958,7 +958,7 @@ final class ShareWithPeersScreenComponent: Component { let isSelected = self.shareToFolders.contains(where: { $0.id == folderPreview.folder.id }) items.append(.action(ContextMenuActionItem(text: folderPreview.folder.title, icon: icon, additionalLeftIcon: { theme in if !isSelected { - return nil + return UIImage() } return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) }, iconSource: iconSource, iconPosition: .left, action: { [weak self] c, f in diff --git a/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift b/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift index 254f31d999..90c0a9f909 100644 --- a/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift +++ b/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift @@ -3241,7 +3241,7 @@ final class StorageUsageScreenComponent: Component { if currentValue == value { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }, action: { _, f in applyValue(value) diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 9f984e1bc3..9c4c730618 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -6388,7 +6388,7 @@ public final class StoryItemSetContainerComponent: Component { if isSelected && value == nil { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: .white) } else { - return nil + return UIImage() } }), action: { [weak self] _, f in f(.default) diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift index 23e3c7949a..1a1ff8c8e4 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift @@ -1397,7 +1397,7 @@ public final class StoryItemSetViewListComponent: Component { return generateTintedImage(image: UIImage(bundleImageName: "Stories/Context Menu/Repost"), color: theme.contextMenu.primaryColor) }, additionalLeftIcon: { theme in if sortMode != .repostsFirst { - return nil + return UIImage() } return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, a in @@ -1416,7 +1416,7 @@ public final class StoryItemSetViewListComponent: Component { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reactions"), color: theme.contextMenu.primaryColor) }, additionalLeftIcon: { theme in if sortMode != .reactionsFirst { - return nil + return UIImage() } return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, a in @@ -1435,7 +1435,7 @@ public final class StoryItemSetViewListComponent: Component { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Time"), color: theme.contextMenu.primaryColor) }, additionalLeftIcon: { theme in if sortMode != .recentFirst { - return nil + return UIImage() } return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, a in diff --git a/submodules/TelegramUI/Components/VideoPlaybackControlsComponent/Sources/VideoPlaybackControlsComponent.swift b/submodules/TelegramUI/Components/VideoPlaybackControlsComponent/Sources/VideoPlaybackControlsComponent.swift index 3804ed3694..3a9e2c9ec5 100644 --- a/submodules/TelegramUI/Components/VideoPlaybackControlsComponent/Sources/VideoPlaybackControlsComponent.swift +++ b/submodules/TelegramUI/Components/VideoPlaybackControlsComponent/Sources/VideoPlaybackControlsComponent.swift @@ -167,6 +167,7 @@ public final class VideoPlaybackControlsComponent: Component { self.leftIconView.update(size: leftButtonFrame.size) transition.setAlpha(view: self.leftIconView, alpha: areSideButtonsVisible ? 1.0 : 0.0) transition.setBlur(layer: self.leftIconView.layer, radius: areSideButtonsVisible ? 0.0 : 10.0) + self.leftButtonBackgroundView.isUserInteractionEnabled = areSideButtonsVisible transition.setFrame(view: self.rightButtonBackgroundView, frame: rightButtonFrame) self.rightButtonBackgroundView.update(size: rightButtonFrame.size, cornerRadius: rightButtonFrame.height * 0.5, isDark: true, tintColor: buttonsTintColor, isInteractive: true, isVisible: areSideButtonsVisible, transition: transition) @@ -174,6 +175,7 @@ public final class VideoPlaybackControlsComponent: Component { self.rightIconView.update(size: rightButtonFrame.size) transition.setAlpha(view: self.rightIconView, alpha: areSideButtonsVisible ? 1.0 : 0.0) transition.setBlur(layer: self.rightIconView.layer, radius: areSideButtonsVisible ? 0.0 : 10.0) + self.rightButtonBackgroundView.isUserInteractionEnabled = areSideButtonsVisible transition.setFrame(view: self.centerButtonBackgroundView, frame: centerButtonFrame) self.centerButtonBackgroundView.update(size: centerButtonFrame.size, cornerRadius: centerButtonFrame.height * 0.5, isDark: true, tintColor: buttonsTintColor, isInteractive: true, isVisible: component.isVisible, transition: transition) diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index d732cdb895..3b886be589 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -3903,7 +3903,9 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto loadState = .messages } else if let historyView = strongSelf.historyView { if historyView.filteredEntries.isEmpty { - if let firstEntry = historyView.originalView.entries.first { + if historyView.originalView.isLoading { + loadState = .loading(false) + } else if let firstEntry = historyView.originalView.entries.first { var emptyType = ChatHistoryNodeLoadState.EmptyType.generic for media in firstEntry.message.media { if let action = media as? TelegramMediaAction { diff --git a/submodules/TelegramUI/Sources/CreateGroupController.swift b/submodules/TelegramUI/Sources/CreateGroupController.swift index b092e1c6a7..e41a064db8 100644 --- a/submodules/TelegramUI/Sources/CreateGroupController.swift +++ b/submodules/TelegramUI/Sources/CreateGroupController.swift @@ -1185,7 +1185,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] if currentValue == 0 { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }, action: { _, f in applyValue(0) @@ -1208,7 +1208,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] if currentValue == value { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }, action: { _, f in applyValue(value) diff --git a/submodules/TelegramUI/Sources/NotificationItemContainerNode.swift b/submodules/TelegramUI/Sources/NotificationItemContainerNode.swift index 4b8642e1f6..3dbada70bc 100644 --- a/submodules/TelegramUI/Sources/NotificationItemContainerNode.swift +++ b/submodules/TelegramUI/Sources/NotificationItemContainerNode.swift @@ -97,7 +97,7 @@ final class NotificationItemContainerNode: ASDisplayNode { if let contentNode = self.contentNode { let inset: CGFloat = 8.0 - var contentInsets = UIEdgeInsets(top: inset, left: inset + layout.safeInsets.left, bottom: inset, right: inset + layout.safeInsets.right) + var contentInsets = UIEdgeInsets(top: inset + layout.safeInsets.left, left: inset, bottom: inset, right: inset + layout.safeInsets.right) if let statusBarHeight = layout.statusBarHeight, statusBarHeight >= 39.0 { if layout.deviceMetrics.hasDynamicIsland { @@ -109,7 +109,7 @@ final class NotificationItemContainerNode: ASDisplayNode { } } - let containerWidth = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: layout.safeInsets.left) + let containerWidth = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: 0.0) let contentWidth = containerWidth - contentInsets.left - contentInsets.right let contentHeight = contentNode.updateLayout(width: contentWidth, transition: transition) diff --git a/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift b/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift index 2c8eeada9e..86550b5cee 100644 --- a/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift +++ b/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift @@ -1310,7 +1310,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode { if isSelected && value == nil { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) } else { - return nil + return UIImage() } }), action: { [weak self] _, f in scheduleTooltip(nil) diff --git a/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIViewController+Navigation.m b/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIViewController+Navigation.m index 3be2d1b264..aa59f705f0 100644 --- a/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIViewController+Navigation.m +++ b/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIViewController+Navigation.m @@ -513,8 +513,10 @@ void WKWebsiteDataStoreReinitializeAppBoundDomains(CFTypeRef dataStoreRef); - (id)_65087dc8_objectForInfoDictionaryKey:(NSString *)key { if ([key isEqualToString:@"WKAppBoundDomains"]) { - //NSLog(@"Returning trusted domains: %@", [WebHelpers threadSafeTrustedDomains]); - return [WebHelpers threadSafeTrustedDomains]; + NSArray *result = [WebHelpers threadSafeTrustedDomains]; + if (result.count != 0) { + return result; + } } return [self _65087dc8_objectForInfoDictionaryKey:key]; } From 002df956d21185f5035c716a45e01a85d6a5e0d8 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 6 Feb 2026 17:14:35 +0400 Subject: [PATCH 03/11] Bug fixes --- submodules/AudioBlob/Sources/BlobView.swift | 11 +++++++ .../PeerChatTopIndexableMessageIds.swift | 6 ++++ submodules/Postbox/Sources/Postbox.swift | 8 ++++- .../Sources/PeerDisplayName.swift | 2 +- .../ChatTextInputMediaRecordingButton.swift | 1 + .../ContextControllerActionsStackNode.swift | 33 ++++++++++++++++--- .../Components/ShareExtensionContext/BUILD | 1 + .../Sources/ShareExtensionContext.swift | 5 +++ .../Sources/ChatHistoryListNode.swift | 8 +++-- third-party/libyuv/BUILD | 1 + third-party/opus/BUILD | 18 ++++++++++ third-party/opus/build-opus-bazel.sh | 24 ++++++++++++-- third-party/webrtc/absl/BUILD | 8 ++++- third-party/webrtc/crc32c/BUILD | 1 + third-party/webrtc/libsrtp/BUILD | 1 + 15 files changed, 115 insertions(+), 13 deletions(-) diff --git a/submodules/AudioBlob/Sources/BlobView.swift b/submodules/AudioBlob/Sources/BlobView.swift index 11a8a47ae4..559fb39d2d 100644 --- a/submodules/AudioBlob/Sources/BlobView.swift +++ b/submodules/AudioBlob/Sources/BlobView.swift @@ -55,6 +55,8 @@ public final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDeco private(set) var isAnimating = false + public var hitTestSize: CGFloat? + public typealias BlobRange = (min: CGFloat, max: CGFloat) public init( @@ -224,6 +226,15 @@ public final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDeco self.updateBlobsState() } + + override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if let hitTestSize = self.hitTestSize { + if !CGSize(width: hitTestSize, height: hitTestSize).centered(in: self.bounds).contains(point) { + return nil + } + } + return super.hitTest(point, with: event) + } } final class BlobNode: ASDisplayNode { diff --git a/submodules/Postbox/Sources/PeerChatTopIndexableMessageIds.swift b/submodules/Postbox/Sources/PeerChatTopIndexableMessageIds.swift index 84e6c9969d..f4e0c55a33 100644 --- a/submodules/Postbox/Sources/PeerChatTopIndexableMessageIds.swift +++ b/submodules/Postbox/Sources/PeerChatTopIndexableMessageIds.swift @@ -83,12 +83,14 @@ final class PeerChatTopTaggedMessageIdsTable: Table { let currentTopMessageId = self.get(peerId: message.id.peerId, threadId: message.threadId, namespace: message.id.namespace) if currentTopMessageId == nil || currentTopMessageId! < message.id { self.set(peerId: message.id.peerId, threadId: message.threadId, namespace: message.id.namespace, id: message.id) + self.set(peerId: message.id.peerId, threadId: 0, namespace: message.id.namespace, id: message.id) } } case let .Remove(indices): for (index, _, threadId) in indices { if let messageId = self.get(peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace), index.id == messageId { self.set(peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace, id: nil) + self.set(peerId: index.id.peerId, threadId: 0, namespace: index.id.namespace, id: nil) } } default: @@ -110,8 +112,12 @@ final class PeerChatTopTaggedMessageIdsTable: Table { if let maybeMessageId = maybeMessageId { var messageIdId: Int32 = maybeMessageId.id self.valueBox.set(self.table, key: self.key(combinedId: record.peerAndThreadId, namespace: record.namespace), value: MemoryBuffer(memory: &messageIdId, capacity: 4, length: 4, freeWhenDone: false)) + if record.peerAndThreadId.threadId != nil { + self.valueBox.set(self.table, key: self.key(combinedId: PeerAndThreadId(peerId: record.peerAndThreadId.peerId, threadId: 0), namespace: record.namespace), value: MemoryBuffer(memory: &messageIdId, capacity: 4, length: 4, freeWhenDone: false)) + } } else { self.valueBox.remove(self.table, key: self.key(combinedId: record.peerAndThreadId, namespace: record.namespace), secure: false) + self.valueBox.remove(self.table, key: self.key(combinedId: PeerAndThreadId(peerId: record.peerAndThreadId.peerId, threadId: 0), namespace: record.namespace), secure: false) } } } diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 396fe12a46..232bb7dfe4 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -3507,7 +3507,13 @@ final class PostboxImpl { } if let peerId = mainPeerIdForTopTaggedMessages { for namespace in topTaggedMessageIdNamespaces { - if let messageId = self.peerChatTopTaggedMessageIdsTable.get(peerId: peerId.peerId, threadId: peerId.threadId, namespace: namespace) { + var messageId: MessageId? + messageId = self.peerChatTopTaggedMessageIdsTable.get(peerId: peerId.peerId, threadId: peerId.threadId, namespace: namespace) + if messageId == nil && peerId.threadId == nil { + messageId = self.peerChatTopTaggedMessageIdsTable.get(peerId: peerId.peerId, threadId: 0, namespace: namespace) + } + + if let messageId { if let index = self.messageHistoryIndexTable.getIndex(messageId) { if let message = self.messageHistoryTable.getMessage(index) { topTaggedMessages[namespace] = MessageHistoryTopTaggedMessage.intermediate(message) diff --git a/submodules/TelegramStringFormatting/Sources/PeerDisplayName.swift b/submodules/TelegramStringFormatting/Sources/PeerDisplayName.swift index 21c26624cf..cb12788532 100644 --- a/submodules/TelegramStringFormatting/Sources/PeerDisplayName.swift +++ b/submodules/TelegramStringFormatting/Sources/PeerDisplayName.swift @@ -12,7 +12,7 @@ public func stringForFullAuthorName(message: EngineMessage, strings: Presentatio } else if author.isDeleted { authorName = strings.User_DeletedAccount } else { - authorName = author.compactDisplayTitle + authorName = author.displayTitle(strings: strings, displayOrder: nameDisplayOrder) } if let peer = message.peers[message.id.peerId].flatMap(EnginePeer.init), author.id != peer.id { authorString = [authorName, peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)] diff --git a/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift index 5dd97ec41b..88cf765598 100644 --- a/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift +++ b/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift @@ -322,6 +322,7 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM ) let theme = self.hidesOnLock ? defaultDarkColorPresentationTheme : self.theme blobView.setColor(theme.chat.inputPanel.actionControlFillColor) + blobView.hitTestSize = 110.0 self.micDecorationValue = blobView return blobView } diff --git a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerActionsStackNode.swift b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerActionsStackNode.swift index cc6168d58e..1a1e7bb9e4 100644 --- a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerActionsStackNode.swift +++ b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerActionsStackNode.swift @@ -827,6 +827,17 @@ public final class ContextControllerActionsListStackItem: ContextControllerActio self.addSubnode(item.node) } + if let tipSignal = tipSignal { + self.tipDisposable = (tipSignal + |> deliverOnMainQueue).start(next: { [weak self] tip in + guard let strongSelf = self else { + return + } + strongSelf.tip = tip + requestUpdate(.immediate) + }).strict() + } + requestUpdateAction = { [weak self] id, action in guard let self else { return @@ -981,17 +992,26 @@ public final class ContextControllerActionsListStackItem: ContextControllerActio if let tip = self.tip { let tipNode: InnerTextSelectionTipContainerNode var tipTransition = transition - if let current = self.tipNode { + if let current = self.tipNode, current.tip == tip { tipNode = current } else { tipTransition = .immediate + + let previousTipNode = self.tipNode tipNode = InnerTextSelectionTipContainerNode(presentationData: presentationData, tip: tip, isInline: true) - self.addSubnode(tipNode) - self.tipNode = tipNode let getController = self.getController tipNode.requestDismiss = { completion in getController()?.dismiss(completion: completion) } + self.addSubnode(tipNode) + self.tipNode = tipNode + + if let previousTipNode = previousTipNode { + previousTipNode.animateTransitionInside(other: tipNode) + previousTipNode.removeFromSupernode() + + tipNode.animateContentIn() + } } let tipSeparatorNode: ContextControllerActionsListSeparatorItemNode @@ -1004,12 +1024,15 @@ public final class ContextControllerActionsListStackItem: ContextControllerActio } let (tipSeparatorMinSize, tipSeparatorApply) = tipSeparatorNode.update(presentationData: presentationData, constrainedSize: CGSize(width: combinedSize.width, height: 10.0)) + tipSeparatorNode.isHidden = self.itemNodes.isEmpty let tipSeparatorSize = CGSize(width: combinedSize.width, height: tipSeparatorMinSize.height) tipSeparatorApply(tipSeparatorSize, tipTransition) let tipSeparatorFrame = CGRect(origin: nextItemOrigin, size: tipSeparatorSize) tipTransition.updateFrame(node: tipSeparatorNode, frame: tipSeparatorFrame) - nextItemOrigin.y += tipSeparatorSize.height - combinedSize.height += tipSeparatorSize.height + if !tipSeparatorNode.isHidden { + nextItemOrigin.y += tipSeparatorSize.height + combinedSize.height += tipSeparatorSize.height + } let tipSize = tipNode.updateLayout(widthClass: .compact, presentation: .inline, width: combinedSize.width, transition: tipTransition) let tipFrame = CGRect(origin: nextItemOrigin, size: tipSize) diff --git a/submodules/TelegramUI/Components/ShareExtensionContext/BUILD b/submodules/TelegramUI/Components/ShareExtensionContext/BUILD index 8a0c3ecf8d..becdf07725 100644 --- a/submodules/TelegramUI/Components/ShareExtensionContext/BUILD +++ b/submodules/TelegramUI/Components/ShareExtensionContext/BUILD @@ -39,6 +39,7 @@ swift_library( "//submodules/TelegramUI/Components/TelegramAccountAuxiliaryMethods", "//submodules/TelegramUI/Components/PeerSelectionController", "//submodules/TelegramUI/Components/ContextMenuScreen", + "//submodules/TelegramUI/Components/NavigationBarImpl", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift b/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift index d491abba5a..9d236de495 100644 --- a/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift +++ b/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift @@ -31,6 +31,7 @@ import TelegramUIDeclareEncodables import TelegramAccountAuxiliaryMethods import PeerSelectionController import ContextMenuScreen +import NavigationBarImpl private var installedSharedLogger = false @@ -194,6 +195,10 @@ public class ShareRootControllerImpl { public init(initializationData: ShareRootControllerInitializationData, getExtensionContext: @escaping () -> NSExtensionContext?) { self.initializationData = initializationData self.getExtensionContext = getExtensionContext + + defaultNavigationBarImpl = { presentationData in + return NavigationBarImpl(presentationData: presentationData) + } } deinit { diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index 3b886be589..38d8072019 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -2324,8 +2324,12 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto } var keyboardButtonsMessage = view.topTaggedMessages.first - if keyboardButtonsMessage != nil && keyboardButtonsMessage?.threadId != chatLocation.threadId { - keyboardButtonsMessage = nil + if let keyboardButtonsMessageValue = keyboardButtonsMessage { + if keyboardButtonsMessageValue.threadId != chatLocation.threadId { + if chatLocation.threadId != nil { + keyboardButtonsMessage = nil + } + } } if let keyboardButtonsMessageValue = keyboardButtonsMessage, keyboardButtonsMessageValue.isRestricted(platform: "ios", contentSettings: context.currentContentSettings.with({ $0 })) { keyboardButtonsMessage = nil diff --git a/third-party/libyuv/BUILD b/third-party/libyuv/BUILD index 402dc97822..14e2255c5e 100644 --- a/third-party/libyuv/BUILD +++ b/third-party/libyuv/BUILD @@ -25,6 +25,7 @@ arch_specific_cflags = select({ "@build_bazel_rules_apple//apple:ios_arm64": common_flags + arm64_specific_flags, "//build-system:ios_sim_arm64": common_flags + arm64_specific_flags, "@build_bazel_rules_apple//apple:ios_x86_64": common_flags + x86_64_specific_flags, + "//conditions:default": common_flags, }) cc_library( diff --git a/third-party/opus/BUILD b/third-party/opus/BUILD index 5ea4abdd86..873cdda53d 100644 --- a/third-party/opus/BUILD +++ b/third-party/opus/BUILD @@ -29,6 +29,10 @@ genrule( BUILD_ARCH="sim_arm64" elif [ "$(TARGET_CPU)" == "ios_x86_64" ]; then BUILD_ARCH="x86_64" + elif [ "$(TARGET_CPU)" == "k8" ] || [ "$(TARGET_CPU)" == "x86_64" ]; then + BUILD_ARCH="linux_x86_64" + elif [ "$(TARGET_CPU)" == "aarch64" ] || [ "$(TARGET_CPU)" == "arm64" ]; then + BUILD_ARCH="linux_arm64" else echo "Unsupported architecture $(TARGET_CPU)" fi @@ -63,6 +67,20 @@ cc_library( srcs = [":Public/opus/lib/lib" + x + ".a" for x in libs], ) +cc_library( + name = "opus_cc", + hdrs = [":Public/opus/" + x for x in headers], + includes = [ + "Public", + ], + deps = [ + ":opus_lib", + ], + visibility = [ + "//visibility:public", + ], +) + objc_library( name = "opus", module_name = "opus", diff --git a/third-party/opus/build-opus-bazel.sh b/third-party/opus/build-opus-bazel.sh index 60c2246a61..bb79c9efc6 100755 --- a/third-party/opus/build-opus-bazel.sh +++ b/third-party/opus/build-opus-bazel.sh @@ -12,8 +12,6 @@ OPT_CFLAGS="-Os -g" OPT_LDFLAGS="" OPT_CONFIG_ARGS="" -DEVELOPER=`xcode-select -print-path` - OUTPUTDIR="$BUILD_DIR/Public" # where we will keep our sources and build from. @@ -28,7 +26,27 @@ mkdir -p $INTERDIR tar zxf "$BUILD_DIR/$SOURCE_CODE_ARCHIVE" -C $SRCDIR cd "${SRCDIR}/opus-"* -if [ "${ARCH}" == "x86_64" ]; then +if [ "${ARCH}" = "linux_x86_64" ] || [ "${ARCH}" = "linux_arm64" ]; then + mkdir -p "${INTERDIR}" + + # Keep it simple and portable for container builds. + ./configure \ + --disable-shared \ + --enable-static \ + --with-pic \ + --disable-extra-programs \ + --disable-doc \ + --disable-asm \ + --enable-intrinsics \ + ${OPT_CONFIG_ARGS} \ + --prefix="${INTERDIR}" \ + CFLAGS="$CFLAGS ${OPT_CFLAGS} -fPIC" \ + LDFLAGS="$LDFLAGS ${OPT_LDFLAGS}" + + make -j"$(getconf _NPROCESSORS_ONLN || echo 4)" + make install + exit 0 +elif [ "${ARCH}" == "x86_64" ]; then PLATFORM="iphonesimulator" EXTRA_CFLAGS="-arch ${ARCH}" EXTRA_CONFIG="--host=x86_64-apple-darwin" diff --git a/third-party/webrtc/absl/BUILD b/third-party/webrtc/absl/BUILD index 62f1d938ff..5ab49294ac 100644 --- a/third-party/webrtc/absl/BUILD +++ b/third-party/webrtc/absl/BUILD @@ -355,9 +355,15 @@ absl_sources = [ "absl/types/bad_variant_access.cc", ] +absl_inc_files = [ + f + for f in glob(["absl/**/*.inc"]) + if f not in absl_headers +] + cc_library( name = "absl", - hdrs = absl_headers, + hdrs = absl_headers + absl_inc_files, srcs = absl_sources, cxxopts = [ "-std=c++17", diff --git a/third-party/webrtc/crc32c/BUILD b/third-party/webrtc/crc32c/BUILD index 52d9138c7e..f32c5e6120 100644 --- a/third-party/webrtc/crc32c/BUILD +++ b/third-party/webrtc/crc32c/BUILD @@ -6,6 +6,7 @@ arch_specific_crc32c_sources = select({ "//build-system:ios_sim_arm64": [ "third_party/crc32c/src/crc32c_arm64.cc", ], + "//conditions:default": [], }) crc32c_sources = ["third_party/crc32c/src/" + x for x in [ diff --git a/third-party/webrtc/libsrtp/BUILD b/third-party/webrtc/libsrtp/BUILD index bc29d57cdb..624b70c184 100644 --- a/third-party/webrtc/libsrtp/BUILD +++ b/third-party/webrtc/libsrtp/BUILD @@ -37,6 +37,7 @@ arm64_specific_flags = [ arch_specific_cflags = select({ "@build_bazel_rules_apple//apple:ios_arm64": common_flags + arm64_specific_flags, "//build-system:ios_sim_arm64": common_flags + arm64_specific_flags, + "//conditions:default": [], }) optimization_flags = select({ From 2057b724cd696a7c9d5a1c26c43f60f612dff761 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 6 Feb 2026 17:17:24 +0400 Subject: [PATCH 04/11] Bump version --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index 44a6538fb3..194875f9b1 100644 --- a/versions.json +++ b/versions.json @@ -1,5 +1,5 @@ { - "app": "12.4", + "app": "12.4.1", "xcode": "26.2", "bazel": "8.4.2:45e9388abf21d1107e146ea366ad080eb93cb6a5f3a4a3b048f78de0bc3faffa", "macos": "26" From c313a43456f5114c4088fd1d7679170e0cc70153 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 6 Feb 2026 17:40:36 +0400 Subject: [PATCH 05/11] Fix forum forwarding --- .../Sources/PeerSelectionController.swift | 15 +++++++++++++++ .../Sources/PeerSelectionControllerNode.swift | 3 +++ 2 files changed, 18 insertions(+) diff --git a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift index 2c9cc45a15..8c370154d6 100644 --- a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift +++ b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift @@ -228,6 +228,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon replaceImpl = { [weak controller] c in controller?.replace(with: c) } + strongSelf.peerSelectionNode.pushedController = controller strongSelf.push(controller) } else { strongSelf.selectTab(id: id) @@ -330,6 +331,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon ) ) controller.peerSelected = self.peerSelected + self.peerSelectionNode.pushedController = controller self.push(controller) } else { peerSelected(.channel(peer), threadId) @@ -373,6 +375,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon ) ) controller.peerSelected = strongSelf.peerSelected + strongSelf.peerSelectionNode.pushedController = controller strongSelf.push(controller) } else { peerSelected(peer, threadId) @@ -626,4 +629,16 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon } }) } + + override public func dismiss(completion: (() -> Void)? = nil) { + guard let navigationController = self.navigationController as? NavigationController else { + return + } + var viewControllers = navigationController.viewControllers + viewControllers.removeAll(where: { $0 === self }) + if let pushedController = self.peerSelectionNode.pushedController { + viewControllers.removeAll(where: { $0 === pushedController }) + } + navigationController.setViewControllers(viewControllers, animated: true) + } } diff --git a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift index d6d8688428..1347675e91 100644 --- a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift @@ -102,6 +102,8 @@ final class PeerSelectionControllerNode: ASDisplayNode { private var countPanelNode: PeersCountPanelNode? + weak var pushedController: ViewController? + private var readyValue = Promise() var ready: Signal { return self.readyValue.get() @@ -350,6 +352,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { replaceImpl = { [weak controller] c in controller?.replace(with: c) } + strongSelf.pushedController = controller strongSelf.controller?.push(controller) } self.addSubnode(mainContainerNode) From a1c3b7a58865954b52bc18ec7696107a6476bd7f Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 6 Feb 2026 17:49:43 +0400 Subject: [PATCH 06/11] Fix send button blur --- .../Sources/ChatTextInputPanelNode.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index 7ffcf2916a..cb93cff1f3 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -4378,7 +4378,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } }) - blurTransitionOut.animateBlur(layer: self.sendActionButtons.sendContainerNode.layer, fromRadius: 0.0, toRadius: sendButtonBlurOut) + blurTransitionOut.setBlur(layer: self.sendActionButtons.sendContainerNode.layer, radius: sendButtonBlurOut) if let sendButtonRadialStatusNode = self.sendActionButtons.sendButtonRadialStatusNode { alphaTransition.updateAlpha(node: sendButtonRadialStatusNode, alpha: 0.0) @@ -4409,7 +4409,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg if (hasText || keepSendButtonEnabled && !mediaInputIsActive && !hasSlowModeButton) { if self.sendActionButtons.sendContainerNode.alpha.isZero && self.rightSlowModeInset.isZero { alphaTransition.updateAlpha(node: self.sendActionButtons.sendContainerNode, alpha: 1.0) - blurTransitionIn.animateBlur(layer: self.sendActionButtons.sendContainerNode.layer, fromRadius: sendButtonBlurOut, toRadius: 0.0) + blurTransitionIn.setBlur(layer: self.sendActionButtons.sendContainerNode.layer, radius: 0.0) transition.animatePositionAdditive(layer: self.sendActionButtons.sendButton.imageNode.layer, offset: CGPoint(x: -22.0, y: 18.0)) if let sendButtonRadialStatusNode = self.sendActionButtons.sendButtonRadialStatusNode { alphaTransition.updateAlpha(node: sendButtonRadialStatusNode, alpha: 1.0) @@ -4424,7 +4424,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg strongSelf.applyUpdateSendButtonIcon() } }) - blurTransitionOut.animateBlur(layer: self.sendActionButtons.sendContainerNode.layer, fromRadius: 0.0, toRadius: sendButtonBlurOut) + blurTransitionOut.setBlur(layer: self.sendActionButtons.sendContainerNode.layer, radius: sendButtonBlurOut) if let sendButtonRadialStatusNode = self.sendActionButtons.sendButtonRadialStatusNode { alphaTransition.updateAlpha(node: sendButtonRadialStatusNode, alpha: 0.0) } From 7606a5a0fe10329cf9da72591b54c5edac883c86 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 6 Feb 2026 18:03:26 +0400 Subject: [PATCH 07/11] Update --- .../UIViewController+Navigation.m | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIViewController+Navigation.m b/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIViewController+Navigation.m index aa59f705f0..7aca166f99 100644 --- a/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIViewController+Navigation.m +++ b/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIViewController+Navigation.m @@ -5,6 +5,7 @@ #import "NSWeakReference.h" #import +#import @interface UIViewControllerPresentingProxy : UIViewController @@ -457,8 +458,6 @@ static NSMutableDictionary *trustedWebRecords() return value; } -void WKWebsiteDataStoreReinitializeAppBoundDomains(CFTypeRef dataStoreRef); - @implementation WebHelpers + (NSArray * _Nonnull)threadSafeTrustedDomains { @@ -504,7 +503,16 @@ void WKWebsiteDataStoreReinitializeAppBoundDomains(CFTypeRef dataStoreRef); } + (void)forceRefreshTrustedDomains:(WKWebsiteDataStore * _Nonnull)websiteDataStore { - WKWebsiteDataStoreReinitializeAppBoundDomains((__bridge CFTypeRef)(websiteDataStore)); + static void (*reinitializeFunction)(CFTypeRef dataStoreRef) = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *nameString = [NSString stringWithFormat:@"WK%@", @"WebsiteDataStoreReinitializeAppBoundDomains"]; + reinitializeFunction = dlsym(RTLD_DEFAULT, [nameString UTF8String]); + }); + + if (reinitializeFunction) { + reinitializeFunction((__bridge CFTypeRef)(websiteDataStore)); + } } @end From b47660b22c4ccb3dd58fc05629497f568b6765b5 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 6 Feb 2026 19:35:09 +0400 Subject: [PATCH 08/11] Various fixes --- .../Sources/GiftCraftScreen.swift | 64 +++++++++++++------ .../Sources/SelectCraftGiftScreen.swift | 15 ++++- .../Sources/GiftStoreScreen.swift | 14 ++-- .../Sources/GiftViewScreen.swift | 36 ++++++++++- 4 files changed, 100 insertions(+), 29 deletions(-) diff --git a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift index 519d1fe142..eefa74f502 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift @@ -69,6 +69,7 @@ private final class CraftGiftPageContent: Component { let starsTopUpOptionsPromise: Promise<[StarsTopUpOption]?> let selectGift: (Int32, GiftItem) -> Void let removeGift: (Int32) -> Void + let craftAnotherGift: () -> Void let dismiss: () -> Void init( @@ -86,6 +87,7 @@ private final class CraftGiftPageContent: Component { starsTopUpOptionsPromise: Promise<[StarsTopUpOption]?>, selectGift: @escaping (Int32, GiftItem) -> Void, removeGift: @escaping (Int32) -> Void, + craftAnotherGift: @escaping () -> Void, dismiss: @escaping () -> Void ) { self.context = context @@ -102,6 +104,7 @@ private final class CraftGiftPageContent: Component { self.starsTopUpOptionsPromise = starsTopUpOptionsPromise self.selectGift = selectGift self.removeGift = removeGift + self.craftAnotherGift = craftAnotherGift self.dismiss = dismiss } @@ -1203,7 +1206,13 @@ private final class CraftGiftPageContent: Component { } if let _ = view { if case let .gift(gift) = component.result { - let giftController = GiftViewScreen(context: component.context, subject: .profileGift(component.context.account.peerId, gift)) + let giftController = GiftViewScreen( + context: component.context, + subject: .profileGift(component.context.account.peerId, gift), + customAction: .init(title: environment.strings.Gift_Craft_CraftingFailed_CraftAnotherGift, action: { + component.craftAnotherGift() + }) + ) if let navigationController = controller.navigationController { navigationController.pushViewController(giftController, animated: true) @@ -1548,6 +1557,36 @@ private final class SheetContainerComponent: CombinedComponent { } } + let navigationController = environment.controller()?.navigationController as? NavigationController + let profileGiftsContext = (environment.controller() as? GiftCraftScreen)?.profileGiftsContext + let resaleContext = state.resaleContext + let starsTopUpOptionsPromise = state.starsTopUpOptionsPromise + let craftAnotherGift = { [weak navigationController] in + guard let navigationController else { + return + } + if let genericGift = externalState.starGiftsMap[component.gift.giftId] { + HapticFeedback().impact(.light) + + let selectController = SelectCraftGiftScreen( + context: component.context, + craftContext: component.craftContext, + resaleContext: resaleContext, + gift: component.gift, + genericGift: genericGift, + selectedGiftIds: Set(), + starsTopUpOptions: starsTopUpOptionsPromise.get(), + selectGift: { [weak navigationController] item in + if let navigationController{ + let craftController = GiftCraftScreen(context: component.context, gift: item.gift, profileGiftsContext: profileGiftsContext) + navigationController.pushViewController(craftController) + } + } + ) + navigationController.pushViewController(selectController) + } + } + let theme = environment.theme var colors: (UIColor, UIColor, UIColor, UIColor, UIColor) = ( @@ -1720,6 +1759,7 @@ private final class SheetContainerComponent: CombinedComponent { state.selectedGiftIds[index] = nil state.updated(transition: .spring(duration: 0.4)) }, + craftAnotherGift: craftAnotherGift, dismiss: { dismiss(true) } @@ -1791,26 +1831,8 @@ private final class SheetContainerComponent: CombinedComponent { if state.displayInfo { state.displayInfo = false state.updated(transition: .spring(duration: 0.3)) - } else if state.displayFailure, let genericGift = externalState.starGiftsMap[component.gift.giftId] { - HapticFeedback().impact(.light) - - let selectController = SelectCraftGiftScreen( - context: component.context, - craftContext: component.craftContext, - resaleContext: state.resaleContext, - gift: component.gift, - genericGift: genericGift, - selectedGiftIds: Set(), - starsTopUpOptions: state.starsTopUpOptionsPromise.get(), - selectGift: { item in - if let controller = controller() as? GiftCraftScreen, let navigationController = controller.navigationController as? NavigationController { - let craftController = GiftCraftScreen(context: component.context, gift: item.gift, profileGiftsContext: controller.profileGiftsContext) - controller.dismissAnimated() - navigationController.pushViewController(craftController) - } - } - ) - environment.controller()?.push(selectController) + } else if state.displayFailure { + craftAnotherGift() } else { HapticFeedback().impact(.medium) diff --git a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/SelectCraftGiftScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/SelectCraftGiftScreen.swift index 456486acd9..e366d5df97 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/SelectCraftGiftScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/SelectCraftGiftScreen.swift @@ -153,6 +153,8 @@ final class SelectGiftPageContent: Component { } transition.setFrame(view: self.loadingView, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight - 170.0), size: loadingSize)) + let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) + var itemFrame = CGRect(origin: CGPoint(x: itemSideInset, y: contentHeight), size: itemSize) var itemsHeight: CGFloat = 0.0 var validIds: [AnyHashable] = [] @@ -245,6 +247,12 @@ final class SelectGiftPageContent: Component { } } itemTransition.setFrame(view: itemView, frame: itemFrame) + + var canCraft = true + if let profileGift = self.giftMap[gift.gift.id], let canCraftDate = profileGift.canCraftAt, currentTime < canCraftDate { + canCraft = false + } + transition.setAlpha(view: itemView, alpha: canCraft ? 1.0 : 0.5) } } @@ -414,6 +422,7 @@ final class SelectGiftPageContent: Component { contentHeight += 32.0 contentHeight = self.updateScrolling(interactive: false, transition: transition) + let originalContentHeight = contentHeight let resaleCount = component.genericGift.availability?.resale ?? 0 let saleTitle = environment.strings.Gift_Craft_Select_SaleGiftsCount(Int32(clamping: resaleCount)).uppercased() @@ -483,7 +492,11 @@ final class SelectGiftPageContent: Component { } transition.setFrame(view: storeGiftsView, frame: storeGiftsFrame) - storeGiftsView.updateScrolling(bounds: CGRect(origin: .zero, size: availableSize), transition: .immediate) + var effectiveBounds = CGRect(origin: .zero, size: CGSize(width: availableSize.width, height: 1000.0)) + if let bounds = self.currentBounds { + effectiveBounds = bounds.offsetBy(dx: 0.0, dy: -originalContentHeight) + } + storeGiftsView.updateScrolling(bounds: effectiveBounds, transition: .immediate) } contentHeight += storeGiftsSize.height contentHeight += 90.0 diff --git a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift index e711deca73..a9676d8f57 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift @@ -183,7 +183,7 @@ public final class GiftStoreContentComponent: Component { if let initialCount = self.initialCount, initialCount < minimumCountToDisplayFilters { topInset = component.navigationHeight } - + let visibleBounds = bounds.insetBy(dx: 0.0, dy: -10.0) if let starGifts = self.effectiveGifts { let sideInset: CGFloat = 16.0 + component.safeInsets.left @@ -1269,8 +1269,10 @@ final class GiftStoreScreenComponent: Component { guard let self, let component = self.component, let environment = self.environment else { return } - let controller = component.context.sharedContext.makeStarsTransactionsScreen(context: component.context, starsContext: starsContext) - environment.controller()?.push(controller) + Queue.mainQueue().after(0.3) { + let controller = component.context.sharedContext.makeStarsTransactionsScreen(context: component.context, starsContext: starsContext) + environment.controller()?.push(controller) + } } ))) @@ -1283,8 +1285,10 @@ final class GiftStoreScreenComponent: Component { guard let self, let component = self.component, let environment = self.environment else { return } - let controller = component.context.sharedContext.makeStarsTransactionsScreen(context: component.context, starsContext: tonContext) - environment.controller()?.push(controller) + Queue.mainQueue().after(0.3) { + let controller = component.context.sharedContext.makeStarsTransactionsScreen(context: component.context, starsContext: tonContext) + environment.controller()?.push(controller) + } } ))) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 7e082fd710..ad6c98bd12 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -4677,7 +4677,26 @@ private final class GiftViewSheetContent: CombinedComponent { ) let buttonChild: _UpdatedChildComponent - if state.canSkip { + if let controller = controller() as? GiftViewScreen, let customAction = controller.customAction { + buttonChild = button.update( + component: ButtonComponent( + background: buttonBackground, + content: AnyComponentWithIdentity( + id: AnyHashable("custom"), + component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: customAction.title, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)))) + ), + isEnabled: true, + displaysProgress: state.inProgress, + action: { [weak state] in + if let state { + customAction.action() + state.dismiss(animated: true) + } + }), + availableSize: buttonSize, + transition: context.transition + ) + } else if state.canSkip { buttonChild = button.update( component: ButtonComponent( background: buttonBackground, @@ -5630,6 +5649,16 @@ public class GiftViewScreen: ViewControllerComponentContainer { } } + public struct CustomAction { + public let title: String + public let action: () -> Void + + public init(title: String, action: @escaping () -> Void) { + self.title = title + self.action = action + } + } + private let context: AccountContext private let subject: GiftViewScreen.Subject @@ -5671,6 +5700,7 @@ public class GiftViewScreen: ViewControllerComponentContainer { fileprivate let togglePinnedToTop: ((StarGiftReference, Bool) -> Bool)? fileprivate let shareStory: ((StarGift.UniqueGift) -> Void)? fileprivate let openChatTheme: (() -> Void)? + fileprivate let customAction: CustomAction? public var disposed: () -> Void = {} @@ -5690,7 +5720,8 @@ public class GiftViewScreen: ViewControllerComponentContainer { updateResellStars: ((StarGiftReference, CurrencyAmount?) -> Signal)? = nil, togglePinnedToTop: ((StarGiftReference, Bool) -> Bool)? = nil, shareStory: ((StarGift.UniqueGift) -> Void)? = nil, - openChatTheme: (() -> Void)? = nil + openChatTheme: (() -> Void)? = nil, + customAction: CustomAction? = nil ) { self.context = context self.subject = subject @@ -5706,6 +5737,7 @@ public class GiftViewScreen: ViewControllerComponentContainer { self.togglePinnedToTop = togglePinnedToTop self.shareStory = shareStory self.openChatTheme = openChatTheme + self.customAction = customAction if case let .unique(gift) = subject.arguments?.gift, gift.resellForTonOnly { self.balanceCurrency = .ton From 8babb95d7e423c47f8784fa81020d0187e2489a8 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 8 Feb 2026 16:10:33 +0400 Subject: [PATCH 09/11] Fix --- .../Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift index eefa74f502..def146b4ce 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift @@ -1883,6 +1883,10 @@ private final class SheetContainerComponent: CombinedComponent { } } } + + Queue.mainQueue().after(1.0) { + craftContext.reload() + } }, error: { error in switch error { case .craftFailed: From 4b9b95cbc5261522bc4157b1a8dea41f7c42530e Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 8 Feb 2026 23:27:38 +0400 Subject: [PATCH 10/11] Fix --- .../Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift index def146b4ce..f7072a03c3 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift @@ -1833,6 +1833,7 @@ private final class SheetContainerComponent: CombinedComponent { state.updated(transition: .spring(duration: 0.3)) } else if state.displayFailure { craftAnotherGift() + dismiss(true) } else { HapticFeedback().impact(.medium) From 0afb17091b6b1baa2753795a8b9ea122065a3641 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Mon, 9 Feb 2026 22:55:28 +0400 Subject: [PATCH 11/11] Various improvements --- .../Sources/NotificationService.swift | 10 ++- .../Sources/DebugController.swift | 34 +++++++--- .../GalleryUI/Sources/GalleryController.swift | 10 ++- .../VoiceChatShareScreenContextItem.swift | 2 +- .../Sources/BoostSlowModeButton.swift | 4 +- .../Sources/ChatTextInputPanelNode.swift | 13 ++-- .../Sources/GlassBackgroundComponent.swift | 65 ++++++++++++------- .../Sources/LegacyGlassView.swift | 41 +++++++----- .../Chat/ChatControllerLoadDisplayNode.swift | 3 + .../TelegramUI/Sources/ChatController.swift | 6 ++ .../Sources/ExperimentalUISettings.swift | 10 ++- 11 files changed, 137 insertions(+), 61 deletions(-) diff --git a/Telegram/NotificationService/Sources/NotificationService.swift b/Telegram/NotificationService/Sources/NotificationService.swift index bde66723dd..b154af734f 100644 --- a/Telegram/NotificationService/Sources/NotificationService.swift +++ b/Telegram/NotificationService/Sources/NotificationService.swift @@ -1980,7 +1980,15 @@ private final class NotificationServiceHandler { } if enableInlineEmoji, let textEntitiesAttribute = message.textEntitiesAttribute, let author = message.author { let authorTitle = author.debugDisplayTitle - let messagePrefix = "\(authorTitle): " + var needsPrefix = false + if message.id.peerId.namespace == Namespaces.Peer.CloudGroup { + needsPrefix = true + } else if let channel = message.peers[message.id.peerId] as? TelegramChannel { + if case .group = channel.info { + needsPrefix = true + } + } + let messagePrefix = needsPrefix ? "\(authorTitle): " : "" let messagePrefixLength = (messagePrefix as NSString).length for entity in textEntitiesAttribute.entities { if case let .CustomEmoji(_, fileId) = entity.type { diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index afc8356b4f..badaffdfe9 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -96,6 +96,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { case experimentalCompatibility(Bool) case enableDebugDataDisplay(Bool) case fakeGlass(Bool) + case forceClearGlass(Bool) case browserExperiment(Bool) case allForumsHaveTabs(Bool) case enableReactionOverrides(Bool) @@ -135,7 +136,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.web.rawValue case .keepChatNavigationStack, .skipReadHistory, .alwaysDisplayTyping, .debugRatingLayout, .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, .fakeGlass, .browserExperiment, .allForumsHaveTabs, .enableReactionOverrides, .restorePurchases, .disableReloginTokens, .liveStreamV2, .experimentalCallMute, .playerV2, .devRequests, .enableUpdates, .pwa, .enableLocalTranslation: + case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .compressedEmojiCache, .storiesJpegExperiment, .checkSerializedData, .enableQuickReactionSwitch, .experimentalCompatibility, .enableDebugDataDisplay, .fakeGlass, .forceClearGlass, .browserExperiment, .allForumsHaveTabs, .enableReactionOverrides, .restorePurchases, .disableReloginTokens, .liveStreamV2, .experimentalCallMute, .playerV2, .devRequests, .enableUpdates, .pwa, .enableLocalTranslation: return DebugControllerSection.experiments.rawValue case .logTranslationRecognition, .resetTranslationStates: return DebugControllerSection.translation.rawValue @@ -228,24 +229,26 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 38 case .fakeGlass: return 39 - case .browserExperiment: + case .forceClearGlass: return 40 - case .allForumsHaveTabs: + case .browserExperiment: return 41 - case .enableReactionOverrides: + case .allForumsHaveTabs: return 42 - case .restorePurchases: + case .enableReactionOverrides: return 43 - case .logTranslationRecognition: + case .restorePurchases: return 44 - case .resetTranslationStates: + case .logTranslationRecognition: return 45 - case .compressedEmojiCache: + case .resetTranslationStates: return 46 - case .storiesJpegExperiment: + case .compressedEmojiCache: return 47 - case .disableReloginTokens: + case .storiesJpegExperiment: return 48 + case .disableReloginTokens: + return 49 case .checkSerializedData: return 50 case .enableQuickReactionSwitch: @@ -1279,6 +1282,16 @@ private enum DebugControllerEntry: ItemListNodeEntry { }) }).start() }) + case let .forceClearGlass(value): + return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: "Force clear glass", 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.forceClearGlass = value + return PreferencesEntry(settings) + }) + }).start() + }) case let .browserExperiment(value): return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: "Inline UI", value: value, sectionId: self.section, style: .blocks, updated: { value in let _ = arguments.sharedContext.accountManager.transaction ({ transaction in @@ -1555,6 +1568,7 @@ private func debugControllerEntries(context: AccountContext?, sharedContext: Sha entries.append(.experimentalCompatibility(experimentalSettings.experimentalCompatibility)) entries.append(.enableDebugDataDisplay(experimentalSettings.enableDebugDataDisplay)) entries.append(.fakeGlass(experimentalSettings.fakeGlass)) + entries.append(.forceClearGlass(experimentalSettings.forceClearGlass)) #if DEBUG entries.append(.browserExperiment(experimentalSettings.browserExperiment)) #else diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index eafca476d6..98becb4ca7 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -1469,8 +1469,14 @@ public class GalleryController: ViewController, StandalonePresentableController, } self.galleryNode.controlsVisibilityChanged = { [weak self] visible in - self?.prefersOnScreenNavigationHidden = !visible - self?.galleryNode.pager.centralItemNode()?.controlsVisibilityUpdated(isVisible: visible) + guard let self else { + return + } + self.prefersOnScreenNavigationHidden = !visible + + self.galleryNode.pager.forEachItemNode { itemNode in + itemNode.controlsVisibilityUpdated(isVisible: visible) + } } self.galleryNode.updateOrientation = { [weak self] orientation in diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatShareScreenContextItem.swift b/submodules/TelegramCallsUI/Sources/VoiceChatShareScreenContextItem.swift index e9f60b2bd7..70360e3234 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatShareScreenContextItem.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatShareScreenContextItem.swift @@ -161,7 +161,7 @@ private final class VoiceChatShareScreenContextItemNode: ASDisplayNode, ContextM } func canBeHighlighted() -> Bool { - return true + return false } func updateIsHighlighted(isHighlighted: Bool) { diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/BoostSlowModeButton.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/BoostSlowModeButton.swift index a3c2700e73..62021ab1c2 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/BoostSlowModeButton.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/BoostSlowModeButton.swift @@ -92,6 +92,8 @@ final class BoostSlowModeButton: HighlightTrackingButtonNode { self?.requestUpdate() }, queue: .mainQueue()) self.updateTimer?.start() + } else { + text = stringForDuration(0) } } else { self.updateTimer?.invalidate() @@ -115,7 +117,7 @@ final class BoostSlowModeButton: HighlightTrackingButtonNode { self.textNode.segments = segments let textSize = self.textNode.updateLayout(size: CGSize(width: 200.0, height: 100.0), animated: true) - let totalSize = CGSize(width: textSize.width > 0.0 ? textSize.width + 38.0 : 33.0, height: 33.0) + let totalSize = CGSize(width: textSize.width > 0.0 ? textSize.width + 38.0 : 40.0, height: 40.0) self.containerNode.bounds = CGRect(origin: .zero, size: totalSize) self.containerNode.position = CGPoint(x: totalSize.width / 2.0, y: totalSize.height / 2.0) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index cb93cff1f3..1f35f5c939 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -2203,9 +2203,11 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg var rightSlowModeInset: CGFloat = 0.0 var slowModeButtonSize: CGSize = .zero - if let presentationInterfaceState = self.presentationInterfaceState, (presentationInterfaceState.boostsToUnrestrict ?? 0) > 0 { + var hasSlowmodeButton = false + if let presentationInterfaceState = self.presentationInterfaceState, (presentationInterfaceState.boostsToUnrestrict ?? 0) > 0, presentationInterfaceState.slowmodeState != nil { slowModeButtonSize = self.slowModeButton.update(size: CGSize(width: width, height: 40.0), interfaceState: presentationInterfaceState) - rightSlowModeInset = max(0.0, slowModeButtonSize.width - 33.0) + rightSlowModeInset = max(0.0, slowModeButtonSize.width + 4.0) + hasSlowmodeButton = true } self.rightSlowModeInset = rightSlowModeInset @@ -2392,7 +2394,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg if additionalSideInsets.right > 0.0 { textFieldInsets.right += additionalSideInsets.right / 3.0 } - if inputHasText || self.extendedSearchLayout || hasMediaDraft || hasForward { + if inputHasText || self.extendedSearchLayout || hasMediaDraft || hasForward || hasSlowmodeButton { } else { if let customRightAction = self.customRightAction, case .empty = customRightAction { textFieldInsets.right = 8.0 @@ -3020,6 +3022,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg var nextButtonTopRight = CGPoint(x: textInputContainerBackgroundFrame.width - accessoryButtonInset, y: textInputContainerBackgroundFrame.height - minimalInputHeight) if self.extendedSearchLayout { nextButtonTopRight.x -= 46.0 + } else if hasSlowmodeButton { } else if inputHasText || hasMediaDraft || hasForward { nextButtonTopRight.x -= sendActionButtonsSize.width } @@ -3169,7 +3172,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } var mediaActionButtonsFrame = CGRect(origin: CGPoint(x: textInputContainerBackgroundFrame.maxX + 6.0, y: textInputContainerBackgroundFrame.maxY - mediaActionButtonsSize.height), size: mediaActionButtonsSize) - if inputHasText || self.extendedSearchLayout || hasMediaDraft || interfaceState.interfaceState.forwardMessageIds != nil { + if inputHasText || self.extendedSearchLayout || hasMediaDraft || interfaceState.interfaceState.forwardMessageIds != nil || hasSlowmodeButton { mediaActionButtonsFrame.origin.x = width + 8.0 } transition.updateFrame(node: self.mediaActionButtons, frame: mediaActionButtonsFrame) @@ -3232,7 +3235,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg self.sendActionButtons.updateAbsoluteRect(CGRect(x: rect.origin.x + sendActionButtonsFrame.origin.x, y: rect.origin.y + sendActionButtonsFrame.origin.y, width: sendActionButtonsFrame.width, height: sendActionButtonsFrame.height), within: containerSize, transition: transition) } - let slowModeButtonFrame = CGRect(origin: CGPoint(x: hideOffset.x + width - rightInset - 5.0 - slowModeButtonSize.width + composeButtonsOffset, y: hideOffset.y + panelHeight - minimalHeight + 6.0), size: slowModeButtonSize) + let slowModeButtonFrame = CGRect(origin: CGPoint(x: hideOffset.x + width - rightInset - 5.0 - slowModeButtonSize.width + composeButtonsOffset, y: hideOffset.y + panelHeight - minimalHeight), size: slowModeButtonSize) transition.updateFrame(node: self.slowModeButton, frame: slowModeButtonFrame) if let _ = interfaceState.inputTextPanelState.mediaRecordingState { diff --git a/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift b/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift index 22b6ad70fc..785146b442 100644 --- a/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift +++ b/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift @@ -437,7 +437,21 @@ public class GlassBackgroundView: UIView { if let legacyView = self.legacyView { switch shape { case let .roundedRect(cornerRadius): - legacyView.update(size: size, cornerRadius: cornerRadius, transition: transition) + let style: LegacyGlassView.Style + switch tintColor.kind { + case .panel: + style = .normal + case .clear: + style = .clear + case let .custom(styleValue, _): + switch styleValue { + case .clear: + style = .clear + case .default: + style = .normal + } + } + legacyView.update(size: size, cornerRadius: cornerRadius, style: style, transition: transition) } transition.setFrame(view: legacyView, frame: CGRect(origin: CGPoint(), size: size)) transition.setAlpha(view: legacyView, alpha: isVisible ? 1.0 : 0.0) @@ -512,19 +526,28 @@ public class GlassBackgroundView: UIView { if let foregroundView = self.foregroundView { let fillColor: UIColor + let borderWidthFactor: CGFloat switch tintColor.kind { case .panel: + borderWidthFactor = 1.0 if isDark { fillColor = UIColor(white: 1.0, alpha: 1.0).mixedWith(.black, alpha: 1.0 - 0.11).withAlphaComponent(0.85) } else { fillColor = UIColor(white: 1.0, alpha: 0.7) } case .clear: + borderWidthFactor = 2.0 fillColor = UIColor(white: 1.0, alpha: 0.0) - case let .custom(_, color): + case let .custom(style, color): fillColor = color + switch style { + case .clear: + borderWidthFactor = 2.0 + case .default: + borderWidthFactor = 1.0 + } } - foregroundView.image = GlassBackgroundView.generateLegacyGlassImage(size: CGSize(width: outerCornerRadius * 2.0, height: outerCornerRadius * 2.0), inset: shadowInset, isDark: isDark, fillColor: fillColor) + foregroundView.image = GlassBackgroundView.generateLegacyGlassImage(size: CGSize(width: outerCornerRadius * 2.0, height: outerCornerRadius * 2.0), inset: shadowInset, borderWidthFactor: borderWidthFactor, isDark: isDark, fillColor: fillColor) transition.setAlpha(view: foregroundView, alpha: isVisible ? 1.0 : 0.0) } else { if let nativeParamsView = self.nativeParamsView, let nativeView = self.nativeView { @@ -565,11 +588,21 @@ public class GlassBackgroundView: UIView { if glassEffect == nil { if nativeView.effect is UIGlassEffect { - if transition.animation.isImmediate { - nativeView.effect = nil - } else { - transition.animateView { + if #available(iOS 26.1, *) { + if transition.animation.isImmediate { nativeView.effect = nil + } else { + transition.animateView { + nativeView.effect = nil + } + } + } else { + if transition.animation.isImmediate { + nativeView.effect = UIVisualEffect() + } else { + transition.animateView { + nativeView.effect = UIVisualEffect() + } } } } @@ -774,7 +807,7 @@ private extension CGContext { } public extension GlassBackgroundView { - static func generateLegacyGlassImage(size: CGSize, inset: CGFloat, isDark: Bool, fillColor: UIColor) -> UIImage { + static func generateLegacyGlassImage(size: CGSize, inset: CGFloat, borderWidthFactor: CGFloat = 1.0, isDark: Bool, fillColor: UIColor) -> UIImage { var size = size if size == .zero { size = CGSize(width: 2.0, height: 2.0) @@ -914,7 +947,7 @@ public extension GlassBackgroundView { var ellipseRect = CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset) context.fillEllipse(in: ellipseRect) - let lineWidth: CGFloat = isDark ? 0.8 : 0.8 + let lineWidth: CGFloat = (isDark ? 0.8 : 0.8) * borderWidthFactor let strokeColor: UIColor let blendMode: CGBlendMode let baseAlpha: CGFloat = isDark ? 0.3 : 0.6 @@ -962,20 +995,6 @@ public extension GlassBackgroundView { context.resetClip() context.setBlendMode(.normal) - - //let image = makeInnerShadowPillImageExact(size: CGSize(width: size.width - inset * 2.0, height: size.height - inset * 2.0), scale: UIScreenScale, glossColor: UIColor(white: 1.0, alpha: 1.0), borderWidth: 1.33) - /*let image = generateCircleImage(diameter: size.width - inset * 2.0, lineWidth: 0.5, color: UIColor(white: 1.0, alpha: 1.0))! - - if s == 0.0 && abs(a - 0.7) < 0.1 && !isDark { - image.draw(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset), blendMode: .normal, alpha: 1.0) - } else if s <= 0.3 && !isDark { - image.draw(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset), blendMode: .normal, alpha: 0.7) - } else if b >= 0.2 { - let maxAlpha: CGFloat = isDark ? 0.7 : 0.8 - image.draw(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset), blendMode: .overlay, alpha: max(0.5, min(1.0, maxAlpha * s))) - } else { - image.draw(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset), blendMode: .normal, alpha: 0.5) - }*/ } innerImage.draw(in: CGRect(origin: CGPoint(), size: size)) }.stretchableImage(withLeftCapWidth: Int(size.width * 0.5), topCapHeight: Int(size.height * 0.5)) diff --git a/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/LegacyGlassView.swift b/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/LegacyGlassView.swift index 54a0ef4a41..4a855e53dc 100644 --- a/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/LegacyGlassView.swift +++ b/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/LegacyGlassView.swift @@ -81,13 +81,20 @@ private final class BackdropLayerDelegate: NSObject, CALayerDelegate { } final class LegacyGlassView: UIView { + enum Style { + case normal + case clear + } + private struct Params: Equatable { let size: CGSize let cornerRadius: CGFloat + let style: Style - init(size: CGSize, cornerRadius: CGFloat) { + init(size: CGSize, cornerRadius: CGFloat, style: Style) { self.size = size self.cornerRadius = cornerRadius + self.style = style } } @@ -109,19 +116,8 @@ final class LegacyGlassView: UIView { self.layer.addSublayer(backdropLayer) backdropLayer.delegate = self.backdropLayerDelegate - let blur: CGFloat - let scale: CGFloat - - blur = 2.0 - scale = 1.0 - - invokeBackdropLayerSetScaleMethod(object: backdropLayer, scale: scale) - backdropLayer.rasterizationScale = scale - - if let blurFilter = CALayer.blur() { - blurFilter.setValue(blur as NSNumber, forKey: "inputRadius") - backdropLayer.filters = [blurFilter] - } + invokeBackdropLayerSetScaleMethod(object: backdropLayer, scale: 1.0) + backdropLayer.rasterizationScale = 1.0 } } @@ -129,8 +125,9 @@ final class LegacyGlassView: UIView { fatalError("init(coder:) has not been implemented") } - func update(size: CGSize, cornerRadius: CGFloat, transition: ComponentTransition) { - let params = Params(size: size, cornerRadius: cornerRadius) + func update(size: CGSize, cornerRadius: CGFloat, style: Style, transition: ComponentTransition) { + let params = Params(size: size, cornerRadius: cornerRadius, style: style) + let previousParams = self.params if self.params == params { return } @@ -140,6 +137,18 @@ final class LegacyGlassView: UIView { return } + if previousParams?.style != style { + if let blurFilter = CALayer.blur() { + switch style { + case .clear: + blurFilter.setValue(6.0 as NSNumber, forKey: "inputRadius") + case .normal: + blurFilter.setValue(2.0 as NSNumber, forKey: "inputRadius") + } + backdropLayer.filters = [blurFilter] + } + } + transition.setCornerRadius(layer: self.layer, cornerRadius: cornerRadius) transition.setFrame(layer: backdropLayer, frame: CGRect(origin: CGPoint(), size: size)) diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index b4a786bf50..73e4ab9d41 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -379,6 +379,9 @@ extension ChatControllerImpl { if previousState.chatTitleContent != contentData.state.chatTitleContent { animated = true } + if previousState.slowmodeState != contentData.state.slowmodeState || previousState.boostsToUnrestrict != contentData.state.boostsToUnrestrict { + animated = true + } var transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.4, curve: .spring) : .immediate if let forceAnimationTransition { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index f344f3ce9c..0521901838 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -743,6 +743,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !self.presentationData.theme.overallDarkAppearance { preferredGlassType = .default } + if self.context.sharedContext.immediateExperimentalUISettings.forceClearGlass { + preferredGlassType = .clear + } if self.presentationInterfaceState.preferredGlassType != preferredGlassType { self.updateChatPresentationInterfaceState(transition: .immediate, interactive: false, { state in return state.updatedPreferredGlassType(preferredGlassType) @@ -6411,6 +6414,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !self.presentationData.theme.overallDarkAppearance { preferredGlassType = .default } + if self.context.sharedContext.immediateExperimentalUISettings.forceClearGlass { + preferredGlassType = .clear + } self.updateChatPresentationInterfaceState(animated: false, interactive: false, { state in var state = state state = state.updatedPresentationReady(self.didSetPresentationData) diff --git a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift index 4bf6e9ec9a..1fc900ca8a 100644 --- a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift +++ b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift @@ -70,6 +70,7 @@ public struct ExperimentalUISettings: Codable, Equatable { public var debugRatingLayout: Bool public var enableUpdates: Bool public var enablePWA: Bool + public var forceClearGlass: Bool public static var defaultSettings: ExperimentalUISettings { return ExperimentalUISettings( @@ -117,7 +118,8 @@ public struct ExperimentalUISettings: Codable, Equatable { allForumsHaveTabs: false, debugRatingLayout: false, enableUpdates: false, - enablePWA: false + enablePWA: false, + forceClearGlass: false ) } @@ -166,7 +168,8 @@ public struct ExperimentalUISettings: Codable, Equatable { allForumsHaveTabs: Bool, debugRatingLayout: Bool, enableUpdates: Bool, - enablePWA: Bool + enablePWA: Bool, + forceClearGlass: Bool ) { self.keepChatNavigationStack = keepChatNavigationStack self.skipReadHistory = skipReadHistory @@ -213,6 +216,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.debugRatingLayout = debugRatingLayout self.enableUpdates = enableUpdates self.enablePWA = enablePWA + self.forceClearGlass = forceClearGlass } public init(from decoder: Decoder) throws { @@ -263,6 +267,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.debugRatingLayout = try container.decodeIfPresent(Bool.self, forKey: "debugRatingLayout") ?? false self.enableUpdates = try container.decodeIfPresent(Bool.self, forKey: "enableUpdates") ?? false self.enablePWA = try container.decodeIfPresent(Bool.self, forKey: "enablePWA") ?? false + self.forceClearGlass = try container.decodeIfPresent(Bool.self, forKey: "forceClearGlass") ?? false } public func encode(to encoder: Encoder) throws { @@ -313,6 +318,7 @@ public struct ExperimentalUISettings: Codable, Equatable { try container.encodeIfPresent(self.debugRatingLayout, forKey: "debugRatingLayout") try container.encodeIfPresent(self.enableUpdates, forKey: "enableUpdates") try container.encodeIfPresent(self.enablePWA, forKey: "enablePWA") + try container.encodeIfPresent(self.forceClearGlass, forKey: "forceClearGlass") } }