diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index f179033672..3256d21dcd 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -1060,14 +1060,9 @@ public class AttachmentController: ViewController, MinimizableController { let sourceButtonScale = sourceButtonFrame.width / targetFrame.width if let sourceGlassView = findParentGlassBackgroundView(attachmentButton), let glassParams = sourceGlassView.params { - let containerView = UIView() - containerView.clipsToBounds = true + let containerView = ClipContainerView() + containerView.update(bounds: CGRect(origin: CGPoint(x: 0.0, y: (targetFrame.height - targetFrame.width) * 0.5), size: CGSize(width: targetFrame.width, height: targetFrame.width)), topCornerRadius: targetFrame.width * 0.5, bottomCornerRadius: targetFrame.width * 0.5, boundsTransition: .immediate, cornersTransition: .immediate) containerView.frame = targetFrame - if #available(iOS 26.0, *) { - containerView.cornerConfiguration = .uniformCorners(radius: .fixed(containerView.bounds.width * 0.5)) - } else { - containerView.layer.cornerRadius = containerView.bounds.width * 0.5 - } self.view.addSubview(containerView) let localGlassView = GlassBackgroundView() @@ -1079,7 +1074,7 @@ public class AttachmentController: ViewController, MinimizableController { transition: .immediate ) localGlassView.frame = CGRect(origin: .zero, size: targetFrame.size) - containerView.addSubview(localGlassView) + containerView.contentView.addSubview(localGlassView) let initialContainerBounds = self.container.bounds let initialContainerFrame = self.container.frame @@ -1087,10 +1082,10 @@ public class AttachmentController: ViewController, MinimizableController { let clipInnerFrame = self.container.container.view.convert(self.container.container.view.bounds, to: self.container.view) self.container.bounds = CGRect(origin: .zero, size: self.container.bounds.size) - self.container.frame = CGRect(origin: CGPoint(x: floorToScreenPixels ((targetFrame.width - self.container.frame.width) / 2.0), y: -clipInnerFrame.minY), size: self.container.frame.size) + self.container.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((targetFrame.width - self.container.frame.width) / 2.0), y: -clipInnerFrame.minY), size: self.container.frame.size) self.container.view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.container.bottomClipNode.cornerRadius = 0.0 - containerView.addSubnode(self.container) + containerView.contentView.addSubnode(self.container) let buttonIcon = GlassBackgroundView.ContentImageView() let presentationData = controller.context.sharedContext.currentPresentationData.with { $0 } @@ -1104,14 +1099,8 @@ public class AttachmentController: ViewController, MinimizableController { localGlassView.contentView.addSubview(buttonIcon) ComponentTransition(buttonTransition).animateBlur(layer: buttonIcon.layer, fromRadius: 0.0, toRadius: 10.0) - scaleTransition.animateBounds(layer: containerView.layer, from: CGRect(origin: CGPoint(x: 0.0, y: (targetFrame.height - targetFrame.width) * 0.5), size: CGSize(width: targetFrame.width, height: targetFrame.width))) - cornersTransition.animateView { - if #available(iOS 26.0, *) { - containerView.cornerConfiguration = .corners(topLeftRadius: 38.0, topRightRadius: 38.0, bottomLeftRadius: .fixed(layout.deviceMetrics.screenCornerRadius - 2.0), bottomRightRadius: .fixed(layout.deviceMetrics.screenCornerRadius - 2.0)) - } else { - containerView.layer.cornerRadius = layout.deviceMetrics.screenCornerRadius - 2.0 - } - } + containerView.update(bounds: CGRect(origin: .zero, size: targetFrame.size), topCornerRadius: 38.0, bottomCornerRadius: layout.deviceMetrics.screenCornerRadius - 2.0, boundsTransition: scaleTransition, cornersTransition: cornersTransition) + scaleTransition.animateBounds(layer: containerView.layer, from: CGRect(origin: .zero, size: CGSize(width: targetFrame.width, height: targetFrame.width))) scaleTransition.animateTransformScale(view: containerView, from: sourceButtonScale) positionTransition.animatePosition(layer: containerView.layer, from: sourceButtonFrame.center, to: containerView.center, completion: { _ in self.container.bottomClipNode.cornerRadius = initialBottomClipRadius @@ -1176,14 +1165,9 @@ public class AttachmentController: ViewController, MinimizableController { let targetButtonScale = targetButtonFrame.width / initialFrame.width if let sourceGlassView = findParentGlassBackgroundView(attachmentButton), let glassParams = sourceGlassView.params { - let containerView = UIView() - containerView.clipsToBounds = true + let containerView = ClipContainerView() containerView.frame = initialFrame - if #available(iOS 26.0, *) { - containerView.cornerConfiguration = .corners(topLeftRadius: 38.0, topRightRadius: 38.0, bottomLeftRadius: .fixed(layout.deviceMetrics.screenCornerRadius - 2.0), bottomRightRadius: .fixed(layout.deviceMetrics.screenCornerRadius - 2.0)) - } else { - containerView.layer.cornerRadius = layout.deviceMetrics.screenCornerRadius - 2.0 - } + containerView.update(bounds: CGRect(origin: .zero, size: initialFrame.size), topCornerRadius: 38.0, bottomCornerRadius: layout.deviceMetrics.screenCornerRadius - 2.0, boundsTransition: .immediate, cornersTransition: .immediate) self.view.addSubview(containerView) let localGlassView = GlassBackgroundView() @@ -1195,14 +1179,14 @@ public class AttachmentController: ViewController, MinimizableController { transition: .immediate ) localGlassView.frame = CGRect(origin: .zero, size: initialFrame.size) - containerView.addSubview(localGlassView) + containerView.contentView.addSubview(localGlassView) let clipInnerFrame = self.container.container.view.convert(self.container.container.view.bounds, to: self.container.view) self.container.bounds = CGRect(origin: .zero, size: self.container.bounds.size) - self.container.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((initialFrame.width - self.container.frame.width) / 2.0), y: -clipInnerFrame.minY), size: self.container.frame.size) + self.container.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((initialFrame.width - self.container.frame.width) / 2.0), y: -clipInnerFrame.minY), size: self.container.frame.size) self.container.isUserInteractionEnabled = false self.container.view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false) - containerView.addSubnode(self.container) + containerView.contentView.addSubnode(self.container) let buttonIcon = GlassBackgroundView.ContentImageView() let presentationData = controller.context.sharedContext.currentPresentationData.with { $0 } @@ -1217,14 +1201,9 @@ public class AttachmentController: ViewController, MinimizableController { ComponentTransition(buttonTransition).animateBlur(layer: buttonIcon.layer, fromRadius: 10.0, toRadius: 0.0) ComponentTransition(buttonTransition).animateBlur(layer: sourceGlassView.contentView.layer, fromRadius: 10.0, toRadius: 0.0) - scaleTransition.updateBounds(layer: containerView.layer, bounds: CGRect(origin: CGPoint(x: 0.0, y: (initialFrame.height - initialFrame.width) * 0.5), size: CGSize(width: initialFrame.width, height: initialFrame.width))) - cornersTransition.animateView { - if #available(iOS 26.0, *) { - containerView.cornerConfiguration = .uniformCorners(radius: .fixed(containerView.bounds.width * 0.5)) - } else { - containerView.layer.cornerRadius = containerView.bounds.width * 0.5 - } - } + containerView.update(bounds: CGRect(origin: CGPoint(x: 0.0, y: (initialFrame.height - initialFrame.width) * 0.5), size: CGSize(width: initialFrame.width, height: initialFrame.width)), topCornerRadius: initialFrame.width * 0.5, bottomCornerRadius: initialFrame.width * 0.5, boundsTransition: scaleTransition, cornersTransition: cornersTransition) + scaleTransition.updateBounds(layer: containerView.layer, bounds: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: initialFrame.width, height: initialFrame.width))) + scaleTransition.updateTransformScale(layer: containerView.layer, scale: targetButtonScale) positionTransition.updatePosition(layer: containerView.layer, position: targetButtonFrame.center, completion: { [weak self] _ in let _ = self?.container.dismiss(transition: .immediate, completion: completion) @@ -1232,7 +1211,6 @@ public class AttachmentController: ViewController, MinimizableController { }) localGlassView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, delay: 0.2, timingFunction: CAMediaTimingFunctionName.linear.rawValue, removeOnCompletion: false) - //sourceGlassView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: 0.27, timingFunction: CAMediaTimingFunctionName.linear.rawValue) scaleTransition.animateTransformScale(view: sourceGlassView, from: 1.0 / targetButtonScale) positionTransition.animatePosition(layer: sourceGlassView.layer, from: self.view.convert(initialFrame.center, to: sourceGlassView.superview), to: sourceGlassView.center) @@ -1712,3 +1690,36 @@ private func findParentGlassBackgroundView(_ view: UIView) -> GlassBackgroundVie } return nil } + +private final class ClipContainerView: UIView { + private let clipView = UIView() + let contentView = UIView() + + override init(frame: CGRect) { + super.init(frame: frame) + + self.clipView.clipsToBounds = true + self.clipView.layer.cornerCurve = .continuous + self.clipView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + + self.contentView.clipsToBounds = true + self.contentView.layer.cornerCurve = .continuous + self.contentView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] + + self.addSubview(self.clipView) + self.clipView.addSubview(self.contentView) + } + + required init?(coder: NSCoder) { + preconditionFailure() + } + + func update(bounds: CGRect, topCornerRadius: CGFloat, bottomCornerRadius: CGFloat, boundsTransition: ContainedViewLayoutTransition, cornersTransition: ContainedViewLayoutTransition) { + cornersTransition.updateCornerRadius(layer: self.clipView.layer, cornerRadius: topCornerRadius) + cornersTransition.updateCornerRadius(layer: self.contentView.layer, cornerRadius: bottomCornerRadius) + + boundsTransition.updateFrame(view: self.clipView, frame: CGRect(origin: .zero, size: bounds.size)) + boundsTransition.updatePosition(layer: self.contentView.layer, position: CGPoint(x: bounds.size.width * 0.5, y: bounds.size.height * 0.5)) + boundsTransition.updateBounds(layer: self.contentView.layer, bounds: bounds) + } +} diff --git a/submodules/Components/SheetComponent/Sources/SheetComponent.swift b/submodules/Components/SheetComponent/Sources/SheetComponent.swift index db41ba334e..4bee09d752 100644 --- a/submodules/Components/SheetComponent/Sources/SheetComponent.swift +++ b/submodules/Components/SheetComponent/Sources/SheetComponent.swift @@ -156,6 +156,40 @@ public final class SheetComponent: C return true } } + + final class BackgroundView: UIView { + let topCornersView = UIView() + let bottomCornersView = UIView() + + override init(frame: CGRect) { + super.init(frame: frame) + + self.topCornersView.clipsToBounds = true + self.topCornersView.layer.cornerCurve = .continuous + self.topCornersView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + + self.bottomCornersView.clipsToBounds = true + self.bottomCornersView.layer.cornerCurve = .continuous + self.bottomCornersView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] + + self.addSubview(self.topCornersView) + self.topCornersView.addSubview(self.bottomCornersView) + } + + required init?(coder: NSCoder) { + preconditionFailure() + } + + func update(size: CGSize, color: UIColor, topCornerRadius: CGFloat, bottomCornerRadius: CGFloat, transition: ComponentTransition) { + transition.setCornerRadius(layer: self.topCornersView.layer, cornerRadius: topCornerRadius) + transition.setCornerRadius(layer: self.bottomCornersView.layer, cornerRadius: bottomCornerRadius) + + transition.setFrame(view: self.topCornersView, frame: CGRect(origin: .zero, size: size)) + transition.setFrame(view: self.bottomCornersView, frame: CGRect(origin: .zero, size: size)) + + transition.setBackgroundColor(view: self.bottomCornersView, color: color) + } + } public final class View: UIView, UIScrollViewDelegate, ComponentTaggedView { public final class Tag { @@ -174,7 +208,7 @@ public final class SheetComponent: C private let dimView: UIView private let scrollView: ScrollView - private let backgroundView: DynamicCornerRadiusView + private let backgroundView: BackgroundView private var effectView: UIVisualEffectView? private let contentView: ComponentView private var headerView: ComponentView? @@ -198,7 +232,7 @@ public final class SheetComponent: C self.scrollView.showsHorizontalScrollIndicator = false self.scrollView.alwaysBounceVertical = true - self.backgroundView = DynamicCornerRadiusView() + self.backgroundView = BackgroundView() self.contentView = ComponentView() @@ -377,21 +411,22 @@ public final class SheetComponent: C bottomCornerRadius = 12.0 } + var backgroundColor: UIColor = .clear switch component.backgroundColor { - case let .blur(style): - self.backgroundView.isHidden = true - if self.effectView == nil { - let effectView = UIVisualEffectView(effect: UIBlurEffect(style: style == .dark ? .dark : .light)) - effectView.layer.cornerRadius = self.backgroundView.layer.cornerRadius - effectView.layer.masksToBounds = true - self.backgroundView.superview?.insertSubview(effectView, aboveSubview: self.backgroundView) - self.effectView = effectView - } - case let .color(color): - self.backgroundView.updateColor(color: color, transition: .immediate) - self.backgroundView.isHidden = false - self.effectView?.removeFromSuperview() - self.effectView = nil + case let .blur(style): + self.backgroundView.isHidden = true + if self.effectView == nil { + let effectView = UIVisualEffectView(effect: UIBlurEffect(style: style == .dark ? .dark : .light)) + effectView.layer.cornerRadius = self.backgroundView.layer.cornerRadius + effectView.layer.masksToBounds = true + self.backgroundView.superview?.insertSubview(effectView, aboveSubview: self.backgroundView) + self.effectView = effectView + } + case let .color(color): + backgroundColor = color + self.backgroundView.isHidden = false + self.effectView?.removeFromSuperview() + self.effectView = nil } transition.setFrame(view: self.dimView, frame: CGRect(origin: CGPoint(), size: availableSize), completion: nil) @@ -432,6 +467,7 @@ public final class SheetComponent: C } contentView.clipsToBounds = component.clipsContent contentView.layer.cornerRadius = topCornerRadius + if sheetEnvironment.isCentered { let y: CGFloat = floorToScreenPixels((availableSize.height - contentSize.height) / 2.0) transition.setFrame(view: contentView, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - contentSize.width) / 2.0), y: -y), size: contentSize), completion: nil) @@ -439,7 +475,7 @@ public final class SheetComponent: C if let effectView = self.effectView { transition.setFrame(view: effectView, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - contentSize.width) / 2.0), y: -y), size: contentSize), completion: nil) } - self.backgroundView.update(size: contentSize, corners: .init(minXMinY: topCornerRadius, maxXMinY: topCornerRadius, minXMaxY: bottomCornerRadius, maxXMaxY: bottomCornerRadius), transition: transition) + self.backgroundView.update(size: contentSize, color: backgroundColor, topCornerRadius: topCornerRadius, bottomCornerRadius: topCornerRadius, transition: transition) } else { switch component.style { case .glass: @@ -452,7 +488,7 @@ public final class SheetComponent: C transition.setFrame(view: effectView, frame: CGRect(origin: .zero, size: CGSize(width: contentSize.width, height: contentSize.height + 1000.0)), completion: nil) } } - self.backgroundView.update(size: contentSize, corners: .init(minXMinY: topCornerRadius, maxXMinY: topCornerRadius, minXMaxY: bottomCornerRadius, maxXMaxY: bottomCornerRadius), transition: transition) + self.backgroundView.update(size: contentSize, color: backgroundColor, topCornerRadius: topCornerRadius, bottomCornerRadius: bottomCornerRadius, transition: transition) } } transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: availableSize), completion: nil) diff --git a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift index ade628dba4..863e353447 100644 --- a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift @@ -25,7 +25,7 @@ import EmojiStatusComponent private let extensionImageCache = Atomic<[UInt32: UIImage]>(value: [:]) -private let redColors: (UInt32, UInt32) = (0xed6b7b, 0xe63f45) +private let redColors: (UInt32, UInt32) = (0xff875f, 0xff5069) private let greenColors: (UInt32, UInt32) = (0x99de6f, 0x5fb84f) private let blueColors: (UInt32, UInt32) = (0x72d5fd, 0x2a9ef1) private let yellowColors: (UInt32, UInt32) = (0xffa24b, 0xed705c) @@ -63,11 +63,22 @@ private func generateExtensionImage(colors: (UInt32, UInt32)) -> UIImage? { context.restoreGState() + context.saveGState() + let rounded = UIBezierPath(roundedRect: CGRect(origin: .zero, size: size), cornerRadius: 13).cgPath + let full = UIBezierPath(rect: CGRect(origin: .zero, size: size)).cgPath + context.addPath(full) + context.addPath(rounded) + context.setBlendMode(.destinationOut) + context.drawPath(using: .eoFill) + context.setBlendMode(.normal) + context.restoreGState() + context.beginPath() let _ = try? drawSvgPath(context, path: "M6,0 L26.7573593,0 C27.5530088,-8.52837125e-16 28.3160705,0.316070521 28.8786797,0.878679656 L39.1213203,11.1213203 C39.6839295,11.6839295 40,12.4469912 40,13.2426407 L40,34 C40,37.3137085 37.3137085,40 34,40 L6,40 C2.6862915,40 4.05812251e-16,37.3137085 0,34 L0,6 C-4.05812251e-16,2.6862915 2.6862915,6.08718376e-16 6,0 ") context.clip() - - context.setFillColor(UIColor(rgb: 0xffffff, alpha: 0.2).cgColor) + + context.setBlendMode(.overlay) + context.setFillColor(UIColor(rgb: 0xffffff, alpha: 0.5).cgColor) context.translateBy(x: 40.0 - 14.0, y: 0.0) let _ = try? drawSvgPath(context, path: "M-1,0 L14,0 L14,15 L14,14 C14,12.8954305 13.1045695,12 12,12 L4,12 C2.8954305,12 2,11.1045695 2,10 L2,2 C2,0.8954305 1.1045695,-2.02906125e-16 0,0 L-1,0 L-1,0 Z ") }) @@ -1250,7 +1261,7 @@ public final class ListMessageFileItemNode: ListMessageNode { let iconFrame = CGRect(origin: CGPoint(x: params.leftInset + leftOffset + 12.0, y: 8.0 + verticalInset), size: iconSize) transition.updateFrame(node: strongSelf.extensionIconNode, frame: iconFrame) strongSelf.extensionIconNode.image = extensionIconImage - transition.updateFrame(node: strongSelf.extensionIconText, frame: CGRect(origin: CGPoint(x: iconFrame.minX + floorToScreenPixels((iconFrame.width - extensionTextLayout.size.width) / 2.0), y: iconFrame.minY + 7.0 + floorToScreenPixels((iconFrame.height - extensionTextLayout.size.height) / 2.0)), size: extensionTextLayout.size)) + transition.updateFrame(node: strongSelf.extensionIconText, frame: CGRect(origin: CGPoint(x: iconFrame.minX + floorToScreenPixels((iconFrame.width - extensionTextLayout.size.width) / 2.0), y: iconFrame.minY + 5.0 + floorToScreenPixels((iconFrame.height - extensionTextLayout.size.height) / 2.0)), size: extensionTextLayout.size)) transition.updateFrame(node: strongSelf.iconStatusNode, frame: iconFrame) diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 557f1ef87c..5fc241f294 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -2564,7 +2564,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att } else { topEdgeColor = .clear } - let topEdgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: 100.0)) + let topEdgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: 80.0)) transition.updateFrame(view: self.controllerNode.topEdgeEffectView, frame: topEdgeEffectFrame) transition.updateAlpha(layer: self.controllerNode.topEdgeEffectView.layer, alpha: self.controllerNode.scrolledExactlyToTop && self.controllerNode.currentDisplayMode == .all ? 0.0 : 1.0) self.controllerNode.topEdgeEffectView.update(content: topEdgeColor, blur: true, alpha: 0.8, rect: topEdgeEffectFrame, edge: .top, edgeSize: topEdgeEffectFrame.height, transition: ComponentTransition(transition)) diff --git a/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift b/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift index 646addf3a6..6be183f4b3 100644 --- a/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift +++ b/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift @@ -399,7 +399,7 @@ public final class SegmentedControlNode: ASDisplayNode, ASGestureRecognizerDeleg } if !self.dividerNodes.isEmpty { - let dividerSize = CGSize(width: 1.0, height: 16.0) + let dividerSize = CGSize(width: 1.0, height: size.height - 8.0) let delta: CGFloat = size.width / CGFloat(self.dividerNodes.count + 1) for i in 0 ..< self.dividerNodes.count { let dividerNode = self.dividerNodes[i] diff --git a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift index 9ec46b40b4..16f4a349ad 100644 --- a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift +++ b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift @@ -797,25 +797,27 @@ public final class SolidRoundedButtonNode: ASDisplayNode { self.subtitleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) } - let chromeView: UIImageView - var chromeTransition = transition - if let current = self.chromeView { - chromeView = current - } else { - chromeTransition = .immediate - chromeView = UIImageView() - self.chromeView = chromeView - if let shimmeringView = self.shimmerView { - self.view.insertSubview(chromeView, aboveSubview: shimmeringView) + if self.glass { + let chromeView: UIImageView + var chromeTransition = transition + if let current = self.chromeView { + chromeView = current } else { - self.view.insertSubview(chromeView, aboveSubview: self.buttonBackgroundNode.view) + chromeTransition = .immediate + chromeView = UIImageView() + self.chromeView = chromeView + if let shimmeringView = self.shimmerView { + self.view.insertSubview(chromeView, aboveSubview: shimmeringView) + } else { + self.view.insertSubview(chromeView, aboveSubview: self.buttonBackgroundNode.view) + } + + chromeView.layer.compositingFilter = "overlayBlendMode" + chromeView.alpha = 0.8 + chromeView.image = GlassBackgroundView.generateForegroundImage(size: CGSize(width: 26.0 * 2.0, height: 26.0 * 2.0), isDark: self.theme.backgroundColor.lightness < 0.4, fillColor: .clear) } - - chromeView.layer.compositingFilter = "overlayBlendMode" - chromeView.alpha = 0.8 - chromeView.image = GlassBackgroundView.generateForegroundImage(size: CGSize(width: 26.0 * 2.0, height: 26.0 * 2.0), isDark: self.theme.backgroundColor.lightness < 0.4, fillColor: .clear) + chromeTransition.updateFrame(view: chromeView, frame: CGRect(origin: .zero, size: buttonSize)) } - chromeTransition.updateFrame(view: chromeView, frame: CGRect(origin: .zero, size: buttonSize)) return buttonSize.height } diff --git a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift index f14c567522..2c434c1e96 100644 --- a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift +++ b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift @@ -10,7 +10,6 @@ import PresentationDataUtils import TelegramPresentationData import TelegramUIPreferences import AccountContext -import SearchBarNode import MergeLists import ChatListSearchItemHeader import ItemListUI @@ -20,92 +19,6 @@ import ListMessageItem import ComponentFlow import SearchInputPanelComponent -private let searchBarFont = Font.regular(17.0) - -private final class AttachmentFileSearchNavigationContentNode: NavigationBarContentNode, ItemListControllerSearchNavigationContentNode { - private var theme: PresentationTheme - private let strings: PresentationStrings - - private let focus: () -> Void - private let cancel: () -> Void - - private let searchBar: SearchBarNode - - private var queryUpdated: ((String) -> Void)? - var activity: Bool = false { - didSet { - self.searchBar.activity = activity - } - } - init(theme: PresentationTheme, strings: PresentationStrings, focus: @escaping () -> Void, cancel: @escaping () -> Void, updateActivity: @escaping(@escaping(Bool)->Void) -> Void) { - self.theme = theme - self.strings = strings - - self.focus = focus - self.cancel = cancel - - self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), strings: strings, fieldStyle: .modern, displayBackground: false) - - super.init() - - //self.addSubnode(self.searchBar) - - self.searchBar.cancel = { [weak self] in - self?.searchBar.deactivate(clear: false) - self?.cancel() - } - - self.searchBar.textUpdated = { [weak self] query, _ in - self?.queryUpdated?(query) - } - - self.searchBar.focusUpdated = { [weak self] focus in - if focus { - self?.focus() - } - } - - updateActivity({ [weak self] value in - self?.activity = value - }) - - self.updatePlaceholder() - } - - func setQueryUpdated(_ f: @escaping (String) -> Void) { - self.queryUpdated = f - } - - func updateTheme(_ theme: PresentationTheme) { - self.theme = theme - self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: self.theme), strings: self.strings) - self.updatePlaceholder() - } - - func updatePlaceholder() { - self.searchBar.placeholderString = NSAttributedString(string: self.strings.Attachment_FilesSearchPlaceholder, font: searchBarFont, textColor: self.theme.rootController.navigationSearchBar.inputPlaceholderTextColor) - } - - override var nominalHeight: CGFloat { - return 56.0 - } - - override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) { - let searchBarFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - self.nominalHeight), size: CGSize(width: size.width, height: 56.0)) - self.searchBar.frame = searchBarFrame - self.searchBar.updateLayout(boundingSize: searchBarFrame.size, leftInset: leftInset, rightInset: rightInset, transition: transition) - } - - func activate() { - //self.searchBar.activate() - } - - func deactivate() { - //self.searchBar.deactivate(clear: false) - } -} - - final class AttachmentFileSearchItem: ItemListControllerSearch { let context: AccountContext let presentationData: PresentationData @@ -153,15 +66,6 @@ final class AttachmentFileSearchItem: ItemListControllerSearch { func titleContentNode(current: (NavigationBarContentNode & ItemListControllerSearchNavigationContentNode)?) -> (NavigationBarContentNode & ItemListControllerSearchNavigationContentNode)? { return nil -// let presentationData = self.presentationData -// if let current = current as? AttachmentFileSearchNavigationContentNode { -// current.updateTheme(presentationData.theme) -// return current -// } else { -// return AttachmentFileSearchNavigationContentNode(theme: presentationData.theme, strings: presentationData.strings, focus: self.focus, cancel: self.cancel, updateActivity: { [weak self] value in -// self?.updateActivity = value -// }) -// } } func node(current: ItemListControllerSearchNode?, titleContentNode: (NavigationBarContentNode & ItemListControllerSearchNavigationContentNode)?) -> ItemListControllerSearchNode { @@ -195,7 +99,6 @@ private final class AttachmentFileSearchItemNode: ItemListControllerSearchNode { send(message) }, updateActivity: updateActivity) - super.init() self.addSubnode(self.containerNode) @@ -346,7 +249,7 @@ private final class AttachmentFileSearchEntry: Comparable, Identifiable { interaction.send(message) return false }, openMessageContextMenu: { _, _, _, _, _ in }, toggleMessagesSelection: { _, _ in }, openUrl: { _, _, _, _ in }, openInstantPage: { _, _ in }, longTap: { _, _ in }, getHiddenMedia: { return [:] }) - return ListMessageItem(presentationData: ChatPresentationData(presentationData: interaction.context.sharedContext.currentPresentationData.with({$0})), context: interaction.context, chatLocation: .peer(id: PeerId(0)), interaction: itemInteraction, message: message, selection: .none, displayHeader: true, displayFileInfo: false, displayBackground: true, style: .plain) + return ListMessageItem(presentationData: ChatPresentationData(presentationData: interaction.context.sharedContext.currentPresentationData.with({$0})), systemStyle: .glass, context: interaction.context, chatLocation: .peer(id: PeerId(0)), interaction: itemInteraction, message: message, selection: .none, displayHeader: true, displayFileInfo: false, displayBackground: true, style: .plain) } } @@ -412,7 +315,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon self.presentationDataPromise = Promise(self.presentationData) self.dimNode = ASDisplayNode() - self.dimNode.backgroundColor = .clear // UIColor.black.withAlphaComponent(0.5) + self.dimNode.backgroundColor = .clear self.listNode = ListView() self.listNode.accessibilityPageScrolledString = { row, count in @@ -435,7 +338,6 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon self.listNode.backgroundColor = self.presentationData.theme.chatList.backgroundColor self.listNode.alpha = 0.0 - //self.listNode.isHidden = true self._hasDim = true @@ -488,7 +390,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon index += 1 } } else { - for _ in 0 ..< 2 { + for _ in 0 ..< 16 { entries.append(AttachmentFileSearchEntry(index: index, message: nil)) index += 1 } diff --git a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift index 0dd817a9d6..7e1b7cd1cf 100644 --- a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift +++ b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift @@ -141,7 +141,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component { size: barButtonSize, backgroundColor: environment.theme.rootController.navigationBar.glassBarButtonBackgroundColor, isDark: environment.theme.overallDarkAppearance, - state: .glass, + state: .generic, component: AnyComponentWithIdentity(id: "close", component: AnyComponent( BundleIconComponent( name: "Navigation/Close", diff --git a/submodules/TelegramUI/Components/FaceScanScreen/Sources/AgeVerificationScreen.swift b/submodules/TelegramUI/Components/FaceScanScreen/Sources/AgeVerificationScreen.swift index 067ab62016..bb51ff3f62 100644 --- a/submodules/TelegramUI/Components/FaceScanScreen/Sources/AgeVerificationScreen.swift +++ b/submodules/TelegramUI/Components/FaceScanScreen/Sources/AgeVerificationScreen.swift @@ -112,7 +112,7 @@ private final class SheetContent: CombinedComponent { size: CGSize(width: 40.0, height: 40.0), backgroundColor: theme.rootController.navigationBar.glassBarButtonBackgroundColor, isDark: theme.overallDarkAppearance, - state: .tintedGlass, + state: .generic, component: AnyComponentWithIdentity(id: "close", component: AnyComponent( BundleIconComponent( name: "Navigation/Close", diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift index b09d533ea2..039b41bb87 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift @@ -283,7 +283,7 @@ final class ThemeGridControllerNode: ASDisplayNode { self.descriptionItem = ItemListTextItem(presentationData: ItemListPresentationData(presentationData), text: .plain(descriptionText), sectionId: 0) self.resetItemNode = ItemListActionItemNode() - self.resetItem = ItemListActionItem(presentationData: ItemListPresentationData(presentationData), title: presentationData.strings.Wallpaper_ResetWallpapers, kind: .generic, alignment: .natural, sectionId: 0, style: .blocks, action: { + self.resetItem = ItemListActionItem(presentationData: ItemListPresentationData(presentationData), systemStyle: .glass, title: presentationData.strings.Wallpaper_ResetWallpapers, kind: .generic, alignment: .natural, sectionId: 0, style: .blocks, action: { resetWallpapers() }) self.resetDescriptionItemNode = ItemListTextItemNode() diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/BUILD b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/BUILD index b4546dbe12..48c14fcad0 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/BUILD +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/BUILD @@ -30,7 +30,7 @@ swift_library( "//submodules/UndoUI", "//submodules/TextFormat", "//submodules/Components/BundleIconComponent", - "//submodules/Components/SolidRoundedButtonComponent", + "//submodules/TelegramUI/Components/ButtonComponent", "//submodules/AvatarNode", "//submodules/TelegramUI/Components/Stars/StarsImageComponent", "//submodules/TelegramUI/Components/Stars/StarsAvatarComponent", @@ -38,6 +38,7 @@ swift_library( "//submodules/TelegramUI/Components/MiniAppListScreen", "//submodules/TelegramUI/Components/Premium/PremiumStarComponent", "//submodules/TelegramUI/Components/Gifts/GiftAnimationComponent", + "//submodules/TelegramUI/Components/GlassBarButtonComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift index 9d36fd41a0..6f98ee3a97 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift @@ -14,7 +14,7 @@ import SheetComponent import MultilineTextComponent import MultilineTextWithEntitiesComponent import BundleIconComponent -import SolidRoundedButtonComponent +import ButtonComponent import Markdown import BalancedTextComponent import AvatarNode @@ -27,6 +27,7 @@ import StarsAvatarComponent import MiniAppListScreen import PremiumStarComponent import GiftAnimationComponent +import GlassBarButtonComponent private final class StarsTransactionSheetContent: CombinedComponent { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -86,8 +87,6 @@ private final class StarsTransactionSheetContent: CombinedComponent { var peerMap: [EnginePeer.Id: EnginePeer] = [:] - var cachedCloseImage: (UIImage, PresentationTheme)? - var cachedOverlayCloseImage: UIImage? var cachedChevronImage: (UIImage, PresentationTheme)? var inProgress = false @@ -153,7 +152,7 @@ private final class StarsTransactionSheetContent: CombinedComponent { } static var body: Body { - let closeButton = Child(Button.self) + let closeButton = Child(GlassBarButtonComponent.self) let title = Child(MultilineTextComponent.self) let star = Child(StarsImageComponent.self) let activeStar = Child(PremiumStarComponent.self) @@ -165,8 +164,8 @@ private final class StarsTransactionSheetContent: CombinedComponent { let table = Child(TableComponent.self) let additional = Child(BalancedTextComponent.self) let status = Child(BalancedTextComponent.self) - let cancelButton = Child(SolidRoundedButtonComponent.self) - let button = Child(SolidRoundedButtonComponent.self) + let cancelButton = Child(ButtonComponent.self) + let button = Child(ButtonComponent.self) let transactionStatusBackgound = Child(RoundedRectangle.self) let transactionStatusText = Child(MultilineTextComponent.self) @@ -189,23 +188,7 @@ private final class StarsTransactionSheetContent: CombinedComponent { let sideInset: CGFloat = 16.0 + environment.safeInsets.left let textSideInset: CGFloat = 32.0 + environment.safeInsets.left - - let closeImage: UIImage - if let (image, theme) = state.cachedCloseImage, theme === environment.theme { - closeImage = image - } else { - closeImage = generateCloseButtonImage(backgroundColor: UIColor(rgb: 0x808084, alpha: 0.1), foregroundColor: theme.actionSheet.inputClearButtonColor)! - state.cachedCloseImage = (closeImage, theme) - } - - let closeOverlayImage: UIImage - if let image = state.cachedOverlayCloseImage { - closeOverlayImage = image - } else { - closeOverlayImage = generateCloseButtonImage(backgroundColor: UIColor(rgb: 0xffffff, alpha: 0.1), foregroundColor: .white)! - state.cachedOverlayCloseImage = closeOverlayImage - } - + let titleText: String let amountText: String var descriptionText: String @@ -655,15 +638,20 @@ private final class StarsTransactionSheetContent: CombinedComponent { descriptionText = modifiedString } - var closeButtonImage = closeImage - if case .unique = giftAnimationSubject { - closeButtonImage = closeOverlayImage - } let closeButton = closeButton.update( - component: Button( - content: AnyComponent(Image(image: closeButtonImage)), - action: { [weak component] in - component?.cancel(true) + component: GlassBarButtonComponent( + size: CGSize(width: 40.0, height: 40.0), + backgroundColor: theme.rootController.navigationBar.glassBarButtonBackgroundColor, + isDark: theme.overallDarkAppearance, + state: .generic, + component: AnyComponentWithIdentity(id: "close", component: AnyComponent( + BundleIconComponent( + name: "Navigation/Close", + tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor + ) + )), + action: { _ in + component.cancel(true) } ), availableSize: CGSize(width: 30.0, height: 30.0), @@ -1615,18 +1603,39 @@ private final class StarsTransactionSheetContent: CombinedComponent { if let cancelButtonText { let cancelButton = cancelButton.update( - component: SolidRoundedButtonComponent( - title: cancelButtonText, - theme: SolidRoundedButtonComponent.Theme(backgroundColor: .clear, foregroundColor: linkColor), - font: .regular, - fontSize: 17.0, - height: 50.0, - cornerRadius: 10.0, - gloss: false, - iconName: nil, - animationName: nil, - iconPosition: .left, - isLoading: state.inProgress, +// component: SolidRoundedButtonComponent( +// title: cancelButtonText, +// theme: SolidRoundedButtonComponent.Theme(backgroundColor: .clear, foregroundColor: linkColor), +// font: .regular, +// fontSize: 17.0, +// height: 50.0, +// cornerRadius: 10.0, +// gloss: false, +// iconName: nil, +// animationName: nil, +// iconPosition: .left, +// isLoading: state.inProgress, +// action: { +// component.cancel(true) +// if isSubscription { +// component.updateSubscription() +// } +// } +// ), + component: ButtonComponent( + background: ButtonComponent.Background( + style: .glass, + color: theme.list.itemCheckColors.fillColor, + foreground: theme.list.itemCheckColors.foregroundColor, + pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9), + cornerRadius: 10.0, + ), + content: AnyComponentWithIdentity( + id: AnyHashable(0), + component: AnyComponent(MultilineTextComponent(text: .plain(NSMutableAttributedString(string: cancelButtonText, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)))) + ), + isEnabled: true, + displaysProgress: state.inProgress, action: { component.cancel(true) if isSubscription { @@ -1634,13 +1643,12 @@ private final class StarsTransactionSheetContent: CombinedComponent { } } ), - availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), + availableSize: CGSize(width: context.availableSize.width - 30.0 * 2.0, height: 52.0), transition: context.transition ) - let cancelButtonFrame = CGRect(origin: CGPoint(x: sideInset, y: originY), size: cancelButton.size) context.add(cancelButton - .position(CGPoint(x: cancelButtonFrame.midX, y: cancelButtonFrame.midY)) + .position(CGPoint(x: context.availableSize.width / 2.0, y: originY + cancelButton.size.height / 2.0)) ) originY += cancelButton.size.height originY += 8.0 @@ -1648,18 +1656,20 @@ private final class StarsTransactionSheetContent: CombinedComponent { if let buttonText { let button = button.update( - component: SolidRoundedButtonComponent( - title: buttonText, - theme: SolidRoundedButtonComponent.Theme(theme: theme), - font: .bold, - fontSize: 17.0, - height: 50.0, - cornerRadius: 10.0, - gloss: false, - iconName: nil, - animationName: nil, - iconPosition: .left, - isLoading: state.inProgress, + component: ButtonComponent( + background: ButtonComponent.Background( + style: .glass, + color: theme.list.itemCheckColors.fillColor, + foreground: theme.list.itemCheckColors.foregroundColor, + pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9), + cornerRadius: 10.0, + ), + content: AnyComponentWithIdentity( + id: AnyHashable(0), + component: AnyComponent(MultilineTextComponent(text: .plain(NSMutableAttributedString(string: buttonText, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)))) + ), + isEnabled: true, + displaysProgress: state.inProgress, action: { component.cancel(true) if isSubscription && cancelButtonText == nil { @@ -1667,20 +1677,19 @@ private final class StarsTransactionSheetContent: CombinedComponent { } } ), - availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), + availableSize: CGSize(width: context.availableSize.width - 30.0 * 2.0, height: 52.0), transition: context.transition ) - let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: originY), size: button.size) context.add(button - .position(CGPoint(x: buttonFrame.midX, y: buttonFrame.midY)) + .position(CGPoint(x: context.availableSize.width / 2.0, y: originY + button.size.height / 2.0)) ) originY += button.size.height originY += 7.0 } context.add(closeButton - .position(CGPoint(x: context.availableSize.width - environment.safeInsets.left - closeButton.size.width, y: 28.0)) + .position(CGPoint(x: 16.0 + closeButton.size.width / 2.0, y: 16.0 + closeButton.size.height / 2.0)) ) let effectiveBottomInset: CGFloat = environment.metrics.isTablet ? 0.0 : environment.safeInsets.bottom @@ -1773,6 +1782,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent { updateSubscription: context.component.updateSubscription, sendGift: context.component.sendGift )), + style: .glass, backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor), followContentSizeChanges: true, clipsContent: true, diff --git a/submodules/TelegramUI/Components/StorageUsageScreen/BUILD b/submodules/TelegramUI/Components/StorageUsageScreen/BUILD index 48894fed16..61ce3c665a 100644 --- a/submodules/TelegramUI/Components/StorageUsageScreen/BUILD +++ b/submodules/TelegramUI/Components/StorageUsageScreen/BUILD @@ -19,7 +19,7 @@ swift_library( "//submodules/Components/ViewControllerComponent:ViewControllerComponent", "//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", "//submodules/Components/MultilineTextComponent:MultilineTextComponent", - "//submodules/Components/SolidRoundedButtonComponent", + "//submodules/TelegramUI/Components/ButtonComponent", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/AccountContext:AccountContext", "//submodules/AppBundle:AppBundle", diff --git a/submodules/TelegramUI/Components/StorageUsageScreen/Sources/SegmentControlComponent.swift b/submodules/TelegramUI/Components/StorageUsageScreen/Sources/SegmentControlComponent.swift index 8a65b0887f..af7e15bd86 100644 --- a/submodules/TelegramUI/Components/StorageUsageScreen/Sources/SegmentControlComponent.swift +++ b/submodules/TelegramUI/Components/StorageUsageScreen/Sources/SegmentControlComponent.swift @@ -51,12 +51,50 @@ final class SegmentControlComponent: Component { return true } + class SegmentedControlView: UISegmentedControl { + var foregroundColor: UIColor? { + didSet { + self.resetChrome() + } + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + super.touchesBegan(touches, with: event) + self.resetChrome() + } + + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + super.touchesEnded(touches, with: event) + self.resetChrome() + } + + func resetChrome() { + for case let view as UIImageView in self.subviews { + view.isHidden = true + } + if let selectorView = self.subviews.last, let loupe = selectorView.subviews.first, let innerLoupe = loupe.subviews.first { + for view in innerLoupe.subviews { + if type(of: view) == UIView.self { + view.backgroundColor = self.foregroundColor + } + } + } + } + + override func layoutSubviews() { + super.layoutSubviews() + + self.resetChrome() + } + } + class View: UIView { private let title = ComponentView() private var component: SegmentControlComponent? - private var segmentedNode: SegmentedControlNode? + private var nativeSegmentedView: SegmentedControlView? + private var legacySegmentedNode: SegmentedControlNode? override init(frame: CGRect) { super.init(frame: frame) @@ -70,34 +108,73 @@ final class SegmentControlComponent: Component { let themeUpdated = self.component?.theme !== component.theme self.component = component - - let segmentedNode: SegmentedControlNode - if let current = self.segmentedNode { - segmentedNode = current + + var controlSize = CGSize() + if #available(iOS 26.0, *) { + let segmentedView: SegmentedControlView + if let current = self.nativeSegmentedView { + segmentedView = current + } else { + let mappedActions: [UIAction] = component.items.map { item -> UIAction in + return UIAction(title: item.title, handler: { [weak self] _ in + guard let self, let component = self.component else { + return + } + component.action(item.id) + }) + } + segmentedView = SegmentedControlView(frame: .zero, actions: mappedActions) + segmentedView.selectedSegmentIndex = component.items.firstIndex(where: { $0.id == component.selectedId }) ?? 0 + self.nativeSegmentedView = segmentedView + self.addSubview(segmentedView) + } if themeUpdated { - segmentedNode.updateTheme(SegmentedControlTheme(theme: component.theme)) + let backgroundColor = component.theme.overallDarkAppearance ? component.theme.list.itemBlocksBackgroundColor : component.theme.rootController.navigationBar.segmentedBackgroundColor + segmentedView.setTitleTextAttributes([ + .font: UIFont.boldSystemFont(ofSize: 15.0), + .foregroundColor: component.theme.rootController.navigationBar.segmentedTextColor + ], for: .normal) + segmentedView.foregroundColor = component.theme.rootController.navigationBar.segmentedForegroundColor + segmentedView.backgroundColor = backgroundColor } - } else { - let mappedItems: [SegmentedControlItem] = component.items.map { item -> SegmentedControlItem in - return SegmentedControlItem(title: item.title) - } - segmentedNode = SegmentedControlNode(theme: SegmentedControlTheme(theme: component.theme), items: mappedItems, selectedIndex: component.items.firstIndex(where: { $0.id == component.selectedId }) ?? 0) - self.segmentedNode = segmentedNode - self.addSubnode(segmentedNode) - segmentedNode.selectedIndexChanged = { [weak self] index in - guard let self, let component = self.component else { - return + controlSize = segmentedView.sizeThatFits(availableSize) + controlSize.width = min(availableSize.width - 32.0, max(300.0, controlSize.width)) + controlSize.height = 36.0 + segmentedView.frame = CGRect(origin: .zero, size: controlSize) + } else { + let segmentedNode: SegmentedControlNode + if let current = self.legacySegmentedNode { + segmentedNode = current + + if themeUpdated { + let backgroundColor = component.theme.overallDarkAppearance ? component.theme.list.itemBlocksBackgroundColor : component.theme.rootController.navigationBar.segmentedBackgroundColor + let controlTheme = SegmentedControlTheme(backgroundColor: backgroundColor, foregroundColor: component.theme.rootController.navigationBar.segmentedForegroundColor, shadowColor: .clear, textColor: component.theme.rootController.navigationBar.segmentedTextColor, dividerColor: component.theme.rootController.navigationBar.segmentedDividerColor) + segmentedNode.updateTheme(controlTheme) + } + } else { + let mappedItems: [SegmentedControlItem] = component.items.map { item -> SegmentedControlItem in + return SegmentedControlItem(title: item.title) + } + let backgroundColor = component.theme.overallDarkAppearance ? component.theme.list.itemBlocksBackgroundColor : component.theme.rootController.navigationBar.segmentedBackgroundColor + let controlTheme = SegmentedControlTheme(backgroundColor: backgroundColor, foregroundColor: component.theme.rootController.navigationBar.segmentedForegroundColor, shadowColor: .clear, textColor: component.theme.rootController.navigationBar.segmentedTextColor, dividerColor: component.theme.rootController.navigationBar.segmentedDividerColor) + segmentedNode = SegmentedControlNode(theme: controlTheme, items: mappedItems, selectedIndex: component.items.firstIndex(where: { $0.id == component.selectedId }) ?? 0, cornerRadius: 18.0) + self.legacySegmentedNode = segmentedNode + self.addSubnode(segmentedNode) + + segmentedNode.selectedIndexChanged = { [weak self] index in + guard let self, let component = self.component else { + return + } + component.action(component.items[index].id) } - self.component?.action(component.items[index].id) } + + controlSize = segmentedNode.updateLayout(SegmentedControlLayout.sizeToFit(maximumWidth: availableSize.width, minimumWidth: min(availableSize.width, 300.0), height: 36.0), transition: transition.containedViewLayoutTransition) + transition.containedViewLayoutTransition.updateFrame(node: segmentedNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: controlSize)) } - let controlSize = segmentedNode.updateLayout(SegmentedControlLayout.sizeToFit(maximumWidth: availableSize.width, minimumWidth: min(availableSize.width, 296.0), height: 31.0), transition: transition.containedViewLayoutTransition) - - transition.containedViewLayoutTransition.updateFrame(node: segmentedNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: controlSize)) - return controlSize } } diff --git a/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageCategoriesComponent.swift b/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageCategoriesComponent.swift index 89b8638f50..5ad2955824 100644 --- a/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageCategoriesComponent.swift +++ b/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageCategoriesComponent.swift @@ -12,7 +12,7 @@ import TelegramCore import MultilineTextComponent import EmojiStatusComponent import CheckNode -import SolidRoundedButtonComponent +import ButtonComponent final class StorageCategoriesComponent: Component { struct CategoryData: Equatable { @@ -214,35 +214,48 @@ final class StorageCategoriesComponent: Component { label = dataSizeString(totalSelectedSize, formatting: DataSizeStringFormatting(strings: component.strings, decimalSeparator: ".")) } + var buttonContents: [AnyComponentWithIdentity] = [ + AnyComponentWithIdentity(id: "title", component: AnyComponent( + MultilineTextComponent(text: .plain(NSMutableAttributedString(string: clearTitle, font: Font.semibold(17.0), textColor: component.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))) + )) + ] + if let label { + buttonContents.append( + AnyComponentWithIdentity(id: "label", component: AnyComponent( + MultilineTextComponent(text: .plain(NSMutableAttributedString(string: label, font: Font.semibold(17.0), textColor: component.theme.list.itemCheckColors.foregroundColor.withMultipliedAlpha(0.6), paragraphAlignment: .center))) + )) + ) + } + contentHeight += 8.0 let buttonSize = self.button.update( transition: transition, - component: AnyComponent(SolidRoundedButtonComponent( - title: clearTitle, - label: label, - theme: SolidRoundedButtonComponent.Theme( - backgroundColor: component.theme.list.itemCheckColors.fillColor, - backgroundColors: [], - foregroundColor: component.theme.list.itemCheckColors.foregroundColor - ), - font: .bold, - fontSize: 17.0, - height: 52.0, - cornerRadius: 26.0, - gloss: false, - isEnabled: totalSelectedSize != 0, - animationName: nil, - iconPosition: .right, - iconSpacing: 4.0, - action: { [weak self] in - guard let self, let component = self.component else { - return + component: AnyComponent( + ButtonComponent( + background: ButtonComponent.Background( + style: .glass, + color: component.theme.list.itemCheckColors.fillColor, + foreground: component.theme.list.itemCheckColors.foregroundColor, + pressedColor: component.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9) + ), + content: AnyComponentWithIdentity( + id: AnyHashable(0), + component: AnyComponent( + HStack(buttonContents, spacing: 4.0) + ) + ), + isEnabled: totalSelectedSize != 0, + displaysProgress: false, + action: { [weak self] in + guard let self, let component = self.component else { + return + } + component.clearAction() } - component.clearAction() - } - )), + ) + ), environment: {}, - containerSize: CGSize(width: availableSize.width - 16.0 * 2.0, height: 50.0) + containerSize: CGSize(width: availableSize.width - 16.0 * 2.0, height: 52.0) ) let buttonFrame = CGRect(origin: CGPoint(x: 16.0, y: contentHeight), size: buttonSize) if let buttonView = self.button.view { diff --git a/submodules/TelegramUI/Components/Stories/StoryStealthModeSheetScreen/Sources/StoryStealthModeSheetScreen.swift b/submodules/TelegramUI/Components/Stories/StoryStealthModeSheetScreen/Sources/StoryStealthModeSheetScreen.swift index ff1195be56..cfb2959f50 100644 --- a/submodules/TelegramUI/Components/Stories/StoryStealthModeSheetScreen/Sources/StoryStealthModeSheetScreen.swift +++ b/submodules/TelegramUI/Components/Stories/StoryStealthModeSheetScreen/Sources/StoryStealthModeSheetScreen.swift @@ -223,7 +223,7 @@ private final class StoryStealthModeSheetContentComponent: Component { size: CGSize(width: 40.0, height: 40.0), backgroundColor: environment.theme.rootController.navigationBar.glassBarButtonBackgroundColor, isDark: environment.theme.overallDarkAppearance, - state: .tintedGlass, + state: .generic, component: AnyComponentWithIdentity(id: "close", component: AnyComponent( BundleIconComponent( name: "Navigation/Close", diff --git a/submodules/TelegramUI/Components/Utils/AnimatableProperty/Sources/AnimatableProperty.swift b/submodules/TelegramUI/Components/Utils/AnimatableProperty/Sources/AnimatableProperty.swift index 8e9885e9b4..e2ea939b81 100644 --- a/submodules/TelegramUI/Components/Utils/AnimatableProperty/Sources/AnimatableProperty.swift +++ b/submodules/TelegramUI/Components/Utils/AnimatableProperty/Sources/AnimatableProperty.swift @@ -65,9 +65,10 @@ public final class AnimatableProperty { guard let animation = self.animation, case let .curve(duration, curve) = animation.animation else { return false } + let effectiveDuration = duration * UIView.animationDurationFactor() let timeFromStart = timestamp - animation.startTimestamp - var t = max(0.0, timeFromStart / duration) + var t = max(0.0, timeFromStart / effectiveDuration) switch curve { case .linear: break @@ -80,7 +81,7 @@ public final class AnimatableProperty { } self.presentationValue = animation.valueAt(t) as! T - if timeFromStart <= duration { + if timeFromStart <= effectiveDuration { return true } self.animation = nil